1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

fix(lsp): make missing import action fix infallible (#26539)

This commit is contained in:
Nayeem Rahman 2024-10-25 21:52:50 +01:00 committed by GitHub
parent ec968aa5ae
commit d92d2fe9b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -18,7 +18,6 @@ use deno_lint::diagnostic::LintDiagnosticRange;
use deno_ast::SourceRange; use deno_ast::SourceRange;
use deno_ast::SourceRangedForSpanned; use deno_ast::SourceRangedForSpanned;
use deno_ast::SourceTextInfo; use deno_ast::SourceTextInfo;
use deno_core::anyhow::anyhow;
use deno_core::error::custom_error; use deno_core::error::custom_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::serde::Deserialize; use deno_core::serde::Deserialize;
@ -40,6 +39,7 @@ use import_map::ImportMap;
use node_resolver::NpmResolver; use node_resolver::NpmResolver;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use std::borrow::Cow;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
@ -598,68 +598,62 @@ pub fn fix_ts_import_changes(
/// Fix tsc import code actions so that the module specifier is correct for /// Fix tsc import code actions so that the module specifier is correct for
/// resolution by Deno (includes the extension). /// resolution by Deno (includes the extension).
fn fix_ts_import_action( fn fix_ts_import_action<'a>(
referrer: &ModuleSpecifier, referrer: &ModuleSpecifier,
action: &tsc::CodeFixAction, action: &'a tsc::CodeFixAction,
import_mapper: &TsResponseImportMapper, import_mapper: &TsResponseImportMapper,
) -> Result<Option<tsc::CodeFixAction>, AnyError> { ) -> Option<Cow<'a, tsc::CodeFixAction>> {
if matches!( if !matches!(
action.fix_name.as_str(), action.fix_name.as_str(),
"import" | "fixMissingFunctionDeclaration" "import" | "fixMissingFunctionDeclaration"
) { ) {
let change = action return Some(Cow::Borrowed(action));
}
let specifier = (|| {
let text_change = action.changes.first()?.text_changes.first()?;
let captures = IMPORT_SPECIFIER_RE.captures(&text_change.new_text)?;
Some(captures.get(1)?.as_str())
})();
let Some(specifier) = specifier else {
return Some(Cow::Borrowed(action));
};
if let Some(new_specifier) =
import_mapper.check_unresolved_specifier(specifier, referrer)
{
let description = action.description.replace(specifier, &new_specifier);
let changes = action
.changes .changes
.first() .iter()
.ok_or_else(|| anyhow!("Unexpected action changes."))?; .map(|c| {
let text_change = change let text_changes = c
.text_changes .text_changes
.first()
.ok_or_else(|| anyhow!("Missing text change."))?;
if let Some(captures) = IMPORT_SPECIFIER_RE.captures(&text_change.new_text)
{
let specifier = captures
.get(1)
.ok_or_else(|| anyhow!("Missing capture."))?
.as_str();
if let Some(new_specifier) =
import_mapper.check_unresolved_specifier(specifier, referrer)
{
let description = action.description.replace(specifier, &new_specifier);
let changes = action
.changes
.iter() .iter()
.map(|c| { .map(|tc| tsc::TextChange {
let text_changes = c span: tc.span.clone(),
.text_changes new_text: tc.new_text.replace(specifier, &new_specifier),
.iter()
.map(|tc| tsc::TextChange {
span: tc.span.clone(),
new_text: tc.new_text.replace(specifier, &new_specifier),
})
.collect();
tsc::FileTextChanges {
file_name: c.file_name.clone(),
text_changes,
is_new_file: c.is_new_file,
}
}) })
.collect(); .collect();
tsc::FileTextChanges {
file_name: c.file_name.clone(),
text_changes,
is_new_file: c.is_new_file,
}
})
.collect();
return Ok(Some(tsc::CodeFixAction { Some(Cow::Owned(tsc::CodeFixAction {
description, description,
changes, changes,
commands: None, commands: None,
fix_name: action.fix_name.clone(), fix_name: action.fix_name.clone(),
fix_id: None, fix_id: None,
fix_all_description: None, fix_all_description: None,
})); }))
} else if !import_mapper.is_valid_import(specifier, referrer) { } else if !import_mapper.is_valid_import(specifier, referrer) {
return Ok(None); None
} } else {
} Some(Cow::Borrowed(action))
} }
Ok(Some(action.clone()))
} }
/// Determines if two TypeScript diagnostic codes are effectively equivalent. /// Determines if two TypeScript diagnostic codes are effectively equivalent.
@ -1004,8 +998,7 @@ impl CodeActionCollection {
specifier, specifier,
action, action,
&language_server.get_ts_response_import_mapper(specifier), &language_server.get_ts_response_import_mapper(specifier),
)? ) else {
else {
return Ok(()); return Ok(());
}; };
let edit = ts_changes_to_edit(&action.changes, language_server)?; let edit = ts_changes_to_edit(&action.changes, language_server)?;
@ -1027,7 +1020,7 @@ impl CodeActionCollection {
}); });
self self
.actions .actions
.push(CodeActionKind::Tsc(code_action, action.clone())); .push(CodeActionKind::Tsc(code_action, action.as_ref().clone()));
if let Some(fix_id) = &action.fix_id { if let Some(fix_id) = &action.fix_id {
if let Some(CodeActionKind::Tsc(existing_fix_all, existing_action)) = if let Some(CodeActionKind::Tsc(existing_fix_all, existing_action)) =