From c4fd0028f5b79aef118f360429f1930ba6c72e97 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 2 Feb 2022 14:00:08 -0800 Subject: [PATCH] Fix @link https:// formatting (#47705) * Fix @link https:// formatting Also improve .d.ts formatting of `@link`,`@linkcode`,`@linkplain`. Fixes #46734 1. Previously, `@link` incorrectly put a space between "https" and "://" when formatting jsdoc for editors. Now it does not. 2. When fixing the same output for .d.ts, I discovered that all `@link` tags were formatted as `@link`, even if they were `@linkcode` or `@linkplain`. I fixed that too. * semicolon lint --- src/compiler/utilitiesPublic.ts | 13 +- src/services/utilities.ts | 2 +- tests/baselines/reference/linkTagEmit1.js | 14 ++ .../baselines/reference/linkTagEmit1.symbols | 6 + tests/baselines/reference/linkTagEmit1.types | 7 + ...foForJSDocWithUnresolvedHttpLinks.baseline | 126 ++++++++++++++++++ tests/cases/conformance/jsdoc/linkTagEmit1.ts | 5 + ...uickInfoForJSDocWithUnresolvedHttpLinks.ts | 12 ++ 8 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline create mode 100644 tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 8f834e5e459..24f812476cd 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -905,9 +905,16 @@ namespace ts { /** Gets the text of a jsdoc comment, flattening links to their text. */ export function getTextOfJSDocComment(comment?: string | NodeArray) { return typeof comment === "string" ? comment - : comment?.map(c => - // TODO: Other kinds here - c.kind === SyntaxKind.JSDocText ? c.text : `{@link ${c.name ? entityNameToString(c.name) + " " : ""}${c.text}}`).join(""); + : comment?.map(c => c.kind === SyntaxKind.JSDocText ? c.text : formatJSDocLink(c)).join(""); + } + + function formatJSDocLink(link: JSDocLink | JSDocLinkCode | JSDocLinkPlain) { + const kind = link.kind === SyntaxKind.JSDocLink ? "link" + : link.kind === SyntaxKind.JSDocLinkCode ? "linkcode" + : "linkplain"; + const name = link.name ? entityNameToString(link.name) : ""; + const space = link.name && link.text.startsWith("://") ? "" : " "; + return `{@${kind} ${name}${space}${link.text}}`; } /** diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 98ac7627e32..f36346a14d4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -2320,7 +2320,7 @@ namespace ts { if (text) parts.push(linkTextPart(text)); } else { - parts.push(linkTextPart(name + (suffix ? "" : " ") + text)); + parts.push(linkTextPart(name + (suffix || text.indexOf("://") === 0 ? "" : " ") + text)); } } parts.push(linkPart("}")); diff --git a/tests/baselines/reference/linkTagEmit1.js b/tests/baselines/reference/linkTagEmit1.js index 377fa211381..0fe024f665a 100644 --- a/tests/baselines/reference/linkTagEmit1.js +++ b/tests/baselines/reference/linkTagEmit1.js @@ -20,6 +20,11 @@ declare namespace NS { function computeCommonSourceDirectoryOfFilenames(integer) { return integer + 1 // pls pls pls } + +/** {@link https://hvad} */ +var see3 = true + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ //// [linkTagEmit1.js] @@ -36,6 +41,9 @@ function computeCommonSourceDirectoryOfFilenames(integer) { function computeCommonSourceDirectoryOfFilenames(integer) { return integer + 1; // pls pls pls } +/** {@link https://hvad} */ +var see3 = true; +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ //// [linkTagEmit1.d.ts] @@ -50,6 +58,8 @@ function computeCommonSourceDirectoryOfFilenames(integer) { * @param {number} integer {@link Z} */ declare function computeCommonSourceDirectoryOfFilenames(integer: number): number; +/** {@link https://hvad} */ +declare var see3: boolean; type N = number; type D1 = { /** @@ -62,3 +72,7 @@ type D1 = { m: 1; }; type Z = number; +/** + * {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk} + */ +type Attempt = number; diff --git a/tests/baselines/reference/linkTagEmit1.symbols b/tests/baselines/reference/linkTagEmit1.symbols index 30b7ab681f8..047da580415 100644 --- a/tests/baselines/reference/linkTagEmit1.symbols +++ b/tests/baselines/reference/linkTagEmit1.symbols @@ -26,3 +26,9 @@ function computeCommonSourceDirectoryOfFilenames(integer) { >integer : Symbol(integer, Decl(linkTagEmit1.js, 12, 49)) } +/** {@link https://hvad} */ +var see3 = true +>see3 : Symbol(see3, Decl(linkTagEmit1.js, 17, 3)) + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ + diff --git a/tests/baselines/reference/linkTagEmit1.types b/tests/baselines/reference/linkTagEmit1.types index a5456e3877f..17bdfb38f62 100644 --- a/tests/baselines/reference/linkTagEmit1.types +++ b/tests/baselines/reference/linkTagEmit1.types @@ -26,3 +26,10 @@ function computeCommonSourceDirectoryOfFilenames(integer) { >1 : 1 } +/** {@link https://hvad} */ +var see3 = true +>see3 : boolean +>true : true + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ + diff --git a/tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline b/tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline new file mode 100644 index 00000000000..7700b2b908f --- /dev/null +++ b/tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline @@ -0,0 +1,126 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForJSDocWithHttpLinks.js", + "position": 36, + "name": "5" + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 36, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "see2", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "boolean", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [ + { + "name": "see", + "text": [ + { + "text": "", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "https://hva", + "kind": "linkText" + }, + { + "text": "}", + "kind": "link" + } + ] + } + ] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForJSDocWithHttpLinks.js", + "position": 81, + "name": "6" + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 81, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "see3", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "boolean", + "kind": "keyword" + } + ], + "documentation": [ + { + "text": "", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "https://hvaD", + "kind": "linkText" + }, + { + "text": "}", + "kind": "link" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/cases/conformance/jsdoc/linkTagEmit1.ts b/tests/cases/conformance/jsdoc/linkTagEmit1.ts index 3c353764146..e53e45c3d4e 100644 --- a/tests/cases/conformance/jsdoc/linkTagEmit1.ts +++ b/tests/cases/conformance/jsdoc/linkTagEmit1.ts @@ -21,3 +21,8 @@ declare namespace NS { function computeCommonSourceDirectoryOfFilenames(integer) { return integer + 1 // pls pls pls } + +/** {@link https://hvad} */ +var see3 = true + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ diff --git a/tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts b/tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts new file mode 100644 index 00000000000..eb892b9ce19 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts @@ -0,0 +1,12 @@ +/// +// @checkJs: true +// @filename: quickInfoForJSDocWithHttpLinks.js +// #46734 + +//// /** @see {@link https://hva} */ +//// var /*5*/see2 = true +//// +//// /** {@link https://hvaD} */ +//// var /*6*/see3 = true + +verify.baselineQuickInfo();