Skip to content
Merged
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
285 changes: 254 additions & 31 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

51 changes: 12 additions & 39 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1881,34 +1881,6 @@ module ts {
writeLine();
}

function isModuleElementExternallyVisible(node: Declaration) {
if (node.flags & NodeFlags.Export) {
// Exported member - emit this declaration
return true;
}

// If this node is in external module, check if this is export assigned
var moduleDeclaration = getContainerOfModuleElementDeclaration(node);
if ((moduleDeclaration.flags & NodeFlags.ExternalModule) || // Source file with external module flag
// Ambient external module declaration
(moduleDeclaration.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>moduleDeclaration).name.kind === SyntaxKind.StringLiteral)) {
return resolver.isReferencedInExportAssignment(node);
}

return false;
}

function canEmitModuleElementDeclaration(node: Declaration) {
if (isModuleElementExternallyVisible(node)) {
// Either exported module element or is referenced in export assignment
return true;
}

// emit the declaration if this is in global scope source file
var moduleDeclaration = getContainerOfModuleElementDeclaration(node);
return moduleDeclaration.kind === SyntaxKind.SourceFile && !(moduleDeclaration.flags & NodeFlags.ExternalModule);
}

function emitDeclarationFlags(node: Declaration) {
if (node.flags & NodeFlags.Static) {
if (node.flags & NodeFlags.Private) {
Expand All @@ -1935,8 +1907,7 @@ module ts {
}

function emitImportDeclaration(node: ImportDeclaration) {
// TODO(shkamat): Emit if import decl is used to declare type in this context
if (isModuleElementExternallyVisible(node)) {
if (resolver.isDeclarationVisible(node)) {
if (node.flags & NodeFlags.Export) {
write("export ");
}
Expand All @@ -1957,7 +1928,7 @@ module ts {
}

function emitModuleDeclaration(node: ModuleDeclaration) {
if (canEmitModuleElementDeclaration(node)) {
if (resolver.isDeclarationVisible(node)) {
emitDeclarationFlags(node);
write("module ");
emitSourceTextOfNode(node.name);
Expand All @@ -1980,7 +1951,7 @@ module ts {
}

function emitEnumDeclaration(node: EnumDeclaration) {
if (canEmitModuleElementDeclaration(node)) {
if (resolver.isDeclarationVisible(node)) {
emitDeclarationFlags(node);
write("enum ");
emitSourceTextOfNode(node.name);
Expand Down Expand Up @@ -2043,7 +2014,7 @@ module ts {
}
}

if (canEmitModuleElementDeclaration(node)) {
if (resolver.isDeclarationVisible(node)) {
emitDeclarationFlags(node);
write("class ");
emitSourceTextOfNode(node.name);
Expand All @@ -2067,7 +2038,7 @@ module ts {
}

function emitInterfaceDeclaration(node: InterfaceDeclaration) {
if (canEmitModuleElementDeclaration(node)) {
if (resolver.isDeclarationVisible(node)) {
emitDeclarationFlags(node);
write("interface ");
emitSourceTextOfNode(node.name);
Expand All @@ -2094,8 +2065,9 @@ module ts {
}

function emitVariableDeclaration(node: VariableDeclaration) {
// If we are emitting property it isnt moduleElement and doesnt need canEmitModuleElement check
if (node.kind !== SyntaxKind.VariableDeclaration || canEmitModuleElementDeclaration(node)) {
// If we are emitting property it isnt moduleElement and hence we already know it needs to be emitted
// so there is no check needed to see if declaration is visible
if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) {
emitSourceTextOfNode(node.name);
// If optional property emit ?
if (node.kind === SyntaxKind.Property && (node.flags & NodeFlags.QuestionMark)) {
Expand All @@ -2109,7 +2081,7 @@ module ts {
}

function emitVariableStatement(node: VariableStatement) {
var hasDeclarationWithEmit = forEach(node.declarations, varDeclaration => canEmitModuleElementDeclaration(varDeclaration));
var hasDeclarationWithEmit = forEach(node.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
if (hasDeclarationWithEmit) {
emitDeclarationFlags(node);
write("var ");
Expand All @@ -2134,8 +2106,9 @@ module ts {
}

function emitFunctionDeclaration(node: FunctionDeclaration) {
// If we are emitting Method/Constructor it isnt moduleElement and doesnt need canEmitModuleElement check
if ((node.kind !== SyntaxKind.FunctionDeclaration || canEmitModuleElementDeclaration(node)) &&
// If we are emitting Method/Constructor it isnt moduleElement and hence already determined to be emitting
// so no need to verify if the declaration is visible
if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) &&
!resolver.isImplementationOfOverload(node)) {
emitDeclarationFlags(node);
if (node.kind === SyntaxKind.FunctionDeclaration) {
Expand Down
6 changes: 0 additions & 6 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,6 @@ module ts {
return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0;
}

export function getContainerOfModuleElementDeclaration(node: Declaration) {
// If the declaration is var declaration, then the parent is variable statement but we actually want the module
var container = node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent;
return container.kind == SyntaxKind.ModuleBlock ? container.parent : container;
}

enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ module ts {
getNodeCheckFlags(node: Node): NodeCheckFlags;
getEnumMemberValue(node: EnumMember): number;
shouldEmitDeclarations(): boolean;
isReferencedInExportAssignment(node: Declaration): boolean;
isDeclarationVisible(node: Declaration): boolean;
isImplementationOfOverload(node: FunctionDeclaration): boolean;
writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: TextWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: TextWriter): void;
Expand Down Expand Up @@ -736,6 +736,7 @@ module ts {
flags?: NodeCheckFlags; // Set of flags specific to Node
enumMemberValue?: number; // Constant value of enum member
isIllegalTypeReferenceInConstraint?: boolean; // Is type reference in constraint refers to the type parameter from the same list
isVisible?: boolean; // Is this node visible
}

export enum TypeFlags {
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/commentsModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ declare module m1 {
function foo2Export(a: string): void;
function foo3Export(): void;
}
declare var myvar: c;
declare var myvar: m1.m2.c;
declare module m2.m3 {
class c {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ declare module "SubModule" {
}
//// [declFileAmbientExternalModuleWithSingleExportedModule_1.d.ts]
/// <reference path='declFileAmbientExternalModuleWithSingleExportedModule_0.d.ts' />
export declare var x: c;
export declare var x: SubModule.m.m3.c;
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,21 @@ module.exports = m;


//// [declFileExportAssignmentImportInternalModule.d.ts]
declare module m3 {
module m2 {
interface connectModule {
(res: any, req: any, next: any): void;
}
interface connectExport {
use: (mod: connectModule) => connectExport;
listen: (port: number) => void;
}
}
var server: {
(): m2.connectExport;
test1: m2.connectModule;
test2(): m2.connectModule;
};
}
import m = m3;
export = m;
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ interface Foo<T> {
}
export = Foo;
//// [declFileExportAssignmentOfGenericInterface_1.d.ts]
export declare var x: Foo<Foo<string>>;
export declare var x: a<a<string>>;
2 changes: 1 addition & 1 deletion tests/baselines/reference/declFileExportImportChain.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ export = b;
//// [declFileExportImportChain_c.d.ts]
export import b1 = require("declFileExportImportChain_b1");
//// [declFileExportImportChain_d.d.ts]
export declare var x: c1;
export declare var x: m1.m2.c1;
2 changes: 1 addition & 1 deletion tests/baselines/reference/declFileExportImportChain2.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,4 @@ export = a;
//// [declFileExportImportChain2_c.d.ts]
export import b = require("declFileExportImportChain2_b");
//// [declFileExportImportChain2_d.d.ts]
export declare var x: c1;
export declare var x: m1.m2.c1;
22 changes: 11 additions & 11 deletions tests/baselines/reference/declFileGenericType.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,16 @@ export declare module C {
constructor(val: T);
}
}
export declare var a: A<B>;
export declare var b: <T>(x: T) => A<B>;
export declare var c: <T>(x: T) => A<B>;
export declare var d: <T>(x: T) => A<B>[];
export declare var e: <T extends A<B>>(x: T) => A<B>[];
export declare var x: A<B>;
export declare function f<T extends A<B>>(): void;
export declare var g: A<B>;
export declare class h extends A<B> {
export declare var a: C.A<C.B>;
export declare var b: <T>(x: T) => C.A<C.B>;
export declare var c: <T>(x: T) => C.A<C.B>;
export declare var d: <T>(x: T) => C.A<C.B>[];
export declare var e: <T extends C.A<C.B>>(x: T) => C.A<C.B>[];
export declare var x: C.A<C.B>;
export declare function f<T extends C.A<C.B>>(): void;
export declare var g: C.A<C.B>;
export declare class h extends C.A<C.B> {
}
export interface i extends A<B> {
export interface i extends C.A<C.B> {
}
export declare var j: <T extends A<B>>(x: T) => T;
export declare var j: <T extends C.A<C.B>>(x: T) => T;
8 changes: 4 additions & 4 deletions tests/baselines/reference/declFileGenericType2.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,17 @@ declare module templa.mvc {
declare module templa.mvc.composite {
}
declare module templa.dom.mvc {
interface IElementController<ModelType extends IModel> extends IController<ModelType> {
interface IElementController<ModelType extends templa.mvc.IModel> extends templa.mvc.IController<ModelType> {
}
}
declare module templa.dom.mvc {
class AbstractElementController<ModelType extends IModel> extends AbstractController<ModelType> implments IElementController<ModelType> {
class AbstractElementController<ModelType extends templa.mvc.IModel> extends templa.mvc.AbstractController<ModelType> implments IElementController<ModelType> {
constructor();
}
}
declare module templa.dom.mvc.composite {
class AbstractCompositeElementController<ModelType extends ICompositeControllerModel> extends AbstractElementController<ModelType> {
_controllers: IController<IModel>[];
class AbstractCompositeElementController<ModelType extends templa.mvc.composite.ICompositeControllerModel> extends AbstractElementController<ModelType> {
_controllers: templa.mvc.IController<templa.mvc.IModel>[];
constructor();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ declare module m2 {
}
}
declare var m2: {
(): connectExport;
test1: connectModule;
test2(): connectModule;
(): m2.connectExport;
test1: m2.connectModule;
test2(): m2.connectModule;
};
export = m2;
//// [declFileImportModuleWithExportAssignment_1.d.ts]
export declare var a: {
(): connectExport;
test1: connectModule;
test2(): connectModule;
(): a1.connectExport;
test1: a1.connectModule;
test2(): a1.connectModule;
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ declare class List<T> {
declare module 'mod1' {
}
declare module 'moo' {
var p: List<Foo>;
var p: List<x.Foo>;
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/declFileInternalAliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ declare module m {
}
}
declare module m1 {
var d: c;
var d: x;
}
declare module m2 {
export import x = m.c;
var d: c;
var d: x;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ declare var d: {
m: typeof m1;
};
m2: {
c: typeof c;
c: typeof m1.c;
};
};
2 changes: 1 addition & 1 deletion tests/baselines/reference/declFileModuleContinuation.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ declare module A.C {
}
}
declare module A.B.C {
class W implments Z {
class W implments A.C.Z {
}
}
10 changes: 5 additions & 5 deletions tests/baselines/reference/declFileTypeofInAnonymousType.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ declare module m1 {
}
}
declare var a: {
c: c;
c: m1.c;
};
declare var b: {
c: typeof c;
c: typeof m1.c;
m1: typeof m1;
};
declare var c: {
Expand All @@ -77,10 +77,10 @@ declare var d: {
mod: typeof m1;
};
mc: {
cl: typeof c;
cl: typeof m1.c;
};
me: {
en: typeof e;
en: typeof m1.e;
};
mh: e;
mh: m1.e;
};
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ declare module A.B.Base {
}
}
declare module X.Y.base {
class W extends W {
class W extends A.B.Base.W {
name: string;
}
}
declare module X.Y.base.Z {
class W<TValue> extends W {
class W<TValue> extends base.W {
value: boolean;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ declare module X.A.C {
}
}
declare module X.A.B.C {
class W implments Z {
class W implments X.A.C.Z {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ declare module X.A.C {
}
}
declare module X.A.B.C {
class W implments Z {
class W implments A.C.Z {
}
}
declare module X.A.B.C {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ declare module X.A.C {
}
}
declare module X.A.B.C {
class W implments Z {
class W implments X.A.C.Z {
}
}
declare module X.A.B.C {
Expand Down
Loading