mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 08:39:09 -05:00
feat(lsp): node specifier completions (#24904)
This commit is contained in:
parent
b3f1f3ba04
commit
9a83efa04b
2 changed files with 143 additions and 1 deletions
|
@ -18,6 +18,7 @@ use crate::util::path::is_importable_ext;
|
|||
use crate::util::path::relative_specifier;
|
||||
use deno_graph::source::ResolutionMode;
|
||||
use deno_graph::Range;
|
||||
use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES;
|
||||
use deno_runtime::fs_util::specifier_to_file_path;
|
||||
|
||||
use deno_ast::LineAndColumnIndex;
|
||||
|
@ -192,6 +193,8 @@ pub async fn get_import_completions(
|
|||
get_npm_completions(specifier, &text, &range, npm_search_api).await
|
||||
{
|
||||
Some(lsp::CompletionResponse::List(completion_list))
|
||||
} else if let Some(completion_list) = get_node_completions(&text, &range) {
|
||||
Some(lsp::CompletionResponse::List(completion_list))
|
||||
} else if let Some(completion_list) =
|
||||
get_import_map_completions(specifier, &text, &range, maybe_import_map)
|
||||
{
|
||||
|
@ -732,6 +735,40 @@ async fn get_npm_completions(
|
|||
})
|
||||
}
|
||||
|
||||
/// Get completions for `node:` specifiers.
|
||||
fn get_node_completions(
|
||||
specifier: &str,
|
||||
range: &lsp::Range,
|
||||
) -> Option<CompletionList> {
|
||||
if !specifier.starts_with("node:") {
|
||||
return None;
|
||||
}
|
||||
let items = SUPPORTED_BUILTIN_NODE_MODULES
|
||||
.iter()
|
||||
.map(|name| {
|
||||
let specifier = format!("node:{}", name);
|
||||
let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
|
||||
range: *range,
|
||||
new_text: specifier.clone(),
|
||||
}));
|
||||
lsp::CompletionItem {
|
||||
label: specifier,
|
||||
kind: Some(lsp::CompletionItemKind::FILE),
|
||||
detail: Some("(node)".to_string()),
|
||||
text_edit,
|
||||
commit_characters: Some(
|
||||
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||
),
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Some(CompletionList {
|
||||
is_incomplete: false,
|
||||
items,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get workspace completions that include modules in the Deno cache which match
|
||||
/// the current specifier string.
|
||||
fn get_workspace_completions(
|
||||
|
|
|
@ -7498,6 +7498,111 @@ fn lsp_npm_completions_auto_import_and_quick_fix_no_import_map() {
|
|||
client.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_completions_node_specifier() {
|
||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||
let temp_dir = context.temp_dir();
|
||||
let mut client = context.new_lsp_command().build();
|
||||
client.initialize_default();
|
||||
client.did_open(json!({
|
||||
"textDocument": {
|
||||
"uri": temp_dir.uri().join("file.ts").unwrap(),
|
||||
"languageId": "typescript",
|
||||
"version": 1,
|
||||
"text": "import fs from \"node:as\";\n",
|
||||
},
|
||||
}));
|
||||
let list = client.get_completion_list(
|
||||
temp_dir.uri().join("file.ts").unwrap(),
|
||||
(0, 23),
|
||||
json!({
|
||||
"triggerKind": 2,
|
||||
"triggerCharacter": ".",
|
||||
}),
|
||||
);
|
||||
assert!(!list.is_incomplete);
|
||||
assert_eq!(
|
||||
list
|
||||
.items
|
||||
.iter()
|
||||
.map(|i| i.label.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
vec![
|
||||
"node:assert",
|
||||
"node:assert/strict",
|
||||
"node:async_hooks",
|
||||
"node:buffer",
|
||||
"node:child_process",
|
||||
"node:cluster",
|
||||
"node:console",
|
||||
"node:constants",
|
||||
"node:crypto",
|
||||
"node:dgram",
|
||||
"node:diagnostics_channel",
|
||||
"node:dns",
|
||||
"node:dns/promises",
|
||||
"node:domain",
|
||||
"node:events",
|
||||
"node:fs",
|
||||
"node:fs/promises",
|
||||
"node:http",
|
||||
"node:http2",
|
||||
"node:https",
|
||||
"node:module",
|
||||
"node:net",
|
||||
"node:os",
|
||||
"node:path",
|
||||
"node:path/posix",
|
||||
"node:path/win32",
|
||||
"node:perf_hooks",
|
||||
"node:process",
|
||||
"node:punycode",
|
||||
"node:querystring",
|
||||
"node:repl",
|
||||
"node:readline",
|
||||
"node:readline/promises",
|
||||
"node:stream",
|
||||
"node:stream/consumers",
|
||||
"node:stream/promises",
|
||||
"node:stream/web",
|
||||
"node:string_decoder",
|
||||
"node:sys",
|
||||
"node:test",
|
||||
"node:timers",
|
||||
"node:timers/promises",
|
||||
"node:tls",
|
||||
"node:tty",
|
||||
"node:url",
|
||||
"node:util",
|
||||
"node:util/types",
|
||||
"node:v8",
|
||||
"node:vm",
|
||||
"node:worker_threads",
|
||||
"node:zlib",
|
||||
],
|
||||
);
|
||||
for item in &list.items {
|
||||
let specifier = item.label.as_str();
|
||||
assert_eq!(
|
||||
json!(item),
|
||||
json!({
|
||||
"label": specifier,
|
||||
"kind": 17,
|
||||
"detail": "(node)",
|
||||
"textEdit": {
|
||||
"range": {
|
||||
"start": { "line": 0, "character": 16 },
|
||||
"end": { "line": 0, "character": 23 },
|
||||
},
|
||||
"newText": specifier,
|
||||
},
|
||||
"commitCharacters": ["\"", "'"],
|
||||
}),
|
||||
);
|
||||
}
|
||||
client.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_infer_return_type() {
|
||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||
|
@ -8614,7 +8719,7 @@ fn lsp_npm_specifier_unopened_file() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_completions_node_specifier() {
|
||||
fn lsp_completions_node_builtin() {
|
||||
let context = TestContextBuilder::new()
|
||||
.use_http_server()
|
||||
.use_temp_cwd()
|
||||
|
|
Loading…
Reference in a new issue