diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6615cc3f015ef..f112e25b18b21 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -36425,6 +36425,17 @@ namespace ts { return node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } + function isJSDocEntryNameReference(node: Identifier | PrivateIdentifier | PropertyAccessExpression | QualifiedName): boolean { + while (node.parent.kind === SyntaxKind.QualifiedName) { + node = node.parent as QualifiedName; + } + while (node.parent.kind === SyntaxKind.PropertyAccessExpression) { + node = node.parent as PropertyAccessExpression; + } + + return node.parent.kind === SyntaxKind.JSDocNameReference; + } + function forEachEnclosingClass(node: Node, callback: (node: Node) => T | undefined): T | undefined { let result: T | undefined; @@ -36609,6 +36620,10 @@ namespace ts { const meaning = name.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace; return resolveEntityName(name, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); } + else if (isJSDocEntryNameReference(name)) { + const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value; + return resolveEntityName(name, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name)); + } if (name.parent.kind === SyntaxKind.TypePredicate) { return resolveEntityName(name, /*meaning*/ SymbolFlags.FunctionScopedVariable); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 332d2ae6de148..fce6e061a2945 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1548,6 +1548,10 @@ namespace ts { case SyntaxKind.JSDocClassTag: case SyntaxKind.JSDocTag: return emitJSDocSimpleTag(node as JSDocTag); + case SyntaxKind.JSDocSeeTag: + return emitJSDocSeeTag(node as JSDocSeeTag); + case SyntaxKind.JSDocNameReference: + return emitJSDocNameReference(node as JSDocNameReference); case SyntaxKind.JSDocComment: return emitJSDoc(node as JSDoc); @@ -3503,6 +3507,19 @@ namespace ts { emitJSDocComment(tag.comment); } + function emitJSDocSeeTag(tag: JSDocSeeTag) { + emitJSDocTagName(tag.tagName); + emit(tag.name); + emitJSDocComment(tag.comment); + } + + function emitJSDocNameReference(node: JSDocNameReference) { + writeSpace(); + writePunctuation("{"); + emit(node.name); + writePunctuation("}"); + } + function emitJSDocHeritageTag(tag: JSDocImplementsTag | JSDocAugmentsTag) { emitJSDocTagName(tag.tagName); writeSpace(); diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 2121f28d5ee75..dbe3fd052a484 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -337,6 +337,10 @@ namespace ts { updateJSDocAugmentsTag, createJSDocImplementsTag, updateJSDocImplementsTag, + createJSDocSeeTag, + updateJSDocSeeTag, + createJSDocNameReference, + updateJSDocNameReference, // lazily load factory members for JSDoc tags with similar structure get createJSDocTypeTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocTypeTag); }, get updateJSDocTypeTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocTypeTag); }, @@ -4259,6 +4263,36 @@ namespace ts { return node; } + // @api + function createJSDocSeeTag(tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string): JSDocSeeTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocSeeTag, tagName ?? createIdentifier("see"), comment); + node.name = name; + return node; + } + + // @api + function updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string): JSDocSeeTag { + return node.tagName !== tagName + || node.name !== name + || node.comment !== comment + ? update(createJSDocSeeTag(tagName, name, comment), node) + : node; + } + + // @api + function createJSDocNameReference(name: EntityName): JSDocNameReference { + const node = createBaseNode(SyntaxKind.JSDocNameReference); + node.name = name; + return node; + } + + // @api + function updateJSDocNameReference(node: JSDocNameReference, name: EntityName): JSDocNameReference { + return node.name !== name + ? update(createJSDocNameReference(name), node) + : node; + } + // @api function updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocImplementsTag["class"], comment: string | undefined): JSDocImplementsTag { return node.tagName !== tagName diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index 9de08306fa167..b7da2127f2aae 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -695,6 +695,10 @@ namespace ts { return node.kind === SyntaxKind.JSDocTypeExpression; } + export function isJSDocNameReference(node: Node): node is JSDocNameReference { + return node.kind === SyntaxKind.JSDocNameReference; + } + export function isJSDocAllType(node: Node): node is JSDocAllType { return node.kind === SyntaxKind.JSDocAllType; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ebcd9ce14994e..4e416c3f79b3b 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -477,6 +477,11 @@ namespace ts { visitNode(cbNode, (node).type); case SyntaxKind.JSDocComment: return visitNodes(cbNode, cbNodes, (node).tags); + case SyntaxKind.JSDocSeeTag: + return visitNode(cbNode, (node as JSDocSeeTag).tagName) || + visitNode(cbNode, (node as JSDocSeeTag).name); + case SyntaxKind.JSDocNameReference: + return visitNode(cbNode, (node as JSDocNameReference).name); case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocPropertyTag: return visitNode(cbNode, (node as JSDocTag).tagName) || @@ -7150,6 +7155,19 @@ namespace ts { return finishNode(result, pos); } + export function parseJSDocNameReference(): JSDocNameReference { + const pos = getNodePos(); + const hasBrace = parseOptional(SyntaxKind.OpenBraceToken); + const entityName = parseEntityName(/* allowReservedWords*/ false); + if (hasBrace) { + parseExpectedJSDoc(SyntaxKind.CloseBraceToken); + } + + const result = factory.createJSDocNameReference(entityName); + fixupParentReferences(result); + return finishNode(result, pos); + } + export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { initializeState("", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); @@ -7431,6 +7449,9 @@ namespace ts { case "callback": tag = parseCallbackTag(start, tagName, margin, indentText); break; + case "see": + tag = parseSeeTag(start, tagName, margin, indentText); + break; default: tag = parseUnknownTag(start, tagName, margin, indentText); break; @@ -7661,6 +7682,13 @@ namespace ts { return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments), start, end); } + function parseSeeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocSeeTag { + const nameExpression = parseJSDocNameReference(); + const end = getNodePos(); + const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, end, indent, indentText) : undefined; + return finishNode(factory.createJSDocSeeTag(tagName, nameExpression, comments), start, end); + } + function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag { const authorInfoWithEmail = tryParse(() => tryParseAuthorNameAndEmail()); if (!authorInfoWithEmail) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d17f444f165d2..206250a6f5461 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -357,6 +357,7 @@ namespace ts { // JSDoc nodes JSDocTypeExpression, + JSDocNameReference, // The * type JSDocAllType, // The ? type @@ -389,6 +390,7 @@ namespace ts { JSDocTypeTag, JSDocTemplateTag, JSDocTypedefTag, + JSDocSeeTag, JSDocPropertyTag, // Synthesized list @@ -3055,6 +3057,11 @@ namespace ts { readonly type: TypeNode; } + export interface JSDocNameReference extends Node { + readonly kind: SyntaxKind.JSDocNameReference; + readonly name: EntityName; + } + export interface JSDocType extends TypeNode { _jsDocTypeBrand: any; } @@ -3179,6 +3186,11 @@ namespace ts { readonly typeParameters: NodeArray; } + export interface JSDocSeeTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocSeeTag; + readonly name?: JSDocNameReference; + } + export interface JSDocReturnTag extends JSDocTag { readonly kind: SyntaxKind.JSDocReturnTag; readonly typeExpression?: JSDocTypeExpression; @@ -6965,6 +6977,8 @@ namespace ts { updateJSDocNamepathType(node: JSDocNamepathType, type: TypeNode): JSDocNamepathType; createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression; updateJSDocTypeExpression(node: JSDocTypeExpression, type: TypeNode): JSDocTypeExpression; + createJSDocNameReference(name: EntityName): JSDocNameReference; + updateJSDocNameReference(node: JSDocNameReference, name: EntityName): JSDocNameReference; createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; updateJSDocTypeLiteral(node: JSDocTypeLiteral, jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean | undefined): JSDocTypeLiteral; createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; @@ -6979,6 +6993,8 @@ namespace ts { updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | undefined): JSDocPropertyTag; createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag; updateJSDocTypeTag(node: JSDocTypeTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | undefined): JSDocTypeTag; + createJSDocSeeTag(tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string): JSDocSeeTag; + updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string): JSDocSeeTag; createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag; updateJSDocReturnTag(node: JSDocReturnTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | undefined): JSDocReturnTag; createJSDocThisTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocThisTag; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 5fca2d095cafb..7bfb55e8ce876 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -105,6 +105,9 @@ namespace ts { else if (isDeclarationName(node)) { return getMeaningFromDeclaration(node.parent); } + else if (isEntityName(node) && isJSDocNameReference(node.parent)) { + return SemanticMeaning.All; + } else if (isTypeReference(node)) { return SemanticMeaning.Type; } diff --git a/src/testRunner/unittests/jsDocParsing.ts b/src/testRunner/unittests/jsDocParsing.ts index ace9f0af99654..878408650678d 100644 --- a/src/testRunner/unittests/jsDocParsing.ts +++ b/src/testRunner/unittests/jsDocParsing.ts @@ -314,7 +314,6 @@ namespace ts { `/** * {@link first link} * Inside {@link link text} thing - * @see {@link second link text} and {@link Foo|a foo} as well. */`); parsesCorrectly("authorTag", `/** diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json index 0d3b49aafba95..1e0ef5dff87a0 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json @@ -1,32 +1,9 @@ { "kind": "JSDocComment", "pos": 0, - "end": 127, + "end": 63, "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "comment": "{@link first link}\nInside {@link link text} thing", - "tags": { - "0": { - "kind": "JSDocTag", - "pos": 63, - "end": 68, - "modifierFlagsCache": 0, - "transformFlags": 0, - "tagName": { - "kind": "Identifier", - "pos": 64, - "end": 67, - "modifierFlagsCache": 0, - "transformFlags": 0, - "escapedText": "see" - }, - "comment": "{@link second link text} and {@link Foo|a foo} as well." - }, - "length": 1, - "pos": 63, - "end": 68, - "hasTrailingComma": false, - "transformFlags": 0 - } + "comment": "{@link first link}\nInside {@link link text} thing" } \ No newline at end of file diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 389e66c9a336a..2474d0c6a0a54 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -403,44 +403,46 @@ declare namespace ts { UnparsedSource = 296, InputFiles = 297, JSDocTypeExpression = 298, - JSDocAllType = 299, - JSDocUnknownType = 300, - JSDocNullableType = 301, - JSDocNonNullableType = 302, - JSDocOptionalType = 303, - JSDocFunctionType = 304, - JSDocVariadicType = 305, - JSDocNamepathType = 306, - JSDocComment = 307, - JSDocTypeLiteral = 308, - JSDocSignature = 309, - JSDocTag = 310, - JSDocAugmentsTag = 311, - JSDocImplementsTag = 312, - JSDocAuthorTag = 313, - JSDocDeprecatedTag = 314, - JSDocClassTag = 315, - JSDocPublicTag = 316, - JSDocPrivateTag = 317, - JSDocProtectedTag = 318, - JSDocReadonlyTag = 319, - JSDocCallbackTag = 320, - JSDocEnumTag = 321, - JSDocParameterTag = 322, - JSDocReturnTag = 323, - JSDocThisTag = 324, - JSDocTypeTag = 325, - JSDocTemplateTag = 326, - JSDocTypedefTag = 327, - JSDocPropertyTag = 328, - SyntaxList = 329, - NotEmittedStatement = 330, - PartiallyEmittedExpression = 331, - CommaListExpression = 332, - MergeDeclarationMarker = 333, - EndOfDeclarationMarker = 334, - SyntheticReferenceExpression = 335, - Count = 336, + JSDocNameReference = 299, + JSDocAllType = 300, + JSDocUnknownType = 301, + JSDocNullableType = 302, + JSDocNonNullableType = 303, + JSDocOptionalType = 304, + JSDocFunctionType = 305, + JSDocVariadicType = 306, + JSDocNamepathType = 307, + JSDocComment = 308, + JSDocTypeLiteral = 309, + JSDocSignature = 310, + JSDocTag = 311, + JSDocAugmentsTag = 312, + JSDocImplementsTag = 313, + JSDocAuthorTag = 314, + JSDocDeprecatedTag = 315, + JSDocClassTag = 316, + JSDocPublicTag = 317, + JSDocPrivateTag = 318, + JSDocProtectedTag = 319, + JSDocReadonlyTag = 320, + JSDocCallbackTag = 321, + JSDocEnumTag = 322, + JSDocParameterTag = 323, + JSDocReturnTag = 324, + JSDocThisTag = 325, + JSDocTypeTag = 326, + JSDocTemplateTag = 327, + JSDocTypedefTag = 328, + JSDocSeeTag = 329, + JSDocPropertyTag = 330, + SyntaxList = 331, + NotEmittedStatement = 332, + PartiallyEmittedExpression = 333, + CommaListExpression = 334, + MergeDeclarationMarker = 335, + EndOfDeclarationMarker = 336, + SyntheticReferenceExpression = 337, + Count = 338, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -469,9 +471,9 @@ declare namespace ts { LastStatement = 245, FirstNode = 156, FirstJSDocNode = 298, - LastJSDocNode = 328, - FirstJSDocTagNode = 310, - LastJSDocTagNode = 328, + LastJSDocNode = 330, + FirstJSDocTagNode = 311, + LastJSDocTagNode = 330, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -1682,6 +1684,10 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocTypeExpression; readonly type: TypeNode; } + export interface JSDocNameReference extends Node { + readonly kind: SyntaxKind.JSDocNameReference; + readonly name: EntityName; + } export interface JSDocType extends TypeNode { _jsDocTypeBrand: any; } @@ -1780,6 +1786,10 @@ declare namespace ts { readonly constraint: JSDocTypeExpression | undefined; readonly typeParameters: NodeArray; } + export interface JSDocSeeTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocSeeTag; + readonly name?: JSDocNameReference; + } export interface JSDocReturnTag extends JSDocTag { readonly kind: SyntaxKind.JSDocReturnTag; readonly typeExpression?: JSDocTypeExpression; @@ -3399,6 +3409,8 @@ declare namespace ts { updateJSDocNamepathType(node: JSDocNamepathType, type: TypeNode): JSDocNamepathType; createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression; updateJSDocTypeExpression(node: JSDocTypeExpression, type: TypeNode): JSDocTypeExpression; + createJSDocNameReference(name: EntityName): JSDocNameReference; + updateJSDocNameReference(node: JSDocNameReference, name: EntityName): JSDocNameReference; createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; updateJSDocTypeLiteral(node: JSDocTypeLiteral, jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean | undefined): JSDocTypeLiteral; createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; @@ -3413,6 +3425,8 @@ declare namespace ts { updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | undefined): JSDocPropertyTag; createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag; updateJSDocTypeTag(node: JSDocTypeTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | undefined): JSDocTypeTag; + createJSDocSeeTag(tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string): JSDocSeeTag; + updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string): JSDocSeeTag; createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag; updateJSDocReturnTag(node: JSDocReturnTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | undefined): JSDocReturnTag; createJSDocThisTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocThisTag; @@ -4422,6 +4436,7 @@ declare namespace ts { function isBundle(node: Node): node is Bundle; function isUnparsedSource(node: Node): node is UnparsedSource; function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression; + function isJSDocNameReference(node: Node): node is JSDocNameReference; function isJSDocAllType(node: Node): node is JSDocAllType; function isJSDocUnknownType(node: Node): node is JSDocUnknownType; function isJSDocNullableType(node: Node): node is JSDocNullableType; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 7b1a38a102b7c..5ae9c048e4607 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -403,44 +403,46 @@ declare namespace ts { UnparsedSource = 296, InputFiles = 297, JSDocTypeExpression = 298, - JSDocAllType = 299, - JSDocUnknownType = 300, - JSDocNullableType = 301, - JSDocNonNullableType = 302, - JSDocOptionalType = 303, - JSDocFunctionType = 304, - JSDocVariadicType = 305, - JSDocNamepathType = 306, - JSDocComment = 307, - JSDocTypeLiteral = 308, - JSDocSignature = 309, - JSDocTag = 310, - JSDocAugmentsTag = 311, - JSDocImplementsTag = 312, - JSDocAuthorTag = 313, - JSDocDeprecatedTag = 314, - JSDocClassTag = 315, - JSDocPublicTag = 316, - JSDocPrivateTag = 317, - JSDocProtectedTag = 318, - JSDocReadonlyTag = 319, - JSDocCallbackTag = 320, - JSDocEnumTag = 321, - JSDocParameterTag = 322, - JSDocReturnTag = 323, - JSDocThisTag = 324, - JSDocTypeTag = 325, - JSDocTemplateTag = 326, - JSDocTypedefTag = 327, - JSDocPropertyTag = 328, - SyntaxList = 329, - NotEmittedStatement = 330, - PartiallyEmittedExpression = 331, - CommaListExpression = 332, - MergeDeclarationMarker = 333, - EndOfDeclarationMarker = 334, - SyntheticReferenceExpression = 335, - Count = 336, + JSDocNameReference = 299, + JSDocAllType = 300, + JSDocUnknownType = 301, + JSDocNullableType = 302, + JSDocNonNullableType = 303, + JSDocOptionalType = 304, + JSDocFunctionType = 305, + JSDocVariadicType = 306, + JSDocNamepathType = 307, + JSDocComment = 308, + JSDocTypeLiteral = 309, + JSDocSignature = 310, + JSDocTag = 311, + JSDocAugmentsTag = 312, + JSDocImplementsTag = 313, + JSDocAuthorTag = 314, + JSDocDeprecatedTag = 315, + JSDocClassTag = 316, + JSDocPublicTag = 317, + JSDocPrivateTag = 318, + JSDocProtectedTag = 319, + JSDocReadonlyTag = 320, + JSDocCallbackTag = 321, + JSDocEnumTag = 322, + JSDocParameterTag = 323, + JSDocReturnTag = 324, + JSDocThisTag = 325, + JSDocTypeTag = 326, + JSDocTemplateTag = 327, + JSDocTypedefTag = 328, + JSDocSeeTag = 329, + JSDocPropertyTag = 330, + SyntaxList = 331, + NotEmittedStatement = 332, + PartiallyEmittedExpression = 333, + CommaListExpression = 334, + MergeDeclarationMarker = 335, + EndOfDeclarationMarker = 336, + SyntheticReferenceExpression = 337, + Count = 338, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -469,9 +471,9 @@ declare namespace ts { LastStatement = 245, FirstNode = 156, FirstJSDocNode = 298, - LastJSDocNode = 328, - FirstJSDocTagNode = 310, - LastJSDocTagNode = 328, + LastJSDocNode = 330, + FirstJSDocTagNode = 311, + LastJSDocTagNode = 330, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -1682,6 +1684,10 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocTypeExpression; readonly type: TypeNode; } + export interface JSDocNameReference extends Node { + readonly kind: SyntaxKind.JSDocNameReference; + readonly name: EntityName; + } export interface JSDocType extends TypeNode { _jsDocTypeBrand: any; } @@ -1780,6 +1786,10 @@ declare namespace ts { readonly constraint: JSDocTypeExpression | undefined; readonly typeParameters: NodeArray; } + export interface JSDocSeeTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocSeeTag; + readonly name?: JSDocNameReference; + } export interface JSDocReturnTag extends JSDocTag { readonly kind: SyntaxKind.JSDocReturnTag; readonly typeExpression?: JSDocTypeExpression; @@ -3399,6 +3409,8 @@ declare namespace ts { updateJSDocNamepathType(node: JSDocNamepathType, type: TypeNode): JSDocNamepathType; createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression; updateJSDocTypeExpression(node: JSDocTypeExpression, type: TypeNode): JSDocTypeExpression; + createJSDocNameReference(name: EntityName): JSDocNameReference; + updateJSDocNameReference(node: JSDocNameReference, name: EntityName): JSDocNameReference; createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; updateJSDocTypeLiteral(node: JSDocTypeLiteral, jsDocPropertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean | undefined): JSDocTypeLiteral; createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; @@ -3413,6 +3425,8 @@ declare namespace ts { updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | undefined): JSDocPropertyTag; createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag; updateJSDocTypeTag(node: JSDocTypeTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | undefined): JSDocTypeTag; + createJSDocSeeTag(tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string): JSDocSeeTag; + updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, nameExpression: JSDocNameReference | undefined, comment?: string): JSDocSeeTag; createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag; updateJSDocReturnTag(node: JSDocReturnTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment: string | undefined): JSDocReturnTag; createJSDocThisTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocThisTag; @@ -4422,6 +4436,7 @@ declare namespace ts { function isBundle(node: Node): node is Bundle; function isUnparsedSource(node: Node): node is UnparsedSource; function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression; + function isJSDocNameReference(node: Node): node is JSDocNameReference; function isJSDocAllType(node: Node): node is JSDocAllType; function isJSDocUnknownType(node: Node): node is JSDocUnknownType; function isJSDocNullableType(node: Node): node is JSDocNullableType; diff --git a/tests/baselines/reference/seeTag1.js b/tests/baselines/reference/seeTag1.js new file mode 100644 index 0000000000000..f6b09bed1293f --- /dev/null +++ b/tests/baselines/reference/seeTag1.js @@ -0,0 +1,45 @@ +//// [seeTag1.ts] +interface Foo { + foo: string +} + +namespace NS { + export interface Bar { + baz: Foo + } +} + +/** @see {Foo} foooo*/ +const a = "" + +/** @see {NS.Bar} ns.bar*/ +const b = "" + +/** @see {b} b */ +const c = "" + + +//// [seeTag1.js] +/** @see {Foo} foooo*/ +var a = ""; +/** @see {NS.Bar} ns.bar*/ +var b = ""; +/** @see {b} b */ +var c = ""; + + +//// [seeTag1.d.ts] +interface Foo { + foo: string; +} +declare namespace NS { + interface Bar { + baz: Foo; + } +} +/** @see {Foo} foooo*/ +declare const a = ""; +/** @see {NS.Bar} ns.bar*/ +declare const b = ""; +/** @see {b} b */ +declare const c = ""; diff --git a/tests/baselines/reference/seeTag1.symbols b/tests/baselines/reference/seeTag1.symbols new file mode 100644 index 0000000000000..5fe78ac3486ae --- /dev/null +++ b/tests/baselines/reference/seeTag1.symbols @@ -0,0 +1,32 @@ +=== tests/cases/conformance/jsdoc/seeTag1.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(seeTag1.ts, 0, 0)) + + foo: string +>foo : Symbol(Foo.foo, Decl(seeTag1.ts, 0, 15)) +} + +namespace NS { +>NS : Symbol(NS, Decl(seeTag1.ts, 2, 1)) + + export interface Bar { +>Bar : Symbol(Bar, Decl(seeTag1.ts, 4, 14)) + + baz: Foo +>baz : Symbol(Bar.baz, Decl(seeTag1.ts, 5, 26)) +>Foo : Symbol(Foo, Decl(seeTag1.ts, 0, 0)) + } +} + +/** @see {Foo} foooo*/ +const a = "" +>a : Symbol(a, Decl(seeTag1.ts, 11, 5)) + +/** @see {NS.Bar} ns.bar*/ +const b = "" +>b : Symbol(b, Decl(seeTag1.ts, 14, 5)) + +/** @see {b} b */ +const c = "" +>c : Symbol(c, Decl(seeTag1.ts, 17, 5)) + diff --git a/tests/baselines/reference/seeTag1.types b/tests/baselines/reference/seeTag1.types new file mode 100644 index 0000000000000..02ef9d6dba343 --- /dev/null +++ b/tests/baselines/reference/seeTag1.types @@ -0,0 +1,28 @@ +=== tests/cases/conformance/jsdoc/seeTag1.ts === +interface Foo { + foo: string +>foo : string +} + +namespace NS { + export interface Bar { + baz: Foo +>baz : Foo + } +} + +/** @see {Foo} foooo*/ +const a = "" +>a : "" +>"" : "" + +/** @see {NS.Bar} ns.bar*/ +const b = "" +>b : "" +>"" : "" + +/** @see {b} b */ +const c = "" +>c : "" +>"" : "" + diff --git a/tests/baselines/reference/seeTag2.js b/tests/baselines/reference/seeTag2.js new file mode 100644 index 0000000000000..936183121044d --- /dev/null +++ b/tests/baselines/reference/seeTag2.js @@ -0,0 +1,55 @@ +//// [seeTag2.ts] +/** @see {} empty*/ +const a = "" + +/** @see {aaaaaa} unknown name*/ +const b = "" + +/** @see {?????} invalid */ +const c = "" + +/** @see c without brace */ +const d = "" + +/** @see ?????? wowwwwww*/ +const e = "" + +/** @see {}*/ +const f = "" + +/** @see */ +const g = "" + + +//// [seeTag2.js] +/** @see {} empty*/ +var a = ""; +/** @see {aaaaaa} unknown name*/ +var b = ""; +/** @see {?????} invalid */ +var c = ""; +/** @see c without brace */ +var d = ""; +/** @see ?????? wowwwwww*/ +var e = ""; +/** @see {}*/ +var f = ""; +/** @see */ +var g = ""; + + +//// [seeTag2.d.ts] +/** @see {} empty*/ +declare const a = ""; +/** @see {aaaaaa} unknown name*/ +declare const b = ""; +/** @see {?????} invalid */ +declare const c = ""; +/** @see c without brace */ +declare const d = ""; +/** @see ?????? wowwwwww*/ +declare const e = ""; +/** @see {}*/ +declare const f = ""; +/** @see */ +declare const g = ""; diff --git a/tests/baselines/reference/seeTag2.symbols b/tests/baselines/reference/seeTag2.symbols new file mode 100644 index 0000000000000..7c213a782bfc6 --- /dev/null +++ b/tests/baselines/reference/seeTag2.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/jsdoc/seeTag2.ts === +/** @see {} empty*/ +const a = "" +>a : Symbol(a, Decl(seeTag2.ts, 1, 5)) + +/** @see {aaaaaa} unknown name*/ +const b = "" +>b : Symbol(b, Decl(seeTag2.ts, 4, 5)) + +/** @see {?????} invalid */ +const c = "" +>c : Symbol(c, Decl(seeTag2.ts, 7, 5)) + +/** @see c without brace */ +const d = "" +>d : Symbol(d, Decl(seeTag2.ts, 10, 5)) + +/** @see ?????? wowwwwww*/ +const e = "" +>e : Symbol(e, Decl(seeTag2.ts, 13, 5)) + +/** @see {}*/ +const f = "" +>f : Symbol(f, Decl(seeTag2.ts, 16, 5)) + +/** @see */ +const g = "" +>g : Symbol(g, Decl(seeTag2.ts, 19, 5)) + diff --git a/tests/baselines/reference/seeTag2.types b/tests/baselines/reference/seeTag2.types new file mode 100644 index 0000000000000..73282eac0edbd --- /dev/null +++ b/tests/baselines/reference/seeTag2.types @@ -0,0 +1,36 @@ +=== tests/cases/conformance/jsdoc/seeTag2.ts === +/** @see {} empty*/ +const a = "" +>a : "" +>"" : "" + +/** @see {aaaaaa} unknown name*/ +const b = "" +>b : "" +>"" : "" + +/** @see {?????} invalid */ +const c = "" +>c : "" +>"" : "" + +/** @see c without brace */ +const d = "" +>d : "" +>"" : "" + +/** @see ?????? wowwwwww*/ +const e = "" +>e : "" +>"" : "" + +/** @see {}*/ +const f = "" +>f : "" +>"" : "" + +/** @see */ +const g = "" +>g : "" +>"" : "" + diff --git a/tests/cases/conformance/jsdoc/seeTag1.ts b/tests/cases/conformance/jsdoc/seeTag1.ts new file mode 100644 index 0000000000000..9cfadaf32ae00 --- /dev/null +++ b/tests/cases/conformance/jsdoc/seeTag1.ts @@ -0,0 +1,20 @@ +// @declaration: true + +interface Foo { + foo: string +} + +namespace NS { + export interface Bar { + baz: Foo + } +} + +/** @see {Foo} foooo*/ +const a = "" + +/** @see {NS.Bar} ns.bar*/ +const b = "" + +/** @see {b} b */ +const c = "" diff --git a/tests/cases/conformance/jsdoc/seeTag2.ts b/tests/cases/conformance/jsdoc/seeTag2.ts new file mode 100644 index 0000000000000..d6b646b57a696 --- /dev/null +++ b/tests/cases/conformance/jsdoc/seeTag2.ts @@ -0,0 +1,22 @@ +// @declaration: true + +/** @see {} empty*/ +const a = "" + +/** @see {aaaaaa} unknown name*/ +const b = "" + +/** @see {?????} invalid */ +const c = "" + +/** @see c without brace */ +const d = "" + +/** @see ?????? wowwwwww*/ +const e = "" + +/** @see {}*/ +const f = "" + +/** @see */ +const g = "" diff --git a/tests/cases/fourslash/codeFixInferFromUsageExistingJSDoc.ts b/tests/cases/fourslash/codeFixInferFromUsageExistingJSDoc.ts index e2490c5793072..c1f12bd5af7c5 100644 --- a/tests/cases/fourslash/codeFixInferFromUsageExistingJSDoc.ts +++ b/tests/cases/fourslash/codeFixInferFromUsageExistingJSDoc.ts @@ -73,7 +73,7 @@ var o = { * 2 * 3 * @returns {number} First one - * @see also + * @see {also} * @return Second one * @extends {C} nothing really * @class diff --git a/tests/cases/fourslash/jsDocSee1.ts b/tests/cases/fourslash/jsDocSee1.ts new file mode 100644 index 0000000000000..1f9f83be47c7b --- /dev/null +++ b/tests/cases/fourslash/jsDocSee1.ts @@ -0,0 +1,41 @@ +/// + +//// interface [|/*def1*/Foo|] { +//// foo: string +//// } + +//// namespace NS { +//// export interface [|/*def2*/Bar|] { +//// baz: Foo +//// } +//// } + +//// /** @see {/*use1*/[|Foo|]} foooo*/ +//// const a = "" + +//// /** @see {NS./*use2*/[|Bar|]} ns.bar*/ +//// const b = "" + +//// /** @see /*use3*/[|Foo|] f1*/ +//// const c = "" + +//// /** @see NS./*use4*/[|Bar|] ns.bar*/ +//// const [|/*def3*/d|] = "" + +//// /** @see /*use5*/[|d|] dd*/ +//// const e = "" + +goTo.marker("use1"); +verify.goToDefinitionIs("def1"); + +goTo.marker("use2"); +verify.goToDefinitionIs("def2"); + +goTo.marker("use3"); +verify.goToDefinitionIs("def1"); + +goTo.marker("use4"); +verify.goToDefinitionIs("def2"); + +goTo.marker("use5"); +verify.goToDefinitionIs("def3"); \ No newline at end of file diff --git a/tests/cases/fourslash/jsDocSee2.ts b/tests/cases/fourslash/jsDocSee2.ts new file mode 100644 index 0000000000000..efbff8e3387a6 --- /dev/null +++ b/tests/cases/fourslash/jsDocSee2.ts @@ -0,0 +1,43 @@ +/// + +//// /** @see {/*use1*/[|foooo|]} unknown reference*/ +//// const a = "" + +//// /** @see {/*use2*/[|@bar|]} invalid tag*/ +//// const b = "" + +//// /** @see /*use3*/[|foooo|] unknown reference without brace*/ +//// const c = "" + +//// /** @see /*use4*/[|@bar|] invalid tag without brace*/ +//// const [|/*def1*/d|] = "" + +//// /** @see {/*use5*/[|d@fff|]} partial reference */ +//// const e = "" + +//// /** @see /*use6*/[|@@@@@@|] total invalid tag*/ +//// const f = "" + +//// /** @see d@{/*use7*/[|fff|]} partial reference */ +//// const g = "" + +goTo.marker("use1"); +verify.goToDefinition([]); + +goTo.marker("use2"); +verify.goToDefinition([]); + +goTo.marker("use3"); +verify.goToDefinition([]); + +goTo.marker("use4"); +verify.goToDefinition([]); + +goTo.marker("use5"); +verify.goToDefinitionIs("def1"); + +goTo.marker("use6"); +verify.goToDefinition([]); + +goTo.marker("use7"); +verify.goToDefinition([]); \ No newline at end of file diff --git a/tests/cases/fourslash/jsDocSee3.ts b/tests/cases/fourslash/jsDocSee3.ts new file mode 100644 index 0000000000000..1438a691f361a --- /dev/null +++ b/tests/cases/fourslash/jsDocSee3.ts @@ -0,0 +1,12 @@ +/// + +//// function foo ([|/*def1*/a|]: string) { +//// /** +//// * @see {/*use1*/[|a|]} +//// */ +//// function bar ([|/*def2*/a|]: string) { +//// } +//// } + +goTo.marker("use1"); +verify.goToDefinitionIs(["def2"]); diff --git a/tests/cases/fourslash/jsDocSee4.ts b/tests/cases/fourslash/jsDocSee4.ts new file mode 100644 index 0000000000000..344060464a467 --- /dev/null +++ b/tests/cases/fourslash/jsDocSee4.ts @@ -0,0 +1,27 @@ +/// + +//// class [|/*def1*/A|] { +//// foo () { } +//// } +//// declare const [|/*def2*/a|]: A; +//// /** +//// * @see {/*use1*/[|A|]#foo} +//// */ +//// const t1 = 1 +//// /** +//// * @see {/*use2*/[|a|].foo()} +//// */ +//// const t2 = 1 +//// /** +//// * @see {@link /*use3*/[|a|].foo()} +//// */ +//// const t3 = 1 + +goTo.marker("use1"); +verify.goToDefinitionIs(["def1"]); + +goTo.marker("use2"); +verify.goToDefinitionIs(["def2"]); + +goTo.marker("use3"); +verify.goToDefinitionIs([]); \ No newline at end of file diff --git a/tests/cases/fourslash/jsDocSee_rename1.ts b/tests/cases/fourslash/jsDocSee_rename1.ts new file mode 100644 index 0000000000000..971b6ddc4f85d --- /dev/null +++ b/tests/cases/fourslash/jsDocSee_rename1.ts @@ -0,0 +1,12 @@ +/// + +//// [|interface [|{| "contextRangeIndex": 0 |}A|] {}|] +//// /** +//// * @see {[|A|]} +//// */ +//// declare const a: [|A|] + + +const [rDef, ...ranges] = test.ranges(); +verify.rangesAreRenameLocations({ findInComments: true, ranges }); +