Skip to content

Preserve comments on elided import declarations #27407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ namespace ts {
case SyntaxKind.VariableStatement:
return emitVariableStatement(<VariableStatement>node);
case SyntaxKind.EmptyStatement:
return emitEmptyStatement();
return !(getEmitFlags(node) & EmitFlags.CommentsOnly) ? emitEmptyStatement() : undefined;
case SyntaxKind.ExpressionStatement:
return emitExpressionStatement(<ExpressionStatement>node);
case SyntaxKind.IfStatement:
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/compiler/transformers/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -939,6 +942,9 @@ namespace ts {
)
);
}
else if (hasLeadingOrTrailingComments(node, currentSourceFile)) {
statements = append(statements, createCommentPreservationStatement(node));
}
}

if (hasAssociatedEndOfDeclarationMarker(node)) {
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/transformers/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ var c = new A();
define(["require", "exports", "M"], function (require, exports, A) {
"use strict";
exports.__esModule = true;
///<reference path='ambientExternalModuleWithInternalImportDeclaration_0.ts'/>
var c = new A();
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ var c = new A();
define(["require", "exports", "M"], function (require, exports, A) {
"use strict";
exports.__esModule = true;
///<reference path='ambientExternalModuleWithoutInternalImportDeclaration_0.ts'/>
var c = new A();
});
1 change: 1 addition & 0 deletions tests/baselines/reference/augmentExportEquals3_1.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ let b = x.b;
define(["require", "exports", "file1"], function (require, exports, x) {
"use strict";
exports.__esModule = true;
/// <reference path="file1.d.ts"/>
x.b = 1;
});
//// [file3.js]
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/augmentExportEquals4_1.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ let b = x.b;
define(["require", "exports", "file1"], function (require, exports, x) {
"use strict";
exports.__esModule = true;
/// <reference path="file1.d.ts"/>
x.b = 1;
});
//// [file3.js]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/commentsExternalModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -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*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right.. This jsdoc comment is associated with import declaration and without it (and missing trailing comments followed by another declaration) could make these associated with that declaration...

// trailing comment1
extMod.m1.fooExport();
var newVar = new extMod.m1.m2.c();
extMod.m4.fooExport();
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/commentsExternalModules2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
10 changes: 10 additions & 0 deletions tests/baselines/reference/commentsOnImportInAMDPreserved.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//// [commentsOnImportInAMDPreserved.ts]
// foo
import 'foo';

//// [commentsOnImportInAMDPreserved.js]
define(["require", "exports", "foo"], function (require, exports) {
"use strict";
exports.__esModule = true;
// foo
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
=== tests/cases/compiler/commentsOnImportInAMDPreserved.ts ===
// foo
No type information for this code.import 'foo';
No type information for this code.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
=== tests/cases/compiler/commentsOnImportInAMDPreserved.ts ===
// foo
No type information for this code.import 'foo';
No type information for this code.
1 change: 1 addition & 0 deletions tests/baselines/reference/constDeclarations-access5.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
///<reference path='constDeclarations_access_1.ts'/>
// Errors
m.x = 1;
m.x += 2;
Expand Down
3 changes: 3 additions & 0 deletions tests/baselines/reference/copyrightWithoutNewLine1.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var __extends = (this && this.__extends) || (function () {
define(["require", "exports", "exportAssignmentOfGenericType1_0"], function (require, exports, q) {
"use strict";
exports.__esModule = true;
///<reference path='exportAssignmentOfGenericType1_0.ts'/>
var M = /** @class */ (function (_super) {
__extends(M, _super);
function M() {
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/exportEqualCallable.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ define(["require", "exports"], function (require, exports) {
define(["require", "exports", "exportEqualCallable_0"], function (require, exports, connect) {
"use strict";
exports.__esModule = true;
///<reference path='exportEqualCallable_0.ts'/>
connect();
});
1 change: 1 addition & 0 deletions tests/baselines/reference/exportEqualErrorType.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ define(["require", "exports"], function (require, exports) {
define(["require", "exports", "exportEqualErrorType_0"], function (require, exports, connect) {
"use strict";
exports.__esModule = true;
///<reference path='exportEqualErrorType_0.ts'/>
connect().use(connect.static('foo')); // Error 1 The property 'static' does not exist on value of type ''.
});
1 change: 1 addition & 0 deletions tests/baselines/reference/externalModuleAssignToVar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
///<reference path='externalModuleAssignToVar_core_require.ts'/>
var y1 = ext;
y1 = ext; // ok
var y2 = ext2;
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/instanceOfInExternalModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ define(["require", "exports"], function (require, exports) {
define(["require", "exports", "instanceOfInExternalModules_require"], function (require, exports, Bar) {
"use strict";
exports.__esModule = true;
///<reference path='instanceOfInExternalModules_require.ts'/>
function IsFoo(value) {
return value instanceof Bar.Foo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ define(["require", "exports"], function (require, exports) {
define(["require", "exports", "memberAccessMustUseModuleInstances_0"], function (require, exports, WinJS) {
"use strict";
exports.__esModule = true;
///<reference path='memberAccessMustUseModuleInstances_0.ts'/>
WinJS.Promise.timeout(10);
});
1 change: 1 addition & 0 deletions tests/baselines/reference/moduleAliasAsFunctionArgument.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ define(["require", "exports"], function (require, exports) {
define(["require", "exports", "moduleAliasAsFunctionArgument_0"], function (require, exports, a) {
"use strict";
exports.__esModule = true;
///<reference path='moduleAliasAsFunctionArgument_0.ts'/>
function fn(arg) {
}
a.x; // OK
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/moduleAugmentationsImports3.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
/// <reference path="c.d.ts"/>
a_1.A.prototype.getCls = function () { return undefined; };
});
define("main", ["require", "exports", "D", "e"], function (require, exports) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
///<reference path='privacyTopLevelAmbientExternalModuleImportWithoutExport_require2.ts'/>
///<reference path='privacyTopLevelAmbientExternalModuleImportWithoutExport_require3.ts'/>
// 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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
2 changes: 2 additions & 0 deletions tests/baselines/reference/requireEmitSemicolon.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ define(["require", "exports"], function (require, exports) {
define(["require", "exports", "requireEmitSemicolon_0"], function (require, exports, P) {
"use strict";
exports.__esModule = true;
///<reference path='requireEmitSemicolon_0.ts'/>
// bug was we were not emitting a ; here and causing runtime failures in node
var Database;
(function (Database) {
var DB = /** @class */ (function () {
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/tsxElementResolution17.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@ import s2 = require('elements2');
define(["require", "exports", "elements1"], function (require, exports, s1) {
"use strict";
exports.__esModule = true;
///<reference path="file.tsx" />
// Should keep s1 and elide s2
<s1.MyElement />;
});
1 change: 1 addition & 0 deletions tests/baselines/reference/tsxElementResolution19.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
1 change: 1 addition & 0 deletions tests/baselines/reference/tsxPreserveEmit1.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <Route />;
var M;
Expand Down
3 changes: 3 additions & 0 deletions tests/cases/compiler/commentsOnImportInAMDPreserved.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @module: amd
// foo
import 'foo';