mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
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:
parent
c3d7a56e90
commit
3d7ec8aab2
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
error TS5055: Cannot write file 'tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js' because it would overwrite input file.
|
||||
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(1,14): error TS2304: Cannot find name 'T'.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(4,17): error TS2304: Cannot find name 'T'.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(4,19): error TS1069: Unexpected token. A type parameter name was expected without curly braces.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(7,35): error TS2339: Property 'foo' does not exist on type 'Bar'.
|
||||
|
||||
|
||||
!!! error TS5055: Cannot write file 'tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js' because it would overwrite input file.
|
||||
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
==== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js (4 errors) ====
|
||||
/** @return {T} */
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'T'.
|
||||
const dedupingMixin = function(mixin) {};
|
||||
|
||||
/** @template {T} */
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'T'.
|
||||
~
|
||||
!!! error TS1069: Unexpected token. A type parameter name was expected without curly braces.
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
class Bar {
|
||||
static bar() { this.prototype.foo(); }
|
||||
~~~
|
||||
!!! error TS2339: Property 'foo' does not exist on type 'Bar'.
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
23
tests/baselines/reference/jsdocOuterTypeParameters1.symbols
Normal file
23
tests/baselines/reference/jsdocOuterTypeParameters1.symbols
Normal file
@ -0,0 +1,23 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js ===
|
||||
/** @return {T} */
|
||||
const dedupingMixin = function(mixin) {};
|
||||
>dedupingMixin : Symbol(dedupingMixin, Decl(jsdocOuterTypeParameters1.js, 1, 5))
|
||||
>mixin : Symbol(mixin, Decl(jsdocOuterTypeParameters1.js, 1, 31))
|
||||
|
||||
/** @template {T} */
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
>PropertyAccessors : Symbol(PropertyAccessors, Decl(jsdocOuterTypeParameters1.js, 4, 5))
|
||||
>dedupingMixin : Symbol(dedupingMixin, Decl(jsdocOuterTypeParameters1.js, 1, 5))
|
||||
|
||||
class Bar {
|
||||
>Bar : Symbol(Bar, Decl(jsdocOuterTypeParameters1.js, 4, 47))
|
||||
|
||||
static bar() { this.prototype.foo(); }
|
||||
>bar : Symbol(Bar.bar, Decl(jsdocOuterTypeParameters1.js, 5, 13))
|
||||
>this.prototype : Symbol(Bar.prototype)
|
||||
>this : Symbol(Bar, Decl(jsdocOuterTypeParameters1.js, 4, 47))
|
||||
>prototype : Symbol(Bar.prototype)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
29
tests/baselines/reference/jsdocOuterTypeParameters1.types
Normal file
29
tests/baselines/reference/jsdocOuterTypeParameters1.types
Normal file
@ -0,0 +1,29 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js ===
|
||||
/** @return {T} */
|
||||
const dedupingMixin = function(mixin) {};
|
||||
>dedupingMixin : (mixin: any) => any
|
||||
>function(mixin) {} : (mixin: any) => any
|
||||
>mixin : any
|
||||
|
||||
/** @template {T} */
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
>PropertyAccessors : any
|
||||
>dedupingMixin(() => { class Bar { static bar() { this.prototype.foo(); } }}) : any
|
||||
>dedupingMixin : (mixin: any) => any
|
||||
>() => { class Bar { static bar() { this.prototype.foo(); } }} : () => void
|
||||
|
||||
class Bar {
|
||||
>Bar : Bar
|
||||
|
||||
static bar() { this.prototype.foo(); }
|
||||
>bar : () => void
|
||||
>this.prototype.foo() : any
|
||||
>this.prototype.foo : any
|
||||
>this.prototype : Bar
|
||||
>this : typeof Bar
|
||||
>prototype : Bar
|
||||
>foo : any
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
error TS5055: Cannot write file 'tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js' because it would overwrite input file.
|
||||
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(1,14): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(7,35): error TS2339: Property 'foo' does not exist on type 'Bar'.
|
||||
|
||||
|
||||
!!! error TS5055: Cannot write file 'tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js' because it would overwrite input file.
|
||||
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
==== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js (2 errors) ====
|
||||
/** @return {T} */
|
||||
~
|
||||
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
|
||||
const dedupingMixin = function(mixin) {};
|
||||
|
||||
/** @template T */
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
class Bar {
|
||||
static bar() { this.prototype.foo(); }
|
||||
~~~
|
||||
!!! error TS2339: Property 'foo' does not exist on type 'Bar'.
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
23
tests/baselines/reference/jsdocOuterTypeParameters2.symbols
Normal file
23
tests/baselines/reference/jsdocOuterTypeParameters2.symbols
Normal file
@ -0,0 +1,23 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js ===
|
||||
/** @return {T} */
|
||||
const dedupingMixin = function(mixin) {};
|
||||
>dedupingMixin : Symbol(dedupingMixin, Decl(jsdocOuterTypeParameters1.js, 1, 5))
|
||||
>mixin : Symbol(mixin, Decl(jsdocOuterTypeParameters1.js, 1, 31))
|
||||
|
||||
/** @template T */
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
>PropertyAccessors : Symbol(PropertyAccessors, Decl(jsdocOuterTypeParameters1.js, 4, 5))
|
||||
>dedupingMixin : Symbol(dedupingMixin, Decl(jsdocOuterTypeParameters1.js, 1, 5))
|
||||
|
||||
class Bar {
|
||||
>Bar : Symbol(Bar, Decl(jsdocOuterTypeParameters1.js, 4, 47))
|
||||
|
||||
static bar() { this.prototype.foo(); }
|
||||
>bar : Symbol(Bar.bar, Decl(jsdocOuterTypeParameters1.js, 5, 13))
|
||||
>this.prototype : Symbol(Bar.prototype)
|
||||
>this : Symbol(Bar, Decl(jsdocOuterTypeParameters1.js, 4, 47))
|
||||
>prototype : Symbol(Bar.prototype)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
29
tests/baselines/reference/jsdocOuterTypeParameters2.types
Normal file
29
tests/baselines/reference/jsdocOuterTypeParameters2.types
Normal file
@ -0,0 +1,29 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js ===
|
||||
/** @return {T} */
|
||||
const dedupingMixin = function(mixin) {};
|
||||
>dedupingMixin : (mixin: any) => T
|
||||
>function(mixin) {} : (mixin: any) => T
|
||||
>mixin : any
|
||||
|
||||
/** @template T */
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
>PropertyAccessors : T
|
||||
>dedupingMixin(() => { class Bar { static bar() { this.prototype.foo(); } }}) : T
|
||||
>dedupingMixin : (mixin: any) => T
|
||||
>() => { class Bar { static bar() { this.prototype.foo(); } }} : () => void
|
||||
|
||||
class Bar {
|
||||
>Bar : Bar
|
||||
|
||||
static bar() { this.prototype.foo(); }
|
||||
>bar : () => void
|
||||
>this.prototype.foo() : any
|
||||
>this.prototype.foo : any
|
||||
>this.prototype : Bar
|
||||
>this : typeof Bar
|
||||
>prototype : Bar
|
||||
>foo : any
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
error TS5055: Cannot write file 'tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js' because it would overwrite input file.
|
||||
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js(1,16): error TS2304: Cannot find name 'T'.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js(1,18): error TS1069: Unexpected token. A type parameter name was expected without curly braces.
|
||||
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js(5,43): error TS2339: Property 'foo' does not exist on type 'Bar'.
|
||||
|
||||
|
||||
!!! error TS5055: Cannot write file 'tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js' because it would overwrite input file.
|
||||
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
==== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js (3 errors) ====
|
||||
/** @template {T} */
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'T'.
|
||||
~
|
||||
!!! error TS1069: Unexpected token. A type parameter name was expected without curly braces.
|
||||
class Baz {
|
||||
m() {
|
||||
class Bar {
|
||||
static bar() { this.prototype.foo(); }
|
||||
~~~
|
||||
!!! error TS2339: Property 'foo' does not exist on type 'Bar'.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
tests/baselines/reference/jsdocOuterTypeParameters3.symbols
Normal file
20
tests/baselines/reference/jsdocOuterTypeParameters3.symbols
Normal file
@ -0,0 +1,20 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js ===
|
||||
/** @template {T} */
|
||||
class Baz {
|
||||
>Baz : Symbol(Baz, Decl(jsdocOuterTypeParameters3.js, 0, 0))
|
||||
|
||||
m() {
|
||||
>m : Symbol(Baz.m, Decl(jsdocOuterTypeParameters3.js, 1, 11))
|
||||
|
||||
class Bar {
|
||||
>Bar : Symbol(Bar, Decl(jsdocOuterTypeParameters3.js, 2, 9))
|
||||
|
||||
static bar() { this.prototype.foo(); }
|
||||
>bar : Symbol(Bar.bar, Decl(jsdocOuterTypeParameters3.js, 3, 19))
|
||||
>this.prototype : Symbol(Bar.prototype)
|
||||
>this : Symbol(Bar, Decl(jsdocOuterTypeParameters3.js, 2, 9))
|
||||
>prototype : Symbol(Bar.prototype)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
tests/baselines/reference/jsdocOuterTypeParameters3.types
Normal file
23
tests/baselines/reference/jsdocOuterTypeParameters3.types
Normal file
@ -0,0 +1,23 @@
|
||||
=== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.js ===
|
||||
/** @template {T} */
|
||||
class Baz {
|
||||
>Baz : Baz
|
||||
|
||||
m() {
|
||||
>m : () => void
|
||||
|
||||
class Bar {
|
||||
>Bar : Bar
|
||||
|
||||
static bar() { this.prototype.foo(); }
|
||||
>bar : () => void
|
||||
>this.prototype.foo() : any
|
||||
>this.prototype.foo : any
|
||||
>this.prototype : Bar
|
||||
>this : typeof Bar
|
||||
>prototype : Bar
|
||||
>foo : any
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
12
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.ts
Normal file
12
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.ts
Normal file
@ -0,0 +1,12 @@
|
||||
// @checkjs: true
|
||||
// @filename: jsdocOuterTypeParameters1.js
|
||||
/** @return {T} */
|
||||
const dedupingMixin = function(mixin) {};
|
||||
|
||||
/** @template {T} */
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
class Bar {
|
||||
static bar() { this.prototype.foo(); }
|
||||
}
|
||||
});
|
||||
|
||||
12
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters2.ts
Normal file
12
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters2.ts
Normal file
@ -0,0 +1,12 @@
|
||||
// @checkjs: true
|
||||
// @filename: jsdocOuterTypeParameters1.js
|
||||
/** @return {T} */
|
||||
const dedupingMixin = function(mixin) {};
|
||||
|
||||
/** @template T */
|
||||
const PropertyAccessors = dedupingMixin(() => {
|
||||
class Bar {
|
||||
static bar() { this.prototype.foo(); }
|
||||
}
|
||||
});
|
||||
|
||||
11
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.ts
Normal file
11
tests/cases/conformance/jsdoc/jsdocOuterTypeParameters3.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// @checkjs: true
|
||||
// @filename: jsdocOuterTypeParameters3.js
|
||||
|
||||
/** @template {T} */
|
||||
class Baz {
|
||||
m() {
|
||||
class Bar {
|
||||
static bar() { this.prototype.foo(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user