diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fe54402d43481..89a4fd613b399 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -727,7 +727,7 @@ namespace ts { case SyntaxKind.VariableStatement: return emitVariableStatement(node); case SyntaxKind.EmptyStatement: - return emitEmptyStatement(); + return !(getEmitFlags(node) & EmitFlags.CommentsOnly) ? emitEmptyStatement() : undefined; case SyntaxKind.ExpressionStatement: return emitExpressionStatement(node); case SyntaxKind.IfStatement: diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 4b2855790a985..b8806983d3e51 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -3355,6 +3355,11 @@ namespace ts { // Utilities + /** @internal */ + export function createCommentPreservationStatement(node: Statement): Statement { + return addEmitFlags(setCommentRange(setOriginalNode(createEmptyStatement(), node), node), EmitFlags.CommentsOnly); + } + export function createForOfBindingStatement(node: ForInitializer, boundValue: Expression): Statement { if (isVariableDeclarationList(node)) { const firstDeclaration = first(node.declarations); diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 1b3a623c32d21..3c78bf4c97e52 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -850,6 +850,9 @@ namespace ts { ) ); } + else if (hasLeadingOrTrailingComments(node, currentSourceFile)) { + statements = append(statements, createCommentPreservationStatement(node)); + } if (hasAssociatedEndOfDeclarationMarker(node)) { // Defer exports until we encounter an EndOfDeclarationMarker node @@ -939,6 +942,9 @@ namespace ts { ) ); } + else if (hasLeadingOrTrailingComments(node, currentSourceFile)) { + statements = append(statements, createCommentPreservationStatement(node)); + } } if (hasAssociatedEndOfDeclarationMarker(node)) { diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 09239d7765fd9..f0aee01af365a 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -255,4 +255,8 @@ namespace ts { return result; }; } + + export function hasLeadingOrTrailingComments(node: Node, sourceFile: SourceFile) { + return !!(getSyntheticLeadingComments(node) || getSyntheticTrailingComments(node) || getLeadingCommentRangesOfNode(node, sourceFile) || getTrailingCommentRanges(sourceFile.text, node.pos)); + } } \ No newline at end of file diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9b1c57b20970a..4497cdf77e1c1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5028,6 +5028,7 @@ namespace ts { NoAsciiEscaping = 1 << 24, // When synthesizing nodes that lack an original node or textSourceNode, we want to write the text on the node with ASCII escaping substitutions. /*@internal*/ TypeScriptClassWrapper = 1 << 25, // The node is an IIFE class wrapper created by the ts transform. /*@internal*/ NeverApplyImportHelper = 1 << 26, // Indicates the node should never be wrapped with an import star helper (because, for example, it imports tslib itself) + /*@internal*/ CommentsOnly = 1 << 27, // Only for empty statements, incidcates that the statement exists for comment preservation, so the semicolon may be elided } export interface EmitHelper { diff --git a/tests/baselines/reference/ambientExternalModuleInAnotherExternalModule.js b/tests/baselines/reference/ambientExternalModuleInAnotherExternalModule.js index d6db77b6050ef..7d2fb52a58db1 100644 --- a/tests/baselines/reference/ambientExternalModuleInAnotherExternalModule.js +++ b/tests/baselines/reference/ambientExternalModuleInAnotherExternalModule.js @@ -18,6 +18,7 @@ define(["require", "exports", "ext"], function (require, exports, ext) { } return D; }()); + // Cannot resolve this ext module reference var x = ext; return D; }); diff --git a/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js b/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js index 9efd9e4ada9fc..4872c6c7b18ff 100644 --- a/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js +++ b/tests/baselines/reference/ambientExternalModuleWithInternalImportDeclaration.js @@ -23,5 +23,6 @@ var c = new A(); define(["require", "exports", "M"], function (require, exports, A) { "use strict"; exports.__esModule = true; + /// var c = new A(); }); diff --git a/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js b/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js index 98d3d46912aae..aea25ab42b45f 100644 --- a/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js +++ b/tests/baselines/reference/ambientExternalModuleWithoutInternalImportDeclaration.js @@ -22,5 +22,6 @@ var c = new A(); define(["require", "exports", "M"], function (require, exports, A) { "use strict"; exports.__esModule = true; + /// var c = new A(); }); diff --git a/tests/baselines/reference/augmentExportEquals3_1.js b/tests/baselines/reference/augmentExportEquals3_1.js index e91ca4498dd86..74af4865879d9 100644 --- a/tests/baselines/reference/augmentExportEquals3_1.js +++ b/tests/baselines/reference/augmentExportEquals3_1.js @@ -31,6 +31,7 @@ let b = x.b; define(["require", "exports", "file1"], function (require, exports, x) { "use strict"; exports.__esModule = true; + /// x.b = 1; }); //// [file3.js] diff --git a/tests/baselines/reference/augmentExportEquals4_1.js b/tests/baselines/reference/augmentExportEquals4_1.js index cd2f54599699e..2b62dbc2352b2 100644 --- a/tests/baselines/reference/augmentExportEquals4_1.js +++ b/tests/baselines/reference/augmentExportEquals4_1.js @@ -31,6 +31,7 @@ let b = x.b; define(["require", "exports", "file1"], function (require, exports, x) { "use strict"; exports.__esModule = true; + /// x.b = 1; }); //// [file3.js] diff --git a/tests/baselines/reference/collisionExportsRequireAndAlias.js b/tests/baselines/reference/collisionExportsRequireAndAlias.js index 487553bb00492..27e109a620638 100644 --- a/tests/baselines/reference/collisionExportsRequireAndAlias.js +++ b/tests/baselines/reference/collisionExportsRequireAndAlias.js @@ -37,6 +37,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "collisionExportsRequireAndAlias_file1", "collisionExportsRequireAndAlias_file3333"], function (require, exports, require, exports) { "use strict"; exports.__esModule = true; + // Error function foo() { require.bar(); } diff --git a/tests/baselines/reference/commentsExternalModules.js b/tests/baselines/reference/commentsExternalModules.js index 6271c677e65bd..a951d85badc75 100644 --- a/tests/baselines/reference/commentsExternalModules.js +++ b/tests/baselines/reference/commentsExternalModules.js @@ -129,6 +129,8 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "commentsExternalModules_0"], function (require, exports, extMod) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); + /**This is on import declaration*/ + // trailing comment1 extMod.m1.fooExport(); var newVar = new extMod.m1.m2.c(); extMod.m4.fooExport(); diff --git a/tests/baselines/reference/commentsExternalModules2.js b/tests/baselines/reference/commentsExternalModules2.js index bb8eab82c1e06..e88f6bccdd620 100644 --- a/tests/baselines/reference/commentsExternalModules2.js +++ b/tests/baselines/reference/commentsExternalModules2.js @@ -129,6 +129,8 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "commentsExternalModules2_0"], function (require, exports, extMod) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); + /**This is on import declaration*/ + // trailing comment 1 extMod.m1.fooExport(); exports.newVar = new extMod.m1.m2.c(); extMod.m4.fooExport(); diff --git a/tests/baselines/reference/commentsOnImportInAMDPreserved.js b/tests/baselines/reference/commentsOnImportInAMDPreserved.js new file mode 100644 index 0000000000000..0142fa2f119ef --- /dev/null +++ b/tests/baselines/reference/commentsOnImportInAMDPreserved.js @@ -0,0 +1,10 @@ +//// [commentsOnImportInAMDPreserved.ts] +// foo +import 'foo'; + +//// [commentsOnImportInAMDPreserved.js] +define(["require", "exports", "foo"], function (require, exports) { + "use strict"; + exports.__esModule = true; + // foo +}); diff --git a/tests/baselines/reference/commentsOnImportInAMDPreserved.symbols b/tests/baselines/reference/commentsOnImportInAMDPreserved.symbols new file mode 100644 index 0000000000000..c2c8e06d00663 --- /dev/null +++ b/tests/baselines/reference/commentsOnImportInAMDPreserved.symbols @@ -0,0 +1,4 @@ +=== tests/cases/compiler/commentsOnImportInAMDPreserved.ts === +// foo +No type information for this code.import 'foo'; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/commentsOnImportInAMDPreserved.types b/tests/baselines/reference/commentsOnImportInAMDPreserved.types new file mode 100644 index 0000000000000..c2c8e06d00663 --- /dev/null +++ b/tests/baselines/reference/commentsOnImportInAMDPreserved.types @@ -0,0 +1,4 @@ +=== tests/cases/compiler/commentsOnImportInAMDPreserved.ts === +// foo +No type information for this code.import 'foo'; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/constDeclarations-access5.js b/tests/baselines/reference/constDeclarations-access5.js index cb5d24477187c..283a30d7cf63d 100644 --- a/tests/baselines/reference/constDeclarations-access5.js +++ b/tests/baselines/reference/constDeclarations-access5.js @@ -56,6 +56,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "constDeclarations_access_1"], function (require, exports, m) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); + /// // Errors m.x = 1; m.x += 2; diff --git a/tests/baselines/reference/copyrightWithoutNewLine1.js b/tests/baselines/reference/copyrightWithoutNewLine1.js index 0f479c3db7f26..9b86d02c38b71 100644 --- a/tests/baselines/reference/copyrightWithoutNewLine1.js +++ b/tests/baselines/reference/copyrightWithoutNewLine1.js @@ -12,6 +12,9 @@ greeter.start(); define(["require", "exports", "./greeter"], function (require, exports, model) { "use strict"; exports.__esModule = true; + /***************************** + * (c) Copyright - Important + ****************************/ var el = document.getElementById('content'); var greeter = new model.Greeter(el); /** things */ diff --git a/tests/baselines/reference/exportAssignmentOfGenericType1.js b/tests/baselines/reference/exportAssignmentOfGenericType1.js index ccb9580f87a49..70c60d5c98cc6 100644 --- a/tests/baselines/reference/exportAssignmentOfGenericType1.js +++ b/tests/baselines/reference/exportAssignmentOfGenericType1.js @@ -40,6 +40,7 @@ var __extends = (this && this.__extends) || (function () { define(["require", "exports", "exportAssignmentOfGenericType1_0"], function (require, exports, q) { "use strict"; exports.__esModule = true; + /// var M = /** @class */ (function (_super) { __extends(M, _super); function M() { diff --git a/tests/baselines/reference/exportEqualCallable.js b/tests/baselines/reference/exportEqualCallable.js index 830af3a2a3656..0d7151747f218 100644 --- a/tests/baselines/reference/exportEqualCallable.js +++ b/tests/baselines/reference/exportEqualCallable.js @@ -22,5 +22,6 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "exportEqualCallable_0"], function (require, exports, connect) { "use strict"; exports.__esModule = true; + /// connect(); }); diff --git a/tests/baselines/reference/exportEqualErrorType.js b/tests/baselines/reference/exportEqualErrorType.js index 4a65ce5fd4908..1b0022dd77d3f 100644 --- a/tests/baselines/reference/exportEqualErrorType.js +++ b/tests/baselines/reference/exportEqualErrorType.js @@ -31,5 +31,6 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "exportEqualErrorType_0"], function (require, exports, connect) { "use strict"; exports.__esModule = true; + /// connect().use(connect.static('foo')); // Error 1 The property 'static' does not exist on value of type ''. }); diff --git a/tests/baselines/reference/externalModuleAssignToVar.js b/tests/baselines/reference/externalModuleAssignToVar.js index 4877fd0c01566..20c87cb339e3b 100644 --- a/tests/baselines/reference/externalModuleAssignToVar.js +++ b/tests/baselines/reference/externalModuleAssignToVar.js @@ -61,6 +61,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "externalModuleAssignToVar_core_require", "externalModuleAssignToVar_core_require2", "externalModuleAssignToVar_ext"], function (require, exports, ext, ext2, ext3) { "use strict"; exports.__esModule = true; + /// var y1 = ext; y1 = ext; // ok var y2 = ext2; diff --git a/tests/baselines/reference/instanceOfInExternalModules.js b/tests/baselines/reference/instanceOfInExternalModules.js index 9e3949a528516..14e31904e958d 100644 --- a/tests/baselines/reference/instanceOfInExternalModules.js +++ b/tests/baselines/reference/instanceOfInExternalModules.js @@ -26,6 +26,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "instanceOfInExternalModules_require"], function (require, exports, Bar) { "use strict"; exports.__esModule = true; + /// function IsFoo(value) { return value instanceof Bar.Foo; } diff --git a/tests/baselines/reference/memberAccessMustUseModuleInstances.js b/tests/baselines/reference/memberAccessMustUseModuleInstances.js index 1612a0632f0ff..949dbfb450422 100644 --- a/tests/baselines/reference/memberAccessMustUseModuleInstances.js +++ b/tests/baselines/reference/memberAccessMustUseModuleInstances.js @@ -32,5 +32,6 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "memberAccessMustUseModuleInstances_0"], function (require, exports, WinJS) { "use strict"; exports.__esModule = true; + /// WinJS.Promise.timeout(10); }); diff --git a/tests/baselines/reference/moduleAliasAsFunctionArgument.js b/tests/baselines/reference/moduleAliasAsFunctionArgument.js index 16eb962a863ce..2f85c53c0ee88 100644 --- a/tests/baselines/reference/moduleAliasAsFunctionArgument.js +++ b/tests/baselines/reference/moduleAliasAsFunctionArgument.js @@ -23,6 +23,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "moduleAliasAsFunctionArgument_0"], function (require, exports, a) { "use strict"; exports.__esModule = true; + /// function fn(arg) { } a.x; // OK diff --git a/tests/baselines/reference/moduleAugmentationsImports3.js b/tests/baselines/reference/moduleAugmentationsImports3.js index 921e65b2e0fe0..b0534521a602b 100644 --- a/tests/baselines/reference/moduleAugmentationsImports3.js +++ b/tests/baselines/reference/moduleAugmentationsImports3.js @@ -69,6 +69,7 @@ define("b", ["require", "exports"], function (require, exports) { define("e", ["require", "exports", "a"], function (require, exports, a_1) { "use strict"; exports.__esModule = true; + /// a_1.A.prototype.getCls = function () { return undefined; }; }); define("main", ["require", "exports", "D", "e"], function (require, exports) { diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.js index 16ef9260e8d12..d1c48367ed8fc 100644 --- a/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.js +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.js @@ -34,6 +34,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "./file3", "file4"], function (require, exports, file3_1, file4_1) { "use strict"; exports.__esModule = true; + // found with fallback exports.x = file3_1.x + file4_1.y; }); //// [file1.js] diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.js index 2a8254fb69687..e5cd2bf448cae 100644 --- a/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.js +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.js @@ -32,6 +32,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "./file3", "file4"], function (require, exports, file3_1, file4_1) { "use strict"; exports.__esModule = true; + // found with fallback exports.x = file3_1.x + file4_1.y; }); //// [file1.js] diff --git a/tests/baselines/reference/privacyTopLevelAmbientExternalModuleImportWithoutExport.js b/tests/baselines/reference/privacyTopLevelAmbientExternalModuleImportWithoutExport.js index 14b52a1ea3ade..ed299f480d49b 100644 --- a/tests/baselines/reference/privacyTopLevelAmbientExternalModuleImportWithoutExport.js +++ b/tests/baselines/reference/privacyTopLevelAmbientExternalModuleImportWithoutExport.js @@ -76,6 +76,9 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "m", "m2", "privacyTopLevelAmbientExternalModuleImportWithoutExport_require"], function (require, exports, im_private_mi_private, im_private_mu_private, im_private_mi_public) { "use strict"; exports.__esModule = true; + /// + /// + // Privacy errors - importing private elements // Usage of privacy error imports var privateUse_im_private_mi_private = new im_private_mi_private.c_private(); exports.publicUse_im_private_mi_private = new im_private_mi_private.c_private(); diff --git a/tests/baselines/reference/project/declarationsImportedInPrivate/amd/useModule.js b/tests/baselines/reference/project/declarationsImportedInPrivate/amd/useModule.js index 6ecb0c59793af..0b2d3fd1fd4c8 100644 --- a/tests/baselines/reference/project/declarationsImportedInPrivate/amd/useModule.js +++ b/tests/baselines/reference/project/declarationsImportedInPrivate/amd/useModule.js @@ -1,6 +1,7 @@ define(["require", "exports", "private_m4"], function (require, exports, private_m4) { "use strict"; exports.__esModule = true; + // only used privately no need to emit var usePrivate_m4_m1; (function (usePrivate_m4_m1) { var x3 = private_m4.x; diff --git a/tests/baselines/reference/project/declarationsIndirectImportShouldResultInError/amd/useModule.js b/tests/baselines/reference/project/declarationsIndirectImportShouldResultInError/amd/useModule.js index 6f962bd42e5ed..92416c38e120c 100644 --- a/tests/baselines/reference/project/declarationsIndirectImportShouldResultInError/amd/useModule.js +++ b/tests/baselines/reference/project/declarationsIndirectImportShouldResultInError/amd/useModule.js @@ -1,6 +1,7 @@ define(["require", "exports", "m5"], function (require, exports, m5) { "use strict"; exports.__esModule = true; + // Do not emit unused import exports.d = m5.foo2(); exports.x = m5.foo2; function n() { diff --git a/tests/baselines/reference/project/declarationsMultipleTimesImport/amd/useModule.js b/tests/baselines/reference/project/declarationsMultipleTimesImport/amd/useModule.js index 5375f44c01361..225f80b990489 100644 --- a/tests/baselines/reference/project/declarationsMultipleTimesImport/amd/useModule.js +++ b/tests/baselines/reference/project/declarationsMultipleTimesImport/amd/useModule.js @@ -13,6 +13,8 @@ define(["require", "exports", "m4", "m4"], function (require, exports, m4, multi var d3 = m4.d; var f3 = m4.foo(); })(m1 = exports.m1 || (exports.m1 = {})); + // Do not emit multiple used import statements + // Emit used exports.useMultiImport_m4_x4 = multiImport_m4.x; exports.useMultiImport_m4_d4 = multiImport_m4.d; exports.useMultiImport_m4_f4 = multiImport_m4.foo(); diff --git a/tests/baselines/reference/project/declarationsMultipleTimesMultipleImport/amd/useModule.js b/tests/baselines/reference/project/declarationsMultipleTimesMultipleImport/amd/useModule.js index b8a22cfdc1f76..132e8a754d3ef 100644 --- a/tests/baselines/reference/project/declarationsMultipleTimesMultipleImport/amd/useModule.js +++ b/tests/baselines/reference/project/declarationsMultipleTimesMultipleImport/amd/useModule.js @@ -13,5 +13,6 @@ define(["require", "exports", "m4", "m5"], function (require, exports, m4, m5) { var d3 = m4.d; var f3 = m4.foo(); })(m1 = exports.m1 || (exports.m1 = {})); + // Do not emit unused import exports.d = m5.foo2(); }); diff --git a/tests/baselines/reference/requireEmitSemicolon.js b/tests/baselines/reference/requireEmitSemicolon.js index daef539e7de39..a349825ec404c 100644 --- a/tests/baselines/reference/requireEmitSemicolon.js +++ b/tests/baselines/reference/requireEmitSemicolon.js @@ -37,6 +37,8 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "requireEmitSemicolon_0"], function (require, exports, P) { "use strict"; exports.__esModule = true; + /// + // bug was we were not emitting a ; here and causing runtime failures in node var Database; (function (Database) { var DB = /** @class */ (function () { diff --git a/tests/baselines/reference/tsxElementResolution17.js b/tests/baselines/reference/tsxElementResolution17.js index 1f61a441d66b9..7aef62ef99411 100644 --- a/tests/baselines/reference/tsxElementResolution17.js +++ b/tests/baselines/reference/tsxElementResolution17.js @@ -31,5 +31,7 @@ import s2 = require('elements2'); define(["require", "exports", "elements1"], function (require, exports, s1) { "use strict"; exports.__esModule = true; + /// + // Should keep s1 and elide s2 ; }); diff --git a/tests/baselines/reference/tsxElementResolution19.js b/tests/baselines/reference/tsxElementResolution19.js index 60b72237354e9..fc534a0fd576e 100644 --- a/tests/baselines/reference/tsxElementResolution19.js +++ b/tests/baselines/reference/tsxElementResolution19.js @@ -34,5 +34,6 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "react", "./file1"], function (require, exports, React, file1_1) { "use strict"; exports.__esModule = true; + // Should not elide React import React.createElement(file1_1.MyClass, null); }); diff --git a/tests/baselines/reference/tsxPreserveEmit1.js b/tests/baselines/reference/tsxPreserveEmit1.js index 4ad18d0d7900c..420427c1a7183 100644 --- a/tests/baselines/reference/tsxPreserveEmit1.js +++ b/tests/baselines/reference/tsxPreserveEmit1.js @@ -36,6 +36,7 @@ module M { define(["require", "exports", "react", "react-router"], function (require, exports, React, ReactRouter) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); + // Should emit 'react-router' in the AMD dependency list var Route = ReactRouter.Route; var routes1 = ; var M; diff --git a/tests/cases/compiler/commentsOnImportInAMDPreserved.ts b/tests/cases/compiler/commentsOnImportInAMDPreserved.ts new file mode 100644 index 0000000000000..0881d6753079b --- /dev/null +++ b/tests/cases/compiler/commentsOnImportInAMDPreserved.ts @@ -0,0 +1,3 @@ +// @module: amd +// foo +import 'foo'; \ No newline at end of file