summaryrefslogtreecommitdiff
path: root/cli/tests/integration/lsp_tests.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-12-06 19:03:18 -0500
committerGitHub <noreply@github.com>2023-12-07 00:03:18 +0000
commit890780a9e905f506e897f632d9cfbe153e66b931 (patch)
tree8e926e3bac67f096f3bec7748e14d507b62cfee4 /cli/tests/integration/lsp_tests.rs
parent9314928990a6cbd0bc0abe3100872ba2682eda9a (diff)
feat(unstable): ability to resolve specifiers with no extension, specifiers for a directory, and TS files from JS extensions (#21464)
Adds an `--unstable-sloppy-imports` flag which supports the following for `file:` specifiers: * Allows writing `./mod` in a specifier to do extension probing. - ex. `import { Example } from "./example"` instead of `import { Example } from "./example.ts"` * Allows writing `./routes` to do directory extension probing for files like `./routes/index.ts` * Allows writing `./mod.js` for *mod.ts* files. This functionality is **NOT RECOMMENDED** for general use with Deno: 1. It's not as optimal for perf: https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-2/ 1. It makes tooling in the ecosystem more complex in order to have to understand this. 1. The "Deno way" is to be explicit about what you're doing. It's better in the long run. 1. It doesn't work if published to the Deno registry because doing stuff like extension probing with remote specifiers would be incredibly slow. This is instead only recommended to help with migrating existing projects to Deno. For example, it's very useful for getting CJS projects written with import/export declaration working in Deno without modifying module specifiers and for supporting TS ESM projects written with `./mod.js` specifiers. This feature will output warnings to guide the user towards correcting their specifiers. Additionally, quick fixes are provided in the LSP to update these specifiers:
Diffstat (limited to 'cli/tests/integration/lsp_tests.rs')
-rw-r--r--cli/tests/integration/lsp_tests.rs166
1 files changed, 164 insertions, 2 deletions
diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs
index 6dfb0a29a..711d0bcd8 100644
--- a/cli/tests/integration/lsp_tests.rs
+++ b/cli/tests/integration/lsp_tests.rs
@@ -1095,8 +1095,7 @@ fn lsp_import_attributes() {
"only": ["quickfix"]
}
}),
- )
- ;
+ );
assert_eq!(
res,
json!([{
@@ -10506,3 +10505,166 @@ fn lsp_jupyter_byonm_diagnostics() {
);
client.shutdown();
}
+
+#[test]
+fn lsp_sloppy_imports_warn() {
+ let context = TestContextBuilder::new().use_temp_cwd().build();
+ let temp_dir = context.temp_dir();
+ let temp_dir = temp_dir.path();
+ temp_dir
+ .join("deno.json")
+ .write(r#"{ "unstable": ["sloppy-imports"] }"#);
+ // should work when exists on the fs and when doesn't
+ temp_dir.join("a.ts").write("export class A {}");
+ let mut client = context.new_lsp_command().build();
+ client.initialize(|builder| {
+ builder.set_root_uri(temp_dir.uri_dir());
+ });
+ client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.join("b.ts").uri_file(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "export class B {}",
+ },
+ }));
+ let diagnostics = client.did_open(json!({
+ "textDocument": {
+ "uri": temp_dir.join("file.ts").uri_file(),
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import * as a from './a';\nimport * as b from './b.js';\nconsole.log(a)\nconsole.log(b);\n",
+ },
+ }));
+ assert_eq!(
+ diagnostics.messages_with_source("deno"),
+ lsp::PublishDiagnosticsParams {
+ uri: temp_dir.join("file.ts").uri_file(),
+ diagnostics: vec![
+ lsp::Diagnostic {
+ range: lsp::Range {
+ start: lsp::Position {
+ line: 0,
+ character: 19
+ },
+ end: lsp::Position {
+ line: 0,
+ character: 24
+ }
+ },
+ severity: Some(lsp::DiagnosticSeverity::INFORMATION),
+ code: Some(lsp::NumberOrString::String("redirect".to_string())),
+ source: Some("deno".to_string()),
+ message: format!(
+ "The import of \"{}\" was redirected to \"{}\".",
+ temp_dir.join("a").uri_file(),
+ temp_dir.join("a.ts").uri_file()
+ ),
+ data: Some(json!({
+ "specifier": temp_dir.join("a").uri_file(),
+ "redirect": temp_dir.join("a.ts").uri_file()
+ })),
+ ..Default::default()
+ },
+ lsp::Diagnostic {
+ range: lsp::Range {
+ start: lsp::Position {
+ line: 1,
+ character: 19
+ },
+ end: lsp::Position {
+ line: 1,
+ character: 27
+ }
+ },
+ severity: Some(lsp::DiagnosticSeverity::INFORMATION),
+ code: Some(lsp::NumberOrString::String("redirect".to_string())),
+ source: Some("deno".to_string()),
+ message: format!(
+ "The import of \"{}\" was redirected to \"{}\".",
+ temp_dir.join("b.js").uri_file(),
+ temp_dir.join("b.ts").uri_file()
+ ),
+ data: Some(json!({
+ "specifier": temp_dir.join("b.js").uri_file(),
+ "redirect": temp_dir.join("b.ts").uri_file()
+ })),
+ ..Default::default()
+ }
+ ],
+ version: Some(1),
+ }
+ );
+
+ let res = client.write_request(
+ "textDocument/codeAction",
+ json!({
+ "textDocument": {
+ "uri": temp_dir.join("file.ts").uri_file()
+ },
+ "range": {
+ "start": { "line": 0, "character": 19 },
+ "end": { "line": 0, "character": 24 }
+ },
+ "context": {
+ "diagnostics": [{
+ "range": {
+ "start": { "line": 0, "character": 19 },
+ "end": { "line": 0, "character": 24 }
+ },
+ "severity": 3,
+ "code": "redirect",
+ "source": "deno",
+ "message": format!(
+ "The import of \"{}\" was redirected to \"{}\".",
+ temp_dir.join("a").uri_file(),
+ temp_dir.join("a.ts").uri_file()
+ ),
+ "data": {
+ "specifier": temp_dir.join("a").uri_file(),
+ "redirect": temp_dir.join("a.ts").uri_file()
+ },
+ }],
+ "only": ["quickfix"]
+ }
+ }),
+ );
+ assert_eq!(
+ res,
+ json!([{
+ "title": "Update specifier to its redirected specifier.",
+ "kind": "quickfix",
+ "diagnostics": [{
+ "range": {
+ "start": { "line": 0, "character": 19 },
+ "end": { "line": 0, "character": 24 }
+ },
+ "severity": 3,
+ "code": "redirect",
+ "source": "deno",
+ "message": format!(
+ "The import of \"{}\" was redirected to \"{}\".",
+ temp_dir.join("a").uri_file(),
+ temp_dir.join("a.ts").uri_file()
+ ),
+ "data": {
+ "specifier": temp_dir.join("a").uri_file(),
+ "redirect": temp_dir.join("a.ts").uri_file()
+ },
+ }],
+ "edit": {
+ "changes": {
+ temp_dir.join("file.ts").uri_file(): [{
+ "range": {
+ "start": { "line": 0, "character": 19 },
+ "end": { "line": 0, "character": 24 }
+ },
+ "newText": "\"./a.ts\""
+ }]
+ }
+ }
+ }])
+ );
+
+ client.shutdown();
+}