Skip to content

Commit 40ae422

Browse files
committed
Better JSDoc generic errors and faster isInJSDoc
1 parent f1145c3 commit 40ae422

File tree

4 files changed

+14
-8
lines changed

4 files changed

+14
-8
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18454,8 +18454,9 @@ namespace ts {
1845418454

1845518455
function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) {
1845618456
checkGrammarTypeArguments(node, node.typeArguments);
18457-
if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDot && !isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) {
18458-
grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
18457+
if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJavaScriptFile(node) && !isInJSDoc(node)) {
18458+
grammarErrorAtPos(getSourceFileOfNode(node), node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
18459+
1845918460
}
1846018461
const type = getTypeFromTypeReference(node);
1846118462
if (type !== unknownType) {
@@ -22046,7 +22047,7 @@ namespace ts {
2204622047
case SyntaxKind.JSDocNullableType:
2204722048
case SyntaxKind.JSDocAllType:
2204822049
case SyntaxKind.JSDocUnknownType:
22049-
if (!isInJavaScriptFile(node) && !findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression)) {
22050+
if (!isInJavaScriptFile(node) && !isInJSDoc(node)) {
2205022051
grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
2205122052
}
2205222053
return;

src/compiler/parser.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,10 +1925,11 @@ namespace ts {
19251925
// The allowReservedWords parameter controls whether reserved words are permitted after the first dot
19261926
function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName {
19271927
let entity: EntityName = allowReservedWords ? parseIdentifierName() : parseIdentifier(diagnosticMessage);
1928+
let dotPos = scanner.getStartPos();
19281929
while (parseOptional(SyntaxKind.DotToken)) {
19291930
if (token() === SyntaxKind.LessThanToken) {
1930-
// the entity is part of a JSDoc-style generic, so record this for later in case it's an error
1931-
entity.jsdocDot = true;
1931+
// the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting
1932+
entity.jsdocDotPos = dotPos;
19321933
break;
19331934
}
19341935
const node: QualifiedName = <QualifiedName>createNode(SyntaxKind.QualifiedName, entity.pos);

src/compiler/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ namespace ts {
576576
/*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name.
577577
isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace
578578
/*@internal*/ typeArguments?: NodeArray<TypeNode>; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics.
579-
/*@internal*/ jsdocDot?: boolean; // Identifier occurs in JSDoc-style generic: Id.<T>
579+
/*@internal*/ jsdocDotPos?: number; // Identifier occurs in JSDoc-style generic: Id.<T>
580580
}
581581

582582
// Transient identifier node (marked by id === -1)
@@ -596,7 +596,7 @@ namespace ts {
596596
kind: SyntaxKind.QualifiedName;
597597
left: EntityName;
598598
right: Identifier;
599-
/*@internal*/ jsdocDot?: boolean; // Identifier occurs in JSDoc-style generic: Id1.Id2.<T>
599+
/*@internal*/ jsdocDotPos?: number; // QualifiedName occurs in JSDoc-style generic: Id1.Id2.<T>
600600
}
601601

602602
export type EntityName = Identifier | QualifiedName;

src/compiler/utilities.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,10 @@ namespace ts {
12921292
return node && !!(node.flags & NodeFlags.JavaScriptFile);
12931293
}
12941294

1295+
export function isInJSDoc(node: Node): boolean {
1296+
return node && !!(node.flags & NodeFlags.JSDoc);
1297+
}
1298+
12951299
/**
12961300
* Returns true if the node is a CallExpression to the identifier 'require' with
12971301
* exactly one argument (of the form 'require("name")').
@@ -3299,7 +3303,7 @@ namespace ts {
32993303
}
33003304

33013305
export function isJSDocTypeReference(node: TypeReferenceType): node is TypeReferenceNode {
3302-
return node.kind === SyntaxKind.TypeReference && !!findAncestor(node, n => n.kind === SyntaxKind.JSDocTypeExpression);
3306+
return node.flags & NodeFlags.JSDoc && node.kind === SyntaxKind.TypeReference;
33033307
}
33043308

33053309
/**

0 commit comments

Comments
 (0)