mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(lsp): rewrite import for 'infer return type' action (#24685)
This commit is contained in:
parent
607fd2d314
commit
142b9f29ae
5 changed files with 122 additions and 8 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -7541,9 +7541,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "v8"
|
||||
version = "0.98.0"
|
||||
version = "0.98.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "feb252d5be11c32cb4755d66d58db30ff30af5f1f17183e83ff54383a402c5f6"
|
||||
checksum = "d03f42deef61349d31ae100e7bcdcc5d9293c1126cb8aff8fd56ba3cba18340b"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bitflags 2.5.0",
|
||||
|
|
|
@ -73,8 +73,9 @@ static PREFERRED_FIXES: Lazy<HashMap<&'static str, (u32, bool)>> =
|
|||
.collect()
|
||||
});
|
||||
|
||||
static IMPORT_SPECIFIER_RE: Lazy<Regex> =
|
||||
lazy_regex::lazy_regex!(r#"\sfrom\s+["']([^"']*)["']"#);
|
||||
static IMPORT_SPECIFIER_RE: Lazy<Regex> = lazy_regex::lazy_regex!(
|
||||
r#"\sfrom\s+["']([^"']*)["']|import\s*\(\s*["']([^"']*)["']\s*\)"#
|
||||
);
|
||||
|
||||
const SUPPORTED_EXTENSIONS: &[&str] = &[
|
||||
".ts", ".tsx", ".js", ".jsx", ".mjs", ".mts", ".cjs", ".cts", ".d.ts",
|
||||
|
@ -528,7 +529,8 @@ pub fn fix_ts_import_changes(
|
|||
.map(|line| {
|
||||
// This assumes that there's only one import per line.
|
||||
if let Some(captures) = IMPORT_SPECIFIER_RE.captures(line) {
|
||||
let specifier = captures.get(1).unwrap().as_str();
|
||||
let specifier =
|
||||
captures.iter().skip(1).find_map(|s| s).unwrap().as_str();
|
||||
if let Some(new_specifier) =
|
||||
import_mapper.check_unresolved_specifier(specifier, referrer)
|
||||
{
|
||||
|
|
|
@ -1810,7 +1810,10 @@ impl Inner {
|
|||
LspError::internal_error()
|
||||
})?;
|
||||
code_action
|
||||
} else if kind.as_str().starts_with(CodeActionKind::REFACTOR.as_str()) {
|
||||
} else if let Some(kind_suffix) = kind
|
||||
.as_str()
|
||||
.strip_prefix(CodeActionKind::REFACTOR.as_str())
|
||||
{
|
||||
let mut code_action = params;
|
||||
let action_data: refactor::RefactorCodeActionData = from_value(data)
|
||||
.map_err(|err| {
|
||||
|
@ -1819,7 +1822,7 @@ impl Inner {
|
|||
})?;
|
||||
let asset_or_doc = self.get_asset_or_document(&action_data.specifier)?;
|
||||
let line_index = asset_or_doc.line_index();
|
||||
let refactor_edit_info = self
|
||||
let mut refactor_edit_info = self
|
||||
.ts_server
|
||||
.get_edits_for_refactor(
|
||||
self.snapshot(),
|
||||
|
@ -1841,6 +1844,17 @@ impl Inner {
|
|||
asset_or_doc.scope().cloned(),
|
||||
)
|
||||
.await?;
|
||||
if kind_suffix == ".rewrite.function.returnType" {
|
||||
refactor_edit_info.edits = fix_ts_import_changes(
|
||||
&action_data.specifier,
|
||||
&refactor_edit_info.edits,
|
||||
&self.get_ts_response_import_mapper(&action_data.specifier),
|
||||
)
|
||||
.map_err(|err| {
|
||||
error!("Unable to remap changes: {:#}", err);
|
||||
LspError::internal_error()
|
||||
})?
|
||||
}
|
||||
code_action.edit = refactor_edit_info.to_workspace_edit(self)?;
|
||||
code_action
|
||||
} else {
|
||||
|
|
|
@ -2944,7 +2944,7 @@ pub fn file_text_changes_to_workspace_edit(
|
|||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RefactorEditInfo {
|
||||
edits: Vec<FileTextChanges>,
|
||||
pub edits: Vec<FileTextChanges>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub rename_location: Option<u32>,
|
||||
}
|
||||
|
|
|
@ -7373,6 +7373,104 @@ fn lsp_npm_completions_auto_import_and_quick_fix_no_import_map() {
|
|||
client.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_infer_return_type() {
|
||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||
let temp_dir = context.temp_dir();
|
||||
temp_dir.write("deno.json", json!({}).to_string());
|
||||
let types_file = source_file(
|
||||
temp_dir.path().join("types.d.ts"),
|
||||
r#"
|
||||
export interface SomeInterface {
|
||||
someField: number;
|
||||
}
|
||||
declare global {
|
||||
export function someFunction(): SomeInterface;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
let file = source_file(
|
||||
temp_dir.path().join("file.ts"),
|
||||
r#"
|
||||
function foo() {
|
||||
return someFunction();
|
||||
}
|
||||
foo();
|
||||
"#,
|
||||
);
|
||||
let mut client = context.new_lsp_command().build();
|
||||
client.initialize_default();
|
||||
let res = client.write_request(
|
||||
"textDocument/codeAction",
|
||||
json!({
|
||||
"textDocument": { "uri": file.uri() },
|
||||
"range": {
|
||||
"start": { "line": 1, "character": 15 },
|
||||
"end": { "line": 1, "character": 18 },
|
||||
},
|
||||
"context": {
|
||||
"diagnostics": [],
|
||||
"only": ["refactor.rewrite.function.returnType"],
|
||||
}
|
||||
}),
|
||||
);
|
||||
assert_eq!(
|
||||
&res,
|
||||
&json!([
|
||||
{
|
||||
"title": "Infer function return type",
|
||||
"kind": "refactor.rewrite.function.returnType",
|
||||
"isPreferred": false,
|
||||
"data": {
|
||||
"specifier": file.uri(),
|
||||
"range": {
|
||||
"start": { "line": 1, "character": 15 },
|
||||
"end": { "line": 1, "character": 18 },
|
||||
},
|
||||
"refactorName": "Infer function return type",
|
||||
"actionName": "Infer function return type",
|
||||
},
|
||||
}
|
||||
]),
|
||||
);
|
||||
let code_action = res.as_array().unwrap().first().unwrap();
|
||||
let res = client.write_request("codeAction/resolve", code_action);
|
||||
assert_eq!(
|
||||
&res,
|
||||
&json!({
|
||||
"title": "Infer function return type",
|
||||
"kind": "refactor.rewrite.function.returnType",
|
||||
"isPreferred": false,
|
||||
"data": {
|
||||
"specifier": file.uri(),
|
||||
"range": {
|
||||
"start": { "line": 1, "character": 15 },
|
||||
"end": { "line": 1, "character": 18 },
|
||||
},
|
||||
"refactorName": "Infer function return type",
|
||||
"actionName": "Infer function return type",
|
||||
},
|
||||
"edit": {
|
||||
"documentChanges": [
|
||||
{
|
||||
"textDocument": { "uri": file.uri(), "version": null },
|
||||
"edits": [
|
||||
{
|
||||
"range": {
|
||||
"start": { "line": 1, "character": 20 },
|
||||
"end": { "line": 1, "character": 20 },
|
||||
},
|
||||
"newText": format!(": import(\"{}\").SomeInterface", types_file.uri()),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
client.shutdown();
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/denoland/deno/issues/23895.
|
||||
#[test]
|
||||
fn lsp_npm_types_nested_js_dts() {
|
||||
|
|
Loading…
Reference in a new issue