diff options
Diffstat (limited to 'cli/lsp/tsc.rs')
-rw-r--r-- | cli/lsp/tsc.rs | 92 |
1 files changed, 67 insertions, 25 deletions
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 48dcb7964..fc7ff5794 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -3417,9 +3417,18 @@ fn parse_code_actions( additional_text_edits.extend(change.text_changes.iter().map(|tc| { let mut text_edit = tc.as_text_edit(asset_or_doc.line_index()); if let Some(specifier_rewrite) = &data.specifier_rewrite { - text_edit.new_text = text_edit - .new_text - .replace(&specifier_rewrite.0, &specifier_rewrite.1); + text_edit.new_text = text_edit.new_text.replace( + &specifier_rewrite.old_specifier, + &specifier_rewrite.new_specifier, + ); + if let Some(deno_types_specifier) = + &specifier_rewrite.new_deno_types_specifier + { + text_edit.new_text = format!( + "// @deno-types=\"{}\"\n{}", + deno_types_specifier, &text_edit.new_text + ); + } } text_edit })); @@ -3578,17 +3587,23 @@ impl CompletionEntryDetails { let mut text_edit = original_item.text_edit.clone(); if let Some(specifier_rewrite) = &data.specifier_rewrite { if let Some(text_edit) = &mut text_edit { - match text_edit { - lsp::CompletionTextEdit::Edit(text_edit) => { - text_edit.new_text = text_edit - .new_text - .replace(&specifier_rewrite.0, &specifier_rewrite.1); - } + let new_text = match text_edit { + lsp::CompletionTextEdit::Edit(text_edit) => &mut text_edit.new_text, lsp::CompletionTextEdit::InsertAndReplace(insert_replace_edit) => { - insert_replace_edit.new_text = insert_replace_edit - .new_text - .replace(&specifier_rewrite.0, &specifier_rewrite.1); + &mut insert_replace_edit.new_text } + }; + *new_text = new_text.replace( + &specifier_rewrite.old_specifier, + &specifier_rewrite.new_specifier, + ); + if let Some(deno_types_specifier) = + &specifier_rewrite.new_deno_types_specifier + { + *new_text = format!( + "// @deno-types=\"{}\"\n{}", + deno_types_specifier, new_text + ); } } } @@ -3693,6 +3708,13 @@ impl CompletionInfo { } } +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct CompletionSpecifierRewrite { + old_specifier: String, + new_specifier: String, + new_deno_types_specifier: Option<String>, +} + #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct CompletionItemData { @@ -3705,7 +3727,7 @@ pub struct CompletionItemData { /// be rewritten by replacing the first string with the second. Intended for /// auto-import specifiers to be reverse-import-mapped. #[serde(skip_serializing_if = "Option::is_none")] - pub specifier_rewrite: Option<(String, String)>, + pub specifier_rewrite: Option<CompletionSpecifierRewrite>, #[serde(skip_serializing_if = "Option::is_none")] pub data: Option<Value>, pub use_code_snippet: bool, @@ -3927,20 +3949,40 @@ impl CompletionEntry { if let Some(source) = &self.source { let mut display_source = source.clone(); if let Some(import_data) = &self.auto_import_data { - if let Some(new_module_specifier) = language_server - .get_ts_response_import_mapper(specifier) + let import_mapper = + language_server.get_ts_response_import_mapper(specifier); + if let Some(mut new_specifier) = import_mapper .check_specifier(&import_data.normalized, specifier) .or_else(|| relative_specifier(specifier, &import_data.normalized)) { - if new_module_specifier.contains("/node_modules/") { + if new_specifier.contains("/node_modules/") { return None; } - display_source.clone_from(&new_module_specifier); - if new_module_specifier != import_data.raw.module_specifier { - specifier_rewrite = Some(( - import_data.raw.module_specifier.clone(), - new_module_specifier, - )); + let mut new_deno_types_specifier = None; + if let Some(code_specifier) = language_server + .resolver + .deno_types_to_code_resolution( + &import_data.normalized, + Some(specifier), + ) + .and_then(|s| { + import_mapper + .check_specifier(&s, specifier) + .or_else(|| relative_specifier(specifier, &s)) + }) + { + new_deno_types_specifier = + Some(std::mem::replace(&mut new_specifier, code_specifier)); + } + display_source.clone_from(&new_specifier); + if new_specifier != import_data.raw.module_specifier + || new_deno_types_specifier.is_some() + { + specifier_rewrite = Some(CompletionSpecifierRewrite { + old_specifier: import_data.raw.module_specifier.clone(), + new_specifier, + new_deno_types_specifier, + }); } } else if source.starts_with(jsr_url().as_str()) { return None; @@ -4246,9 +4288,7 @@ impl TscSpecifierMap { return specifier.to_string(); } let mut specifier = original.to_string(); - if specifier.contains("/node_modules/.deno/") - && !specifier.contains("/node_modules/@types/node/") - { + if !specifier.contains("/node_modules/@types/node/") { // The ts server doesn't give completions from files in // `node_modules/.deno/`. We work around it like this. specifier = specifier.replace("/node_modules/", "/$node_modules/"); @@ -4415,6 +4455,8 @@ fn op_load<'s>( }) }; + lsp_warn!("op_load {} {}", &specifier, maybe_load_response.is_some()); + let serialized = serde_v8::to_v8(scope, maybe_load_response)?; state.performance.measure(mark); |