mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
feat(lsp): support more vscode built-in settings (#20679)
This commit is contained in:
parent
8e1304ced4
commit
939279aa10
4 changed files with 399 additions and 175 deletions
|
@ -94,26 +94,67 @@ pub struct DenoCompletionSettings {
|
|||
pub imports: ImportCompletionSettings,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ClassMemberSnippets {
|
||||
#[serde(default = "is_true")]
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
impl Default for ClassMemberSnippets {
|
||||
fn default() -> Self {
|
||||
Self { enabled: true }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ObjectLiteralMethodSnippets {
|
||||
#[serde(default = "is_true")]
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
impl Default for ObjectLiteralMethodSnippets {
|
||||
fn default() -> Self {
|
||||
Self { enabled: true }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CompletionSettings {
|
||||
#[serde(default)]
|
||||
pub complete_function_calls: bool,
|
||||
#[serde(default = "is_true")]
|
||||
pub include_automatic_optional_chain_completions: bool,
|
||||
#[serde(default = "is_true")]
|
||||
pub include_completions_for_import_statements: bool,
|
||||
#[serde(default = "is_true")]
|
||||
pub names: bool,
|
||||
#[serde(default = "is_true")]
|
||||
pub paths: bool,
|
||||
#[serde(default = "is_true")]
|
||||
pub auto_imports: bool,
|
||||
#[serde(default = "is_true")]
|
||||
pub enabled: bool,
|
||||
#[serde(default)]
|
||||
pub class_member_snippets: ClassMemberSnippets,
|
||||
#[serde(default)]
|
||||
pub object_literal_method_snippets: ObjectLiteralMethodSnippets,
|
||||
}
|
||||
|
||||
impl Default for CompletionSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
complete_function_calls: false,
|
||||
include_automatic_optional_chain_completions: true,
|
||||
include_completions_for_import_statements: true,
|
||||
names: true,
|
||||
paths: true,
|
||||
auto_imports: true,
|
||||
enabled: true,
|
||||
class_member_snippets: Default::default(),
|
||||
object_literal_method_snippets: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,13 +327,91 @@ fn empty_string_none<'de, D: serde::Deserializer<'de>>(
|
|||
Ok(o.filter(|s| !s.is_empty()))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum ImportModuleSpecifier {
|
||||
NonRelative,
|
||||
ProjectRelative,
|
||||
Relative,
|
||||
Shortest,
|
||||
}
|
||||
|
||||
impl Default for ImportModuleSpecifier {
|
||||
fn default() -> Self {
|
||||
Self::Shortest
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum JsxAttributeCompletionStyle {
|
||||
Auto,
|
||||
Braces,
|
||||
None,
|
||||
}
|
||||
|
||||
impl Default for JsxAttributeCompletionStyle {
|
||||
fn default() -> Self {
|
||||
Self::Auto
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LanguagePreferences {
|
||||
#[serde(default)]
|
||||
pub import_module_specifier: ImportModuleSpecifier,
|
||||
#[serde(default)]
|
||||
pub jsx_attribute_completion_style: JsxAttributeCompletionStyle,
|
||||
#[serde(default)]
|
||||
pub auto_import_file_exclude_patterns: Vec<String>,
|
||||
#[serde(default = "is_true")]
|
||||
pub use_aliases_for_renames: bool,
|
||||
}
|
||||
|
||||
impl Default for LanguagePreferences {
|
||||
fn default() -> Self {
|
||||
LanguagePreferences {
|
||||
import_module_specifier: Default::default(),
|
||||
jsx_attribute_completion_style: Default::default(),
|
||||
auto_import_file_exclude_patterns: vec![],
|
||||
use_aliases_for_renames: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UpdateImportsOnFileMoveOptions {
|
||||
#[serde(default)]
|
||||
pub enabled: UpdateImportsOnFileMoveEnabled,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum UpdateImportsOnFileMoveEnabled {
|
||||
Always,
|
||||
Prompt,
|
||||
Never,
|
||||
}
|
||||
|
||||
impl Default for UpdateImportsOnFileMoveEnabled {
|
||||
fn default() -> Self {
|
||||
Self::Prompt
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LanguageWorkspaceSettings {
|
||||
#[serde(default)]
|
||||
pub inlay_hints: InlayHintsSettings,
|
||||
#[serde(default)]
|
||||
pub preferences: LanguagePreferences,
|
||||
#[serde(default)]
|
||||
pub suggest: CompletionSettings,
|
||||
#[serde(default)]
|
||||
pub update_imports_on_file_move: UpdateImportsOnFileMoveOptions,
|
||||
}
|
||||
|
||||
/// Deno language server specific settings that are applied to a workspace.
|
||||
|
@ -1244,12 +1363,28 @@ mod tests {
|
|||
enabled: false
|
||||
},
|
||||
},
|
||||
preferences: LanguagePreferences {
|
||||
import_module_specifier: ImportModuleSpecifier::Shortest,
|
||||
jsx_attribute_completion_style: JsxAttributeCompletionStyle::Auto,
|
||||
auto_import_file_exclude_patterns: vec![],
|
||||
use_aliases_for_renames: true,
|
||||
},
|
||||
suggest: CompletionSettings {
|
||||
complete_function_calls: false,
|
||||
include_automatic_optional_chain_completions: true,
|
||||
include_completions_for_import_statements: true,
|
||||
names: true,
|
||||
paths: true,
|
||||
auto_imports: true,
|
||||
enabled: true,
|
||||
class_member_snippets: ClassMemberSnippets { enabled: true },
|
||||
object_literal_method_snippets: ObjectLiteralMethodSnippets {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
update_imports_on_file_move: UpdateImportsOnFileMoveOptions {
|
||||
enabled: UpdateImportsOnFileMoveEnabled::Prompt
|
||||
}
|
||||
},
|
||||
typescript: LanguageWorkspaceSettings {
|
||||
inlay_hints: InlayHintsSettings {
|
||||
|
@ -1272,12 +1407,28 @@ mod tests {
|
|||
enabled: false
|
||||
},
|
||||
},
|
||||
preferences: LanguagePreferences {
|
||||
import_module_specifier: ImportModuleSpecifier::Shortest,
|
||||
jsx_attribute_completion_style: JsxAttributeCompletionStyle::Auto,
|
||||
auto_import_file_exclude_patterns: vec![],
|
||||
use_aliases_for_renames: true,
|
||||
},
|
||||
suggest: CompletionSettings {
|
||||
complete_function_calls: false,
|
||||
include_automatic_optional_chain_completions: true,
|
||||
include_completions_for_import_statements: true,
|
||||
names: true,
|
||||
paths: true,
|
||||
auto_imports: true,
|
||||
enabled: true,
|
||||
class_member_snippets: ClassMemberSnippets { enabled: true },
|
||||
object_literal_method_snippets: ObjectLiteralMethodSnippets {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
update_imports_on_file_move: UpdateImportsOnFileMoveOptions {
|
||||
enabled: UpdateImportsOnFileMoveEnabled::Prompt
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
@ -45,6 +45,7 @@ use super::code_lens;
|
|||
use super::completions;
|
||||
use super::config::Config;
|
||||
use super::config::ConfigSnapshot;
|
||||
use super::config::UpdateImportsOnFileMoveEnabled;
|
||||
use super::config::WorkspaceSettings;
|
||||
use super::config::SETTINGS_SECTION;
|
||||
use super::diagnostics;
|
||||
|
@ -1933,13 +1934,11 @@ impl Inner {
|
|||
..line_index.offset_tsc(diagnostic.range.end)?,
|
||||
codes,
|
||||
(&self.fmt_options.options).into(),
|
||||
tsc::UserPreferences {
|
||||
quote_preference: Some((&self.fmt_options.options).into()),
|
||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
||||
self.config.workspace_settings(),
|
||||
&specifier,
|
||||
)
|
||||
},
|
||||
tsc::UserPreferences::from_config_for_specifier(
|
||||
&self.config,
|
||||
&self.fmt_options.options,
|
||||
&specifier,
|
||||
),
|
||||
)
|
||||
.await;
|
||||
for action in actions {
|
||||
|
@ -2024,13 +2023,11 @@ impl Inner {
|
|||
specifier.clone(),
|
||||
line_index.offset_tsc(params.range.start)?
|
||||
..line_index.offset_tsc(params.range.end)?,
|
||||
Some(tsc::UserPreferences {
|
||||
quote_preference: Some((&self.fmt_options.options).into()),
|
||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
||||
self.config.workspace_settings(),
|
||||
&specifier,
|
||||
)
|
||||
}),
|
||||
Some(tsc::UserPreferences::from_config_for_specifier(
|
||||
&self.config,
|
||||
&self.fmt_options.options,
|
||||
&specifier,
|
||||
)),
|
||||
only,
|
||||
)
|
||||
.await?;
|
||||
|
@ -2086,13 +2083,11 @@ impl Inner {
|
|||
self.snapshot(),
|
||||
&code_action_data,
|
||||
(&self.fmt_options.options).into(),
|
||||
tsc::UserPreferences {
|
||||
quote_preference: Some((&self.fmt_options.options).into()),
|
||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
||||
self.config.workspace_settings(),
|
||||
&code_action_data.specifier,
|
||||
)
|
||||
},
|
||||
tsc::UserPreferences::from_config_for_specifier(
|
||||
&self.config,
|
||||
&self.fmt_options.options,
|
||||
&code_action_data.specifier,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
if combined_code_actions.commands.is_some() {
|
||||
|
@ -2138,13 +2133,11 @@ impl Inner {
|
|||
..line_index.offset_tsc(action_data.range.end)?,
|
||||
action_data.refactor_name,
|
||||
action_data.action_name,
|
||||
Some(tsc::UserPreferences {
|
||||
quote_preference: Some((&self.fmt_options.options).into()),
|
||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
||||
self.config.workspace_settings(),
|
||||
&action_data.specifier,
|
||||
)
|
||||
}),
|
||||
Some(tsc::UserPreferences::from_config_for_specifier(
|
||||
&self.config,
|
||||
&self.fmt_options.options,
|
||||
&action_data.specifier,
|
||||
)),
|
||||
)
|
||||
.await?;
|
||||
code_action.edit = refactor_edit_info.to_workspace_edit(self).await?;
|
||||
|
@ -2413,8 +2406,13 @@ impl Inner {
|
|||
¶ms.text_document_position.text_document.uri,
|
||||
LspUrlKind::File,
|
||||
);
|
||||
let language_settings = self
|
||||
.config
|
||||
.workspace_settings()
|
||||
.language_settings_for_specifier(&specifier);
|
||||
if !self.is_diagnosable(&specifier)
|
||||
|| !self.config.specifier_enabled(&specifier)
|
||||
|| !language_settings.map(|s| s.suggest.enabled).unwrap_or(true)
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -2425,20 +2423,24 @@ impl Inner {
|
|||
// completions, we will use internal logic and if there are completions
|
||||
// for imports, we will return those and not send a message into tsc, where
|
||||
// other completions come from.
|
||||
let response = if let Some(response) = completions::get_import_completions(
|
||||
&specifier,
|
||||
¶ms.text_document_position.position,
|
||||
&self.config.snapshot(),
|
||||
&self.client,
|
||||
&self.module_registries,
|
||||
&self.npm.search_api,
|
||||
&self.documents,
|
||||
self.maybe_import_map.clone(),
|
||||
)
|
||||
.await
|
||||
let mut response = None;
|
||||
if language_settings
|
||||
.map(|s| s.suggest.include_completions_for_import_statements)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
Some(response)
|
||||
} else {
|
||||
response = completions::get_import_completions(
|
||||
&specifier,
|
||||
¶ms.text_document_position.position,
|
||||
&self.config.snapshot(),
|
||||
&self.client,
|
||||
&self.module_registries,
|
||||
&self.npm.search_api,
|
||||
&self.documents,
|
||||
self.maybe_import_map.clone(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
if response.is_none() {
|
||||
let line_index = asset_or_doc.line_index();
|
||||
let (trigger_character, trigger_kind) =
|
||||
if let Some(context) = ¶ms.context {
|
||||
|
@ -2451,7 +2453,6 @@ impl Inner {
|
|||
};
|
||||
let position =
|
||||
line_index.offset_tsc(params.text_document_position.position)?;
|
||||
let use_snippets = self.config.client_capabilities.snippet_support;
|
||||
let maybe_completion_info = self
|
||||
.ts_server
|
||||
.get_completions(
|
||||
|
@ -2459,38 +2460,11 @@ impl Inner {
|
|||
specifier.clone(),
|
||||
position,
|
||||
tsc::GetCompletionsAtPositionOptions {
|
||||
user_preferences: tsc::UserPreferences {
|
||||
quote_preference: Some((&self.fmt_options.options).into()),
|
||||
allow_incomplete_completions: Some(true),
|
||||
allow_text_changes_in_new_files: Some(
|
||||
specifier.scheme() == "file",
|
||||
),
|
||||
import_module_specifier_ending: Some(
|
||||
tsc::ImportModuleSpecifierEnding::Index,
|
||||
),
|
||||
include_automatic_optional_chain_completions: Some(true),
|
||||
include_completions_for_import_statements: Some(true),
|
||||
include_completions_for_module_exports: self
|
||||
.config
|
||||
.workspace_settings()
|
||||
.language_settings_for_specifier(&specifier)
|
||||
.map(|s| s.suggest.auto_imports),
|
||||
include_completions_with_object_literal_method_snippets: Some(
|
||||
use_snippets,
|
||||
),
|
||||
include_completions_with_class_member_snippets: Some(
|
||||
use_snippets,
|
||||
),
|
||||
include_completions_with_insert_text: Some(true),
|
||||
include_completions_with_snippet_text: Some(use_snippets),
|
||||
jsx_attribute_completion_style: Some(
|
||||
tsc::JsxAttributeCompletionStyle::Auto,
|
||||
),
|
||||
provide_prefix_and_suffix_text_for_rename: Some(true),
|
||||
provide_refactor_not_applicable_reason: Some(true),
|
||||
use_label_details_in_completion_entries: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
user_preferences: tsc::UserPreferences::from_config_for_specifier(
|
||||
&self.config,
|
||||
&self.fmt_options.options,
|
||||
&specifier,
|
||||
),
|
||||
trigger_character,
|
||||
trigger_kind,
|
||||
},
|
||||
|
@ -2499,22 +2473,21 @@ impl Inner {
|
|||
.await;
|
||||
|
||||
if let Some(completions) = maybe_completion_info {
|
||||
let results = completions.as_completion_response(
|
||||
line_index,
|
||||
&self
|
||||
.config
|
||||
.workspace_settings()
|
||||
.language_settings_for_specifier(&specifier)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.suggest,
|
||||
&specifier,
|
||||
position,
|
||||
self,
|
||||
response = Some(
|
||||
completions.as_completion_response(
|
||||
line_index,
|
||||
&self
|
||||
.config
|
||||
.workspace_settings()
|
||||
.language_settings_for_specifier(&specifier)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.suggest,
|
||||
&specifier,
|
||||
position,
|
||||
self,
|
||||
),
|
||||
);
|
||||
Some(results)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
self.performance.measure(mark);
|
||||
|
@ -2536,17 +2509,22 @@ impl Inner {
|
|||
})?;
|
||||
if let Some(data) = &data.tsc {
|
||||
let specifier = &data.specifier;
|
||||
let mut args = GetCompletionDetailsArgs {
|
||||
format_code_settings: Some((&self.fmt_options.options).into()),
|
||||
..data.into()
|
||||
};
|
||||
args
|
||||
.preferences
|
||||
.get_or_insert(Default::default())
|
||||
.quote_preference = Some((&self.fmt_options.options).into());
|
||||
let result = self
|
||||
.ts_server
|
||||
.get_completion_details(self.snapshot(), args)
|
||||
.get_completion_details(
|
||||
self.snapshot(),
|
||||
GetCompletionDetailsArgs {
|
||||
format_code_settings: Some((&self.fmt_options.options).into()),
|
||||
preferences: Some(
|
||||
tsc::UserPreferences::from_config_for_specifier(
|
||||
&self.config,
|
||||
&self.fmt_options.options,
|
||||
specifier,
|
||||
),
|
||||
),
|
||||
..data.into()
|
||||
},
|
||||
)
|
||||
.await;
|
||||
match result {
|
||||
Ok(maybe_completion_info) => {
|
||||
|
@ -3029,15 +3007,27 @@ impl Inner {
|
|||
) -> LspResult<Option<WorkspaceEdit>> {
|
||||
let mut changes = vec![];
|
||||
for rename in params.files {
|
||||
let old_specifier = self.url_map.normalize_url(
|
||||
&resolve_url(&rename.old_uri).unwrap(),
|
||||
LspUrlKind::File,
|
||||
);
|
||||
let options = self
|
||||
.config
|
||||
.workspace_settings()
|
||||
.language_settings_for_specifier(&old_specifier)
|
||||
.map(|s| s.update_imports_on_file_move.clone())
|
||||
.unwrap_or_default();
|
||||
// Note that `Always` and `Prompt` are treated the same in the server, the
|
||||
// client will worry about that after receiving the edits.
|
||||
if options.enabled == UpdateImportsOnFileMoveEnabled::Never {
|
||||
continue;
|
||||
}
|
||||
changes.extend(
|
||||
self
|
||||
.ts_server
|
||||
.get_edits_for_file_rename(
|
||||
self.snapshot(),
|
||||
self.url_map.normalize_url(
|
||||
&resolve_url(&rename.old_uri).unwrap(),
|
||||
LspUrlKind::File,
|
||||
),
|
||||
old_specifier,
|
||||
self.url_map.normalize_url(
|
||||
&resolve_url(&rename.new_uri).unwrap(),
|
||||
LspUrlKind::File,
|
||||
|
@ -3300,20 +3290,19 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
|||
|
||||
async fn did_save(&self, params: DidSaveTextDocumentParams) {
|
||||
let uri = ¶ms.text_document.uri;
|
||||
let Ok(path) = specifier_to_file_path(uri) else {
|
||||
return;
|
||||
};
|
||||
if !is_importable_ext(&path) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
let inner = self.0.read().await;
|
||||
let specifier = inner.url_map.normalize_url(uri, LspUrlKind::File);
|
||||
if !inner.config.workspace_settings().cache_on_save
|
||||
|| !inner.config.specifier_enabled(uri)
|
||||
|| !inner.diagnostics_state.has_no_cache_diagnostics(uri)
|
||||
|| !inner.config.specifier_enabled(&specifier)
|
||||
|| !inner.diagnostics_state.has_no_cache_diagnostics(&specifier)
|
||||
{
|
||||
return;
|
||||
}
|
||||
match specifier_to_file_path(&specifier) {
|
||||
Ok(path) if is_importable_ext(&path) => {}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
if let Err(err) = self
|
||||
.cache_request(Some(
|
||||
|
@ -3677,10 +3666,12 @@ impl Inner {
|
|||
let specifier = self
|
||||
.url_map
|
||||
.normalize_url(¶ms.text_document.uri, LspUrlKind::File);
|
||||
let workspace_settings = self.config.workspace_settings();
|
||||
if !self.is_diagnosable(&specifier)
|
||||
|| !self.config.specifier_enabled(&specifier)
|
||||
|| !workspace_settings.enabled_inlay_hints(&specifier)
|
||||
|| !self
|
||||
.config
|
||||
.workspace_settings()
|
||||
.enabled_inlay_hints(&specifier)
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -3701,13 +3692,11 @@ impl Inner {
|
|||
self.snapshot(),
|
||||
specifier.clone(),
|
||||
text_span,
|
||||
tsc::UserPreferences {
|
||||
quote_preference: Some((&self.fmt_options.options).into()),
|
||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
||||
workspace_settings,
|
||||
&specifier,
|
||||
)
|
||||
},
|
||||
tsc::UserPreferences::from_config_for_specifier(
|
||||
&self.config,
|
||||
&self.fmt_options.options,
|
||||
&specifier,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
let maybe_inlay_hints = maybe_inlay_hints.map(|hints| {
|
||||
|
|
|
@ -32,10 +32,12 @@ use tower_lsp::lsp_types::WorkDoneProgressParams;
|
|||
use tower_lsp::LanguageServer;
|
||||
|
||||
use super::client::Client;
|
||||
use super::config::ClassMemberSnippets;
|
||||
use super::config::CompletionSettings;
|
||||
use super::config::DenoCompletionSettings;
|
||||
use super::config::ImportCompletionSettings;
|
||||
use super::config::LanguageWorkspaceSettings;
|
||||
use super::config::ObjectLiteralMethodSnippets;
|
||||
use super::config::TestingSettings;
|
||||
use super::config::WorkspaceSettings;
|
||||
|
||||
|
@ -309,22 +311,36 @@ pub fn get_repl_workspace_settings() -> WorkspaceSettings {
|
|||
},
|
||||
testing: TestingSettings { args: vec![] },
|
||||
javascript: LanguageWorkspaceSettings {
|
||||
inlay_hints: Default::default(),
|
||||
suggest: CompletionSettings {
|
||||
complete_function_calls: false,
|
||||
names: false,
|
||||
paths: false,
|
||||
auto_imports: false,
|
||||
class_member_snippets: ClassMemberSnippets { enabled: false },
|
||||
complete_function_calls: false,
|
||||
enabled: true,
|
||||
include_automatic_optional_chain_completions: false,
|
||||
include_completions_for_import_statements: true,
|
||||
names: false,
|
||||
object_literal_method_snippets: ObjectLiteralMethodSnippets {
|
||||
enabled: false,
|
||||
},
|
||||
paths: false,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
typescript: LanguageWorkspaceSettings {
|
||||
inlay_hints: Default::default(),
|
||||
suggest: CompletionSettings {
|
||||
complete_function_calls: false,
|
||||
names: false,
|
||||
paths: false,
|
||||
auto_imports: false,
|
||||
class_member_snippets: ClassMemberSnippets { enabled: false },
|
||||
complete_function_calls: false,
|
||||
enabled: true,
|
||||
include_automatic_optional_chain_completions: false,
|
||||
include_completions_for_import_statements: true,
|
||||
names: false,
|
||||
object_literal_method_snippets: ObjectLiteralMethodSnippets {
|
||||
enabled: false,
|
||||
},
|
||||
paths: false,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
164
cli/lsp/tsc.rs
164
cli/lsp/tsc.rs
|
@ -3532,14 +3532,7 @@ impl From<&FmtOptionsConfig> for QuotePreference {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[allow(dead_code)]
|
||||
pub enum ImportModuleSpecifierPreference {
|
||||
Auto,
|
||||
Relative,
|
||||
NonRelative,
|
||||
}
|
||||
pub type ImportModuleSpecifierPreference = config::ImportModuleSpecifier;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
|
@ -3581,14 +3574,7 @@ pub enum IncludePackageJsonAutoImports {
|
|||
Off,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[allow(dead_code)]
|
||||
pub enum JsxAttributeCompletionStyle {
|
||||
Auto,
|
||||
Braces,
|
||||
None,
|
||||
}
|
||||
pub type JsxAttributeCompletionStyle = config::JsxAttributeCompletionStyle;
|
||||
|
||||
#[derive(Debug, Default, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
@ -3666,35 +3652,115 @@ pub struct UserPreferences {
|
|||
}
|
||||
|
||||
impl UserPreferences {
|
||||
pub fn from_workspace_settings_for_specifier(
|
||||
settings: &config::WorkspaceSettings,
|
||||
pub fn from_config_for_specifier(
|
||||
config: &config::Config,
|
||||
fmt_config: &FmtOptionsConfig,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Self {
|
||||
let language_settings = settings.language_settings_for_specifier(specifier);
|
||||
Self {
|
||||
include_inlay_parameter_name_hints: language_settings
|
||||
.map(|s| (&s.inlay_hints.parameter_names.enabled).into()),
|
||||
include_inlay_parameter_name_hints_when_argument_matches_name:
|
||||
language_settings.map(|s| {
|
||||
!s.inlay_hints
|
||||
.parameter_names
|
||||
.suppress_when_argument_matches_name
|
||||
}),
|
||||
include_inlay_function_parameter_type_hints: language_settings
|
||||
.map(|s| s.inlay_hints.parameter_types.enabled),
|
||||
include_inlay_variable_type_hints: language_settings
|
||||
.map(|s| s.inlay_hints.variable_types.enabled),
|
||||
include_inlay_variable_type_hints_when_type_matches_name:
|
||||
language_settings.map(|s| {
|
||||
!s.inlay_hints.variable_types.suppress_when_type_matches_name
|
||||
}),
|
||||
include_inlay_property_declaration_type_hints: language_settings
|
||||
.map(|s| s.inlay_hints.property_declaration_types.enabled),
|
||||
include_inlay_function_like_return_type_hints: language_settings
|
||||
.map(|s| s.inlay_hints.function_like_return_types.enabled),
|
||||
include_inlay_enum_member_value_hints: language_settings
|
||||
.map(|s| s.inlay_hints.enum_member_values.enabled),
|
||||
let base_preferences = Self {
|
||||
allow_incomplete_completions: Some(true),
|
||||
allow_text_changes_in_new_files: Some(specifier.scheme() == "file"),
|
||||
// TODO(nayeemrmn): Investigate why we use `Index` here.
|
||||
import_module_specifier_ending: Some(ImportModuleSpecifierEnding::Index),
|
||||
include_completions_with_snippet_text: Some(
|
||||
config.client_capabilities.snippet_support,
|
||||
),
|
||||
provide_refactor_not_applicable_reason: Some(true),
|
||||
quote_preference: Some(fmt_config.into()),
|
||||
use_label_details_in_completion_entries: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let Some(language_settings) = config
|
||||
.workspace_settings()
|
||||
.language_settings_for_specifier(specifier)
|
||||
else {
|
||||
return base_preferences;
|
||||
};
|
||||
Self {
|
||||
auto_import_file_exclude_patterns: Some(
|
||||
language_settings
|
||||
.preferences
|
||||
.auto_import_file_exclude_patterns
|
||||
.clone(),
|
||||
),
|
||||
include_automatic_optional_chain_completions: Some(
|
||||
language_settings.suggest.enabled
|
||||
&& language_settings
|
||||
.suggest
|
||||
.include_automatic_optional_chain_completions,
|
||||
),
|
||||
include_completions_for_import_statements: Some(
|
||||
language_settings.suggest.enabled
|
||||
&& language_settings
|
||||
.suggest
|
||||
.include_completions_for_import_statements,
|
||||
),
|
||||
include_completions_for_module_exports: Some(
|
||||
language_settings.suggest.enabled
|
||||
&& language_settings.suggest.auto_imports,
|
||||
),
|
||||
include_completions_with_class_member_snippets: Some(
|
||||
language_settings.suggest.enabled
|
||||
&& language_settings.suggest.class_member_snippets.enabled
|
||||
&& config.client_capabilities.snippet_support,
|
||||
),
|
||||
include_completions_with_insert_text: Some(
|
||||
language_settings.suggest.enabled,
|
||||
),
|
||||
include_completions_with_object_literal_method_snippets: Some(
|
||||
language_settings.suggest.enabled
|
||||
&& language_settings
|
||||
.suggest
|
||||
.object_literal_method_snippets
|
||||
.enabled
|
||||
&& config.client_capabilities.snippet_support,
|
||||
),
|
||||
import_module_specifier_preference: Some(
|
||||
language_settings.preferences.import_module_specifier,
|
||||
),
|
||||
include_inlay_parameter_name_hints: Some(
|
||||
(&language_settings.inlay_hints.parameter_names.enabled).into(),
|
||||
),
|
||||
include_inlay_parameter_name_hints_when_argument_matches_name: Some(
|
||||
!language_settings
|
||||
.inlay_hints
|
||||
.parameter_names
|
||||
.suppress_when_argument_matches_name,
|
||||
),
|
||||
include_inlay_function_parameter_type_hints: Some(
|
||||
language_settings.inlay_hints.parameter_types.enabled,
|
||||
),
|
||||
include_inlay_variable_type_hints: Some(
|
||||
language_settings.inlay_hints.variable_types.enabled,
|
||||
),
|
||||
include_inlay_variable_type_hints_when_type_matches_name: Some(
|
||||
!language_settings
|
||||
.inlay_hints
|
||||
.variable_types
|
||||
.suppress_when_type_matches_name,
|
||||
),
|
||||
include_inlay_property_declaration_type_hints: Some(
|
||||
language_settings
|
||||
.inlay_hints
|
||||
.property_declaration_types
|
||||
.enabled,
|
||||
),
|
||||
include_inlay_function_like_return_type_hints: Some(
|
||||
language_settings
|
||||
.inlay_hints
|
||||
.function_like_return_types
|
||||
.enabled,
|
||||
),
|
||||
include_inlay_enum_member_value_hints: Some(
|
||||
language_settings.inlay_hints.enum_member_values.enabled,
|
||||
),
|
||||
jsx_attribute_completion_style: Some(
|
||||
language_settings.preferences.jsx_attribute_completion_style,
|
||||
),
|
||||
provide_prefix_and_suffix_text_for_rename: Some(
|
||||
language_settings.preferences.use_aliases_for_renames,
|
||||
),
|
||||
..base_preferences
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5149,7 +5215,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn include_suppress_inlay_hit_settings() {
|
||||
fn include_suppress_inlay_hint_settings() {
|
||||
let mut settings = WorkspaceSettings::default();
|
||||
settings
|
||||
.typescript
|
||||
|
@ -5161,11 +5227,13 @@ mod tests {
|
|||
.inlay_hints
|
||||
.variable_types
|
||||
.suppress_when_type_matches_name = true;
|
||||
let user_preferences =
|
||||
UserPreferences::from_workspace_settings_for_specifier(
|
||||
&settings,
|
||||
&ModuleSpecifier::parse("file:///foo.ts").unwrap(),
|
||||
);
|
||||
let mut config = config::Config::new();
|
||||
config.set_workspace_settings(settings);
|
||||
let user_preferences = UserPreferences::from_config_for_specifier(
|
||||
&config,
|
||||
&Default::default(),
|
||||
&ModuleSpecifier::parse("file:///foo.ts").unwrap(),
|
||||
);
|
||||
assert_eq!(
|
||||
user_preferences.include_inlay_variable_type_hints_when_type_matches_name,
|
||||
Some(false)
|
||||
|
|
Loading…
Reference in a new issue