summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2024-05-21 21:15:16 +0100
committerGitHub <noreply@github.com>2024-05-21 21:15:16 +0100
commitcc8c0609ebec9f101a1739a0c42c91718ca2abba (patch)
tree2d62b2b2250a1e478e7d06cd0983a0681acdd6ad
parentddb5449f42051a2c7e92142a5d0750cdc49cb281 (diff)
fix(lsp): apply import fix to missing declaration code action (#23924)
-rw-r--r--cli/jsr.rs24
-rw-r--r--cli/lsp/analysis.rs5
-rw-r--r--tests/integration/lsp_tests.rs120
-rw-r--r--tests/registry/jsr/@denotest/types-file/1.0.0/mod.ts5
-rw-r--r--tests/registry/jsr/@denotest/types-file/1.0.0/types.d.ts1
-rw-r--r--tests/registry/jsr/@denotest/types-file/1.0.0_meta.json28
-rw-r--r--tests/registry/jsr/@denotest/types-file/meta.json5
7 files changed, 185 insertions, 3 deletions
diff --git a/cli/jsr.rs b/cli/jsr.rs
index c4cb87dbd..bdfba7f10 100644
--- a/cli/jsr.rs
+++ b/cli/jsr.rs
@@ -111,12 +111,32 @@ impl JsrCacheResolver {
) -> Option<String> {
let info = self.package_version_info(nv)?;
let path = path.strip_prefix("./").unwrap_or(path);
+ let mut sloppy_fallback = None;
for (export, path_) in info.exports() {
- if path_.strip_prefix("./").unwrap_or(path_) == path {
+ let path_ = path_.strip_prefix("./").unwrap_or(path_);
+ if path_ == path {
return Some(export.strip_prefix("./").unwrap_or(export).to_string());
}
+ // TSC in some cases will suggest a `.js` import path for a `.d.ts` source
+ // file.
+ if sloppy_fallback.is_none() {
+ let path = path
+ .strip_suffix(".js")
+ .or_else(|| path.strip_suffix(".mjs"))
+ .or_else(|| path.strip_suffix(".cjs"))
+ .unwrap_or(path);
+ let path_ = path_
+ .strip_suffix(".d.ts")
+ .or_else(|| path_.strip_suffix(".d.mts"))
+ .or_else(|| path_.strip_suffix(".d.cts"))
+ .unwrap_or(path_);
+ if path_ == path {
+ sloppy_fallback =
+ Some(export.strip_prefix("./").unwrap_or(export).to_string());
+ }
+ }
}
- None
+ sloppy_fallback
}
pub fn lookup_req_for_nv(&self, nv: &PackageNv) -> Option<PackageReq> {
diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs
index 23b6bb099..133f5f0ac 100644
--- a/cli/lsp/analysis.rs
+++ b/cli/lsp/analysis.rs
@@ -544,7 +544,10 @@ fn fix_ts_import_action(
action: &tsc::CodeFixAction,
import_mapper: &TsResponseImportMapper,
) -> Result<tsc::CodeFixAction, AnyError> {
- if action.fix_name == "import" {
+ if matches!(
+ action.fix_name.as_str(),
+ "import" | "fixMissingFunctionDeclaration"
+ ) {
let change = action
.changes
.first()
diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs
index 347324899..ed95541d2 100644
--- a/tests/integration/lsp_tests.rs
+++ b/tests/integration/lsp_tests.rs
@@ -5365,6 +5365,126 @@ fn lsp_jsr_auto_import_completion_import_map() {
}
#[test]
+fn lsp_jsr_code_action_missing_declaration() {
+ let context = TestContextBuilder::new()
+ .use_http_server()
+ .use_temp_cwd()
+ .build();
+ let temp_dir = context.temp_dir();
+ let file = source_file(
+ temp_dir.path().join("file.ts"),
+ r#"
+ import { someFunction } from "jsr:@denotest/types-file";
+ assertReturnType(someFunction());
+ "#,
+ );
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+ client.write_request(
+ "workspace/executeCommand",
+ json!({
+ "command": "deno.cache",
+ "arguments": [[], file.uri()],
+ }),
+ );
+ client.did_open_file(&file);
+ let res = client.write_request(
+ "textDocument/codeAction",
+ json!({
+ "textDocument": {
+ "uri": file.uri(),
+ },
+ "range": {
+ "start": { "line": 2, "character": 6 },
+ "end": { "line": 2, "character": 22 },
+ },
+ "context": {
+ "diagnostics": [
+ {
+ "range": {
+ "start": { "line": 2, "character": 6 },
+ "end": { "line": 2, "character": 22 },
+ },
+ "severity": 8,
+ "code": 2304,
+ "source": "deno-ts",
+ "message": "Cannot find name 'assertReturnType'.",
+ "relatedInformation": [],
+ },
+ ],
+ "only": ["quickfix"],
+ },
+ }),
+ );
+ assert_eq!(
+ res,
+ json!([
+ {
+ "title": "Add missing function declaration 'assertReturnType'",
+ "kind": "quickfix",
+ "diagnostics": [
+ {
+ "range": {
+ "start": {
+ "line": 2,
+ "character": 6,
+ },
+ "end": {
+ "line": 2,
+ "character": 22,
+ },
+ },
+ "severity": 8,
+ "code": 2304,
+ "source": "deno-ts",
+ "message": "Cannot find name 'assertReturnType'.",
+ "relatedInformation": [],
+ },
+ ],
+ "edit": {
+ "documentChanges": [
+ {
+ "textDocument": {
+ "uri": file.uri(),
+ "version": 1,
+ },
+ "edits": [
+ {
+ "range": {
+ "start": {
+ "line": 1,
+ "character": 6,
+ },
+ "end": {
+ "line": 1,
+ "character": 6,
+ },
+ },
+ "newText": "import { ReturnType } from \"jsr:@denotest/types-file/types\";\n",
+ },
+ {
+ "range": {
+ "start": {
+ "line": 3,
+ "character": 0,
+ },
+ "end": {
+ "line": 3,
+ "character": 0,
+ },
+ },
+ "newText": "\n function assertReturnType(arg0: ReturnType) {\n throw new Error(\"Function not implemented.\");\n }\n",
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ])
+ );
+}
+
+#[test]
fn lsp_code_actions_deno_cache_npm() {
let context = TestContextBuilder::new().use_temp_cwd().build();
let mut client = context.new_lsp_command().build();
diff --git a/tests/registry/jsr/@denotest/types-file/1.0.0/mod.ts b/tests/registry/jsr/@denotest/types-file/1.0.0/mod.ts
new file mode 100644
index 000000000..4d0d73bb5
--- /dev/null
+++ b/tests/registry/jsr/@denotest/types-file/1.0.0/mod.ts
@@ -0,0 +1,5 @@
+import type { ReturnType } from "./types.d.ts";
+
+export function someFunction(): ReturnType {
+ return {};
+}
diff --git a/tests/registry/jsr/@denotest/types-file/1.0.0/types.d.ts b/tests/registry/jsr/@denotest/types-file/1.0.0/types.d.ts
new file mode 100644
index 000000000..dabbb6a37
--- /dev/null
+++ b/tests/registry/jsr/@denotest/types-file/1.0.0/types.d.ts
@@ -0,0 +1 @@
+export interface ReturnType {}
diff --git a/tests/registry/jsr/@denotest/types-file/1.0.0_meta.json b/tests/registry/jsr/@denotest/types-file/1.0.0_meta.json
new file mode 100644
index 000000000..99ba71b5f
--- /dev/null
+++ b/tests/registry/jsr/@denotest/types-file/1.0.0_meta.json
@@ -0,0 +1,28 @@
+{
+ "exports": {
+ ".": "./mod.ts",
+ "./types": "./types.d.ts"
+ },
+ "moduleGraph1": {
+ "/types.d.ts": {},
+ "/mod.ts": {
+ "dependencies": [
+ {
+ "type": "static",
+ "kind": "importType",
+ "specifier": "./types.d.ts",
+ "specifierRange": [
+ [
+ 0,
+ 42
+ ],
+ [
+ 0,
+ 46
+ ]
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/registry/jsr/@denotest/types-file/meta.json b/tests/registry/jsr/@denotest/types-file/meta.json
new file mode 100644
index 000000000..02601e4d0
--- /dev/null
+++ b/tests/registry/jsr/@denotest/types-file/meta.json
@@ -0,0 +1,5 @@
+{
+ "versions": {
+ "1.0.0": {}
+ }
+}