diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e87701cddbe4e..b51c90eb742dc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2431,6 +2431,25 @@ namespace ts { function parseJSDocType(): TypeNode { scanner.setInJSDocType(true); + const moduleSpecifier = parseOptionalToken(SyntaxKind.ModuleKeyword); + if (moduleSpecifier) { + const moduleTag = createNode(SyntaxKind.JSDocNamepathType, moduleSpecifier.pos) as JSDocNamepathType; + terminate: while (true) { + switch (token()) { + case SyntaxKind.CloseBraceToken: + case SyntaxKind.EndOfFileToken: + case SyntaxKind.CommaToken: + case SyntaxKind.WhitespaceTrivia: + break terminate; + default: + nextTokenJSDoc(); + } + } + + scanner.setInJSDocType(false); + return finishNode(moduleTag); + } + const dotdotdot = parseOptionalToken(SyntaxKind.DotDotDotToken); let type = parseTypeOrTypePredicate(); scanner.setInJSDocType(false); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 7eaca34a21228..110b4a8b37f4f 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1995,7 +1995,7 @@ namespace ts { // First non-whitespace character on this line. let firstNonWhitespace = 0; // These initial values are special because the first line is: - // firstNonWhitespace = 0 to indicate that we want leading whitspace, + // firstNonWhitespace = 0 to indicate that we want leading whitespace, while (pos < end) { char = text.charCodeAt(pos); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3f1b30feb4526..8e28b574b8ed3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -455,6 +455,8 @@ namespace ts { JSDocOptionalType, JSDocFunctionType, JSDocVariadicType, + // https://jsdoc.app/about-namepaths.html + JSDocNamepathType, JSDocComment, JSDocTypeLiteral, JSDocSignature, @@ -2430,6 +2432,11 @@ namespace ts { type: TypeNode; } + export interface JSDocNamepathType extends JSDocType { + kind: SyntaxKind.JSDocNamepathType; + type: TypeNode; + } + export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; export interface JSDoc extends Node { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 3b09fc01fc071..942e860e0d8f4 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1269,6 +1269,10 @@ namespace FourSlash { private verifySignatureHelpWorker(options: FourSlashInterface.VerifySignatureHelpOptions) { const help = this.getSignatureHelp({ triggerReason: options.triggerReason })!; + if (!help) { + this.raiseError("Could not get a help signature"); + } + const selectedItem = help.items[help.selectedItemIndex]; // Argument index may exceed number of parameters const currentParameter = selectedItem.parameters[help.argumentIndex] as ts.SignatureHelpParameter | undefined; diff --git a/src/services/classifier.ts b/src/services/classifier.ts index f1db477481f0a..1e1309a2eacf0 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -1,4 +1,5 @@ namespace ts { + /** The classifier is used for syntactic highlighting in editors via the TSServer */ export function createClassifier(): Classifier { const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2f5960f9c215d..0923d3b95d629 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -374,29 +374,30 @@ declare namespace ts { JSDocOptionalType = 294, JSDocFunctionType = 295, JSDocVariadicType = 296, - JSDocComment = 297, - JSDocTypeLiteral = 298, - JSDocSignature = 299, - JSDocTag = 300, - JSDocAugmentsTag = 301, - JSDocAuthorTag = 302, - JSDocClassTag = 303, - JSDocCallbackTag = 304, - JSDocEnumTag = 305, - JSDocParameterTag = 306, - JSDocReturnTag = 307, - JSDocThisTag = 308, - JSDocTypeTag = 309, - JSDocTemplateTag = 310, - JSDocTypedefTag = 311, - JSDocPropertyTag = 312, - SyntaxList = 313, - NotEmittedStatement = 314, - PartiallyEmittedExpression = 315, - CommaListExpression = 316, - MergeDeclarationMarker = 317, - EndOfDeclarationMarker = 318, - Count = 319, + JSDocNamepathType = 297, + JSDocComment = 298, + JSDocTypeLiteral = 299, + JSDocSignature = 300, + JSDocTag = 301, + JSDocAugmentsTag = 302, + JSDocAuthorTag = 303, + JSDocClassTag = 304, + JSDocCallbackTag = 305, + JSDocEnumTag = 306, + JSDocParameterTag = 307, + JSDocReturnTag = 308, + JSDocThisTag = 309, + JSDocTypeTag = 310, + JSDocTemplateTag = 311, + JSDocTypedefTag = 312, + JSDocPropertyTag = 313, + SyntaxList = 314, + NotEmittedStatement = 315, + PartiallyEmittedExpression = 316, + CommaListExpression = 317, + MergeDeclarationMarker = 318, + EndOfDeclarationMarker = 319, + Count = 320, FirstAssignment = 60, LastAssignment = 72, FirstCompoundAssignment = 61, @@ -423,9 +424,9 @@ declare namespace ts { LastBinaryOperator = 72, FirstNode = 149, FirstJSDocNode = 289, - LastJSDocNode = 312, - FirstJSDocTagNode = 300, - LastJSDocTagNode = 312, + LastJSDocNode = 313, + FirstJSDocTagNode = 301, + LastJSDocTagNode = 313, } export enum NodeFlags { None = 0, @@ -1558,6 +1559,10 @@ declare namespace ts { kind: SyntaxKind.JSDocVariadicType; type: TypeNode; } + export interface JSDocNamepathType extends JSDocType { + kind: SyntaxKind.JSDocNamepathType; + type: TypeNode; + } export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; export interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; @@ -5671,6 +5676,7 @@ declare namespace ts { } } declare namespace ts { + /** The classifier is used for syntactic highlighting in editors via the TSServer */ function createClassifier(): Classifier; } declare namespace ts { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0b7ee8d086de3..352f7ddd1aaf1 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -374,29 +374,30 @@ declare namespace ts { JSDocOptionalType = 294, JSDocFunctionType = 295, JSDocVariadicType = 296, - JSDocComment = 297, - JSDocTypeLiteral = 298, - JSDocSignature = 299, - JSDocTag = 300, - JSDocAugmentsTag = 301, - JSDocAuthorTag = 302, - JSDocClassTag = 303, - JSDocCallbackTag = 304, - JSDocEnumTag = 305, - JSDocParameterTag = 306, - JSDocReturnTag = 307, - JSDocThisTag = 308, - JSDocTypeTag = 309, - JSDocTemplateTag = 310, - JSDocTypedefTag = 311, - JSDocPropertyTag = 312, - SyntaxList = 313, - NotEmittedStatement = 314, - PartiallyEmittedExpression = 315, - CommaListExpression = 316, - MergeDeclarationMarker = 317, - EndOfDeclarationMarker = 318, - Count = 319, + JSDocNamepathType = 297, + JSDocComment = 298, + JSDocTypeLiteral = 299, + JSDocSignature = 300, + JSDocTag = 301, + JSDocAugmentsTag = 302, + JSDocAuthorTag = 303, + JSDocClassTag = 304, + JSDocCallbackTag = 305, + JSDocEnumTag = 306, + JSDocParameterTag = 307, + JSDocReturnTag = 308, + JSDocThisTag = 309, + JSDocTypeTag = 310, + JSDocTemplateTag = 311, + JSDocTypedefTag = 312, + JSDocPropertyTag = 313, + SyntaxList = 314, + NotEmittedStatement = 315, + PartiallyEmittedExpression = 316, + CommaListExpression = 317, + MergeDeclarationMarker = 318, + EndOfDeclarationMarker = 319, + Count = 320, FirstAssignment = 60, LastAssignment = 72, FirstCompoundAssignment = 61, @@ -423,9 +424,9 @@ declare namespace ts { LastBinaryOperator = 72, FirstNode = 149, FirstJSDocNode = 289, - LastJSDocNode = 312, - FirstJSDocTagNode = 300, - LastJSDocTagNode = 312, + LastJSDocNode = 313, + FirstJSDocTagNode = 301, + LastJSDocTagNode = 313, } export enum NodeFlags { None = 0, @@ -1558,6 +1559,10 @@ declare namespace ts { kind: SyntaxKind.JSDocVariadicType; type: TypeNode; } + export interface JSDocNamepathType extends JSDocType { + kind: SyntaxKind.JSDocNamepathType; + type: TypeNode; + } export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; export interface JSDoc extends Node { kind: SyntaxKind.JSDocComment; @@ -5671,6 +5676,7 @@ declare namespace ts { } } declare namespace ts { + /** The classifier is used for syntactic highlighting in editors via the TSServer */ function createClassifier(): Classifier; } declare namespace ts { diff --git a/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt b/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt index b131c8adac071..bacaab76e4d15 100644 --- a/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt +++ b/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt @@ -1,14 +1,8 @@ -tests/cases/conformance/jsdoc/bug26693.js(1,15): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. -tests/cases/conformance/jsdoc/bug26693.js(1,21): error TS1005: '}' expected. tests/cases/conformance/jsdoc/bug26693.js(2,22): error TS2307: Cannot find module 'nope'. -==== tests/cases/conformance/jsdoc/bug26693.js (3 errors) ==== +==== tests/cases/conformance/jsdoc/bug26693.js (1 errors) ==== /** @typedef {module:locale} hi */ - ~~~~~~ -!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. - ~ -!!! error TS1005: '}' expected. import { nope } from 'nope'; ~~~~~~ !!! error TS2307: Cannot find module 'nope'. diff --git a/tests/cases/fourslash/jsDocDontBreakWithNamespaces.ts b/tests/cases/fourslash/jsDocDontBreakWithNamespaces.ts new file mode 100644 index 0000000000000..12899d23df38d --- /dev/null +++ b/tests/cases/fourslash/jsDocDontBreakWithNamespaces.ts @@ -0,0 +1,45 @@ +/// +// @allowJs: true +// @Filename: 31298.js +/////** +//// * @returns {module:@nodefuel/web~Webserver~wsServer#hello} Websocket server object +//// */ +////function foo() { } +////foo(''/*foo*/); +//// +/////** +//// * @type {module:xxxxx} */ +//// */ +////function bar() { } +////bar(''/*bar*/); +//// +/////** @type {function(module:xxxx, module:xxxx): module:xxxxx} */ +////function zee() { } +////zee(''/*zee*/); + + +verify.signatureHelp({ + marker: "foo", + text: "foo(): any", + docComment: "", + tags: [ + { name: "returns", text: "Websocket server object" }, + ], +}); + +verify.signatureHelp({ + marker: "bar", + text: "bar(): void", + docComment: "", + tags: [], +}); + + +verify.signatureHelp({ + marker: "zee", + text: "zee(): any", + docComment: "", + tags: [ + { name: "type", text: "{function(module:xxxx, module:xxxx): module:xxxxx}" }, + ], +});