mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #1466 from Microsoft/linked_imports
defer decision whether import used on the right side of import declarati...
This commit is contained in:
+57
-15
@@ -4734,14 +4734,49 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
/*Transitively mark all linked imports as referenced*/
|
||||
function markLinkedImportsAsReferenced(node: ImportDeclaration): void {
|
||||
var nodeLinks = getNodeLinks(node);
|
||||
while (nodeLinks.importOnRightSide) {
|
||||
var rightSide = nodeLinks.importOnRightSide;
|
||||
nodeLinks.importOnRightSide = undefined;
|
||||
|
||||
getSymbolLinks(rightSide).referenced = true;
|
||||
Debug.assert((rightSide.flags & SymbolFlags.Import) !== 0);
|
||||
|
||||
nodeLinks = getNodeLinks(getDeclarationOfKind(rightSide, SyntaxKind.ImportDeclaration))
|
||||
}
|
||||
}
|
||||
|
||||
function checkIdentifier(node: Identifier): Type {
|
||||
var symbol = getResolvedSymbol(node);
|
||||
|
||||
if (symbol.flags & SymbolFlags.Import) {
|
||||
// Mark the import as referenced so that we emit it in the final .js file.
|
||||
// exception: identifiers that appear in type queries, const enums, modules that contain only const enums
|
||||
getSymbolLinks(symbol).referenced = getSymbolLinks(symbol).referenced || (!isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveImport(symbol)));
|
||||
var symbolLinks = getSymbolLinks(symbol);
|
||||
if (!symbolLinks.referenced) {
|
||||
var importOrExportAssignment = getLeftSideOfImportOrExportAssignment(node);
|
||||
|
||||
// decision about whether import is referenced can be made now if
|
||||
// - import that are used anywhere except right side of import declarations
|
||||
// - imports that are used on the right side of exported import declarations
|
||||
// for other cases defer decision until the check of left side
|
||||
if (!importOrExportAssignment ||
|
||||
(importOrExportAssignment.flags & NodeFlags.Export) ||
|
||||
(importOrExportAssignment.kind === SyntaxKind.ExportAssignment)) {
|
||||
// Mark the import as referenced so that we emit it in the final .js file.
|
||||
// exception: identifiers that appear in type queries, const enums, modules that contain only const enums
|
||||
symbolLinks.referenced = !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveImport(symbol));
|
||||
}
|
||||
else {
|
||||
var nodeLinks = getNodeLinks(importOrExportAssignment);
|
||||
Debug.assert(!nodeLinks.importOnRightSide);
|
||||
nodeLinks.importOnRightSide = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
if (symbolLinks.referenced) {
|
||||
markLinkedImportsAsReferenced(<ImportDeclaration>getDeclarationOfKind(symbol, SyntaxKind.ImportDeclaration));
|
||||
}
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node);
|
||||
@@ -8872,6 +8907,8 @@ module ts {
|
||||
if (symbol && symbol.flags & SymbolFlags.Import) {
|
||||
// Mark the import as referenced so that we emit it in the final .js file.
|
||||
getSymbolLinks(symbol).referenced = true;
|
||||
// mark any import declarations that depend upon this import as referenced
|
||||
markLinkedImportsAsReferenced(<ImportDeclaration>getDeclarationOfKind(symbol, SyntaxKind.ImportDeclaration))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9097,19 +9134,24 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getLeftSideOfImportOrExportAssignment(nodeOnRightSide: EntityName): ImportDeclaration | ExportAssignment {
|
||||
while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) {
|
||||
nodeOnRightSide = <QualifiedName>nodeOnRightSide.parent;
|
||||
}
|
||||
|
||||
if (nodeOnRightSide.parent.kind === SyntaxKind.ImportDeclaration) {
|
||||
return (<ImportDeclaration>nodeOnRightSide.parent).moduleReference === nodeOnRightSide && <ImportDeclaration>nodeOnRightSide.parent;
|
||||
}
|
||||
|
||||
if (nodeOnRightSide.parent.kind === SyntaxKind.ExportAssignment) {
|
||||
return (<ExportAssignment>nodeOnRightSide.parent).exportName === nodeOnRightSide && <ExportAssignment>nodeOnRightSide.parent;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isInRightSideOfImportOrExportAssignment(node: EntityName) {
|
||||
while (node.parent.kind === SyntaxKind.QualifiedName) {
|
||||
node = <QualifiedName>node.parent;
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.ImportDeclaration) {
|
||||
return (<ImportDeclaration>node.parent).moduleReference === node;
|
||||
}
|
||||
if (node.parent.kind === SyntaxKind.ExportAssignment) {
|
||||
return (<ExportAssignment>node.parent).exportName === node;
|
||||
}
|
||||
|
||||
return false;
|
||||
return getLeftSideOfImportOrExportAssignment(node) !== undefined;
|
||||
}
|
||||
|
||||
function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
|
||||
|
||||
@@ -1222,6 +1222,7 @@ module ts {
|
||||
isVisible?: boolean; // Is this node visible
|
||||
localModuleName?: string; // Local name for module instance
|
||||
assignmentChecks?: Map<boolean>; // Cache of assignment checks
|
||||
importOnRightSide?: Symbol; // for import declarations - import that appear on the right side
|
||||
}
|
||||
|
||||
export const enum TypeFlags {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
//// [tests/cases/compiler/importedAliasesInTypePositions.ts] ////
|
||||
|
||||
//// [file1.ts]
|
||||
export module elaborate.nested.mod.name {
|
||||
export class ReferredTo {
|
||||
doSomething(): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [file2.ts]
|
||||
import RT_ALIAS = require("file1");
|
||||
import ReferredTo = RT_ALIAS.elaborate.nested.mod.name.ReferredTo;
|
||||
|
||||
export module ImportingModule {
|
||||
class UsesReferredType {
|
||||
constructor(private referred: ReferredTo) { }
|
||||
}
|
||||
}
|
||||
|
||||
//// [file1.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
var elaborate;
|
||||
(function (elaborate) {
|
||||
var nested;
|
||||
(function (nested) {
|
||||
var mod;
|
||||
(function (mod) {
|
||||
var name;
|
||||
(function (name) {
|
||||
var ReferredTo = (function () {
|
||||
function ReferredTo() {
|
||||
}
|
||||
ReferredTo.prototype.doSomething = function () {
|
||||
};
|
||||
return ReferredTo;
|
||||
})();
|
||||
name.ReferredTo = ReferredTo;
|
||||
})(name = mod.name || (mod.name = {}));
|
||||
})(mod = nested.mod || (nested.mod = {}));
|
||||
})(nested = elaborate.nested || (elaborate.nested = {}));
|
||||
})(elaborate = exports.elaborate || (exports.elaborate = {}));
|
||||
});
|
||||
//// [file2.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
var ImportingModule;
|
||||
(function (ImportingModule) {
|
||||
var UsesReferredType = (function () {
|
||||
function UsesReferredType(referred) {
|
||||
this.referred = referred;
|
||||
}
|
||||
return UsesReferredType;
|
||||
})();
|
||||
})(ImportingModule = exports.ImportingModule || (exports.ImportingModule = {}));
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
=== tests/cases/compiler/file2.ts ===
|
||||
import RT_ALIAS = require("file1");
|
||||
>RT_ALIAS : typeof RT_ALIAS
|
||||
|
||||
import ReferredTo = RT_ALIAS.elaborate.nested.mod.name.ReferredTo;
|
||||
>ReferredTo : typeof ReferredTo
|
||||
>RT_ALIAS : typeof RT_ALIAS
|
||||
>elaborate : typeof RT_ALIAS.elaborate
|
||||
>nested : typeof RT_ALIAS.elaborate.nested
|
||||
>mod : typeof RT_ALIAS.elaborate.nested.mod
|
||||
>name : typeof RT_ALIAS.elaborate.nested.mod.name
|
||||
>ReferredTo : ReferredTo
|
||||
|
||||
export module ImportingModule {
|
||||
>ImportingModule : typeof ImportingModule
|
||||
|
||||
class UsesReferredType {
|
||||
>UsesReferredType : UsesReferredType
|
||||
|
||||
constructor(private referred: ReferredTo) { }
|
||||
>referred : ReferredTo
|
||||
>ReferredTo : ReferredTo
|
||||
}
|
||||
}
|
||||
=== tests/cases/compiler/file1.ts ===
|
||||
export module elaborate.nested.mod.name {
|
||||
>elaborate : typeof elaborate
|
||||
>nested : typeof nested
|
||||
>mod : typeof mod
|
||||
>name : typeof name
|
||||
|
||||
export class ReferredTo {
|
||||
>ReferredTo : ReferredTo
|
||||
|
||||
doSomething(): void {
|
||||
>doSomething : () => void
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// @module:amd
|
||||
// @Filename: file1.ts
|
||||
export module elaborate.nested.mod.name {
|
||||
export class ReferredTo {
|
||||
doSomething(): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Filename: file2.ts
|
||||
// @module: amd
|
||||
import RT_ALIAS = require("file1");
|
||||
import ReferredTo = RT_ALIAS.elaborate.nested.mod.name.ReferredTo;
|
||||
|
||||
export module ImportingModule {
|
||||
class UsesReferredType {
|
||||
constructor(private referred: ReferredTo) { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user