diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index edb25e9cb717a..a106a5c4d09fe 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -588,6 +588,12 @@ namespace ts { category: Diagnostics.Module_Resolution_Options, description: Diagnostics.Do_not_resolve_the_real_path_of_symlinks, }, + { + name: "disableImportOptimizations", + type: "boolean", + category: Diagnostics.Module_Resolution_Options, + description: Diagnostics.Do_not_optimize_imports, + }, // Source Maps { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 52fb34565f885..1c7a5c767a57d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4072,6 +4072,10 @@ "category": "Message", "code": 6381 }, + "Do not optimize imports": { + "category": "Message", + "code": 6382 + }, "The expected type comes from property '{0}' which is declared here on type '{1}'": { "category": "Message", diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 63d621c665439..f26b803433bd1 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -3049,6 +3049,10 @@ namespace ts { * @param node The import declaration node. */ function visitImportDeclaration(node: ImportDeclaration): VisitResult { + if (compilerOptions.disableImportOptimizations) { + return node; + } + if (!node.importClause) { // Do not elide a side-effect only import declaration. // import "foo"; @@ -3073,6 +3077,10 @@ namespace ts { * @param node The import clause node. */ function visitImportClause(node: ImportClause): VisitResult { + if (compilerOptions.disableImportOptimizations) { + return node; + } + // Elide the import clause if we elide both its name and its named bindings. const name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined; const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings); @@ -3085,6 +3093,10 @@ namespace ts { * @param node The named import bindings node. */ function visitNamedImportBindings(node: NamedImportBindings): VisitResult { + if (compilerOptions.disableImportOptimizations) { + return node; + } + if (node.kind === SyntaxKind.NamespaceImport) { // Elide a namespace import if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? node : undefined; @@ -3102,6 +3114,10 @@ namespace ts { * @param node The import specifier node. */ function visitImportSpecifier(node: ImportSpecifier): VisitResult { + if (compilerOptions.disableImportOptimizations) { + return node; + } + // Elide an import specifier if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? node : undefined; } @@ -3113,6 +3129,10 @@ namespace ts { * @param node The export assignment node. */ function visitExportAssignment(node: ExportAssignment): VisitResult { + if (compilerOptions.disableImportOptimizations) { + return node; + } + // Elide the export assignment if it does not reference a value. return resolver.isValueAliasDeclaration(node) ? visitEachChild(node, visitor, context) diff --git a/tests/baselines/reference/disableImportOptimizations.js b/tests/baselines/reference/disableImportOptimizations.js new file mode 100644 index 0000000000000..dcfc6ac371c77 --- /dev/null +++ b/tests/baselines/reference/disableImportOptimizations.js @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/disableImportOptimizations.ts] //// + +//// [disableImportOptimizations1.ts] +export class ClassWithSideEffect { + static someValue = ClassWithSideEffect.initValue(); + + static initValue(): string { + console.log("We have a side-effect here!"); + return "something"; + } +} + +//// [disableImportOptimizations2.ts] +import { ClassWithSideEffect } from "./disableImportOptimizations1"; //Import gets removed without disableImportOptimizations + +export class OtherClass { +} + +//// [disableImportOptimizations1.js] +"use strict"; +exports.__esModule = true; +var ClassWithSideEffect = /** @class */ (function () { + function ClassWithSideEffect() { + } + ClassWithSideEffect.initValue = function () { + console.log("We have a side-effect here!"); + return "something"; + }; + ClassWithSideEffect.someValue = ClassWithSideEffect.initValue(); + return ClassWithSideEffect; +}()); +exports.ClassWithSideEffect = ClassWithSideEffect; +//// [disableImportOptimizations2.js] +"use strict"; +exports.__esModule = true; +var disableImportOptimizations1_1 = require("./disableImportOptimizations1"); //Import gets removed without disableImportOptimizations +var OtherClass = /** @class */ (function () { + function OtherClass() { + } + return OtherClass; +}()); +exports.OtherClass = OtherClass; diff --git a/tests/baselines/reference/disableImportOptimizations.symbols b/tests/baselines/reference/disableImportOptimizations.symbols new file mode 100644 index 0000000000000..af6e94b222a21 --- /dev/null +++ b/tests/baselines/reference/disableImportOptimizations.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/disableImportOptimizations1.ts === +export class ClassWithSideEffect { +>ClassWithSideEffect : Symbol(ClassWithSideEffect, Decl(disableImportOptimizations1.ts, 0, 0)) + + static someValue = ClassWithSideEffect.initValue(); +>someValue : Symbol(ClassWithSideEffect.someValue, Decl(disableImportOptimizations1.ts, 0, 34)) +>ClassWithSideEffect.initValue : Symbol(ClassWithSideEffect.initValue, Decl(disableImportOptimizations1.ts, 1, 53)) +>ClassWithSideEffect : Symbol(ClassWithSideEffect, Decl(disableImportOptimizations1.ts, 0, 0)) +>initValue : Symbol(ClassWithSideEffect.initValue, Decl(disableImportOptimizations1.ts, 1, 53)) + + static initValue(): string { +>initValue : Symbol(ClassWithSideEffect.initValue, Decl(disableImportOptimizations1.ts, 1, 53)) + + console.log("We have a side-effect here!"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + + return "something"; + } +} + +=== tests/cases/compiler/disableImportOptimizations2.ts === +import { ClassWithSideEffect } from "./disableImportOptimizations1"; //Import gets removed without disableImportOptimizations +>ClassWithSideEffect : Symbol(ClassWithSideEffect, Decl(disableImportOptimizations2.ts, 0, 8)) + +export class OtherClass { +>OtherClass : Symbol(OtherClass, Decl(disableImportOptimizations2.ts, 0, 68)) +} diff --git a/tests/baselines/reference/disableImportOptimizations.types b/tests/baselines/reference/disableImportOptimizations.types new file mode 100644 index 0000000000000..90c30e8c75b4f --- /dev/null +++ b/tests/baselines/reference/disableImportOptimizations.types @@ -0,0 +1,33 @@ +=== tests/cases/compiler/disableImportOptimizations1.ts === +export class ClassWithSideEffect { +>ClassWithSideEffect : ClassWithSideEffect + + static someValue = ClassWithSideEffect.initValue(); +>someValue : string +>ClassWithSideEffect.initValue() : string +>ClassWithSideEffect.initValue : () => string +>ClassWithSideEffect : typeof ClassWithSideEffect +>initValue : () => string + + static initValue(): string { +>initValue : () => string + + console.log("We have a side-effect here!"); +>console.log("We have a side-effect here!") : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>"We have a side-effect here!" : "We have a side-effect here!" + + return "something"; +>"something" : "something" + } +} + +=== tests/cases/compiler/disableImportOptimizations2.ts === +import { ClassWithSideEffect } from "./disableImportOptimizations1"; //Import gets removed without disableImportOptimizations +>ClassWithSideEffect : typeof ClassWithSideEffect + +export class OtherClass { +>OtherClass : OtherClass +} diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/disableImportOptimizations/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/disableImportOptimizations/tsconfig.json new file mode 100644 index 0000000000000..91760fa1370b8 --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/disableImportOptimizations/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "disableImportOptimizations": true + } +} diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 8e4ff5171868d..d67a7b882d3dc 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json index 7332496971fba..bbffbc42aaacc 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index ebf7070cfa4d4..f2ae95d25dee7 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index 25f9b39967a8d..0847ae3ad3ad1 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index fc1fb8ec631d8..79e1b45f4e713 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index dcff85de986d4..3b3663bcb2e3e 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 8e4ff5171868d..d67a7b882d3dc 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index 112be7a95f953..11681b39ee331 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 4c4b740a12284..4a5a8ebeb5531 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -48,6 +48,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "disableImportOptimizations": true, /* Do not optimize imports */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ diff --git a/tests/cases/compiler/disableImportOptimizations.ts b/tests/cases/compiler/disableImportOptimizations.ts new file mode 100644 index 0000000000000..689bed099ba18 --- /dev/null +++ b/tests/cases/compiler/disableImportOptimizations.ts @@ -0,0 +1,17 @@ +// @disableImportOptimizations: true + +// @fileName: disableImportOptimizations1.ts +export class ClassWithSideEffect { + static someValue = ClassWithSideEffect.initValue(); + + static initValue(): string { + console.log("We have a side-effect here!"); + return "something"; + } +} + +// @fileName: disableImportOptimizations2.ts +import { ClassWithSideEffect } from "./disableImportOptimizations1"; //Import gets removed without disableImportOptimizations + +export class OtherClass { +} \ No newline at end of file