Skip to content

Commit

Permalink
Add see tag support (#39760)
Browse files Browse the repository at this point in the history
* Add see tag parser

* add baseline

* fix symbol resolve

* add more case

* fix unittests

* improve tests and parser

* accept baseline

* Adopt package-lock.json and npm ci

* Add a workflow to update package-lock.json daily

* Git ignore package-lock.json and forcibly update in workflow

* Update bot email address

* Delete extra npm update

* Update package-lock.json

* Add compactDisplay and signDisplay to NumberFormatOptions (#40039)

* Fix typo in (Readonly)Set.keys comment (fixes #40164) (#40176)

* fix(26325): use a unique name for reserved words in 'constructor like' function name (#39684)

* fix(25770): add diagnostic message for the possible mapped type used as an index (#39973)

* fix(31046): add new diagnostic message for incompatible constructor signature (#40073)

* Update package-lock.json

* Update package-lock.json

* Add rename support

* Accpet baseline

* wip

* fix anders

* Revert "fix anders"

This reverts commit b3178d4.

* Fix call hierarchy item serialization and server tests (#40348)

* Avoid error

* accept baseline

* Add more tests

* Add signature name resolve

Co-authored-by: Andrew Casey <andrew.casey@microsoft.com>
Co-authored-by: TypeScript Bot <typescriptbot@microsoft.com>
Co-authored-by: Neil Kistner <neil.kistner@gmail.com>
Co-authored-by: cherryblossom000 <31467609+cherryblossom000@users.noreply.github.com>
Co-authored-by: Alexander T <alexander.tarasyuk@outlook.com>
Co-authored-by: Erich Gamma <egamma@microsoft.com>
Co-authored-by: Andrew Branch <andrewbranch@users.noreply.github.com>
  • Loading branch information
8 people committed Sep 9, 2020
1 parent 4584d6d commit ee5f51b
Show file tree
Hide file tree
Showing 25 changed files with 634 additions and 109 deletions.
15 changes: 15 additions & 0 deletions src/compiler/checker.ts
Expand Up @@ -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<T>(node: Node, callback: (node: Node) => T | undefined): T | undefined {
let result: T | undefined;

Expand Down Expand Up @@ -36609,6 +36620,10 @@ namespace ts {
const meaning = name.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
return resolveEntityName(<EntityName>name, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true);
}
else if (isJSDocEntryNameReference(name)) {
const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value;
return resolveEntityName(<EntityName>name, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name));
}

if (name.parent.kind === SyntaxKind.TypePredicate) {
return resolveEntityName(<Identifier>name, /*meaning*/ SymbolFlags.FunctionScopedVariable);
Expand Down
17 changes: 17 additions & 0 deletions src/compiler/emitter.ts
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down
34 changes: 34 additions & 0 deletions src/compiler/factory/nodeFactory.ts
Expand Up @@ -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<JSDocTypeTag>(SyntaxKind.JSDocTypeTag); },
get updateJSDocTypeTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocTypeTag>(SyntaxKind.JSDocTypeTag); },
Expand Down Expand Up @@ -4259,6 +4263,36 @@ namespace ts {
return node;
}

// @api
function createJSDocSeeTag(tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string): JSDocSeeTag {
const node = createBaseJSDocTag<JSDocSeeTag>(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<JSDocNameReference>(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
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/factory/nodeTests.ts
Expand Up @@ -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;
}
Expand Down
28 changes: 28 additions & 0 deletions src/compiler/parser.ts
Expand Up @@ -477,6 +477,11 @@ namespace ts {
visitNode(cbNode, (<JSDocFunctionType>node).type);
case SyntaxKind.JSDocComment:
return visitNodes(cbNode, cbNodes, (<JSDoc>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) ||
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
16 changes: 16 additions & 0 deletions src/compiler/types.ts
Expand Up @@ -357,6 +357,7 @@ namespace ts {

// JSDoc nodes
JSDocTypeExpression,
JSDocNameReference,
// The * type
JSDocAllType,
// The ? type
Expand Down Expand Up @@ -389,6 +390,7 @@ namespace ts {
JSDocTypeTag,
JSDocTemplateTag,
JSDocTypedefTag,
JSDocSeeTag,
JSDocPropertyTag,

// Synthesized list
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -3179,6 +3186,11 @@ namespace ts {
readonly typeParameters: NodeArray<TypeParameterDeclaration>;
}

export interface JSDocSeeTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocSeeTag;
readonly name?: JSDocNameReference;
}

export interface JSDocReturnTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocReturnTag;
readonly typeExpression?: JSDocTypeExpression;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/services/utilities.ts
Expand Up @@ -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;
}
Expand Down
1 change: 0 additions & 1 deletion src/testRunner/unittests/jsDocParsing.ts
Expand Up @@ -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",
`/**
Expand Down
@@ -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"
}

0 comments on commit ee5f51b

Please sign in to comment.