From e427387f62b4ab40c46520abdaccef5112121248 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 1 Dec 2020 12:13:41 -0800 Subject: [PATCH 1/2] JSDoc declaration emit should reuse input nodes where possible when serializing typedefs --- src/compiler/checker.ts | 14 +++- ...tionsFunctionClassesCjsExportAssignment.js | 2 +- ...ationsImportAliasExposedWithinNamespace.js | 17 ++--- ...onsImportAliasExposedWithinNamespaceCjs.js | 6 +- ...ameterTagReusesInputNodeInEmit1.errors.txt | 30 +++++++++ ...tionsParameterTagReusesInputNodeInEmit1.js | 57 ++++++++++++++++ ...ParameterTagReusesInputNodeInEmit1.symbols | 44 +++++++++++++ ...nsParameterTagReusesInputNodeInEmit1.types | 49 ++++++++++++++ ...tionsParameterTagReusesInputNodeInEmit2.js | 66 +++++++++++++++++++ ...ParameterTagReusesInputNodeInEmit2.symbols | 44 +++++++++++++ ...nsParameterTagReusesInputNodeInEmit2.types | 49 ++++++++++++++ .../reference/jsDeclarationsTypeAliases.js | 4 +- ...tionsTypedefPropertyAndExportAssignment.js | 8 +-- ...cImportTypeReferenceToCommonjsModule.types | 2 +- .../jsdocImportTypeReferenceToESModule.types | 2 +- .../reference/recursiveTypeReferences2.js | 4 +- ...based-projects-and-emits-them-correctly.js | 26 ++++++-- ...rojects-and-concatenates-them-correctly.js | 34 ++++------ ...rojects-and-concatenates-them-correctly.js | 60 +++++++---------- ...tionsParameterTagReusesInputNodeInEmit1.ts | 29 ++++++++ ...tionsParameterTagReusesInputNodeInEmit2.ts | 29 ++++++++ 21 files changed, 484 insertions(+), 92 deletions(-) create mode 100644 tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.errors.txt create mode 100644 tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.js create mode 100644 tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.symbols create mode 100644 tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.types create mode 100644 tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.js create mode 100644 tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.symbols create mode 100644 tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.types create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit1.ts create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f96f374005dd9..94e7da2a288a9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5961,6 +5961,17 @@ namespace ts { return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); } if (isLiteralImportTypeNode(node)) { + if (isInJSDoc(node) && + getNodeLinks(node).resolvedSymbol && + ( + // The import type resolved using jsdoc fallback logic + (!node.isTypeOf && !(getNodeLinks(node).resolvedSymbol!.flags & SymbolFlags.Type)) || + // The import type had type arguments autofilled by js fallback logic + !(length(node.typeArguments) >= getMinTypeArgumentCount(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(getNodeLinks(node).resolvedSymbol!))) + ) + ) { + return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); + } return factory.updateImportTypeNode( node, factory.updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)), @@ -6536,8 +6547,9 @@ namespace ts { const commentText = jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined; const oldFlags = context.flags; context.flags |= NodeBuilderFlags.InTypeAlias; + const typeNode = jsdocAliasDecl && jsdocAliasDecl.typeExpression && isJSDocTypeExpression(jsdocAliasDecl.typeExpression) && serializeExistingTypeNode(context, jsdocAliasDecl.typeExpression.type, includePrivateSymbol, bundled) || typeToTypeNodeHelper(aliasType, context); addResult(setSyntheticLeadingComments( - factory.createTypeAliasDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeToTypeNodeHelper(aliasType, context)), + factory.createTypeAliasDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeNode), !commentText ? [] : [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }] ), modifierFlags); context.flags = oldFlags; diff --git a/tests/baselines/reference/jsDeclarationsFunctionClassesCjsExportAssignment.js b/tests/baselines/reference/jsDeclarationsFunctionClassesCjsExportAssignment.js index 60279bcf09c1e..04abac07a28a9 100644 --- a/tests/baselines/reference/jsDeclarationsFunctionClassesCjsExportAssignment.js +++ b/tests/baselines/reference/jsDeclarationsFunctionClassesCjsExportAssignment.js @@ -231,7 +231,7 @@ type Input = { /** * Imports */ -type HookHandler = (arg: Context) => void; +type HookHandler = import("./hook").HookHandler; /** * State type definition */ diff --git a/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.js b/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.js index 22ac11764483e..bc85ba95d0de5 100644 --- a/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.js +++ b/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.js @@ -55,7 +55,7 @@ export {testFn, testFnTypes}; //// [file.d.ts] export namespace myTypes { - type typeA = string | RegExp | (string | RegExp)[]; + type typeA = string | RegExp | Array; type typeB = { /** * - Prop 1. @@ -66,19 +66,14 @@ export namespace myTypes { */ prop2: string; }; - type typeC = Function | typeB; + type typeC = myTypes.typeB | Function; + const myTypes: { + [x: string]: any; + }; } -/** - * @namespace myTypes - * @global - * @type {Object} - */ -export const myTypes: { - [x: string]: any; -}; //// [file2.d.ts] export namespace testFnTypes { - type input = boolean | Function | myTypes.typeB; + type input = boolean | myTypes.typeC; } /** @typedef {boolean|myTypes.typeC} testFnTypes.input */ /** diff --git a/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespaceCjs.js b/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespaceCjs.js index 56fda8a042590..f635869cea711 100644 --- a/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespaceCjs.js +++ b/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespaceCjs.js @@ -63,7 +63,7 @@ export const myTypes: { [x: string]: any; }; export namespace myTypes { - type typeA = string | RegExp | (string | RegExp)[]; + type typeA = string | RegExp | Array; type typeB = { /** * - Prop 1. @@ -74,7 +74,7 @@ export namespace myTypes { */ prop2: string; }; - type typeC = Function | typeB; + type typeC = myTypes.typeB | Function; } //// [file2.d.ts] /** @typedef {boolean|myTypes.typeC} testFnTypes.input */ @@ -94,6 +94,6 @@ export const testFnTypes: { [x: string]: any; }; export namespace testFnTypes { - type input = boolean | Function | myTypes.typeB; + type input = boolean | myTypes.typeC; } import { myTypes } from "./file.js"; diff --git a/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.errors.txt b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.errors.txt new file mode 100644 index 0000000000000..a231ff1aaf495 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.errors.txt @@ -0,0 +1,30 @@ +tests/cases/conformance/jsdoc/declarations/file.js(8,1): error TS9006: Declaration emit for this file requires using private name 'Base' from module '"tests/cases/conformance/jsdoc/declarations/base"'. An explicit type annotation may unblock declaration emit. + + +==== tests/cases/conformance/jsdoc/declarations/base.js (0 errors) ==== + class Base { + constructor() {} + } + + const BaseFactory = () => { + return new Base(); + }; + + BaseFactory.Base = Base; + + module.exports = BaseFactory; + +==== tests/cases/conformance/jsdoc/declarations/file.js (1 errors) ==== + /** @typedef {import('./base')} BaseFactory */ + + /** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ + const test = (base) => { + ~~~~~ +!!! error TS9006: Declaration emit for this file requires using private name 'Base' from module '"tests/cases/conformance/jsdoc/declarations/base"'. An explicit type annotation may unblock declaration emit. + return base; + }; + \ No newline at end of file diff --git a/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.js b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.js new file mode 100644 index 0000000000000..c4a5b8c5018a1 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.js @@ -0,0 +1,57 @@ +//// [tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit1.ts] //// + +//// [base.js] +class Base { + constructor() {} +} + +const BaseFactory = () => { + return new Base(); +}; + +BaseFactory.Base = Base; + +module.exports = BaseFactory; + +//// [file.js] +/** @typedef {import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { + return base; +}; + + +//// [base.js] +class Base { + constructor() { } +} +const BaseFactory = () => { + return new Base(); +}; +BaseFactory.Base = Base; +module.exports = BaseFactory; +//// [file.js] +/** @typedef {import('./base')} BaseFactory */ +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { + return base; +}; + + +//// [base.d.ts] +export = BaseFactory; +declare function BaseFactory(): Base; +declare namespace BaseFactory { + export { Base }; +} +declare class Base { +} diff --git a/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.symbols b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.symbols new file mode 100644 index 0000000000000..d927bfa797baf --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.symbols @@ -0,0 +1,44 @@ +=== tests/cases/conformance/jsdoc/declarations/base.js === +class Base { +>Base : Symbol(Base, Decl(base.js, 0, 0)) + + constructor() {} +} + +const BaseFactory = () => { +>BaseFactory : Symbol(BaseFactory, Decl(base.js, 4, 5), Decl(base.js, 6, 2)) + + return new Base(); +>Base : Symbol(Base, Decl(base.js, 0, 0)) + +}; + +BaseFactory.Base = Base; +>BaseFactory.Base : Symbol(BaseFactory.Base, Decl(base.js, 6, 2)) +>BaseFactory : Symbol(BaseFactory, Decl(base.js, 4, 5), Decl(base.js, 6, 2)) +>Base : Symbol(BaseFactory.Base, Decl(base.js, 6, 2)) +>Base : Symbol(Base, Decl(base.js, 0, 0)) + +module.exports = BaseFactory; +>module.exports : Symbol("tests/cases/conformance/jsdoc/declarations/base", Decl(base.js, 0, 0)) +>module : Symbol(export=, Decl(base.js, 8, 24)) +>exports : Symbol(export=, Decl(base.js, 8, 24)) +>BaseFactory : Symbol(BaseFactory, Decl(base.js, 4, 5), Decl(base.js, 6, 2)) + +=== tests/cases/conformance/jsdoc/declarations/file.js === +/** @typedef {import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { +>test : Symbol(test, Decl(file.js, 7, 5)) +>base : Symbol(base, Decl(file.js, 7, 14)) + + return base; +>base : Symbol(base, Decl(file.js, 7, 14)) + +}; + diff --git a/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.types b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.types new file mode 100644 index 0000000000000..0c45177a183b3 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit1.types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/jsdoc/declarations/base.js === +class Base { +>Base : Base + + constructor() {} +} + +const BaseFactory = () => { +>BaseFactory : { (): Base; Base: typeof Base; } +>() => { return new Base();} : { (): Base; Base: typeof Base; } + + return new Base(); +>new Base() : Base +>Base : typeof Base + +}; + +BaseFactory.Base = Base; +>BaseFactory.Base = Base : typeof Base +>BaseFactory.Base : typeof Base +>BaseFactory : { (): Base; Base: typeof Base; } +>Base : typeof Base +>Base : typeof Base + +module.exports = BaseFactory; +>module.exports = BaseFactory : { (): Base; Base: typeof Base; } +>module.exports : { (): Base; Base: typeof Base; } +>module : { "\"tests/cases/conformance/jsdoc/declarations/base\"": { (): Base; Base: typeof Base; }; } +>exports : { (): Base; Base: typeof Base; } +>BaseFactory : { (): Base; Base: typeof Base; } + +=== tests/cases/conformance/jsdoc/declarations/file.js === +/** @typedef {import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { +>test : (base: InstanceType) => Base +>(base) => { return base;} : (base: InstanceType) => Base +>base : Base + + return base; +>base : Base + +}; + diff --git a/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.js b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.js new file mode 100644 index 0000000000000..15357997c00fe --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.js @@ -0,0 +1,66 @@ +//// [tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit2.ts] //// + +//// [base.js] +class Base { + constructor() {} +} + +const BaseFactory = () => { + return new Base(); +}; + +BaseFactory.Base = Base; + +module.exports = BaseFactory; + +//// [file.js] +/** @typedef {typeof import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { + return base; +}; + + +//// [base.js] +class Base { + constructor() { } +} +const BaseFactory = () => { + return new Base(); +}; +BaseFactory.Base = Base; +module.exports = BaseFactory; +//// [file.js] +/** @typedef {typeof import('./base')} BaseFactory */ +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { + return base; +}; + + +//// [base.d.ts] +export = BaseFactory; +declare function BaseFactory(): Base; +declare namespace BaseFactory { + export { Base }; +} +declare class Base { +} +//// [file.d.ts] +/** @typedef {typeof import('./base')} BaseFactory */ +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +declare function test(base: InstanceType): InstanceType; +type BaseFactory = typeof import('./base'); diff --git a/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.symbols b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.symbols new file mode 100644 index 0000000000000..f23f9f84f2d34 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.symbols @@ -0,0 +1,44 @@ +=== tests/cases/conformance/jsdoc/declarations/base.js === +class Base { +>Base : Symbol(Base, Decl(base.js, 0, 0)) + + constructor() {} +} + +const BaseFactory = () => { +>BaseFactory : Symbol(BaseFactory, Decl(base.js, 4, 5), Decl(base.js, 6, 2)) + + return new Base(); +>Base : Symbol(Base, Decl(base.js, 0, 0)) + +}; + +BaseFactory.Base = Base; +>BaseFactory.Base : Symbol(BaseFactory.Base, Decl(base.js, 6, 2)) +>BaseFactory : Symbol(BaseFactory, Decl(base.js, 4, 5), Decl(base.js, 6, 2)) +>Base : Symbol(BaseFactory.Base, Decl(base.js, 6, 2)) +>Base : Symbol(Base, Decl(base.js, 0, 0)) + +module.exports = BaseFactory; +>module.exports : Symbol("tests/cases/conformance/jsdoc/declarations/base", Decl(base.js, 0, 0)) +>module : Symbol(export=, Decl(base.js, 8, 24)) +>exports : Symbol(export=, Decl(base.js, 8, 24)) +>BaseFactory : Symbol(BaseFactory, Decl(base.js, 4, 5), Decl(base.js, 6, 2)) + +=== tests/cases/conformance/jsdoc/declarations/file.js === +/** @typedef {typeof import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { +>test : Symbol(test, Decl(file.js, 7, 5)) +>base : Symbol(base, Decl(file.js, 7, 14)) + + return base; +>base : Symbol(base, Decl(file.js, 7, 14)) + +}; + diff --git a/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.types b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.types new file mode 100644 index 0000000000000..196e7c7dff00c --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsParameterTagReusesInputNodeInEmit2.types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/jsdoc/declarations/base.js === +class Base { +>Base : Base + + constructor() {} +} + +const BaseFactory = () => { +>BaseFactory : { (): Base; Base: typeof Base; } +>() => { return new Base();} : { (): Base; Base: typeof Base; } + + return new Base(); +>new Base() : Base +>Base : typeof Base + +}; + +BaseFactory.Base = Base; +>BaseFactory.Base = Base : typeof Base +>BaseFactory.Base : typeof Base +>BaseFactory : { (): Base; Base: typeof Base; } +>Base : typeof Base +>Base : typeof Base + +module.exports = BaseFactory; +>module.exports = BaseFactory : { (): Base; Base: typeof Base; } +>module.exports : { (): Base; Base: typeof Base; } +>module : { "\"tests/cases/conformance/jsdoc/declarations/base\"": { (): Base; Base: typeof Base; }; } +>exports : { (): Base; Base: typeof Base; } +>BaseFactory : { (): Base; Base: typeof Base; } + +=== tests/cases/conformance/jsdoc/declarations/file.js === +/** @typedef {typeof import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { +>test : (base: InstanceType) => Base +>(base) => { return base;} : (base: InstanceType) => Base +>base : Base + + return base; +>base : Base + +}; + diff --git a/tests/baselines/reference/jsDeclarationsTypeAliases.js b/tests/baselines/reference/jsDeclarationsTypeAliases.js index 0b37a9a5b2644..79aa5ef4f5d12 100644 --- a/tests/baselines/reference/jsDeclarationsTypeAliases.js +++ b/tests/baselines/reference/jsDeclarationsTypeAliases.js @@ -119,9 +119,9 @@ export type MixinName = T & { */ export type Identity = (x: T) => T; //// [mixed.d.ts] -export type SomeType = number | { +export type SomeType = { x: string; -} | LocalThing | ExportedThing; +} | number | LocalThing | ExportedThing; /** * @typedef {{x: string} | number | LocalThing | ExportedThing} SomeType */ diff --git a/tests/baselines/reference/jsDeclarationsTypedefPropertyAndExportAssignment.js b/tests/baselines/reference/jsDeclarationsTypedefPropertyAndExportAssignment.js index 7ef19ce822f8a..7b6bcdecb0c27 100644 --- a/tests/baselines/reference/jsDeclarationsTypedefPropertyAndExportAssignment.js +++ b/tests/baselines/reference/jsDeclarationsTypedefPropertyAndExportAssignment.js @@ -104,7 +104,7 @@ module.exports = MainThreadTasks; //// [module.d.ts] -export type TaskGroupIds = "parseHTML" | "styleLayout"; +export type TaskGroupIds = 'parseHTML' | 'styleLayout'; export type TaskGroup = { id: TaskGroupIds; label: string; @@ -154,11 +154,7 @@ declare class MainThreadTasks { declare namespace MainThreadTasks { export { TaskGroup, TaskNode, PriorTaskData }; } -type TaskGroup = { - id: import("./module.js").TaskGroupIds; - label: string; - traceEventNames: string[]; -}; +type TaskGroup = import('./module.js').TaskGroup; type TaskNode = { children: TaskNode[]; parent: TaskNode | undefined; diff --git a/tests/baselines/reference/jsdocImportTypeReferenceToCommonjsModule.types b/tests/baselines/reference/jsdocImportTypeReferenceToCommonjsModule.types index 50d2bcc48d0fb..5d376c2852fda 100644 --- a/tests/baselines/reference/jsdocImportTypeReferenceToCommonjsModule.types +++ b/tests/baselines/reference/jsdocImportTypeReferenceToCommonjsModule.types @@ -11,7 +11,7 @@ export = config; === tests/cases/conformance/jsdoc/test.js === /** @param {import('./ex')} a */ function demo(a) { ->demo : (a: import('./ex')) => void +>demo : (a: { fix: boolean; }) => void >a : { fix: boolean; } a.fix diff --git a/tests/baselines/reference/jsdocImportTypeReferenceToESModule.types b/tests/baselines/reference/jsdocImportTypeReferenceToESModule.types index 7866b98bd2750..d2cf23fbdd026 100644 --- a/tests/baselines/reference/jsdocImportTypeReferenceToESModule.types +++ b/tests/baselines/reference/jsdocImportTypeReferenceToESModule.types @@ -5,7 +5,7 @@ export var config: {} === tests/cases/conformance/jsdoc/test.js === /** @param {import('./ex')} a */ function demo(a) { ->demo : (a: import('./ex')) => void +>demo : (a: typeof import("tests/cases/conformance/jsdoc/ex")) => void >a : typeof import("tests/cases/conformance/jsdoc/ex") a.config diff --git a/tests/baselines/reference/recursiveTypeReferences2.js b/tests/baselines/reference/recursiveTypeReferences2.js index fd1ee48e1af1a..852417eca2850 100644 --- a/tests/baselines/reference/recursiveTypeReferences2.js +++ b/tests/baselines/reference/recursiveTypeReferences2.js @@ -78,11 +78,11 @@ var p = {}; declare const p: XMLObject<{ foo: string; }>; -type JsonArray = readonly Json[]; +type JsonArray = ReadonlyArray; type JsonRecord = { readonly [key: string]: Json; }; -type Json = string | number | boolean | JsonRecord | JsonArray | readonly []; +type Json = boolean | number | string | null | JsonRecord | readonly Json[] | readonly []; /** * */ diff --git a/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-js-based-projects-and-emits-them-correctly.js b/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-js-based-projects-and-emits-them-correctly.js index d60d47bb28ae7..f1e988e16f528 100644 --- a/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-js-based-projects-and-emits-them-correctly.js +++ b/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-js-based-projects-and-emits-them-correctly.js @@ -168,9 +168,8 @@ module.exports = {}; } //// [/lib/sub-project/index.d.ts] -export type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +export type MyNominal = Nominal; +import { Nominal } from "../common/nominal"; //// [/lib/sub-project/index.js] @@ -197,7 +196,7 @@ exports.__esModule = true; }, "../../src/sub-project/index.js": { "version": "-23375763082-import { Nominal } from '../common/nominal';\n\n/**\n * @typedef {Nominal} MyNominal\n */\n", - "signature": "-4500199036-export type MyNominal = string & {\r\n [Symbol.species]: \"MyNominal\";\r\n};\r\n", + "signature": "-1163946571-export type MyNominal = Nominal;\r\nimport { Nominal } from \"../common/nominal\";\r\n", "affectsGlobalScope": false } }, @@ -263,9 +262,14 @@ exports.getVar = getVar; "signature": "-32082413277-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };\ninterface SymbolConstructor {\n readonly species: symbol;\n readonly toStringTag: symbol;\n}\ndeclare var Symbol: SymbolConstructor;\ninterface Symbol {\n readonly [Symbol.toStringTag]: string;\n}\n", "affectsGlobalScope": true }, + "../common/nominal.d.ts": { + "version": "-15964609857-export type Nominal = T & {\r\n [Symbol.species]: Name;\r\n};\r\n", + "signature": "-15964609857-export type Nominal = T & {\r\n [Symbol.species]: Name;\r\n};\r\n", + "affectsGlobalScope": false + }, "../sub-project/index.d.ts": { - "version": "-4500199036-export type MyNominal = string & {\r\n [Symbol.species]: \"MyNominal\";\r\n};\r\n", - "signature": "-4500199036-export type MyNominal = string & {\r\n [Symbol.species]: \"MyNominal\";\r\n};\r\n", + "version": "-1163946571-export type MyNominal = Nominal;\r\nimport { Nominal } from \"../common/nominal\";\r\n", + "signature": "-1163946571-export type MyNominal = Nominal;\r\nimport { Nominal } from \"../common/nominal\";\r\n", "affectsGlobalScope": false }, "../../src/sub-project-2/index.js": { @@ -285,12 +289,20 @@ exports.getVar = getVar; "configFilePath": "../../src/sub-project-2/tsconfig.json" }, "referencedMap": { + "../sub-project/index.d.ts": [ + "../common/nominal.d.ts" + ], "../../src/sub-project-2/index.js": [ "../sub-project/index.d.ts" ] }, - "exportedModulesMap": {}, + "exportedModulesMap": { + "../sub-project/index.d.ts": [ + "../common/nominal.d.ts" + ] + }, "semanticDiagnosticsPerFile": [ + "../common/nominal.d.ts", "../lib.d.ts", "../sub-project/index.d.ts", "../../src/sub-project-2/index.js" diff --git a/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-outfile-js-projects-and-concatenates-them-correctly.js b/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-outfile-js-projects-and-concatenates-them-correctly.js index e95a85b307165..b83d2ecf65cd1 100644 --- a/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-outfile-js-projects-and-concatenates-them-correctly.js +++ b/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/loads-outfile-js-projects-and-concatenates-them-correctly.js @@ -191,9 +191,7 @@ type Nominal = T & { * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; //// [/src/sub-project/sub-project.js] @@ -253,7 +251,7 @@ var c = /** @type {*} */ (null); }, { "pos": 64, - "end": 220, + "end": 199, "kind": "text" } ] @@ -293,14 +291,12 @@ type Nominal = T & { }; ---------------------------------------------------------------------- -text: (64-220) +text: (64-199) /** * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; ====================================================================== @@ -312,9 +308,7 @@ type Nominal = T & { * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; /** * @return {keyof typeof variable} */ @@ -377,20 +371,20 @@ function getVar() { "sections": [ { "pos": 0, - "end": 220, + "end": 199, "kind": "prepend", "data": "../sub-project/sub-project.d.ts", "texts": [ { "pos": 0, - "end": 220, + "end": 199, "kind": "text" } ] }, { - "pos": 220, - "end": 377, + "pos": 199, + "end": 356, "kind": "text" } ] @@ -431,9 +425,9 @@ function getVar() { ====================================================================== File:: /src/sub-project-2/sub-project-2.d.ts ---------------------------------------------------------------------- -prepend: (0-220):: ../sub-project/sub-project.d.ts texts:: 1 +prepend: (0-199):: ../sub-project/sub-project.d.ts texts:: 1 >>-------------------------------------------------------------------- -text: (0-220) +text: (0-199) type Nominal = T & { [Symbol.species]: Name; }; @@ -441,12 +435,10 @@ type Nominal = T & { * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; ---------------------------------------------------------------------- -text: (220-377) +text: (199-356) /** * @return {keyof typeof variable} */ diff --git a/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/modifies-outfile-js-projects-and-concatenates-them-correctly.js b/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/modifies-outfile-js-projects-and-concatenates-them-correctly.js index d386ee34b0792..1956dd29fdc50 100644 --- a/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/modifies-outfile-js-projects-and-concatenates-them-correctly.js +++ b/tests/baselines/reference/tsbuild/javascriptProjectEmit/initial-build/modifies-outfile-js-projects-and-concatenates-them-correctly.js @@ -191,9 +191,7 @@ type Nominal = T & { * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; //// [/src/sub-project/sub-project.js] @@ -253,7 +251,7 @@ var c = /** @type {*} */ (null); }, { "pos": 64, - "end": 220, + "end": 199, "kind": "text" } ] @@ -293,14 +291,12 @@ type Nominal = T & { }; ---------------------------------------------------------------------- -text: (64-220) +text: (64-199) /** * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; ====================================================================== @@ -312,9 +308,7 @@ type Nominal = T & { * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; /** * @return {keyof typeof variable} */ @@ -377,20 +371,20 @@ function getVar() { "sections": [ { "pos": 0, - "end": 220, + "end": 199, "kind": "prepend", "data": "../sub-project/sub-project.d.ts", "texts": [ { "pos": 0, - "end": 220, + "end": 199, "kind": "text" } ] }, { - "pos": 220, - "end": 377, + "pos": 199, + "end": 356, "kind": "text" } ] @@ -431,9 +425,9 @@ function getVar() { ====================================================================== File:: /src/sub-project-2/sub-project-2.d.ts ---------------------------------------------------------------------- -prepend: (0-220):: ../sub-project/sub-project.d.ts texts:: 1 +prepend: (0-199):: ../sub-project/sub-project.d.ts texts:: 1 >>-------------------------------------------------------------------- -text: (0-220) +text: (0-199) type Nominal = T & { [Symbol.species]: Name; }; @@ -441,12 +435,10 @@ type Nominal = T & { * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; ---------------------------------------------------------------------- -text: (220-377) +text: (199-356) /** * @return {keyof typeof variable} */ @@ -533,7 +525,7 @@ var c = /** @type {*} */ (undefined); }, { "pos": 64, - "end": 220, + "end": 199, "kind": "text" } ] @@ -573,14 +565,12 @@ type Nominal = T & { }; ---------------------------------------------------------------------- -text: (64-220) +text: (64-199) /** * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; ====================================================================== @@ -637,20 +627,20 @@ function getVar() { "sections": [ { "pos": 0, - "end": 220, + "end": 199, "kind": "prepend", "data": "../sub-project/sub-project.d.ts", "texts": [ { "pos": 0, - "end": 220, + "end": 199, "kind": "text" } ] }, { - "pos": 220, - "end": 377, + "pos": 199, + "end": 356, "kind": "text" } ] @@ -691,9 +681,9 @@ function getVar() { ====================================================================== File:: /src/sub-project-2/sub-project-2.d.ts ---------------------------------------------------------------------- -prepend: (0-220):: ../sub-project/sub-project.d.ts texts:: 1 +prepend: (0-199):: ../sub-project/sub-project.d.ts texts:: 1 >>-------------------------------------------------------------------- -text: (0-220) +text: (0-199) type Nominal = T & { [Symbol.species]: Name; }; @@ -701,12 +691,10 @@ type Nominal = T & { * @typedef {Nominal} MyNominal */ declare const c: any; -type MyNominal = string & { - [Symbol.species]: "MyNominal"; -}; +type MyNominal = Nominal; ---------------------------------------------------------------------- -text: (220-377) +text: (199-356) /** * @return {keyof typeof variable} */ diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit1.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit1.ts new file mode 100644 index 0000000000000..6fe01d7b515b3 --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit1.ts @@ -0,0 +1,29 @@ +// @allowJs: true +// @checkJs: true +// @target: es6 +// @outDir: ./out +// @declaration: true +// @filename: base.js +class Base { + constructor() {} +} + +const BaseFactory = () => { + return new Base(); +}; + +BaseFactory.Base = Base; + +module.exports = BaseFactory; + +// @filename: file.js +/** @typedef {import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { + return base; +}; diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit2.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit2.ts new file mode 100644 index 0000000000000..733ac3b676028 --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsParameterTagReusesInputNodeInEmit2.ts @@ -0,0 +1,29 @@ +// @allowJs: true +// @checkJs: true +// @target: es6 +// @outDir: ./out +// @declaration: true +// @filename: base.js +class Base { + constructor() {} +} + +const BaseFactory = () => { + return new Base(); +}; + +BaseFactory.Base = Base; + +module.exports = BaseFactory; + +// @filename: file.js +/** @typedef {typeof import('./base')} BaseFactory */ + +/** + * + * @param {InstanceType} base + * @returns {InstanceType} + */ +const test = (base) => { + return base; +}; From f7c8ddb0de7cb056bca204edbaabe90e7cbe6f28 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 4 Dec 2020 13:19:25 -0800 Subject: [PATCH 2/2] Style comments --- src/compiler/checker.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 94e7da2a288a9..8ea0d47a63451 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5961,13 +5961,14 @@ namespace ts { return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); } if (isLiteralImportTypeNode(node)) { + const nodeSymbol = getNodeLinks(node).resolvedSymbol; if (isInJSDoc(node) && - getNodeLinks(node).resolvedSymbol && + nodeSymbol && ( // The import type resolved using jsdoc fallback logic - (!node.isTypeOf && !(getNodeLinks(node).resolvedSymbol!.flags & SymbolFlags.Type)) || + (!node.isTypeOf && !(nodeSymbol.flags & SymbolFlags.Type)) || // The import type had type arguments autofilled by js fallback logic - !(length(node.typeArguments) >= getMinTypeArgumentCount(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(getNodeLinks(node).resolvedSymbol!))) + !(length(node.typeArguments) >= getMinTypeArgumentCount(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(nodeSymbol))) ) ) { return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); @@ -6547,7 +6548,10 @@ namespace ts { const commentText = jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined; const oldFlags = context.flags; context.flags |= NodeBuilderFlags.InTypeAlias; - const typeNode = jsdocAliasDecl && jsdocAliasDecl.typeExpression && isJSDocTypeExpression(jsdocAliasDecl.typeExpression) && serializeExistingTypeNode(context, jsdocAliasDecl.typeExpression.type, includePrivateSymbol, bundled) || typeToTypeNodeHelper(aliasType, context); + const typeNode = jsdocAliasDecl && jsdocAliasDecl.typeExpression + && isJSDocTypeExpression(jsdocAliasDecl.typeExpression) + && serializeExistingTypeNode(context, jsdocAliasDecl.typeExpression.type, includePrivateSymbol, bundled) + || typeToTypeNodeHelper(aliasType, context); addResult(setSyntheticLeadingComments( factory.createTypeAliasDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeNode), !commentText ? [] : [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]