@@ -4882,7 +4882,16 @@ namespace ts {
48824882 }
48834883
48844884 function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments {
4885- return getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>type.symbol.valueDeclaration);
4885+ const decl = <ClassLikeDeclaration>type.symbol.valueDeclaration;
4886+ if (isInJavaScriptFile(decl)) {
4887+ // Prefer an @augments tag because it may have type parameters.
4888+ const tag = getJSDocAugmentsTag(decl);
4889+ if (tag) {
4890+ return tag.class;
4891+ }
4892+ }
4893+
4894+ return getClassExtendsHeritageClauseElement(decl);
48864895 }
48874896
48884897 function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray<TypeNode>, location: Node): Signature[] {
@@ -4986,15 +4995,6 @@ namespace ts {
49864995 baseType = getReturnTypeOfSignature(constructors[0]);
49874996 }
49884997
4989- // In a JS file, you can use the @augments jsdoc tag to specify a base type with type parameters
4990- const valueDecl = type.symbol.valueDeclaration;
4991- if (valueDecl && isInJavaScriptFile(valueDecl)) {
4992- const augTag = getJSDocAugmentsTag(type.symbol.valueDeclaration);
4993- if (augTag && augTag.typeExpression && augTag.typeExpression.type) {
4994- baseType = getTypeFromTypeNode(augTag.typeExpression.type);
4995- }
4996- }
4997-
49984998 if (baseType === unknownType) {
49994999 return;
50005000 }
@@ -5003,7 +5003,7 @@ namespace ts {
50035003 return;
50045004 }
50055005 if (type === baseType || hasBaseType(baseType, type)) {
5006- error(valueDecl , Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
5006+ error(type.symbol.valueDeclaration , Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
50075007 typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
50085008 return;
50095009 }
@@ -19789,6 +19789,38 @@ namespace ts {
1978919789 }
1979019790 }
1979119791
19792+ function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void {
19793+ const cls = getJSDocHost(node);
19794+ if (!isClassDeclaration(cls) && !isClassExpression(cls)) {
19795+ error(cls, Diagnostics.JSDoc_augments_is_not_attached_to_a_class_declaration);
19796+ return;
19797+ }
19798+
19799+ const name = getIdentifierFromEntityNameExpression(node.class.expression);
19800+ const extend = getClassExtendsHeritageClauseElement(cls);
19801+ if (extend) {
19802+ const className = getIdentifierFromEntityNameExpression(extend.expression);
19803+ if (className && name.escapedText !== className.escapedText) {
19804+ error(name, Diagnostics.JSDoc_augments_0_does_not_match_the_extends_1_clause,
19805+ unescapeLeadingUnderscores(name.escapedText),
19806+ unescapeLeadingUnderscores(className.escapedText));
19807+ }
19808+ }
19809+ }
19810+
19811+ function getIdentifierFromEntityNameExpression(node: Identifier | PropertyAccessExpression): Identifier;
19812+ function getIdentifierFromEntityNameExpression(node: Expression): Identifier | undefined;
19813+ function getIdentifierFromEntityNameExpression(node: Expression): Identifier | undefined {
19814+ switch (node.kind) {
19815+ case SyntaxKind.Identifier:
19816+ return node as Identifier;
19817+ case SyntaxKind.PropertyAccessExpression:
19818+ return (node as PropertyAccessExpression).name;
19819+ default:
19820+ return undefined;
19821+ }
19822+ }
19823+
1979219824 function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration): void {
1979319825 checkDecorators(node);
1979419826 checkSignatureDeclaration(node);
@@ -22483,6 +22515,8 @@ namespace ts {
2248322515 case SyntaxKind.ParenthesizedType:
2248422516 case SyntaxKind.TypeOperator:
2248522517 return checkSourceElement((<ParenthesizedTypeNode | TypeOperatorNode>node).type);
22518+ case SyntaxKind.JSDocAugmentsTag:
22519+ return checkJSDocAugmentsTag(node as JSDocAugmentsTag);
2248622520 case SyntaxKind.JSDocTypedefTag:
2248722521 return checkJSDocTypedefTag(node as JSDocTypedefTag);
2248822522 case SyntaxKind.JSDocParameterTag:
0 commit comments