mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -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,
|
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)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CompletionSettings {
|
pub struct CompletionSettings {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub complete_function_calls: bool,
|
pub complete_function_calls: bool,
|
||||||
#[serde(default = "is_true")]
|
#[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,
|
pub names: bool,
|
||||||
#[serde(default = "is_true")]
|
#[serde(default = "is_true")]
|
||||||
pub paths: bool,
|
pub paths: bool,
|
||||||
#[serde(default = "is_true")]
|
#[serde(default = "is_true")]
|
||||||
pub auto_imports: bool,
|
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 {
|
impl Default for CompletionSettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
complete_function_calls: false,
|
complete_function_calls: false,
|
||||||
|
include_automatic_optional_chain_completions: true,
|
||||||
|
include_completions_for_import_statements: true,
|
||||||
names: true,
|
names: true,
|
||||||
paths: true,
|
paths: true,
|
||||||
auto_imports: 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()))
|
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)]
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct LanguageWorkspaceSettings {
|
pub struct LanguageWorkspaceSettings {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub inlay_hints: InlayHintsSettings,
|
pub inlay_hints: InlayHintsSettings,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub preferences: LanguagePreferences,
|
||||||
|
#[serde(default)]
|
||||||
pub suggest: CompletionSettings,
|
pub suggest: CompletionSettings,
|
||||||
|
#[serde(default)]
|
||||||
|
pub update_imports_on_file_move: UpdateImportsOnFileMoveOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deno language server specific settings that are applied to a workspace.
|
/// Deno language server specific settings that are applied to a workspace.
|
||||||
|
@ -1244,12 +1363,28 @@ mod tests {
|
||||||
enabled: false
|
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 {
|
suggest: CompletionSettings {
|
||||||
complete_function_calls: false,
|
complete_function_calls: false,
|
||||||
|
include_automatic_optional_chain_completions: true,
|
||||||
|
include_completions_for_import_statements: true,
|
||||||
names: true,
|
names: true,
|
||||||
paths: true,
|
paths: true,
|
||||||
auto_imports: 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 {
|
typescript: LanguageWorkspaceSettings {
|
||||||
inlay_hints: InlayHintsSettings {
|
inlay_hints: InlayHintsSettings {
|
||||||
|
@ -1272,12 +1407,28 @@ mod tests {
|
||||||
enabled: false
|
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 {
|
suggest: CompletionSettings {
|
||||||
complete_function_calls: false,
|
complete_function_calls: false,
|
||||||
|
include_automatic_optional_chain_completions: true,
|
||||||
|
include_completions_for_import_statements: true,
|
||||||
names: true,
|
names: true,
|
||||||
paths: true,
|
paths: true,
|
||||||
auto_imports: 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::completions;
|
||||||
use super::config::Config;
|
use super::config::Config;
|
||||||
use super::config::ConfigSnapshot;
|
use super::config::ConfigSnapshot;
|
||||||
|
use super::config::UpdateImportsOnFileMoveEnabled;
|
||||||
use super::config::WorkspaceSettings;
|
use super::config::WorkspaceSettings;
|
||||||
use super::config::SETTINGS_SECTION;
|
use super::config::SETTINGS_SECTION;
|
||||||
use super::diagnostics;
|
use super::diagnostics;
|
||||||
|
@ -1933,13 +1934,11 @@ impl Inner {
|
||||||
..line_index.offset_tsc(diagnostic.range.end)?,
|
..line_index.offset_tsc(diagnostic.range.end)?,
|
||||||
codes,
|
codes,
|
||||||
(&self.fmt_options.options).into(),
|
(&self.fmt_options.options).into(),
|
||||||
tsc::UserPreferences {
|
tsc::UserPreferences::from_config_for_specifier(
|
||||||
quote_preference: Some((&self.fmt_options.options).into()),
|
&self.config,
|
||||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
&self.fmt_options.options,
|
||||||
self.config.workspace_settings(),
|
&specifier,
|
||||||
&specifier,
|
),
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
for action in actions {
|
for action in actions {
|
||||||
|
@ -2024,13 +2023,11 @@ impl Inner {
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
line_index.offset_tsc(params.range.start)?
|
line_index.offset_tsc(params.range.start)?
|
||||||
..line_index.offset_tsc(params.range.end)?,
|
..line_index.offset_tsc(params.range.end)?,
|
||||||
Some(tsc::UserPreferences {
|
Some(tsc::UserPreferences::from_config_for_specifier(
|
||||||
quote_preference: Some((&self.fmt_options.options).into()),
|
&self.config,
|
||||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
&self.fmt_options.options,
|
||||||
self.config.workspace_settings(),
|
&specifier,
|
||||||
&specifier,
|
)),
|
||||||
)
|
|
||||||
}),
|
|
||||||
only,
|
only,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -2086,13 +2083,11 @@ impl Inner {
|
||||||
self.snapshot(),
|
self.snapshot(),
|
||||||
&code_action_data,
|
&code_action_data,
|
||||||
(&self.fmt_options.options).into(),
|
(&self.fmt_options.options).into(),
|
||||||
tsc::UserPreferences {
|
tsc::UserPreferences::from_config_for_specifier(
|
||||||
quote_preference: Some((&self.fmt_options.options).into()),
|
&self.config,
|
||||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
&self.fmt_options.options,
|
||||||
self.config.workspace_settings(),
|
&code_action_data.specifier,
|
||||||
&code_action_data.specifier,
|
),
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
if combined_code_actions.commands.is_some() {
|
if combined_code_actions.commands.is_some() {
|
||||||
|
@ -2138,13 +2133,11 @@ impl Inner {
|
||||||
..line_index.offset_tsc(action_data.range.end)?,
|
..line_index.offset_tsc(action_data.range.end)?,
|
||||||
action_data.refactor_name,
|
action_data.refactor_name,
|
||||||
action_data.action_name,
|
action_data.action_name,
|
||||||
Some(tsc::UserPreferences {
|
Some(tsc::UserPreferences::from_config_for_specifier(
|
||||||
quote_preference: Some((&self.fmt_options.options).into()),
|
&self.config,
|
||||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
&self.fmt_options.options,
|
||||||
self.config.workspace_settings(),
|
&action_data.specifier,
|
||||||
&action_data.specifier,
|
)),
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
code_action.edit = refactor_edit_info.to_workspace_edit(self).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,
|
¶ms.text_document_position.text_document.uri,
|
||||||
LspUrlKind::File,
|
LspUrlKind::File,
|
||||||
);
|
);
|
||||||
|
let language_settings = self
|
||||||
|
.config
|
||||||
|
.workspace_settings()
|
||||||
|
.language_settings_for_specifier(&specifier);
|
||||||
if !self.is_diagnosable(&specifier)
|
if !self.is_diagnosable(&specifier)
|
||||||
|| !self.config.specifier_enabled(&specifier)
|
|| !self.config.specifier_enabled(&specifier)
|
||||||
|
|| !language_settings.map(|s| s.suggest.enabled).unwrap_or(true)
|
||||||
{
|
{
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
@ -2425,20 +2423,24 @@ impl Inner {
|
||||||
// completions, we will use internal logic and if there are completions
|
// 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
|
// for imports, we will return those and not send a message into tsc, where
|
||||||
// other completions come from.
|
// other completions come from.
|
||||||
let response = if let Some(response) = completions::get_import_completions(
|
let mut response = None;
|
||||||
&specifier,
|
if language_settings
|
||||||
¶ms.text_document_position.position,
|
.map(|s| s.suggest.include_completions_for_import_statements)
|
||||||
&self.config.snapshot(),
|
.unwrap_or(true)
|
||||||
&self.client,
|
|
||||||
&self.module_registries,
|
|
||||||
&self.npm.search_api,
|
|
||||||
&self.documents,
|
|
||||||
self.maybe_import_map.clone(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
Some(response)
|
response = completions::get_import_completions(
|
||||||
} else {
|
&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 line_index = asset_or_doc.line_index();
|
||||||
let (trigger_character, trigger_kind) =
|
let (trigger_character, trigger_kind) =
|
||||||
if let Some(context) = ¶ms.context {
|
if let Some(context) = ¶ms.context {
|
||||||
|
@ -2451,7 +2453,6 @@ impl Inner {
|
||||||
};
|
};
|
||||||
let position =
|
let position =
|
||||||
line_index.offset_tsc(params.text_document_position.position)?;
|
line_index.offset_tsc(params.text_document_position.position)?;
|
||||||
let use_snippets = self.config.client_capabilities.snippet_support;
|
|
||||||
let maybe_completion_info = self
|
let maybe_completion_info = self
|
||||||
.ts_server
|
.ts_server
|
||||||
.get_completions(
|
.get_completions(
|
||||||
|
@ -2459,38 +2460,11 @@ impl Inner {
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
position,
|
position,
|
||||||
tsc::GetCompletionsAtPositionOptions {
|
tsc::GetCompletionsAtPositionOptions {
|
||||||
user_preferences: tsc::UserPreferences {
|
user_preferences: tsc::UserPreferences::from_config_for_specifier(
|
||||||
quote_preference: Some((&self.fmt_options.options).into()),
|
&self.config,
|
||||||
allow_incomplete_completions: Some(true),
|
&self.fmt_options.options,
|
||||||
allow_text_changes_in_new_files: Some(
|
&specifier,
|
||||||
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()
|
|
||||||
},
|
|
||||||
trigger_character,
|
trigger_character,
|
||||||
trigger_kind,
|
trigger_kind,
|
||||||
},
|
},
|
||||||
|
@ -2499,22 +2473,21 @@ impl Inner {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
if let Some(completions) = maybe_completion_info {
|
if let Some(completions) = maybe_completion_info {
|
||||||
let results = completions.as_completion_response(
|
response = Some(
|
||||||
line_index,
|
completions.as_completion_response(
|
||||||
&self
|
line_index,
|
||||||
.config
|
&self
|
||||||
.workspace_settings()
|
.config
|
||||||
.language_settings_for_specifier(&specifier)
|
.workspace_settings()
|
||||||
.cloned()
|
.language_settings_for_specifier(&specifier)
|
||||||
.unwrap_or_default()
|
.cloned()
|
||||||
.suggest,
|
.unwrap_or_default()
|
||||||
&specifier,
|
.suggest,
|
||||||
position,
|
&specifier,
|
||||||
self,
|
position,
|
||||||
|
self,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
Some(results)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.performance.measure(mark);
|
self.performance.measure(mark);
|
||||||
|
@ -2536,17 +2509,22 @@ impl Inner {
|
||||||
})?;
|
})?;
|
||||||
if let Some(data) = &data.tsc {
|
if let Some(data) = &data.tsc {
|
||||||
let specifier = &data.specifier;
|
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
|
let result = self
|
||||||
.ts_server
|
.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;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
Ok(maybe_completion_info) => {
|
Ok(maybe_completion_info) => {
|
||||||
|
@ -3029,15 +3007,27 @@ impl Inner {
|
||||||
) -> LspResult<Option<WorkspaceEdit>> {
|
) -> LspResult<Option<WorkspaceEdit>> {
|
||||||
let mut changes = vec![];
|
let mut changes = vec![];
|
||||||
for rename in params.files {
|
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(
|
changes.extend(
|
||||||
self
|
self
|
||||||
.ts_server
|
.ts_server
|
||||||
.get_edits_for_file_rename(
|
.get_edits_for_file_rename(
|
||||||
self.snapshot(),
|
self.snapshot(),
|
||||||
self.url_map.normalize_url(
|
old_specifier,
|
||||||
&resolve_url(&rename.old_uri).unwrap(),
|
|
||||||
LspUrlKind::File,
|
|
||||||
),
|
|
||||||
self.url_map.normalize_url(
|
self.url_map.normalize_url(
|
||||||
&resolve_url(&rename.new_uri).unwrap(),
|
&resolve_url(&rename.new_uri).unwrap(),
|
||||||
LspUrlKind::File,
|
LspUrlKind::File,
|
||||||
|
@ -3300,20 +3290,19 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
||||||
|
|
||||||
async fn did_save(&self, params: DidSaveTextDocumentParams) {
|
async fn did_save(&self, params: DidSaveTextDocumentParams) {
|
||||||
let uri = ¶ms.text_document.uri;
|
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 inner = self.0.read().await;
|
||||||
|
let specifier = inner.url_map.normalize_url(uri, LspUrlKind::File);
|
||||||
if !inner.config.workspace_settings().cache_on_save
|
if !inner.config.workspace_settings().cache_on_save
|
||||||
|| !inner.config.specifier_enabled(uri)
|
|| !inner.config.specifier_enabled(&specifier)
|
||||||
|| !inner.diagnostics_state.has_no_cache_diagnostics(uri)
|
|| !inner.diagnostics_state.has_no_cache_diagnostics(&specifier)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
match specifier_to_file_path(&specifier) {
|
||||||
|
Ok(path) if is_importable_ext(&path) => {}
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Err(err) = self
|
if let Err(err) = self
|
||||||
.cache_request(Some(
|
.cache_request(Some(
|
||||||
|
@ -3677,10 +3666,12 @@ impl Inner {
|
||||||
let specifier = self
|
let specifier = self
|
||||||
.url_map
|
.url_map
|
||||||
.normalize_url(¶ms.text_document.uri, LspUrlKind::File);
|
.normalize_url(¶ms.text_document.uri, LspUrlKind::File);
|
||||||
let workspace_settings = self.config.workspace_settings();
|
|
||||||
if !self.is_diagnosable(&specifier)
|
if !self.is_diagnosable(&specifier)
|
||||||
|| !self.config.specifier_enabled(&specifier)
|
|| !self.config.specifier_enabled(&specifier)
|
||||||
|| !workspace_settings.enabled_inlay_hints(&specifier)
|
|| !self
|
||||||
|
.config
|
||||||
|
.workspace_settings()
|
||||||
|
.enabled_inlay_hints(&specifier)
|
||||||
{
|
{
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
@ -3701,13 +3692,11 @@ impl Inner {
|
||||||
self.snapshot(),
|
self.snapshot(),
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
text_span,
|
text_span,
|
||||||
tsc::UserPreferences {
|
tsc::UserPreferences::from_config_for_specifier(
|
||||||
quote_preference: Some((&self.fmt_options.options).into()),
|
&self.config,
|
||||||
..tsc::UserPreferences::from_workspace_settings_for_specifier(
|
&self.fmt_options.options,
|
||||||
workspace_settings,
|
&specifier,
|
||||||
&specifier,
|
),
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let maybe_inlay_hints = maybe_inlay_hints.map(|hints| {
|
let maybe_inlay_hints = maybe_inlay_hints.map(|hints| {
|
||||||
|
|
|
@ -32,10 +32,12 @@ use tower_lsp::lsp_types::WorkDoneProgressParams;
|
||||||
use tower_lsp::LanguageServer;
|
use tower_lsp::LanguageServer;
|
||||||
|
|
||||||
use super::client::Client;
|
use super::client::Client;
|
||||||
|
use super::config::ClassMemberSnippets;
|
||||||
use super::config::CompletionSettings;
|
use super::config::CompletionSettings;
|
||||||
use super::config::DenoCompletionSettings;
|
use super::config::DenoCompletionSettings;
|
||||||
use super::config::ImportCompletionSettings;
|
use super::config::ImportCompletionSettings;
|
||||||
use super::config::LanguageWorkspaceSettings;
|
use super::config::LanguageWorkspaceSettings;
|
||||||
|
use super::config::ObjectLiteralMethodSnippets;
|
||||||
use super::config::TestingSettings;
|
use super::config::TestingSettings;
|
||||||
use super::config::WorkspaceSettings;
|
use super::config::WorkspaceSettings;
|
||||||
|
|
||||||
|
@ -309,22 +311,36 @@ pub fn get_repl_workspace_settings() -> WorkspaceSettings {
|
||||||
},
|
},
|
||||||
testing: TestingSettings { args: vec![] },
|
testing: TestingSettings { args: vec![] },
|
||||||
javascript: LanguageWorkspaceSettings {
|
javascript: LanguageWorkspaceSettings {
|
||||||
inlay_hints: Default::default(),
|
|
||||||
suggest: CompletionSettings {
|
suggest: CompletionSettings {
|
||||||
complete_function_calls: false,
|
|
||||||
names: false,
|
|
||||||
paths: false,
|
|
||||||
auto_imports: 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 {
|
typescript: LanguageWorkspaceSettings {
|
||||||
inlay_hints: Default::default(),
|
|
||||||
suggest: CompletionSettings {
|
suggest: CompletionSettings {
|
||||||
complete_function_calls: false,
|
|
||||||
names: false,
|
|
||||||
paths: false,
|
|
||||||
auto_imports: 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)]
|
pub type ImportModuleSpecifierPreference = config::ImportModuleSpecifier;
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum ImportModuleSpecifierPreference {
|
|
||||||
Auto,
|
|
||||||
Relative,
|
|
||||||
NonRelative,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
@ -3581,14 +3574,7 @@ pub enum IncludePackageJsonAutoImports {
|
||||||
Off,
|
Off,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
pub type JsxAttributeCompletionStyle = config::JsxAttributeCompletionStyle;
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub enum JsxAttributeCompletionStyle {
|
|
||||||
Auto,
|
|
||||||
Braces,
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize)]
|
#[derive(Debug, Default, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -3666,35 +3652,115 @@ pub struct UserPreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserPreferences {
|
impl UserPreferences {
|
||||||
pub fn from_workspace_settings_for_specifier(
|
pub fn from_config_for_specifier(
|
||||||
settings: &config::WorkspaceSettings,
|
config: &config::Config,
|
||||||
|
fmt_config: &FmtOptionsConfig,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let language_settings = settings.language_settings_for_specifier(specifier);
|
let base_preferences = Self {
|
||||||
Self {
|
allow_incomplete_completions: Some(true),
|
||||||
include_inlay_parameter_name_hints: language_settings
|
allow_text_changes_in_new_files: Some(specifier.scheme() == "file"),
|
||||||
.map(|s| (&s.inlay_hints.parameter_names.enabled).into()),
|
// TODO(nayeemrmn): Investigate why we use `Index` here.
|
||||||
include_inlay_parameter_name_hints_when_argument_matches_name:
|
import_module_specifier_ending: Some(ImportModuleSpecifierEnding::Index),
|
||||||
language_settings.map(|s| {
|
include_completions_with_snippet_text: Some(
|
||||||
!s.inlay_hints
|
config.client_capabilities.snippet_support,
|
||||||
.parameter_names
|
),
|
||||||
.suppress_when_argument_matches_name
|
provide_refactor_not_applicable_reason: Some(true),
|
||||||
}),
|
quote_preference: Some(fmt_config.into()),
|
||||||
include_inlay_function_parameter_type_hints: language_settings
|
use_label_details_in_completion_entries: Some(true),
|
||||||
.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),
|
|
||||||
..Default::default()
|
..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]
|
#[test]
|
||||||
fn include_suppress_inlay_hit_settings() {
|
fn include_suppress_inlay_hint_settings() {
|
||||||
let mut settings = WorkspaceSettings::default();
|
let mut settings = WorkspaceSettings::default();
|
||||||
settings
|
settings
|
||||||
.typescript
|
.typescript
|
||||||
|
@ -5161,11 +5227,13 @@ mod tests {
|
||||||
.inlay_hints
|
.inlay_hints
|
||||||
.variable_types
|
.variable_types
|
||||||
.suppress_when_type_matches_name = true;
|
.suppress_when_type_matches_name = true;
|
||||||
let user_preferences =
|
let mut config = config::Config::new();
|
||||||
UserPreferences::from_workspace_settings_for_specifier(
|
config.set_workspace_settings(settings);
|
||||||
&settings,
|
let user_preferences = UserPreferences::from_config_for_specifier(
|
||||||
&ModuleSpecifier::parse("file:///foo.ts").unwrap(),
|
&config,
|
||||||
);
|
&Default::default(),
|
||||||
|
&ModuleSpecifier::parse("file:///foo.ts").unwrap(),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
user_preferences.include_inlay_variable_type_hints_when_type_matches_name,
|
user_preferences.include_inlay_variable_type_hints_when_type_matches_name,
|
||||||
Some(false)
|
Some(false)
|
||||||
|
|
Loading…
Add table
Reference in a new issue