fix(lsp): completions for using decl identifiers (#23748)

Closes #23688
This commit is contained in:
David Sherret 2024-05-09 13:18:13 -04:00 committed by GitHub
parent 684377c92c
commit f0e8ec0146
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 2 deletions

View file

@ -1372,6 +1372,7 @@ pub enum OneOrMany<T> {
Many(Vec<T>), Many(Vec<T>),
} }
/// Aligns with ts.ScriptElementKind
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub enum ScriptElementKind { pub enum ScriptElementKind {
#[serde(rename = "")] #[serde(rename = "")]
@ -1400,6 +1401,10 @@ pub enum ScriptElementKind {
VariableElement, VariableElement,
#[serde(rename = "local var")] #[serde(rename = "local var")]
LocalVariableElement, LocalVariableElement,
#[serde(rename = "using")]
VariableUsingElement,
#[serde(rename = "await using")]
VariableAwaitUsingElement,
#[serde(rename = "function")] #[serde(rename = "function")]
FunctionElement, FunctionElement,
#[serde(rename = "local function")] #[serde(rename = "local function")]
@ -1412,6 +1417,8 @@ pub enum ScriptElementKind {
MemberSetAccessorElement, MemberSetAccessorElement,
#[serde(rename = "property")] #[serde(rename = "property")]
MemberVariableElement, MemberVariableElement,
#[serde(rename = "accessor")]
MemberAccessorVariableElement,
#[serde(rename = "constructor")] #[serde(rename = "constructor")]
ConstructorImplementationElement, ConstructorImplementationElement,
#[serde(rename = "call")] #[serde(rename = "call")]
@ -1456,7 +1463,8 @@ impl Default for ScriptElementKind {
} }
} }
/// This mirrors the method `convertKind` in `completions.ts` in vscode /// This mirrors the method `convertKind` in `completions.ts` in vscode (extensions/typescript-language-features)
/// https://github.com/microsoft/vscode/blob/bd2df940d74b51105aefb11304e028d2fb56a9dc/extensions/typescript-language-features/src/languageFeatures/completions.ts#L440
impl From<ScriptElementKind> for lsp::CompletionItemKind { impl From<ScriptElementKind> for lsp::CompletionItemKind {
fn from(kind: ScriptElementKind) -> Self { fn from(kind: ScriptElementKind) -> Self {
match kind { match kind {
@ -1502,7 +1510,18 @@ impl From<ScriptElementKind> for lsp::CompletionItemKind {
ScriptElementKind::ScriptElement => lsp::CompletionItemKind::FILE, ScriptElementKind::ScriptElement => lsp::CompletionItemKind::FILE,
ScriptElementKind::Directory => lsp::CompletionItemKind::FOLDER, ScriptElementKind::Directory => lsp::CompletionItemKind::FOLDER,
ScriptElementKind::String => lsp::CompletionItemKind::CONSTANT, ScriptElementKind::String => lsp::CompletionItemKind::CONSTANT,
_ => lsp::CompletionItemKind::PROPERTY, ScriptElementKind::LocalClassElement
| ScriptElementKind::ConstructorImplementationElement
| ScriptElementKind::TypeParameterElement
| ScriptElementKind::Label
| ScriptElementKind::JsxAttribute
| ScriptElementKind::Link
| ScriptElementKind::LinkName
| ScriptElementKind::LinkText
| ScriptElementKind::VariableUsingElement
| ScriptElementKind::VariableAwaitUsingElement
| ScriptElementKind::MemberAccessorVariableElement
| ScriptElementKind::Unknown => lsp::CompletionItemKind::PROPERTY,
} }
} }
} }

View file

@ -7081,6 +7081,43 @@ fn lsp_npm_completions_auto_import_and_quick_fix_no_import_map() {
client.shutdown(); client.shutdown();
} }
#[test]
fn lsp_completions_using_decl() {
let context = TestContextBuilder::new().use_temp_cwd().build();
let mut client = context.new_lsp_command().build();
client.initialize_default();
client.did_open(json!({
"textDocument": {
"uri": "file:///a/file.ts",
"languageId": "typescript",
"version": 1,
"text": r#"function makeResource() {
return {
[Symbol.dispose]() {
},
};
}
using resource = makeResource();
res"#
}
}));
let list = client.get_completion_list(
"file:///a/file.ts",
(9, 3),
json!({
"triggerKind": 2,
"triggerCharacter": "."
}),
);
assert!(list.items.iter().any(|i| i.label == "resource"));
assert!(!list.is_incomplete);
client.shutdown();
}
#[test] #[test]
fn lsp_npm_always_caches() { fn lsp_npm_always_caches() {
// npm specifiers should always be cached even when not specified // npm specifiers should always be cached even when not specified