mirror of
https://github.com/denoland/deno.git
synced 2024-11-22 04:51:22 +00:00
fix(lsp): pass quote preference to tsc (#20547)
This commit is contained in:
parent
f7ba701304
commit
86c04f43e0
@ -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| {
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4906,6 +4906,174 @@ fn lsp_code_actions_refactor() {
|
||||
client.shutdown();
|
||||
}
|
||||
|
||||
#[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();
|
||||
|
@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
8
cli/tsc/compiler.d.ts
vendored
8
cli/tsc/compiler.d.ts
vendored
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user