From 1ed30c6d4d78aeb7de0c81604dbf38120d82e82b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 29 Mar 2018 16:15:55 -0700 Subject: [PATCH] Elide type reference comments which are also imported (#22752) * Elide type reference comments which are also imported * Explicit undefined * Accept reordered symbols --- src/compiler/transformers/declarations.ts | 17 ++++- ...ionEmitUnnessesaryTypeReferenceNotAdded.js | 73 +++++++++++++++++++ ...itUnnessesaryTypeReferenceNotAdded.symbols | 40 ++++++++++ ...EmitUnnessesaryTypeReferenceNotAdded.types | 47 ++++++++++++ ...ionEmitUnnessesaryTypeReferenceNotAdded.ts | 34 +++++++++ 5 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.js create mode 100644 tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.symbols create mode 100644 tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.types create mode 100644 tests/cases/compiler/declarationEmitUnnessesaryTypeReferenceNotAdded.ts diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index a7ecab0b4fe..8ce0e32a3ba 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -191,6 +191,7 @@ namespace ts { refs.forEach(referenceVisitor); const statements = visitNodes(node.statements, visitDeclarationStatements); let combinedStatements = setTextRange(createNodeArray(filterCandidateImports(statements)), node.statements); + const emittedImports = filter(combinedStatements, isAnyImportSyntax); if (isExternalModule(node) && !resultHasExternalModuleIndicator) { combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements); } @@ -198,10 +199,22 @@ namespace ts { return updated; function getFileReferencesForUsedTypeReferences() { - return necessaryTypeRefernces ? map(arrayFrom(necessaryTypeRefernces.keys()), getFileReferenceForTypeName) : []; + return necessaryTypeRefernces ? mapDefined(arrayFrom(necessaryTypeRefernces.keys()), getFileReferenceForTypeName) : []; } - function getFileReferenceForTypeName(typeName: string): FileReference { + function getFileReferenceForTypeName(typeName: string): FileReference | undefined { + // Elide type references for which we have imports + for (const importStatement of emittedImports) { + if (isImportEqualsDeclaration(importStatement) && isExternalModuleReference(importStatement.moduleReference)) { + const expr = importStatement.moduleReference.expression; + if (isStringLiteralLike(expr) && expr.text === typeName) { + return undefined; + } + } + else if (isImportDeclaration(importStatement) && isStringLiteral(importStatement.moduleSpecifier) && importStatement.moduleSpecifier.text === typeName) { + return undefined; + } + } return { fileName: typeName, pos: -1, end: -1 }; } diff --git a/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.js b/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.js new file mode 100644 index 00000000000..f3ea5920983 --- /dev/null +++ b/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.js @@ -0,0 +1,73 @@ +//// [tests/cases/compiler/declarationEmitUnnessesaryTypeReferenceNotAdded.ts] //// + +//// [minimist.d.ts] +declare namespace thing { + interface ParsedArgs {} +} +declare function thing(x: any): thing.ParsedArgs; +export = thing; +//// [package.json] +{ + "name": "minimist", + "version": "0.0.1", + "types": "./minimist.d.ts" +} +//// [process.d.ts] +declare const thing: any; +export = thing; +//// [package.json] +{ + "name": "process", + "version": "0.0.1", + "types": "./process.d.ts" +} +//// [index.ts] +import minimist = require('minimist'); +import process = require('process'); + +export default function parseArgs(): minimist.ParsedArgs { + return minimist(process.argv.slice(2)); +} + + +//// [index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var minimist = require("minimist"); +var process = require("process"); +function parseArgs() { + return minimist(process.argv.slice(2)); +} +exports.default = parseArgs; + + +//// [index.d.ts] +import minimist = require('minimist'); +export default function parseArgs(): minimist.ParsedArgs; + + +//// [DtsFileErrors] + + +error TS2688: Cannot find type definition file for 'minimist'. +error TS2688: Cannot find type definition file for 'process'. +/index.d.ts(1,27): error TS2307: Cannot find module 'minimist'. + + +!!! error TS2688: Cannot find type definition file for 'minimist'. +!!! error TS2688: Cannot find type definition file for 'process'. +==== /index.d.ts (1 errors) ==== + import minimist = require('minimist'); + ~~~~~~~~~~ +!!! error TS2307: Cannot find module 'minimist'. + export default function parseArgs(): minimist.ParsedArgs; + +==== /node_modules/@types/minimist/minimist.d.ts (0 errors) ==== + declare namespace thing { + interface ParsedArgs {} + } + declare function thing(x: any): thing.ParsedArgs; + export = thing; +==== /node_modules/@types/process/process.d.ts (0 errors) ==== + declare const thing: any; + export = thing; \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.symbols b/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.symbols new file mode 100644 index 00000000000..30d3f39d910 --- /dev/null +++ b/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.symbols @@ -0,0 +1,40 @@ +=== /index.ts === +import minimist = require('minimist'); +>minimist : Symbol(minimist, Decl(index.ts, 0, 0)) + +import process = require('process'); +>process : Symbol(process, Decl(index.ts, 0, 38)) + +export default function parseArgs(): minimist.ParsedArgs { +>parseArgs : Symbol(parseArgs, Decl(index.ts, 1, 36)) +>minimist : Symbol(minimist, Decl(index.ts, 0, 0)) +>ParsedArgs : Symbol(minimist.ParsedArgs, Decl(minimist.d.ts, 0, 25)) + + return minimist(process.argv.slice(2)); +>minimist : Symbol(minimist, Decl(index.ts, 0, 0)) +>process : Symbol(process, Decl(index.ts, 0, 38)) +} + +=== /node_modules/@types/minimist/minimist.d.ts === +declare namespace thing { +>thing : Symbol(thing, Decl(minimist.d.ts, 2, 1), Decl(minimist.d.ts, 0, 0)) + + interface ParsedArgs {} +>ParsedArgs : Symbol(ParsedArgs, Decl(minimist.d.ts, 0, 25)) +} +declare function thing(x: any): thing.ParsedArgs; +>thing : Symbol(thing, Decl(minimist.d.ts, 2, 1), Decl(minimist.d.ts, 0, 0)) +>x : Symbol(x, Decl(minimist.d.ts, 3, 23)) +>thing : Symbol(thing, Decl(minimist.d.ts, 2, 1), Decl(minimist.d.ts, 0, 0)) +>ParsedArgs : Symbol(thing.ParsedArgs, Decl(minimist.d.ts, 0, 25)) + +export = thing; +>thing : Symbol(thing, Decl(minimist.d.ts, 2, 1), Decl(minimist.d.ts, 0, 0)) + +=== /node_modules/@types/process/process.d.ts === +declare const thing: any; +>thing : Symbol(thing, Decl(process.d.ts, 0, 13)) + +export = thing; +>thing : Symbol(thing, Decl(process.d.ts, 0, 13)) + diff --git a/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.types b/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.types new file mode 100644 index 00000000000..feff017381d --- /dev/null +++ b/tests/baselines/reference/declarationEmitUnnessesaryTypeReferenceNotAdded.types @@ -0,0 +1,47 @@ +=== /index.ts === +import minimist = require('minimist'); +>minimist : (x: any) => minimist.ParsedArgs + +import process = require('process'); +>process : any + +export default function parseArgs(): minimist.ParsedArgs { +>parseArgs : () => minimist.ParsedArgs +>minimist : any +>ParsedArgs : minimist.ParsedArgs + + return minimist(process.argv.slice(2)); +>minimist(process.argv.slice(2)) : minimist.ParsedArgs +>minimist : (x: any) => minimist.ParsedArgs +>process.argv.slice(2) : any +>process.argv.slice : any +>process.argv : any +>process : any +>argv : any +>slice : any +>2 : 2 +} + +=== /node_modules/@types/minimist/minimist.d.ts === +declare namespace thing { +>thing : (x: any) => ParsedArgs + + interface ParsedArgs {} +>ParsedArgs : ParsedArgs +} +declare function thing(x: any): thing.ParsedArgs; +>thing : (x: any) => thing.ParsedArgs +>x : any +>thing : any +>ParsedArgs : thing.ParsedArgs + +export = thing; +>thing : (x: any) => thing.ParsedArgs + +=== /node_modules/@types/process/process.d.ts === +declare const thing: any; +>thing : any + +export = thing; +>thing : any + diff --git a/tests/cases/compiler/declarationEmitUnnessesaryTypeReferenceNotAdded.ts b/tests/cases/compiler/declarationEmitUnnessesaryTypeReferenceNotAdded.ts new file mode 100644 index 00000000000..5247514dc6f --- /dev/null +++ b/tests/cases/compiler/declarationEmitUnnessesaryTypeReferenceNotAdded.ts @@ -0,0 +1,34 @@ +// @declaration: true +// @target: es5 +// @module: commonjs +// @strict: true +// @noImplicitReferences: true +// @currentDirectory: / +// @filename: /node_modules/@types/minimist/minimist.d.ts +declare namespace thing { + interface ParsedArgs {} +} +declare function thing(x: any): thing.ParsedArgs; +export = thing; +// @filename: /node_modules/@types/minimist/package.json +{ + "name": "minimist", + "version": "0.0.1", + "types": "./minimist.d.ts" +} +// @filename: /node_modules/@types/process/process.d.ts +declare const thing: any; +export = thing; +// @filename: /node_modules/@types/process/package.json +{ + "name": "process", + "version": "0.0.1", + "types": "./process.d.ts" +} +// @filename: /index.ts +import minimist = require('minimist'); +import process = require('process'); + +export default function parseArgs(): minimist.ParsedArgs { + return minimist(process.argv.slice(2)); +}