summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/lsp/language_server.rs29
-rw-r--r--cli/lsp/tsc.rs61
-rw-r--r--cli/tests/integration/lsp_tests.rs168
-rw-r--r--cli/tsc/99_main_compiler.js14
-rw-r--r--cli/tsc/compiler.d.ts8
5 files changed, 260 insertions, 20 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index df5552764..102408df4 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -1927,6 +1927,10 @@ 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()),
+ ..self.config.workspace_settings().into()
+ },
)
.await;
for action in actions {
@@ -1984,6 +1988,10 @@ 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()),
+ ..self.config.workspace_settings().into()
+ }),
only,
)
.await?;
@@ -2039,6 +2047,10 @@ impl Inner {
self.snapshot(),
&code_action_data,
(&self.fmt_options.options).into(),
+ tsc::UserPreferences {
+ quote_preference: Some((&self.fmt_options.options).into()),
+ ..self.config.workspace_settings().into()
+ },
)
.await?;
if combined_code_actions.commands.is_some() {
@@ -2084,6 +2096,10 @@ 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()),
+ ..self.config.workspace_settings().into()
+ }),
)
.await?;
code_action.edit = refactor_edit_info.to_workspace_edit(self).await?;
@@ -2399,6 +2415,7 @@ impl Inner {
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",
@@ -2466,10 +2483,14 @@ impl Inner {
})?;
if let Some(data) = &data.tsc {
let specifier = &data.specifier;
- let args = GetCompletionDetailsArgs {
+ 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)
@@ -2971,6 +2992,7 @@ impl Inner {
(&self.fmt_options.options).into(),
tsc::UserPreferences {
allow_text_changes_in_new_files: Some(true),
+ quote_preference: Some((&self.fmt_options.options).into()),
..Default::default()
},
)
@@ -3600,7 +3622,10 @@ impl Inner {
self.snapshot(),
specifier,
text_span,
- workspace_settings.into(),
+ tsc::UserPreferences {
+ quote_preference: Some((&self.fmt_options.options).into()),
+ ..workspace_settings.into()
+ },
)
.await?;
let maybe_inlay_hints = maybe_inlay_hints.map(|hints| {
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index 2c63131b6..81950f2e3 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -234,6 +234,7 @@ impl TsServer {
range: Range<u32>,
codes: Vec<String>,
format_code_settings: FormatCodeSettings,
+ preferences: UserPreferences,
) -> Vec<CodeFixAction> {
let req = RequestMethod::GetCodeFixes((
specifier,
@@ -241,6 +242,7 @@ impl TsServer {
range.end,
codes,
format_code_settings,
+ preferences,
));
match self.request(snapshot, req).await {
Ok(items) => items,
@@ -260,6 +262,7 @@ impl TsServer {
snapshot: Arc<StateSnapshot>,
specifier: ModuleSpecifier,
range: Range<u32>,
+ preferences: Option<UserPreferences>,
only: String,
) -> Result<Vec<ApplicableRefactorInfo>, LspError> {
let req = RequestMethod::GetApplicableRefactors((
@@ -268,6 +271,7 @@ impl TsServer {
start: range.start,
length: range.end - range.start,
},
+ preferences,
only,
));
self.request(snapshot, req).await.map_err(|err| {
@@ -281,11 +285,13 @@ impl TsServer {
snapshot: Arc<StateSnapshot>,
code_action_data: &CodeActionData,
format_code_settings: FormatCodeSettings,
+ preferences: UserPreferences,
) -> Result<CombinedCodeActions, LspError> {
let req = RequestMethod::GetCombinedCodeFix((
code_action_data.specifier.clone(),
json!(code_action_data.fix_id.clone()),
format_code_settings,
+ preferences,
));
self.request(snapshot, req).await.map_err(|err| {
log::error!("Unable to get combined fix from TypeScript: {}", err);
@@ -293,6 +299,7 @@ impl TsServer {
})
}
+ #[allow(clippy::too_many_arguments)]
pub async fn get_edits_for_refactor(
&self,
snapshot: Arc<StateSnapshot>,
@@ -301,6 +308,7 @@ impl TsServer {
range: Range<u32>,
refactor_name: String,
action_name: String,
+ preferences: Option<UserPreferences>,
) -> Result<RefactorEditInfo, LspError> {
let req = RequestMethod::GetEditsForRefactor((
specifier,
@@ -311,6 +319,7 @@ impl TsServer {
},
refactor_name,
action_name,
+ preferences,
));
self.request(snapshot, req).await.map_err(|err| {
log::error!("Failed to request to tsserver {}", err);
@@ -3507,6 +3516,15 @@ pub enum QuotePreference {
Single,
}
+impl From<&FmtOptionsConfig> for QuotePreference {
+ fn from(config: &FmtOptionsConfig) -> Self {
+ match config.single_quote {
+ Some(true) => QuotePreference::Single,
+ _ => QuotePreference::Double,
+ }
+ }
+}
+
#[derive(Debug, Serialize)]
#[serde(rename_all = "kebab-case")]
#[allow(dead_code)]
@@ -3765,7 +3783,9 @@ enum RequestMethod {
},
GetAssets,
/// Retrieve the possible refactor info for a range of a file.
- GetApplicableRefactors((ModuleSpecifier, TextSpan, String)),
+ GetApplicableRefactors(
+ (ModuleSpecifier, TextSpan, Option<UserPreferences>, String),
+ ),
/// Retrieve the refactor edit info for a range.
GetEditsForRefactor(
(
@@ -3774,6 +3794,7 @@ enum RequestMethod {
TextSpan,
String,
String,
+ Option<UserPreferences>,
),
),
/// Retrieve the refactor edit info for a range.
@@ -3786,7 +3807,16 @@ enum RequestMethod {
),
),
/// Retrieve code fixes for a range of a file with the provided error codes.
- GetCodeFixes((ModuleSpecifier, u32, u32, Vec<String>, FormatCodeSettings)),
+ GetCodeFixes(
+ (
+ ModuleSpecifier,
+ u32,
+ u32,
+ Vec<String>,
+ FormatCodeSettings,
+ UserPreferences,
+ ),
+ ),
/// Get completion information at a given position (IntelliSense).
GetCompletions(
(
@@ -3799,7 +3829,9 @@ enum RequestMethod {
/// Get details about a specific completion entry.
GetCompletionDetails(GetCompletionDetailsArgs),
/// Retrieve the combined code fixes for a fix id for a module.
- GetCombinedCodeFix((ModuleSpecifier, Value, FormatCodeSettings)),
+ GetCombinedCodeFix(
+ (ModuleSpecifier, Value, FormatCodeSettings, UserPreferences),
+ ),
/// Get declaration information for a specific position.
GetDefinition((ModuleSpecifier, u32)),
/// Return diagnostics for given file.
@@ -3876,11 +3908,17 @@ impl RequestMethod {
"id": id,
"method": "getAssets",
}),
- RequestMethod::GetApplicableRefactors((specifier, span, kind)) => json!({
+ RequestMethod::GetApplicableRefactors((
+ specifier,
+ span,
+ preferences,
+ kind,
+ )) => json!({
"id": id,
"method": "getApplicableRefactors",
"specifier": state.denormalize_specifier(specifier),
"range": { "pos": span.start, "end": span.start + span.length },
+ "preferences": preferences,
"kind": kind,
}),
RequestMethod::GetEditsForRefactor((
@@ -3889,6 +3927,7 @@ impl RequestMethod {
span,
refactor_name,
action_name,
+ preferences,
)) => json!({
"id": id,
"method": "getEditsForRefactor",
@@ -3897,6 +3936,7 @@ impl RequestMethod {
"range": { "pos": span.start, "end": span.start + span.length},
"refactorName": refactor_name,
"actionName": action_name,
+ "preferences": preferences,
}),
RequestMethod::GetEditsForFileRename((
old_specifier,
@@ -3917,6 +3957,7 @@ impl RequestMethod {
end_pos,
error_codes,
format_code_settings,
+ preferences,
)) => json!({
"id": id,
"method": "getCodeFixes",
@@ -3925,17 +3966,20 @@ impl RequestMethod {
"endPosition": end_pos,
"errorCodes": error_codes,
"formatCodeSettings": format_code_settings,
+ "preferences": preferences,
}),
RequestMethod::GetCombinedCodeFix((
specifier,
fix_id,
format_code_settings,
+ preferences,
)) => json!({
"id": id,
"method": "getCombinedCodeFix",
"specifier": state.denormalize_specifier(specifier),
"fixId": fix_id,
"formatCodeSettings": format_code_settings,
+ "preferences": preferences,
}),
RequestMethod::GetCompletionDetails(args) => json!({
"id": id,
@@ -4976,6 +5020,7 @@ mod tests {
assert!(result.is_ok());
let fmt_options_config = FmtOptionsConfig {
semi_colons: Some(false),
+ single_quote: Some(true),
..Default::default()
};
let result = request(
@@ -4986,6 +5031,7 @@ mod tests {
position,
GetCompletionsAtPositionOptions {
user_preferences: UserPreferences {
+ quote_preference: Some((&fmt_options_config).into()),
include_completions_for_module_exports: Some(true),
include_completions_with_insert_text: Some(true),
..Default::default()
@@ -5011,7 +5057,10 @@ mod tests {
position,
name: entry.name.clone(),
source: entry.source.clone(),
- preferences: None,
+ preferences: Some(UserPreferences {
+ quote_preference: Some((&fmt_options_config).into()),
+ ..Default::default()
+ }),
format_code_settings: Some((&fmt_options_config).into()),
data: entry.data.clone(),
}),
@@ -5029,7 +5078,7 @@ mod tests {
let change = changes.text_changes.first().unwrap();
assert_eq!(
change.new_text,
- "import { someLongVariable } from \"./b.ts\"\n"
+ "import { someLongVariable } from './b.ts'\n"
);
}
diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs
index de9626620..8b265f911 100644
--- a/cli/tests/integration/lsp_tests.rs
+++ b/cli/tests/integration/lsp_tests.rs
@@ -4907,6 +4907,174 @@ fn lsp_code_actions_refactor() {
}
#[test]
+fn lsp_code_actions_imports_respects_fmt_config() {
+ let context = TestContextBuilder::new().use_temp_cwd().build();
+ let temp_dir = context.temp_dir();
+ temp_dir.write(
+ "./deno.jsonc",
+ json!({
+ "fmt": {
+ "semiColons": false,
+ "singleQuote": true,
+ }
+ })
+ .to_string(),
+ );
+ temp_dir.write(
+ "file00.ts",
+ r#"
+ export interface MallardDuckConfigOptions extends DuckConfigOptions {
+ kind: "mallard";
+ }
+ "#,
+ );
+ temp_dir.write(
+ "file01.ts",
+ r#"
+ export interface DuckConfigOptions {
+ kind: string;
+ quacks: boolean;
+ }
+ "#,
+ );
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("file00.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": temp_dir.read_to_string("file00.ts"),
+ }
+ }));
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("file01.ts").unwrap(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": temp_dir.read_to_string("file01.ts"),
+ }
+ }));
+
+ let res = client.write_request(
+ "textDocument/codeAction",
+ json!({
+ "textDocument": {
+ "uri": temp_dir.uri().join("file00.ts").unwrap()
+ },
+ "range": {
+ "start": { "line": 0, "character": 0 },
+ "end": { "line": 4, "character": 0 }
+ },
+ "context": {
+ "diagnostics": [{
+ "range": {
+ "start": { "line": 1, "character": 55 },
+ "end": { "line": 1, "character": 64 }
+ },
+ "severity": 1,
+ "code": 2304,
+ "source": "deno-ts",
+ "message": "Cannot find name 'DuckConfigOptions'."
+ }],
+ "only": ["quickfix"]
+ }
+ }),
+ );
+ assert_eq!(
+ res,
+ json!([{
+ "title": "Add import from \"./file01.ts\"",
+ "kind": "quickfix",
+ "diagnostics": [{
+ "range": {
+ "start": { "line": 1, "character": 55 },
+ "end": { "line": 1, "character": 64 }
+ },
+ "severity": 1,
+ "code": 2304,
+ "source": "deno-ts",
+ "message": "Cannot find name 'DuckConfigOptions'."
+ }],
+ "edit": {
+ "documentChanges": [{
+ "textDocument": {
+ "uri": temp_dir.uri().join("file00.ts").unwrap(),
+ "version": 1
+ },
+ "edits": [{
+ "range": {
+ "start": { "line": 0, "character": 0 },
+ "end": { "line": 0, "character": 0 }
+ },
+ "newText": "import { DuckConfigOptions } from './file01.ts'\n"
+ }]
+ }]
+ }
+ }])
+ );
+ let res = client.write_request(
+ "codeAction/resolve",
+ json!({
+ "title": "Add all missing imports",
+ "kind": "quickfix",
+ "diagnostics": [{
+ "range": {
+ "start": { "line": 1, "character": 55 },
+ "end": { "line": 1, "character": 64 }
+ },
+ "severity": 1,
+ "code": 2304,
+ "source": "deno-ts",
+ "message": "Cannot find name 'DuckConfigOptions'."
+ }],
+ "data": {
+ "specifier": temp_dir.uri().join("file00.ts").unwrap(),
+ "fixId": "fixMissingImport"
+ }
+ }),
+ );
+ assert_eq!(
+ res,
+ json!({
+ "title": "Add all missing imports",
+ "kind": "quickfix",
+ "diagnostics": [{
+ "range": {
+ "start": { "line": 1, "character": 55 },
+ "end": { "line": 1, "character": 64 }
+ },
+ "severity": 1,
+ "code": 2304,
+ "source": "deno-ts",
+ "message": "Cannot find name 'DuckConfigOptions'."
+ }],
+ "edit": {
+ "documentChanges": [{
+ "textDocument": {
+ "uri": temp_dir.uri().join("file00.ts").unwrap(),
+ "version": 1
+ },
+ "edits": [{
+ "range": {
+ "start": { "line": 0, "character": 0 },
+ "end": { "line": 0, "character": 0 }
+ },
+ "newText": "import { DuckConfigOptions } from './file01.ts'\n"
+ }]
+ }]
+ },
+ "data": {
+ "specifier": temp_dir.uri().join("file00.ts").unwrap(),
+ "fixId": "fixMissingImport"
+ }
+ })
+ );
+
+ client.shutdown();
+}
+
+#[test]
fn lsp_code_actions_refactor_no_disabled_support() {
let context = TestContextBuilder::new().use_temp_cwd().build();
let mut client = context.new_lsp_command().build();
diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js
index 451e36b96..8978bf1be 100644
--- a/cli/tsc/99_main_compiler.js
+++ b/cli/tsc/99_main_compiler.js
@@ -1020,7 +1020,7 @@ delete Object.prototype.__proto__;
request.specifier,
request.range,
{
- quotePreference: "double",
+ ...(request.preferences ?? {}),
allowTextChangesInNewFiles: true,
provideRefactorNotApplicableReason: true,
},
@@ -1043,9 +1043,7 @@ delete Object.prototype.__proto__;
request.range,
request.refactorName,
request.actionName,
- {
- quotePreference: "double",
- },
+ request.preferences,
),
);
}
@@ -1072,9 +1070,7 @@ delete Object.prototype.__proto__;
...request.formatCodeSettings,
indentStyle: ts.IndentStyle.Block,
},
- {
- quotePreference: "double",
- },
+ request.preferences,
),
);
}
@@ -1091,9 +1087,7 @@ delete Object.prototype.__proto__;
...request.formatCodeSettings,
indentStyle: ts.IndentStyle.Block,
},
- {
- quotePreference: "double",
- },
+ request.preferences,
),
);
}
diff --git a/cli/tsc/compiler.d.ts b/cli/tsc/compiler.d.ts
index 7b8340093..30e433405 100644
--- a/cli/tsc/compiler.d.ts
+++ b/cli/tsc/compiler.d.ts
@@ -116,6 +116,7 @@ declare global {
method: "getApplicableRefactors";
specifier: string;
range: ts.TextRange;
+ preferences?: ts.UserPreferences;
kind: string;
}
@@ -126,12 +127,13 @@ declare global {
range: ts.TextRange;
refactorName: string;
actionName: string;
+ preferences?: ts.UserPreferences;
}
interface GetEditsForFileRename extends BaseLanguageServerRequest {
method: "getEditsForFileRename";
- old_specifier: string;
- new_specifier: string;
+ oldSpecifier: string;
+ newSpecifier: string;
formatCodeSettings: ts.FormatCodeSettings;
preferences?: ts.UserPreferences;
}
@@ -143,6 +145,7 @@ declare global {
endPosition: number;
errorCodes: string[];
formatCodeSettings: ts.FormatCodeSettings;
+ preferences: ts.UserPreferences;
}
interface GetCombinedCodeFix extends BaseLanguageServerRequest {
@@ -151,6 +154,7 @@ declare global {
// deno-lint-ignore ban-types
fixId: {};
formatCodeSettings: ts.FormatCodeSettings;
+ preferences: ts.UserPreferences;
}
interface GetCompletionDetails extends BaseLanguageServerRequest {