From 623f78e20f0e3332aacfa73b7af195d32cc825e2 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 8 May 2020 07:06:06 +0000 Subject: [PATCH] Cherry-pick PR #38368 into release-3.9 Component commits: c827007a38 Fix js missing type arguments on existing nodes and jsdoc object literal declaration emit 128ef9370b Merge branch 'master' into js-declaration-fixes-mk2 a90f97c6f6 Add special lookups test case, rename helper 04e6b6fe92 Accept slightly modified baselines --- src/compiler/checker.ts | 26 ++++- .../reference/exportNestedNamespaces.types | 2 +- .../reference/jsDeclarationsClassStatic.js | 2 +- .../jsDeclarationsJSDocRedirectedLookups.js | 82 ++++++++++++++++ ...DeclarationsJSDocRedirectedLookups.symbols | 69 +++++++++++++ ...jsDeclarationsJSDocRedirectedLookups.types | 89 +++++++++++++++++ .../jsDeclarationsMissingGenerics.js | 30 ++++++ .../jsDeclarationsMissingGenerics.symbols | 15 +++ .../jsDeclarationsMissingGenerics.types | 15 +++ .../reference/jsDeclarationsNestedParams.js | 96 +++++++++++++++++++ .../jsDeclarationsNestedParams.symbols | 35 +++++++ .../jsDeclarationsNestedParams.types | 35 +++++++ .../jsdocArrayObjectPromiseImplicitAny.types | 6 +- ...jsdocArrayObjectPromiseNoImplicitAny.types | 4 +- .../jsdocClassMissingTypeArguments.types | 2 +- .../baselines/reference/jsdocParamTag2.types | 8 +- .../reference/jsdocParamTagTypeLiteral.types | 10 +- .../jsdocTemplateConstructorFunction2.types | 4 +- .../reference/jsdocTemplateTag.types | 4 +- ...ocTypeNongenericInstantiationAttempt.types | 2 +- .../reference/jsdocTypeReferenceToValue.types | 2 +- .../moduleExportNestedNamespaces.types | 2 +- ...tyAssignmentMergeWithInterfaceMethod.types | 4 +- .../typeFromPropertyAssignment35.types | 2 +- .../typeFromPropertyAssignment6.types | 2 +- .../reference/varRequireFromJavascript.types | 2 +- .../reference/varRequireFromTypescript.types | 2 +- .../jsDeclarationsJSDocRedirectedLookups.ts | 39 ++++++++ .../jsDeclarationsMissingGenerics.ts | 14 +++ .../jsDeclarationsNestedParams.ts | 29 ++++++ 30 files changed, 602 insertions(+), 32 deletions(-) create mode 100644 tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.js create mode 100644 tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.symbols create mode 100644 tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.types create mode 100644 tests/baselines/reference/jsDeclarationsMissingGenerics.js create mode 100644 tests/baselines/reference/jsDeclarationsMissingGenerics.symbols create mode 100644 tests/baselines/reference/jsDeclarationsMissingGenerics.types create mode 100644 tests/baselines/reference/jsDeclarationsNestedParams.js create mode 100644 tests/baselines/reference/jsDeclarationsNestedParams.symbols create mode 100644 tests/baselines/reference/jsDeclarationsNestedParams.types create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsJSDocRedirectedLookups.ts create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsMissingGenerics.ts create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsNestedParams.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e020ff149db33..21ea8c7347ebc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5503,6 +5503,10 @@ namespace ts { return symbol.declarations && find(symbol.declarations, s => !!getEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration))); } + function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing: TypeNode, type: Type) { + return !(getObjectFlags(type) & ObjectFlags.Reference) || !isTypeReferenceNode(existing) || length(existing.typeArguments) >= getMinTypeArgumentCount((type as TypeReference).target.typeParameters); + } + /** * Unlike `typeToTypeNodeHelper`, this handles setting up the `AllowUniqueESSymbolType` flag * so a `unique symbol` is returned when appropriate for the input symbol, rather than `typeof sym` @@ -5513,7 +5517,7 @@ namespace ts { if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation)) { // try to reuse the existing annotation const existing = getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!; - if (getTypeFromTypeNode(existing) === type) { + if (getTypeFromTypeNode(existing) === type && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing, type)) { const result = serializeExistingTypeNode(context, existing, includePrivateSymbol, bundled); if (result) { return result; @@ -5534,7 +5538,7 @@ namespace ts { function serializeReturnTypeForSignature(context: NodeBuilderContext, type: Type, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { if (type !== errorType && context.enclosingDeclaration) { const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); - if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation && instantiateType(getTypeFromTypeNode(annotation), signature.mapper) === type) { + if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation && instantiateType(getTypeFromTypeNode(annotation), signature.mapper) === type && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(annotation, type)) { const result = serializeExistingTypeNode(context, annotation, includePrivateSymbol, bundled); if (result) { return result; @@ -5575,6 +5579,21 @@ namespace ts { if (isJSDocVariadicType(node)) { return createArrayTypeNode(visitNode((node as JSDocVariadicType).type, visitExistingNodeTreeSymbols)); } + if (isJSDocTypeLiteral(node)) { + return createTypeLiteralNode(map(node.jsDocPropertyTags, t => { + const name = isIdentifier(t.name) ? t.name : t.name.right; + const typeViaParent = getTypeOfPropertyOfType(getTypeFromTypeNode(node), name.escapedText); + const overrideTypeNode = typeViaParent && t.typeExpression && getTypeFromTypeNode(t.typeExpression.type) !== typeViaParent ? typeToTypeNodeHelper(typeViaParent, context) : undefined; + + return createPropertySignature( + /*modifiers*/ undefined, + name, + t.typeExpression && isJSDocOptionalType(t.typeExpression.type) ? createToken(SyntaxKind.QuestionToken) : undefined, + overrideTypeNode || (t.typeExpression && visitNode(t.typeExpression.type, visitExistingNodeTreeSymbols)) || createKeywordTypeNode(SyntaxKind.AnyKeyword), + /*initializer*/ undefined + ); + })); + } if (isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "") { return setOriginalNode(createKeywordTypeNode(SyntaxKind.AnyKeyword), node); } @@ -5626,6 +5645,9 @@ namespace ts { ); } } + if (isTypeReferenceNode(node) && isInJSDoc(node) && (getIntendedTypeFromJSDocTypeReference(node) || unknownSymbol === resolveTypeReferenceName(getTypeReferenceName(node), SymbolFlags.Type, /*ignoreErrors*/ true))) { + return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); + } if (isLiteralImportTypeNode(node)) { return updateImportTypeNode( node, diff --git a/tests/baselines/reference/exportNestedNamespaces.types b/tests/baselines/reference/exportNestedNamespaces.types index 97ce99af19a02..51d79ce2257c3 100644 --- a/tests/baselines/reference/exportNestedNamespaces.types +++ b/tests/baselines/reference/exportNestedNamespaces.types @@ -68,7 +68,7 @@ var classic = new s.Classic() /** @param {s.n.K} c @param {s.Classic} classic */ function f(c, classic) { ->f : (c: s.n.K, classic: s.Classic) => void +>f : (c: K, classic: s.Classic) => void >c : K >classic : Classic diff --git a/tests/baselines/reference/jsDeclarationsClassStatic.js b/tests/baselines/reference/jsDeclarationsClassStatic.js index 1498b8bd6bd5f..4af5f3fd83e98 100644 --- a/tests/baselines/reference/jsDeclarationsClassStatic.js +++ b/tests/baselines/reference/jsDeclarationsClassStatic.js @@ -70,5 +70,5 @@ type HandlerOptions = { /** * Should be able to export a type alias at the same time. */ - name: String; + name: string; }; diff --git a/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.js b/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.js new file mode 100644 index 0000000000000..294407154c3f3 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.js @@ -0,0 +1,82 @@ +//// [index.js] +// these are recognized as TS concepts by the checker +/** @type {String} */const a = ""; +/** @type {Number} */const b = 0; +/** @type {Boolean} */const c = true; +/** @type {Void} */const d = undefined; +/** @type {Undefined} */const e = undefined; +/** @type {Null} */const f = null; + +/** @type {Function} */const g = () => void 0; +/** @type {function} */const h = () => void 0; +/** @type {array} */const i = []; +/** @type {promise} */const j = Promise.resolve(0); +/** @type {Object} */const k = {x: "x"}; + + +// these are not recognized as anything and should just be lookup failures +// ignore the errors to try to ensure they're emitted as `any` in declaration emit +// @ts-ignore +/** @type {class} */const l = true; +// @ts-ignore +/** @type {bool} */const m = true; +// @ts-ignore +/** @type {int} */const n = true; +// @ts-ignore +/** @type {float} */const o = true; +// @ts-ignore +/** @type {integer} */const p = true; + +// or, in the case of `event` likely erroneously refers to the type of the global Event object +/** @type {event} */const q = undefined; + +//// [index.js] +"use strict"; +// these are recognized as TS concepts by the checker +/** @type {String} */ const a = ""; +/** @type {Number} */ const b = 0; +/** @type {Boolean} */ const c = true; +/** @type {Void} */ const d = undefined; +/** @type {Undefined} */ const e = undefined; +/** @type {Null} */ const f = null; +/** @type {Function} */ const g = () => void 0; +/** @type {function} */ const h = () => void 0; +/** @type {array} */ const i = []; +/** @type {promise} */ const j = Promise.resolve(0); +/** @type {Object} */ const k = { x: "x" }; +// these are not recognized as anything and should just be lookup failures +// ignore the errors to try to ensure they're emitted as `any` in declaration emit +// @ts-ignore +/** @type {class} */ const l = true; +// @ts-ignore +/** @type {bool} */ const m = true; +// @ts-ignore +/** @type {int} */ const n = true; +// @ts-ignore +/** @type {float} */ const o = true; +// @ts-ignore +/** @type {integer} */ const p = true; +// or, in the case of `event` likely erroneously refers to the type of the global Event object +/** @type {event} */ const q = undefined; + + +//// [index.d.ts] +/** @type {String} */ declare const a: string; +/** @type {Number} */ declare const b: number; +/** @type {Boolean} */ declare const c: boolean; +/** @type {Void} */ declare const d: void; +/** @type {Undefined} */ declare const e: undefined; +/** @type {Null} */ declare const f: null; +/** @type {Function} */ declare const g: Function; +/** @type {function} */ declare const h: Function; +/** @type {array} */ declare const i: any[]; +/** @type {promise} */ declare const j: Promise; +/** @type {Object} */ declare const k: { + [x: string]: string; +}; +/** @type {class} */ declare const l: any; +/** @type {bool} */ declare const m: any; +/** @type {int} */ declare const n: any; +/** @type {float} */ declare const o: any; +/** @type {integer} */ declare const p: any; +/** @type {event} */ declare const q: Event | undefined; diff --git a/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.symbols b/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.symbols new file mode 100644 index 0000000000000..b24b2964a493b --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.symbols @@ -0,0 +1,69 @@ +=== tests/cases/conformance/jsdoc/declarations/index.js === +// these are recognized as TS concepts by the checker +/** @type {String} */const a = ""; +>a : Symbol(a, Decl(index.js, 1, 26)) + +/** @type {Number} */const b = 0; +>b : Symbol(b, Decl(index.js, 2, 26)) + +/** @type {Boolean} */const c = true; +>c : Symbol(c, Decl(index.js, 3, 27)) + +/** @type {Void} */const d = undefined; +>d : Symbol(d, Decl(index.js, 4, 24)) +>undefined : Symbol(undefined) + +/** @type {Undefined} */const e = undefined; +>e : Symbol(e, Decl(index.js, 5, 29)) +>undefined : Symbol(undefined) + +/** @type {Null} */const f = null; +>f : Symbol(f, Decl(index.js, 6, 24)) + +/** @type {Function} */const g = () => void 0; +>g : Symbol(g, Decl(index.js, 8, 28)) + +/** @type {function} */const h = () => void 0; +>h : Symbol(h, Decl(index.js, 9, 28)) + +/** @type {array} */const i = []; +>i : Symbol(i, Decl(index.js, 10, 25)) + +/** @type {promise} */const j = Promise.resolve(0); +>j : Symbol(j, Decl(index.js, 11, 27)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>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, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + +/** @type {Object} */const k = {x: "x"}; +>k : Symbol(k, Decl(index.js, 12, 42)) +>x : Symbol(x, Decl(index.js, 12, 48)) + + +// these are not recognized as anything and should just be lookup failures +// ignore the errors to try to ensure they're emitted as `any` in declaration emit +// @ts-ignore +/** @type {class} */const l = true; +>l : Symbol(l, Decl(index.js, 18, 25)) + +// @ts-ignore +/** @type {bool} */const m = true; +>m : Symbol(m, Decl(index.js, 20, 24)) + +// @ts-ignore +/** @type {int} */const n = true; +>n : Symbol(n, Decl(index.js, 22, 23)) + +// @ts-ignore +/** @type {float} */const o = true; +>o : Symbol(o, Decl(index.js, 24, 25)) + +// @ts-ignore +/** @type {integer} */const p = true; +>p : Symbol(p, Decl(index.js, 26, 27)) + +// or, in the case of `event` likely erroneously refers to the type of the global Event object +/** @type {event} */const q = undefined; +>q : Symbol(q, Decl(index.js, 29, 25)) +>undefined : Symbol(undefined) + diff --git a/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.types b/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.types new file mode 100644 index 0000000000000..43281db54a307 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsJSDocRedirectedLookups.types @@ -0,0 +1,89 @@ +=== tests/cases/conformance/jsdoc/declarations/index.js === +// these are recognized as TS concepts by the checker +/** @type {String} */const a = ""; +>a : string +>"" : "" + +/** @type {Number} */const b = 0; +>b : number +>0 : 0 + +/** @type {Boolean} */const c = true; +>c : boolean +>true : true + +/** @type {Void} */const d = undefined; +>d : void +>undefined : undefined + +/** @type {Undefined} */const e = undefined; +>e : undefined +>undefined : undefined + +/** @type {Null} */const f = null; +>f : null +>null : null + +/** @type {Function} */const g = () => void 0; +>g : Function +>() => void 0 : () => undefined +>void 0 : undefined +>0 : 0 + +/** @type {function} */const h = () => void 0; +>h : Function +>() => void 0 : () => undefined +>void 0 : undefined +>0 : 0 + +/** @type {array} */const i = []; +>i : any[] +>[] : never[] + +/** @type {promise} */const j = Promise.resolve(0); +>j : Promise +>Promise.resolve(0) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>0 : 0 + +/** @type {Object} */const k = {x: "x"}; +>k : { [x: string]: string; } +>{x: "x"} : { x: string; } +>x : string +>"x" : "x" + + +// these are not recognized as anything and should just be lookup failures +// ignore the errors to try to ensure they're emitted as `any` in declaration emit +// @ts-ignore +/** @type {class} */const l = true; +>l : error +>true : true + +// @ts-ignore +/** @type {bool} */const m = true; +>m : error +>true : true + +// @ts-ignore +/** @type {int} */const n = true; +>n : error +>true : true + +// @ts-ignore +/** @type {float} */const o = true; +>o : error +>true : true + +// @ts-ignore +/** @type {integer} */const p = true; +>p : error +>true : true + +// or, in the case of `event` likely erroneously refers to the type of the global Event object +/** @type {event} */const q = undefined; +>q : Event | undefined +>undefined : undefined + diff --git a/tests/baselines/reference/jsDeclarationsMissingGenerics.js b/tests/baselines/reference/jsDeclarationsMissingGenerics.js new file mode 100644 index 0000000000000..50d260f785a4c --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsMissingGenerics.js @@ -0,0 +1,30 @@ +//// [file.js] +/** + * @param {Array} x + */ +function x(x) {} +/** + * @param {Promise} x + */ +function y(x) {} + +//// [file.js] +/** + * @param {Array} x + */ +function x(x) { } +/** + * @param {Promise} x + */ +function y(x) { } + + +//// [file.d.ts] +/** + * @param {Array} x + */ +declare function x(x: any[]): void; +/** + * @param {Promise} x + */ +declare function y(x: Promise): void; diff --git a/tests/baselines/reference/jsDeclarationsMissingGenerics.symbols b/tests/baselines/reference/jsDeclarationsMissingGenerics.symbols new file mode 100644 index 0000000000000..a28d52c3dc530 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsMissingGenerics.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/jsdoc/declarations/file.js === +/** + * @param {Array} x + */ +function x(x) {} +>x : Symbol(x, Decl(file.js, 0, 0)) +>x : Symbol(x, Decl(file.js, 3, 11)) + +/** + * @param {Promise} x + */ +function y(x) {} +>y : Symbol(y, Decl(file.js, 3, 16)) +>x : Symbol(x, Decl(file.js, 7, 11)) + diff --git a/tests/baselines/reference/jsDeclarationsMissingGenerics.types b/tests/baselines/reference/jsDeclarationsMissingGenerics.types new file mode 100644 index 0000000000000..55045a38844b6 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsMissingGenerics.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/jsdoc/declarations/file.js === +/** + * @param {Array} x + */ +function x(x) {} +>x : (x: any[]) => void +>x : any[] + +/** + * @param {Promise} x + */ +function y(x) {} +>y : (x: Promise) => void +>x : Promise + diff --git a/tests/baselines/reference/jsDeclarationsNestedParams.js b/tests/baselines/reference/jsDeclarationsNestedParams.js new file mode 100644 index 0000000000000..f2ced1ba7cf8f --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsNestedParams.js @@ -0,0 +1,96 @@ +//// [file.js] +class X { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {string?} error.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, code}) {} +} + +class Y { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {Object} error.suberr + * @param {string?} error.suberr.reason the error reason to send the cancellation with + * @param {string?} error.suberr.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, suberr}) {} +} + + +//// [file.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +class X { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {string?} error.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + cancel({ reason, code }) { + return __awaiter(this, void 0, void 0, function* () { }); + } +} +class Y { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {Object} error.suberr + * @param {string?} error.suberr.reason the error reason to send the cancellation with + * @param {string?} error.suberr.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + cancel({ reason, suberr }) { + return __awaiter(this, void 0, void 0, function* () { }); + } +} + + +//// [file.d.ts] +declare class X { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {string?} error.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + cancel({ reason, code }: { + reason: string | null; + code: string | null; + }): Promise; +} +declare class Y { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {Object} error.suberr + * @param {string?} error.suberr.reason the error reason to send the cancellation with + * @param {string?} error.suberr.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + cancel({ reason, suberr }: { + reason: string | null; + suberr: { + reason: string | null; + code: string | null; + }; + }): Promise; +} diff --git a/tests/baselines/reference/jsDeclarationsNestedParams.symbols b/tests/baselines/reference/jsDeclarationsNestedParams.symbols new file mode 100644 index 0000000000000..3b567a5952c2f --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsNestedParams.symbols @@ -0,0 +1,35 @@ +=== tests/cases/conformance/jsdoc/declarations/file.js === +class X { +>X : Symbol(X, Decl(file.js, 0, 0)) + + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {string?} error.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, code}) {} +>cancel : Symbol(X.cancel, Decl(file.js, 0, 9)) +>reason : Symbol(reason, Decl(file.js, 8, 18)) +>code : Symbol(code, Decl(file.js, 8, 25)) +} + +class Y { +>Y : Symbol(Y, Decl(file.js, 9, 1)) + + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {Object} error.suberr + * @param {string?} error.suberr.reason the error reason to send the cancellation with + * @param {string?} error.suberr.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, suberr}) {} +>cancel : Symbol(Y.cancel, Decl(file.js, 11, 9)) +>reason : Symbol(reason, Decl(file.js, 21, 18)) +>suberr : Symbol(suberr, Decl(file.js, 21, 25)) +} + diff --git a/tests/baselines/reference/jsDeclarationsNestedParams.types b/tests/baselines/reference/jsDeclarationsNestedParams.types new file mode 100644 index 0000000000000..483a707a08984 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsNestedParams.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/jsdoc/declarations/file.js === +class X { +>X : X + + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {string?} error.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, code}) {} +>cancel : ({ reason, code }: { reason: string | null; code: string | null;}) => Promise +>reason : string +>code : string +} + +class Y { +>Y : Y + + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {Object} error.suberr + * @param {string?} error.suberr.reason the error reason to send the cancellation with + * @param {string?} error.suberr.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, suberr}) {} +>cancel : ({ reason, suberr }: { reason: string | null; suberr: { reason: string | null; code: string | null; };}) => Promise +>reason : string +>suberr : { reason: string; code: string; } +} + diff --git a/tests/baselines/reference/jsdocArrayObjectPromiseImplicitAny.types b/tests/baselines/reference/jsdocArrayObjectPromiseImplicitAny.types index 7ea21afe4c88a..3fab5033c2305 100644 --- a/tests/baselines/reference/jsdocArrayObjectPromiseImplicitAny.types +++ b/tests/baselines/reference/jsdocArrayObjectPromiseImplicitAny.types @@ -16,7 +16,7 @@ var numberArray = [5]; * @return {Array} */ function returnAnyArray(arr) { ->returnAnyArray : (arr: Array) => Array +>returnAnyArray : (arr: any[]) => any[] >arr : any[] return arr; @@ -46,7 +46,7 @@ var numberPromise = Promise.resolve(5); * @return {Promise} */ function returnAnyPromise(pr) { ->returnAnyPromise : (pr: Promise) => Promise +>returnAnyPromise : (pr: Promise) => Promise >pr : Promise return pr; @@ -72,7 +72,7 @@ var paramedObject = {valueOf: 1}; * @return {Object} */ function returnAnyObject(obj) { ->returnAnyObject : (obj: Object) => Object +>returnAnyObject : (obj: any) => any >obj : any return obj; diff --git a/tests/baselines/reference/jsdocArrayObjectPromiseNoImplicitAny.types b/tests/baselines/reference/jsdocArrayObjectPromiseNoImplicitAny.types index e5dba449a09aa..82ff886f1ec68 100644 --- a/tests/baselines/reference/jsdocArrayObjectPromiseNoImplicitAny.types +++ b/tests/baselines/reference/jsdocArrayObjectPromiseNoImplicitAny.types @@ -16,7 +16,7 @@ var numberArray = [5]; * @return {Array} */ function returnNotAnyArray(arr) { ->returnNotAnyArray : (arr: Array) => Array +>returnNotAnyArray : (arr: any[]) => any[] >arr : any[] return arr; @@ -46,7 +46,7 @@ var numberPromise = Promise.resolve(5); * @return {Promise} */ function returnNotAnyPromise(pr) { ->returnNotAnyPromise : (pr: Promise) => Promise +>returnNotAnyPromise : (pr: Promise) => Promise >pr : Promise return pr; diff --git a/tests/baselines/reference/jsdocClassMissingTypeArguments.types b/tests/baselines/reference/jsdocClassMissingTypeArguments.types index 8be84d6df5df2..0c64fd3c5a7d3 100644 --- a/tests/baselines/reference/jsdocClassMissingTypeArguments.types +++ b/tests/baselines/reference/jsdocClassMissingTypeArguments.types @@ -5,6 +5,6 @@ class C {} /** @param {C} p */ function f(p) {} ->f : (p: C) => void +>f : (p: C) => void >p : C diff --git a/tests/baselines/reference/jsdocParamTag2.types b/tests/baselines/reference/jsdocParamTag2.types index bc4d0f3b10a22..e81155ccb3cd8 100644 --- a/tests/baselines/reference/jsdocParamTag2.types +++ b/tests/baselines/reference/jsdocParamTag2.types @@ -49,7 +49,7 @@ function good4({a, b}) {} * @param {string} x */ function good5({a, b}, x) {} ->good5 : ({ a, b }: * @param {string} obj.a - this is like the saddest way to specify a type * @param {string} obj.b - but it sure does allow a lot of documentation, x: string) => void +>good5 : ({ a, b }: { a: string; b: string;}, x: string) => void >a : string >b : string >x : string @@ -63,7 +63,7 @@ function good5({a, b}, x) {} * @param {string} OBJECTION.d - meh */ function good6({a, b}, {c, d}) {} ->good6 : ({ a, b }: * @param {string} obj.a * @param {string} obj.b - but it sure does allow a lot of documentation, { c, d }: * @param {string} OBJECTION.c * @param {string} OBJECTION.d - meh) => void +>good6 : ({ a, b }: { a: string; b: string;}, { c, d }: { c: string; d: string;}) => void >a : string >b : string >c : string @@ -77,7 +77,7 @@ function good6({a, b}, {c, d}) {} * @param {string} y */ function good7(x, {a, b}, y) {} ->good7 : (x: number, { a, b }: * @param {string} obj.a * @param {string} obj.b, y: string) => void +>good7 : (x: number, { a, b }: { a: string; b: string;}, y: string) => void >x : number >a : string >b : string @@ -89,7 +89,7 @@ function good7(x, {a, b}, y) {} * @param {string} obj.b */ function good8({a, b}) {} ->good8 : ({ a, b }: * @param {string} obj.a * @param {string} obj.b) => void +>good8 : ({ a, b }: { a: string; b: string;}) => void >a : string >b : string diff --git a/tests/baselines/reference/jsdocParamTagTypeLiteral.types b/tests/baselines/reference/jsdocParamTagTypeLiteral.types index a27d8b4d50c64..6a51e49ee6c15 100644 --- a/tests/baselines/reference/jsdocParamTagTypeLiteral.types +++ b/tests/baselines/reference/jsdocParamTagTypeLiteral.types @@ -23,7 +23,7 @@ normal(12); * @param {string} [opts1.w="hi"] doc5 */ function foo1(opts1) { ->foo1 : (opts1: * @param {string} opts1.x doc2 * @param {string=} opts1.y doc3 * @param {string} [opts1.z] doc4 * @param {string} [opts1.w] doc5) => void +>foo1 : (opts1: { x: string; y?: string | undefined; z: string; w: string;}) => void >opts1 : { x: string; y?: string | undefined; z?: string; w?: string; } opts1.x; @@ -45,7 +45,7 @@ foo1({x: 'abc'}); * @param {string=} opts2[].anotherY */ function foo2(/** @param opts2 bad idea theatre! */opts2) { ->foo2 : (opts2: * @param {string} opts2.anotherX * @param {string=} opts2.anotherY) => void +>foo2 : (opts2: { anotherX: string; anotherY?: string | undefined;}) => void >opts2 : { anotherX: string; anotherY?: string | undefined; }[] opts2[0].anotherX; @@ -69,7 +69,7 @@ foo2([{anotherX: "world"}]); * @param {string} opts3.x */ function foo3(opts3) { ->foo3 : (opts3: * @param {string} opts3.x) => void +>foo3 : (opts3: { x: string;}) => void >opts3 : { x: string; } opts3.x; @@ -92,7 +92,7 @@ foo3({x: 'abc'}); * @param {string} [opts4[].w="hi"] */ function foo4(opts4) { ->foo4 : (opts4: * @param {string} opts4.x * @param {string=} opts4.y * @param {string} [opts4.z] * @param {string} [opts4.w]) => void +>foo4 : (opts4: { x: string; y?: string | undefined; z: string; w: string;}) => void >opts4 : { x: string; y?: string | undefined; z?: string; w?: string; }[] opts4[0].x; @@ -122,7 +122,7 @@ foo4([{ x: 'hi' }]); * @param {number} opts5[].unnest - Here we are almost all the way back at the beginning. */ function foo5(opts5) { ->foo5 : (opts5: * @param {string} opts5.help - (This one is just normal) * @param { * @param {string} opts5.what.a - (Another normal one) * @param { * @param {string} opts5.what.bad.idea - I don't think you can get back out of this level... * @param {boolean} opts5.what.bad.oh - Oh ... that's how you do it.} opts5.what.bad - Now we're nesting inside a nested type} opts5.what - Look at us go! Here's the first nest! * @param {number} opts5.unnest - Here we are almost all the way back at the beginning.) => void +>foo5 : (opts5: { help: string; what: { a: string; bad: { idea: string; oh: boolean; }; }; unnest: number;}) => void >opts5 : { help: string; what: { a: string; bad: { idea: string; oh: boolean; }[]; }; unnest: number; }[] opts5[0].what.bad[0].idea; diff --git a/tests/baselines/reference/jsdocTemplateConstructorFunction2.types b/tests/baselines/reference/jsdocTemplateConstructorFunction2.types index 19270bb4b6731..dc70e5282c31f 100644 --- a/tests/baselines/reference/jsdocTemplateConstructorFunction2.types +++ b/tests/baselines/reference/jsdocTemplateConstructorFunction2.types @@ -26,13 +26,13 @@ function Zet(t) { * @param {T} o.nested */ Zet.prototype.add = function(v, o) { ->Zet.prototype.add = function(v, o) { this.u = v || o.nested return this.u} : (v: T, o: * @param {T} o.nested) => T +>Zet.prototype.add = function(v, o) { this.u = v || o.nested return this.u} : (v: T, o: { nested: T; }) => T >Zet.prototype.add : any >Zet.prototype : any >Zet : typeof Zet >prototype : any >add : any ->function(v, o) { this.u = v || o.nested return this.u} : (v: T, o: * @param {T} o.nested) => T +>function(v, o) { this.u = v || o.nested return this.u} : (v: T, o: { nested: T; }) => T >v : T >o : { nested: T; } diff --git a/tests/baselines/reference/jsdocTemplateTag.types b/tests/baselines/reference/jsdocTemplateTag.types index 860244c6315da..7b5a2f5da71c0 100644 --- a/tests/baselines/reference/jsdocTemplateTag.types +++ b/tests/baselines/reference/jsdocTemplateTag.types @@ -42,12 +42,12 @@ let s = g('hi')() * @param {Array.} keyframes - Can't look up types on Element since it's a global in another file. (But it shouldn't crash). */ Element.prototype.animate = function(keyframes) {}; ->Element.prototype.animate = function(keyframes) {} : (keyframes: Array) => void +>Element.prototype.animate = function(keyframes) {} : (keyframes: Array) => void >Element.prototype.animate : (keyframes: Keyframe[] | PropertyIndexedKeyframes, options?: number | KeyframeAnimationOptions) => Animation >Element.prototype : Element >Element : { new (): Element; prototype: Element; } >prototype : Element >animate : (keyframes: Keyframe[] | PropertyIndexedKeyframes, options?: number | KeyframeAnimationOptions) => Animation ->function(keyframes) {} : (keyframes: Array) => void +>function(keyframes) {} : (keyframes: Array) => void >keyframes : any[] diff --git a/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.types b/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.types index 1549c5605831d..21dc8d546ce52 100644 --- a/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.types +++ b/tests/baselines/reference/jsdocTypeNongenericInstantiationAttempt.types @@ -109,6 +109,6 @@ function fn() {} * @param {fn} somebody */ function sayHello8(somebody) { } ->sayHello8 : (somebody: fn) => void +>sayHello8 : (somebody: () => void) => void >somebody : () => void diff --git a/tests/baselines/reference/jsdocTypeReferenceToValue.types b/tests/baselines/reference/jsdocTypeReferenceToValue.types index 4db6664b84d11..91f8e26d35d4b 100644 --- a/tests/baselines/reference/jsdocTypeReferenceToValue.types +++ b/tests/baselines/reference/jsdocTypeReferenceToValue.types @@ -1,7 +1,7 @@ === tests/cases/conformance/jsdoc/foo.js === /** @param {Image} image */ function process(image) { ->process : (image: Image) => HTMLImageElement +>process : (image: new (width?: number, height?: number) => HTMLImageElement) => HTMLImageElement >image : new (width?: number, height?: number) => HTMLImageElement return new image(1, 1) diff --git a/tests/baselines/reference/moduleExportNestedNamespaces.types b/tests/baselines/reference/moduleExportNestedNamespaces.types index 249739a3beb8a..8fcb3815bd7b8 100644 --- a/tests/baselines/reference/moduleExportNestedNamespaces.types +++ b/tests/baselines/reference/moduleExportNestedNamespaces.types @@ -75,7 +75,7 @@ var classic = new s.Classic() /** @param {s.n.K} c @param {s.Classic} classic */ function f(c, classic) { ->f : (c: s.n.K, classic: s.Classic) => void +>f : (c: C, classic: s.Classic) => void >c : C >classic : Classic diff --git a/tests/baselines/reference/prototypePropertyAssignmentMergeWithInterfaceMethod.types b/tests/baselines/reference/prototypePropertyAssignmentMergeWithInterfaceMethod.types index b61471495b143..1a4d86e89cdc2 100644 --- a/tests/baselines/reference/prototypePropertyAssignmentMergeWithInterfaceMethod.types +++ b/tests/baselines/reference/prototypePropertyAssignmentMergeWithInterfaceMethod.types @@ -40,7 +40,7 @@ lf.Transaction = function() {}; * @return {!IThenable} */ lf.Transaction.prototype.begin = function(scope) {}; ->lf.Transaction.prototype.begin = function(scope) {} : (scope: Array) => any +>lf.Transaction.prototype.begin = function(scope) {} : (scope: Array) => any >lf.Transaction.prototype.begin : any >lf.Transaction.prototype : any >lf.Transaction : typeof Transaction @@ -48,6 +48,6 @@ lf.Transaction.prototype.begin = function(scope) {}; >Transaction : typeof Transaction >prototype : any >begin : any ->function(scope) {} : (scope: Array) => any +>function(scope) {} : (scope: Array) => any >scope : any[] diff --git a/tests/baselines/reference/typeFromPropertyAssignment35.types b/tests/baselines/reference/typeFromPropertyAssignment35.types index 4eebf48bbc168..678adb1ba5346 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment35.types +++ b/tests/baselines/reference/typeFromPropertyAssignment35.types @@ -1,7 +1,7 @@ === tests/cases/conformance/salsa/bug26877.js === /** @param {Emu.D} x */ function ollKorrect(x) { ->ollKorrect : (x: Emu.D) => void +>ollKorrect : (x: D) => void >x : D x._model diff --git a/tests/baselines/reference/typeFromPropertyAssignment6.types b/tests/baselines/reference/typeFromPropertyAssignment6.types index 7bcbddebe73fb..2649b8171558e 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment6.types +++ b/tests/baselines/reference/typeFromPropertyAssignment6.types @@ -33,7 +33,7 @@ var msgs = Outer.i.messages() /** @param {Outer.Inner} inner */ function x(inner) { ->x : (inner: Outer.Inner) => void +>x : (inner: I) => void >inner : I } diff --git a/tests/baselines/reference/varRequireFromJavascript.types b/tests/baselines/reference/varRequireFromJavascript.types index 7537eecb6396a..813c38898c5d1 100644 --- a/tests/baselines/reference/varRequireFromJavascript.types +++ b/tests/baselines/reference/varRequireFromJavascript.types @@ -25,7 +25,7 @@ crunch.n * @param {ex.Crunch} wrap */ function f(wrap) { ->f : (wrap: ex.Crunch) => void +>f : (wrap: import("tests/cases/conformance/salsa/ex").Crunch) => void >wrap : import("tests/cases/conformance/salsa/ex").Crunch wrap.n diff --git a/tests/baselines/reference/varRequireFromTypescript.types b/tests/baselines/reference/varRequireFromTypescript.types index cb7c44cfc8425..7010bfaf1a800 100644 --- a/tests/baselines/reference/varRequireFromTypescript.types +++ b/tests/baselines/reference/varRequireFromTypescript.types @@ -26,7 +26,7 @@ crunch.n * @param {ex.Crunch} wrap */ function f(greatest, wrap) { ->f : (greatest: ex.Greatest, wrap: ex.Crunch) => void +>f : (greatest: import("tests/cases/conformance/salsa/ex").Greatest, wrap: import("tests/cases/conformance/salsa/ex").Crunch) => void >greatest : import("tests/cases/conformance/salsa/ex").Greatest >wrap : import("tests/cases/conformance/salsa/ex").Crunch diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsJSDocRedirectedLookups.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsJSDocRedirectedLookups.ts new file mode 100644 index 0000000000000..cdc9604880232 --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsJSDocRedirectedLookups.ts @@ -0,0 +1,39 @@ +// @allowJs: true +// @checkJs: true +// @target: es6 +// @outDir: ./out +// @declaration: true +// @strict: true +// @noImplicitAny: false +// @filename: index.js + +// these are recognized as TS concepts by the checker +/** @type {String} */const a = ""; +/** @type {Number} */const b = 0; +/** @type {Boolean} */const c = true; +/** @type {Void} */const d = undefined; +/** @type {Undefined} */const e = undefined; +/** @type {Null} */const f = null; + +/** @type {Function} */const g = () => void 0; +/** @type {function} */const h = () => void 0; +/** @type {array} */const i = []; +/** @type {promise} */const j = Promise.resolve(0); +/** @type {Object} */const k = {x: "x"}; + + +// these are not recognized as anything and should just be lookup failures +// ignore the errors to try to ensure they're emitted as `any` in declaration emit +// @ts-ignore +/** @type {class} */const l = true; +// @ts-ignore +/** @type {bool} */const m = true; +// @ts-ignore +/** @type {int} */const n = true; +// @ts-ignore +/** @type {float} */const o = true; +// @ts-ignore +/** @type {integer} */const p = true; + +// or, in the case of `event` likely erroneously refers to the type of the global Event object +/** @type {event} */const q = undefined; \ No newline at end of file diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsMissingGenerics.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsMissingGenerics.ts new file mode 100644 index 0000000000000..ff9396ac90479 --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsMissingGenerics.ts @@ -0,0 +1,14 @@ +// @allowJs: true +// @checkJs: true +// @target: es5 +// @outDir: ./out +// @declaration: true +// @filename: file.js +/** + * @param {Array} x + */ +function x(x) {} +/** + * @param {Promise} x + */ +function y(x) {} \ No newline at end of file diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsNestedParams.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsNestedParams.ts new file mode 100644 index 0000000000000..2fa550f5ee9e4 --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsNestedParams.ts @@ -0,0 +1,29 @@ +// @allowJs: true +// @checkJs: true +// @target: es6 +// @outDir: ./out +// @declaration: true +// @filename: file.js +class X { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {string?} error.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, code}) {} +} + +class Y { + /** + * Cancels the request, sending a cancellation to the other party + * @param {Object} error __auto_generated__ + * @param {string?} error.reason the error reason to send the cancellation with + * @param {Object} error.suberr + * @param {string?} error.suberr.reason the error reason to send the cancellation with + * @param {string?} error.suberr.code the error code to send the cancellation with + * @returns {Promise.<*>} resolves when the event has been sent. + */ + async cancel({reason, suberr}) {} +}