Skip to content

Commit a90f97c

Browse files
committed
Add special lookups test case, rename helper
1 parent 128ef93 commit a90f97c

File tree

5 files changed

+285
-3
lines changed

5 files changed

+285
-3
lines changed

src/compiler/checker.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -5505,7 +5505,7 @@ namespace ts {
55055505
return symbol.declarations && find(symbol.declarations, s => !!getEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration)));
55065506
}
55075507

5508-
function getExistingNodeHasNoTypeParametersOrMatchingTypeParameters(existing: TypeNode, type: Type) {
5508+
function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing: TypeNode, type: Type) {
55095509
return !(getObjectFlags(type) & ObjectFlags.Reference) || !isTypeReferenceNode(existing) || length(existing.typeArguments) >= getMinTypeArgumentCount((type as TypeReference).target.typeParameters);
55105510
}
55115511

@@ -5519,7 +5519,7 @@ namespace ts {
55195519
if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation)) {
55205520
// try to reuse the existing annotation
55215521
const existing = getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!;
5522-
if (getTypeFromTypeNode(existing) === type && getExistingNodeHasNoTypeParametersOrMatchingTypeParameters(existing, type)) {
5522+
if (getTypeFromTypeNode(existing) === type && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing, type)) {
55235523
const result = serializeExistingTypeNode(context, existing, includePrivateSymbol, bundled);
55245524
if (result) {
55255525
return result;
@@ -5540,7 +5540,7 @@ namespace ts {
55405540
function serializeReturnTypeForSignature(context: NodeBuilderContext, type: Type, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
55415541
if (type !== errorType && context.enclosingDeclaration) {
55425542
const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration);
5543-
if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation && instantiateType(getTypeFromTypeNode(annotation), signature.mapper) === type && getExistingNodeHasNoTypeParametersOrMatchingTypeParameters(annotation, type)) {
5543+
if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation && instantiateType(getTypeFromTypeNode(annotation), signature.mapper) === type && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(annotation, type)) {
55445544
const result = serializeExistingTypeNode(context, annotation, includePrivateSymbol, bundled);
55455545
if (result) {
55465546
return result;
@@ -5647,6 +5647,9 @@ namespace ts {
56475647
);
56485648
}
56495649
}
5650+
if (isTypeReferenceNode(node) && isInJSDoc(node) && (getIntendedTypeFromJSDocTypeReference(node) || unknownSymbol === resolveTypeReferenceName(getTypeReferenceName(node), SymbolFlags.Type, /*ignoreErrors*/ true))) {
5651+
return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node);
5652+
}
56505653
if (isLiteralImportTypeNode(node)) {
56515654
return updateImportTypeNode(
56525655
node,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//// [index.js]
2+
// these are recognized as TS concepts by the checker
3+
/** @type {String} */const a = "";
4+
/** @type {Number} */const b = 0;
5+
/** @type {Boolean} */const c = true;
6+
/** @type {Void} */const d = undefined;
7+
/** @type {Undefined} */const e = undefined;
8+
/** @type {Null} */const f = null;
9+
10+
/** @type {Function} */const g = () => void 0;
11+
/** @type {function} */const h = () => void 0;
12+
/** @type {array} */const i = [];
13+
/** @type {promise} */const j = Promise.resolve(0);
14+
/** @type {Object<string, string>} */const k = {x: "x"};
15+
16+
17+
// these are not recognized as anything and should just be lookup failures
18+
// ignore the errors to try to ensure they're emitted as `any` in declaration emit
19+
// @ts-ignore
20+
/** @type {class} */const l = true;
21+
// @ts-ignore
22+
/** @type {bool} */const m = true;
23+
// @ts-ignore
24+
/** @type {int} */const n = true;
25+
// @ts-ignore
26+
/** @type {float} */const o = true;
27+
// @ts-ignore
28+
/** @type {integer} */const p = true;
29+
30+
// or, in the case of `event` likely erroneously refers to the type of the global Event object
31+
/** @type {event} */const q = undefined;
32+
33+
//// [index.js]
34+
"use strict";
35+
// these are recognized as TS concepts by the checker
36+
/** @type {String} */ const a = "";
37+
/** @type {Number} */ const b = 0;
38+
/** @type {Boolean} */ const c = true;
39+
/** @type {Void} */ const d = undefined;
40+
/** @type {Undefined} */ const e = undefined;
41+
/** @type {Null} */ const f = null;
42+
/** @type {Function} */ const g = () => void 0;
43+
/** @type {function} */ const h = () => void 0;
44+
/** @type {array} */ const i = [];
45+
/** @type {promise} */ const j = Promise.resolve(0);
46+
/** @type {Object<string, string>} */ const k = { x: "x" };
47+
// these are not recognized as anything and should just be lookup failures
48+
// ignore the errors to try to ensure they're emitted as `any` in declaration emit
49+
// @ts-ignore
50+
/** @type {class} */ const l = true;
51+
// @ts-ignore
52+
/** @type {bool} */ const m = true;
53+
// @ts-ignore
54+
/** @type {int} */ const n = true;
55+
// @ts-ignore
56+
/** @type {float} */ const o = true;
57+
// @ts-ignore
58+
/** @type {integer} */ const p = true;
59+
// or, in the case of `event` likely erroneously refers to the type of the global Event object
60+
/** @type {event} */ const q = undefined;
61+
62+
63+
//// [index.d.ts]
64+
/** @type {String} */ declare const a: string;
65+
/** @type {Number} */ declare const b: number;
66+
/** @type {Boolean} */ declare const c: boolean;
67+
/** @type {Void} */ declare const d: void;
68+
/** @type {Undefined} */ declare const e: undefined;
69+
/** @type {Null} */ declare const f: null;
70+
/** @type {Function} */ declare const g: Function;
71+
/** @type {function} */ declare const h: Function;
72+
/** @type {array} */ declare const i: any[];
73+
/** @type {promise} */ declare const j: Promise<any>;
74+
/** @type {Object<string, string>} */ declare const k: {
75+
[x: string]: string;
76+
};
77+
/** @type {class} */ declare const l: any;
78+
/** @type {bool} */ declare const m: any;
79+
/** @type {int} */ declare const n: any;
80+
/** @type {float} */ declare const o: any;
81+
/** @type {integer} */ declare const p: any;
82+
/** @type {event} */ declare const q: Event | undefined;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
=== tests/cases/conformance/jsdoc/declarations/index.js ===
2+
// these are recognized as TS concepts by the checker
3+
/** @type {String} */const a = "";
4+
>a : Symbol(a, Decl(index.js, 1, 26))
5+
6+
/** @type {Number} */const b = 0;
7+
>b : Symbol(b, Decl(index.js, 2, 26))
8+
9+
/** @type {Boolean} */const c = true;
10+
>c : Symbol(c, Decl(index.js, 3, 27))
11+
12+
/** @type {Void} */const d = undefined;
13+
>d : Symbol(d, Decl(index.js, 4, 24))
14+
>undefined : Symbol(undefined)
15+
16+
/** @type {Undefined} */const e = undefined;
17+
>e : Symbol(e, Decl(index.js, 5, 29))
18+
>undefined : Symbol(undefined)
19+
20+
/** @type {Null} */const f = null;
21+
>f : Symbol(f, Decl(index.js, 6, 24))
22+
23+
/** @type {Function} */const g = () => void 0;
24+
>g : Symbol(g, Decl(index.js, 8, 28))
25+
26+
/** @type {function} */const h = () => void 0;
27+
>h : Symbol(h, Decl(index.js, 9, 28))
28+
29+
/** @type {array} */const i = [];
30+
>i : Symbol(i, Decl(index.js, 10, 25))
31+
32+
/** @type {promise} */const j = Promise.resolve(0);
33+
>j : Symbol(j, Decl(index.js, 11, 27))
34+
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
35+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
36+
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
37+
38+
/** @type {Object<string, string>} */const k = {x: "x"};
39+
>k : Symbol(k, Decl(index.js, 12, 42))
40+
>x : Symbol(x, Decl(index.js, 12, 48))
41+
42+
43+
// these are not recognized as anything and should just be lookup failures
44+
// ignore the errors to try to ensure they're emitted as `any` in declaration emit
45+
// @ts-ignore
46+
/** @type {class} */const l = true;
47+
>l : Symbol(l, Decl(index.js, 18, 25))
48+
49+
// @ts-ignore
50+
/** @type {bool} */const m = true;
51+
>m : Symbol(m, Decl(index.js, 20, 24))
52+
53+
// @ts-ignore
54+
/** @type {int} */const n = true;
55+
>n : Symbol(n, Decl(index.js, 22, 23))
56+
57+
// @ts-ignore
58+
/** @type {float} */const o = true;
59+
>o : Symbol(o, Decl(index.js, 24, 25))
60+
61+
// @ts-ignore
62+
/** @type {integer} */const p = true;
63+
>p : Symbol(p, Decl(index.js, 26, 27))
64+
65+
// or, in the case of `event` likely erroneously refers to the type of the global Event object
66+
/** @type {event} */const q = undefined;
67+
>q : Symbol(q, Decl(index.js, 29, 25))
68+
>undefined : Symbol(undefined)
69+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
=== tests/cases/conformance/jsdoc/declarations/index.js ===
2+
// these are recognized as TS concepts by the checker
3+
/** @type {String} */const a = "";
4+
>a : string
5+
>"" : ""
6+
7+
/** @type {Number} */const b = 0;
8+
>b : number
9+
>0 : 0
10+
11+
/** @type {Boolean} */const c = true;
12+
>c : boolean
13+
>true : true
14+
15+
/** @type {Void} */const d = undefined;
16+
>d : void
17+
>undefined : undefined
18+
19+
/** @type {Undefined} */const e = undefined;
20+
>e : undefined
21+
>undefined : undefined
22+
23+
/** @type {Null} */const f = null;
24+
>f : null
25+
>null : null
26+
27+
/** @type {Function} */const g = () => void 0;
28+
>g : Function
29+
>() => void 0 : () => undefined
30+
>void 0 : undefined
31+
>0 : 0
32+
33+
/** @type {function} */const h = () => void 0;
34+
>h : Function
35+
>() => void 0 : () => undefined
36+
>void 0 : undefined
37+
>0 : 0
38+
39+
/** @type {array} */const i = [];
40+
>i : any[]
41+
>[] : never[]
42+
43+
/** @type {promise} */const j = Promise.resolve(0);
44+
>j : Promise<any>
45+
>Promise.resolve(0) : Promise<number>
46+
>Promise.resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
47+
>Promise : PromiseConstructor
48+
>resolve : { <T>(value: T | PromiseLike<T>): Promise<T>; (): Promise<void>; }
49+
>0 : 0
50+
51+
/** @type {Object<string, string>} */const k = {x: "x"};
52+
>k : { [x: string]: string; }
53+
>{x: "x"} : { x: string; }
54+
>x : string
55+
>"x" : "x"
56+
57+
58+
// these are not recognized as anything and should just be lookup failures
59+
// ignore the errors to try to ensure they're emitted as `any` in declaration emit
60+
// @ts-ignore
61+
/** @type {class} */const l = true;
62+
>l : error
63+
>true : true
64+
65+
// @ts-ignore
66+
/** @type {bool} */const m = true;
67+
>m : error
68+
>true : true
69+
70+
// @ts-ignore
71+
/** @type {int} */const n = true;
72+
>n : error
73+
>true : true
74+
75+
// @ts-ignore
76+
/** @type {float} */const o = true;
77+
>o : error
78+
>true : true
79+
80+
// @ts-ignore
81+
/** @type {integer} */const p = true;
82+
>p : error
83+
>true : true
84+
85+
// or, in the case of `event` likely erroneously refers to the type of the global Event object
86+
/** @type {event} */const q = undefined;
87+
>q : Event | undefined
88+
>undefined : undefined
89+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// @allowJs: true
2+
// @checkJs: true
3+
// @target: es6
4+
// @outDir: ./out
5+
// @declaration: true
6+
// @strict: true
7+
// @noImplicitAny: false
8+
// @filename: index.js
9+
10+
// these are recognized as TS concepts by the checker
11+
/** @type {String} */const a = "";
12+
/** @type {Number} */const b = 0;
13+
/** @type {Boolean} */const c = true;
14+
/** @type {Void} */const d = undefined;
15+
/** @type {Undefined} */const e = undefined;
16+
/** @type {Null} */const f = null;
17+
18+
/** @type {Function} */const g = () => void 0;
19+
/** @type {function} */const h = () => void 0;
20+
/** @type {array} */const i = [];
21+
/** @type {promise} */const j = Promise.resolve(0);
22+
/** @type {Object<string, string>} */const k = {x: "x"};
23+
24+
25+
// these are not recognized as anything and should just be lookup failures
26+
// ignore the errors to try to ensure they're emitted as `any` in declaration emit
27+
// @ts-ignore
28+
/** @type {class} */const l = true;
29+
// @ts-ignore
30+
/** @type {bool} */const m = true;
31+
// @ts-ignore
32+
/** @type {int} */const n = true;
33+
// @ts-ignore
34+
/** @type {float} */const o = true;
35+
// @ts-ignore
36+
/** @type {integer} */const p = true;
37+
38+
// or, in the case of `event` likely erroneously refers to the type of the global Event object
39+
/** @type {event} */const q = undefined;

0 commit comments

Comments
 (0)