From fc2e00152b162280e78b06028d51274e33275629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Tue, 24 Jan 2023 15:05:54 +0100 Subject: feat: support node built-in module imports (#17264) Co-authored-by: David Sherret --- cli/tests/integration/check_tests.rs | 12 ++ cli/tests/integration/lsp_tests.rs | 184 +++++++++++++++++++++ cli/tests/integration/run_tests.rs | 20 +++ .../testdata/check/node_builtin_modules/mod.js | 3 + .../testdata/check/node_builtin_modules/mod.js.out | 5 + .../testdata/check/node_builtin_modules/mod.ts | 9 + .../testdata/check/node_builtin_modules/mod.ts.out | 13 ++ cli/tests/testdata/run/node_builtin_modules/mod.js | 2 + .../testdata/run/node_builtin_modules/mod.js.out | 1 + cli/tests/testdata/run/node_builtin_modules/mod.ts | 2 + .../testdata/run/node_builtin_modules/mod.ts.out | 1 + 11 files changed, 252 insertions(+) create mode 100644 cli/tests/testdata/check/node_builtin_modules/mod.js create mode 100644 cli/tests/testdata/check/node_builtin_modules/mod.js.out create mode 100644 cli/tests/testdata/check/node_builtin_modules/mod.ts create mode 100644 cli/tests/testdata/check/node_builtin_modules/mod.ts.out create mode 100644 cli/tests/testdata/run/node_builtin_modules/mod.js create mode 100644 cli/tests/testdata/run/node_builtin_modules/mod.js.out create mode 100644 cli/tests/testdata/run/node_builtin_modules/mod.ts create mode 100644 cli/tests/testdata/run/node_builtin_modules/mod.ts.out (limited to 'cli/tests') diff --git a/cli/tests/integration/check_tests.rs b/cli/tests/integration/check_tests.rs index 38301f079..66433f81d 100644 --- a/cli/tests/integration/check_tests.rs +++ b/cli/tests/integration/check_tests.rs @@ -64,6 +64,18 @@ itest!(check_static_response_json { exit_code: 0, }); +itest!(check_node_builtin_modules_ts { + args: "check --quiet check/node_builtin_modules/mod.ts", + output: "check/node_builtin_modules/mod.ts.out", + exit_code: 1, +}); + +itest!(check_node_builtin_modules_js { + args: "check --quiet check/node_builtin_modules/mod.js", + output: "check/node_builtin_modules/mod.js.out", + exit_code: 1, +}); + itest!(check_no_error_truncation { args: "check --quiet check/no_error_truncation/main.ts --config check/no_error_truncation/deno.json", output: "check/no_error_truncation/main.out", diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 3fba65c46..4f08ad84b 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -4407,6 +4407,190 @@ fn lsp_npm_specifier_unopened_file() { } } +#[test] +fn lsp_completions_node_specifier() { + let _g = http_server(); + let mut client = init("initialize_params.json"); + let diagnostics = CollectedDiagnostics(did_open( + &mut client, + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "import fs from 'node:non-existent';\n\n", + } + }), + )); + + let non_existent_diagnostics = diagnostics + .with_file_and_source("file:///a/file.ts", "deno") + .diagnostics + .into_iter() + .filter(|d| { + d.code == Some(lsp::NumberOrString::String("resolver-error".to_string())) + }) + .collect::>(); + assert_eq!( + json!(non_existent_diagnostics), + json!([ + { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 34 + } + }, + "severity": 1, + "code": "resolver-error", + "source": "deno", + "message": "Unknown Node built-in module: non-existent" + } + ]) + ); + + // update to have node:fs import + client + .write_notification( + "textDocument/didChange", + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "version": 2 + }, + "contentChanges": [ + { + "range": { + "start": { + "line": 0, + "character": 16 + }, + "end": { + "line": 0, + "character": 33 + } + }, + "text": "node:fs" + } + ] + }), + ) + .unwrap(); + let diagnostics = read_diagnostics(&mut client); + let cache_diagnostics = diagnostics + .with_file_and_source("file:///a/file.ts", "deno") + .diagnostics + .into_iter() + .filter(|d| { + d.code == Some(lsp::NumberOrString::String("no-cache-npm".to_string())) + }) + .collect::>(); + + assert_eq!( + json!(cache_diagnostics), + json!([ + { + "range": { + "start": { + "line": 0, + "character": 15 + }, + "end": { + "line": 0, + "character": 24 + } + }, + "data": { + "specifier": "npm:@types/node", + }, + "severity": 1, + "code": "no-cache-npm", + "source": "deno", + "message": "Uncached or missing npm package: \"@types/node\"." + } + ]) + ); + + let (maybe_res, maybe_err) = client + .write_request::<_, _, Value>( + "deno/cache", + json!({ + "referrer": { + "uri": "file:///a/file.ts", + }, + "uris": [ + { + "uri": "npm:@types/node", + } + ] + }), + ) + .unwrap(); + assert!(maybe_err.is_none()); + assert!(maybe_res.is_some()); + + client + .write_notification( + "textDocument/didChange", + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "version": 2 + }, + "contentChanges": [ + { + "range": { + "start": { + "line": 2, + "character": 0 + }, + "end": { + "line": 2, + "character": 0 + } + }, + "text": "fs." + } + ] + }), + ) + .unwrap(); + read_diagnostics(&mut client); + + let (maybe_res, maybe_err) = client + .write_request( + "textDocument/completion", + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "position": { + "line": 2, + "character": 3 + }, + "context": { + "triggerKind": 2, + "triggerCharacter": "." + } + }), + ) + .unwrap(); + assert!(maybe_err.is_none()); + if let Some(lsp::CompletionResponse::List(list)) = maybe_res { + assert!(!list.is_incomplete); + assert!(list.items.iter().any(|i| i.label == "writeFile")); + assert!(list.items.iter().any(|i| i.label == "writeFileSync")); + } else { + panic!("unexpected response"); + } + + shutdown(&mut client); +} + #[test] fn lsp_completions_registry() { let _g = http_server(); diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 564b7355f..f12282b9f 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -3743,3 +3743,23 @@ fn stdio_streams_are_locked_in_permission_prompt() { assert_eq!(output, expected_output); }); } + +itest!(run_node_builtin_modules_ts { + args: "run --quiet run/node_builtin_modules/mod.ts", + output: "run/node_builtin_modules/mod.ts.out", + envs: vec![( + "DENO_NODE_COMPAT_URL".to_string(), + test_util::std_file_url() + )], + exit_code: 0, +}); + +itest!(run_node_builtin_modules_js { + args: "run --quiet run/node_builtin_modules/mod.js", + output: "run/node_builtin_modules/mod.js.out", + envs: vec![( + "DENO_NODE_COMPAT_URL".to_string(), + test_util::std_file_url() + )], + exit_code: 0, +}); diff --git a/cli/tests/testdata/check/node_builtin_modules/mod.js b/cli/tests/testdata/check/node_builtin_modules/mod.js new file mode 100644 index 000000000..196fb9be9 --- /dev/null +++ b/cli/tests/testdata/check/node_builtin_modules/mod.js @@ -0,0 +1,3 @@ +// @ts-check +import fs from "node:fs"; +const _data = fs.readFileSync("./node_builtin.js", 123); diff --git a/cli/tests/testdata/check/node_builtin_modules/mod.js.out b/cli/tests/testdata/check/node_builtin_modules/mod.js.out new file mode 100644 index 000000000..97786ebae --- /dev/null +++ b/cli/tests/testdata/check/node_builtin_modules/mod.js.out @@ -0,0 +1,5 @@ +error: TS2769 [ERROR]: No overload matches this call. + [WILDCARD] +const _data = fs.readFileSync("./node_builtin.js", 123); + ~~~ + at file:///[WILDCARD]/node_builtin_modules/mod.js:3:52 diff --git a/cli/tests/testdata/check/node_builtin_modules/mod.ts b/cli/tests/testdata/check/node_builtin_modules/mod.ts new file mode 100644 index 000000000..0e62353fe --- /dev/null +++ b/cli/tests/testdata/check/node_builtin_modules/mod.ts @@ -0,0 +1,9 @@ +import fs from "node:fs"; +const _data = fs.readFileSync("./node_builtin.js", 123); + +// check node:module specifically because for deno check it should +// resolve to the @types/node package, but at runtime it uses a different +// builtin object than deno_std +import { builtinModules } from "node:module"; +// should error about being string[] +const _testString: number[] = builtinModules; diff --git a/cli/tests/testdata/check/node_builtin_modules/mod.ts.out b/cli/tests/testdata/check/node_builtin_modules/mod.ts.out new file mode 100644 index 000000000..49b762cff --- /dev/null +++ b/cli/tests/testdata/check/node_builtin_modules/mod.ts.out @@ -0,0 +1,13 @@ +error: TS2769 [ERROR]: No overload matches this call. + [WILDCARD] +const _data = fs.readFileSync("./node_builtin.js", 123); + ~~~ + at file:///[WILDCARD]/node_builtin_modules/mod.ts:2:52 + +TS2322 [ERROR]: Type 'string[]' is not assignable to type 'number[]'. + Type 'string' is not assignable to type 'number'. +const _testString: number[] = builtinModules; + ~~~~~~~~~~~ + at file:///[WILDCARD]/node_builtin_modules/mod.ts:9:7 + +Found 2 errors. diff --git a/cli/tests/testdata/run/node_builtin_modules/mod.js b/cli/tests/testdata/run/node_builtin_modules/mod.js new file mode 100644 index 000000000..70e39be56 --- /dev/null +++ b/cli/tests/testdata/run/node_builtin_modules/mod.js @@ -0,0 +1,2 @@ +import process from "node:process"; +console.log(process.version); diff --git a/cli/tests/testdata/run/node_builtin_modules/mod.js.out b/cli/tests/testdata/run/node_builtin_modules/mod.js.out new file mode 100644 index 000000000..9dc2247f4 --- /dev/null +++ b/cli/tests/testdata/run/node_builtin_modules/mod.js.out @@ -0,0 +1 @@ +v[WILDCARD].[WILDCARD].[WILDCARD] diff --git a/cli/tests/testdata/run/node_builtin_modules/mod.ts b/cli/tests/testdata/run/node_builtin_modules/mod.ts new file mode 100644 index 000000000..70e39be56 --- /dev/null +++ b/cli/tests/testdata/run/node_builtin_modules/mod.ts @@ -0,0 +1,2 @@ +import process from "node:process"; +console.log(process.version); diff --git a/cli/tests/testdata/run/node_builtin_modules/mod.ts.out b/cli/tests/testdata/run/node_builtin_modules/mod.ts.out new file mode 100644 index 000000000..9dc2247f4 --- /dev/null +++ b/cli/tests/testdata/run/node_builtin_modules/mod.ts.out @@ -0,0 +1 @@ +v[WILDCARD].[WILDCARD].[WILDCARD] -- cgit v1.2.3