From f2e59479354c4d925949e83a377deb33d9850ea1 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 20 Oct 2021 17:01:01 -0700 Subject: [PATCH] @link parses trailing <...> as part of linkName (#46450) Similar to #46428. Fixes #44818 --- src/services/utilities.ts | 22 +- .../reference/quickInfoLink3.baseline | 227 ++++++++++++++++++ tests/cases/fourslash/quickInfoLink3.ts | 16 ++ 3 files changed, 261 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/quickInfoLink3.baseline create mode 100644 tests/cases/fourslash/quickInfoLink3.ts diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 05ed20effbad5..b7e26ffeccbd3 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -2315,22 +2315,36 @@ namespace ts { } else { const symbol = checker?.getSymbolAtLocation(link.name); - const trailingParen = link.text.indexOf("()") === 0; - const name = getTextOfNode(link.name) + (trailingParen ? "()" : ""); - const text = trailingParen ? link.text.slice(2) : link.text; + const suffix = findLinkNameEnd(link.text); + const name = getTextOfNode(link.name) + link.text.slice(0, suffix); + const text = link.text.slice(suffix); const decl = symbol?.valueDeclaration || symbol?.declarations?.[0]; if (decl) { parts.push(linkNamePart(name, decl)); if (text) parts.push(linkTextPart(text)); } else { - parts.push(linkTextPart(name + (trailingParen ? "" : " ") + text)); + parts.push(linkTextPart(name + (suffix ? "" : " ") + text)); } } parts.push(linkPart("}")); return parts; } + function findLinkNameEnd(text: string) { + if (text.indexOf("()") === 0) return 2; + if (text[0] !== "<") return 0; + let brackets = 0; + let i = 0; + while (i < text.length) { + if (text[i] === "<") brackets++; + if (text[i] === ">") brackets--; + i++; + if (!brackets) return i; + } + return 0; + } + const carriageReturnLineFeed = "\r\n"; /** * The default is CRLF. diff --git a/tests/baselines/reference/quickInfoLink3.baseline b/tests/baselines/reference/quickInfoLink3.baseline new file mode 100644 index 0000000000000..65f4d33cef510 --- /dev/null +++ b/tests/baselines/reference/quickInfoLink3.baseline @@ -0,0 +1,227 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoLink3.ts", + "position": 169, + "name": "" + }, + "quickInfo": { + "kind": "method", + "kindModifiers": "", + "textSpan": { + "start": 166, + "length": 3 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "method", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Foo", + "kind": "className" + }, + { + "text": "<", + "kind": "punctuation" + }, + { + "text": "T", + "kind": "typeParameterName" + }, + { + "text": ">", + "kind": "punctuation" + }, + { + "text": ".", + "kind": "punctuation" + }, + { + "text": "bar", + "kind": "methodName" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "void", + "kind": "keyword" + } + ], + "documentation": [ + { + "text": "", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "Foo", + "kind": "linkName", + "target": { + "fileName": "/tests/cases/fourslash/quickInfoLink3.ts", + "textSpan": { + "start": 0, + "length": 175 + } + } + }, + { + "text": "}", + "kind": "link" + }, + { + "text": "\n", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "Foo", + "kind": "linkName", + "target": { + "fileName": "/tests/cases/fourslash/quickInfoLink3.ts", + "textSpan": { + "start": 0, + "length": 175 + } + } + }, + { + "text": "}", + "kind": "link" + }, + { + "text": "\n", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "Foo>", + "kind": "linkName", + "target": { + "fileName": "/tests/cases/fourslash/quickInfoLink3.ts", + "textSpan": { + "start": 0, + "length": 175 + } + } + }, + { + "text": "}", + "kind": "link" + }, + { + "text": "\n", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "Foo<>", + "kind": "linkName", + "target": { + "fileName": "/tests/cases/fourslash/quickInfoLink3.ts", + "textSpan": { + "start": 0, + "length": 175 + } + } + }, + { + "text": "}", + "kind": "link" + }, + { + "text": "\n", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "Foo", + "kind": "linkName", + "target": { + "fileName": "/tests/cases/fourslash/quickInfoLink3.ts", + "textSpan": { + "start": 0, + "length": 175 + } + } + }, + { + "text": ">", + "kind": "linkText" + }, + { + "text": "}", + "kind": "link" + }, + { + "text": "\n", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "Foo", + "kind": "linkName", + "target": { + "fileName": "/tests/cases/fourslash/quickInfoLink3.ts", + "textSpan": { + "start": 0, + "length": 175 + } + } + }, + { + "text": "<", + "kind": "linkText" + }, + { + "text": "}", + "kind": "link" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoLink3.ts b/tests/cases/fourslash/quickInfoLink3.ts new file mode 100644 index 0000000000000..7c0681c25aa87 --- /dev/null +++ b/tests/cases/fourslash/quickInfoLink3.ts @@ -0,0 +1,16 @@ +/// + +//// class Foo { +//// /** +//// * {@link Foo} +//// * {@link Foo} +//// * {@link Foo>} +//// * {@link Foo<>} +//// * {@link Foo>} +//// * {@link Foo<} +//// */ +//// bar/**/(){} +//// } + +verify.noErrors() +verify.baselineQuickInfo();