1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 16:19:12 -05:00

fix(lsp): process Fenced Code Block in JSDoc on completion correctly (#23822)

partially fixing https://github.com/denoland/deno/issues/23820


https://github.com/denoland/deno/assets/41257923/0adb5d4e-cfd5-4195-9045-19d1c0a07a43

BTW, it is out of scope on this PR that to process type of `@param` to
be an code block due to it's a bit complicated.
This commit is contained in:
Hajime-san 2024-05-23 04:00:14 +09:00 committed by GitHub
parent 466cc68afe
commit cbddf468e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 16 deletions

View file

@ -3283,14 +3283,17 @@ impl CompletionEntryDetails {
None None
}; };
let documentation = if let Some(parts) = &self.documentation { let documentation = if let Some(parts) = &self.documentation {
// NOTE: similar as `QuickInfo::to_hover()`
let mut value = display_parts_to_string(parts, language_server); let mut value = display_parts_to_string(parts, language_server);
if let Some(tags) = &self.tags { if let Some(tags) = &self.tags {
let tag_documentation = tags let tags_preview = tags
.iter() .iter()
.map(|tag_info| get_tag_documentation(tag_info, language_server)) .map(|tag_info| get_tag_documentation(tag_info, language_server))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(""); .join(" \n\n");
value = format!("{value}\n\n{tag_documentation}"); if !tags_preview.is_empty() {
value = format!("{value}\n\n{tags_preview}");
}
} }
Some(lsp::Documentation::MarkupContent(lsp::MarkupContent { Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
kind: lsp::MarkupKind::Markdown, kind: lsp::MarkupKind::Markdown,

View file

@ -6967,7 +6967,7 @@ fn lsp_completions_auto_import() {
"uri": "file:///a/🦕.ts", "uri": "file:///a/🦕.ts",
"languageId": "typescript", "languageId": "typescript",
"version": 1, "version": 1,
"text": "export const foo = \"foo\";\n", "text": "/**\n *\n * @example\n * ```ts\n * const result = add(1, 2);\n * console.log(result); // 3\n * ```\n *\n * @param {number} a - The first number\n * @param {number} b - The second number\n */\nexport function add(a: number, b: number) {\n return a + b;\n}",
} }
})); }));
client.did_open(json!({ client.did_open(json!({
@ -6984,20 +6984,20 @@ fn lsp_completions_auto_import() {
json!({ "triggerKind": 1 }), json!({ "triggerKind": 1 }),
); );
assert!(!list.is_incomplete); assert!(!list.is_incomplete);
let item = list.items.iter().find(|item| item.label == "foo"); let item = list.items.iter().find(|item| item.label == "add");
let Some(item) = item else { let Some(item) = item else {
panic!("completions items missing 'foo' symbol"); panic!("completions items missing 'add' symbol");
}; };
let mut item_value = serde_json::to_value(item).unwrap(); let mut item_value = serde_json::to_value(item).unwrap();
item_value["data"]["tsc"]["data"]["exportMapKey"] = item_value["data"]["tsc"]["data"]["exportMapKey"] =
serde_json::Value::String("".to_string()); serde_json::Value::String("".to_string());
let req = json!({ let req = json!({
"label": "foo", "label": "add",
"labelDetails": { "labelDetails": {
"description": "./🦕.ts", "description": "./🦕.ts",
}, },
"kind": 6, "kind": 3,
"sortText": "￿16_0", "sortText": "￿16_0",
"commitCharacters": [ "commitCharacters": [
".", ".",
@ -7009,14 +7009,14 @@ fn lsp_completions_auto_import() {
"tsc": { "tsc": {
"specifier": "file:///a/file.ts", "specifier": "file:///a/file.ts",
"position": 12, "position": 12,
"name": "foo", "name": "add",
"source": "./%F0%9F%A6%95.ts", "source": "./%F0%9F%A6%95.ts",
"specifierRewrite": [ "specifierRewrite": [
"./%F0%9F%A6%95.ts", "./%F0%9F%A6%95.ts",
"./🦕.ts", "./🦕.ts",
], ],
"data": { "data": {
"exportName": "foo", "exportName": "add",
"exportMapKey": "", "exportMapKey": "",
"moduleSpecifier": "./%F0%9F%A6%95.ts", "moduleSpecifier": "./%F0%9F%A6%95.ts",
"fileName": "file:///a/%F0%9F%A6%95.ts" "fileName": "file:///a/%F0%9F%A6%95.ts"
@ -7031,15 +7031,15 @@ fn lsp_completions_auto_import() {
assert_eq!( assert_eq!(
res, res,
json!({ json!({
"label": "foo", "label": "add",
"labelDetails": { "labelDetails": {
"description": "./🦕.ts", "description": "./🦕.ts",
}, },
"kind": 6, "kind": 3,
"detail": "const foo: \"foo\"", "detail": "function add(a: number, b: number): number",
"documentation": { "documentation": {
"kind": "markdown", "kind": "markdown",
"value": "" "value": "\n\n*@example* \n```ts\nconst result = add(1, 2);\nconsole.log(result); // 3\n``` \n\n*@param* - a - The first number \n\n*@param* - b - The second number"
}, },
"sortText": "￿16_0", "sortText": "￿16_0",
"additionalTextEdits": [ "additionalTextEdits": [
@ -7048,7 +7048,7 @@ fn lsp_completions_auto_import() {
"start": { "line": 0, "character": 0 }, "start": { "line": 0, "character": 0 },
"end": { "line": 0, "character": 0 } "end": { "line": 0, "character": 0 }
}, },
"newText": "import { foo } from \"./🦕.ts\";\n\n" "newText": "import { add } from \"./🦕.ts\";\n\n"
} }
] ]
}) })
@ -10161,7 +10161,7 @@ fn lsp_completions_complete_function_calls() {
"detail": "(method) Array<never>.map<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any): U[]", "detail": "(method) Array<never>.map<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any): U[]",
"documentation": { "documentation": {
"kind": "markdown", "kind": "markdown",
"value": "Calls a defined callback function on each element of an array, and returns an array that contains the results.\n\n*@param* - callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.*@param* - thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value." "value": "Calls a defined callback function on each element of an array, and returns an array that contains the results.\n\n*@param* - callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. \n\n*@param* - thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value."
}, },
"sortText": "1", "sortText": "1",
"insertText": "map(${1:callbackfn})", "insertText": "map(${1:callbackfn})",