Improve @template lookup and resilience (#42851)

* Improve @template lookup and resilience

1. @template parsing may produce a template tag with a type parameter
whose name is the missing identifier. These tags should be skipped
in the checker because they receive an error in the parser.
2. The fix in #37819 was incorrect; there's no such thing as a type
parameter declared on a variable declaration. Instead, there needs to be a type
parameter declared on a jsdoc comment, because that's the scope for tags
like `@return` and `@typedef`.

There are 3 tests because either fix (1) and (2) fix the first test's
failure, but both are required to fix the last two tests' failures.

* remove containsParseError call
This commit is contained in:
Nathan Shively-Sanders
2021-02-17 17:21:17 -08:00
committed by GitHub
parent c3d7a56e90
commit 3d7ec8aab2
13 changed files with 269 additions and 5 deletions
+8 -5
View File
@@ -9185,7 +9185,6 @@ namespace ts {
return undefined;
}
switch (node.kind) {
case SyntaxKind.VariableStatement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
@@ -9205,7 +9204,7 @@ namespace ts {
case SyntaxKind.JSDocEnumTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.MappedType:
case SyntaxKind.ConditionalType:
case SyntaxKind.ConditionalType: {
const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
if (node.kind === SyntaxKind.MappedType) {
return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((<MappedTypeNode>node).typeParameter)));
@@ -9213,20 +9212,24 @@ namespace ts {
else if (node.kind === SyntaxKind.ConditionalType) {
return concatenate(outerTypeParameters, getInferTypeParameters(<ConditionalTypeNode>node));
}
else if (node.kind === SyntaxKind.VariableStatement && !isInJSFile(node)) {
break;
}
const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(<DeclarationWithTypeParameters>node));
const thisType = includeThisTypes &&
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType;
return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters;
}
case SyntaxKind.JSDocParameterTag:
const paramSymbol = getParameterSymbolFromJSDoc(node as JSDocParameterTag);
if (paramSymbol) {
node = paramSymbol.valueDeclaration;
}
break;
case SyntaxKind.JSDocComment: {
const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
return (node as JSDoc).tags
? appendTypeParameters(outerTypeParameters, flatMap((node as JSDoc).tags, t => isJSDocTemplateTag(t) ? t.typeParameters : undefined))
: outerTypeParameters;
}
}
}
}