diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1646b51702a..31665734167 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14306,7 +14306,7 @@ namespace ts { } const { declarations, flags } = exports[id]; // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. (TS Exceptions: namespaces, function overloads, enums, and interfaces) - if (!(flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) && declarations.length > 1) { + if (!(flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) && (flags & SymbolFlags.TypeAlias ? declarations.length - 1 : declarations.length) > 1) { const exportedDeclarations: Declaration[] = filter(declarations, isNotOverload); if (exportedDeclarations.length > 1) { for (const declaration of exportedDeclarations) { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 61accfb71af..836b2daeab2 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -51,6 +51,8 @@ namespace ts { args: string[]; currentDirectory: string; executingFile: string; + newLine?: string; + useCaseSensitiveFileNames?: boolean; echo(s: string): void; quit(exitCode?: number): void; fileExists(path: string): boolean; @@ -60,6 +62,8 @@ namespace ts { readFile(path: string): string; writeFile(path: string, contents: string): void; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; + watchFile?(path: string, callback: (path: string, removed?: boolean) => void): FileWatcher; + watchDirectory?(path: string, callback: (path: string) => void, recursive?: boolean): FileWatcher; }; export var sys: System = (function () { @@ -469,9 +473,9 @@ namespace ts { function getChakraSystem(): System { return { - newLine: "\r\n", + newLine: ChakraHost.newLine || "\r\n", args: ChakraHost.args, - useCaseSensitiveFileNames: false, + useCaseSensitiveFileNames: !!ChakraHost.useCaseSensitiveFileNames, write: ChakraHost.echo, readFile(path: string, encoding?: string) { // encoding is automatically handled by the implementation in ChakraHost diff --git a/tests/baselines/reference/superPropertyAccess_ES5.js b/tests/baselines/reference/superPropertyAccess_ES5.js index a31c1dfdcba..63f5f6f316a 100644 --- a/tests/baselines/reference/superPropertyAccess_ES5.js +++ b/tests/baselines/reference/superPropertyAccess_ES5.js @@ -45,7 +45,7 @@ var MyBase = (function () { configurable: true }); return MyBase; -})(); +}()); var MyDerived = (function (_super) { __extends(MyDerived, _super); function MyDerived() { @@ -54,7 +54,7 @@ var MyDerived = (function (_super) { var f2 = _super.prototype.value; } return MyDerived; -})(MyBase); +}(MyBase)); var d = new MyDerived(); var f3 = d.value; var A = (function () { @@ -67,7 +67,7 @@ var A = (function () { configurable: true }); return A; -})(); +}()); var B = (function (_super) { __extends(B, _super); function B() { @@ -81,4 +81,4 @@ var B = (function (_super) { configurable: true }); return B; -})(A); +}(A)); diff --git a/tests/baselines/reference/typeAliasExport.js b/tests/baselines/reference/typeAliasExport.js new file mode 100644 index 00000000000..fa864f571ea --- /dev/null +++ b/tests/baselines/reference/typeAliasExport.js @@ -0,0 +1,8 @@ +//// [typeAliasExport.ts] +declare module "a" { + export default 0 + export var a; + export type a = typeof a; +} + +//// [typeAliasExport.js] diff --git a/tests/baselines/reference/typeAliasExport.symbols b/tests/baselines/reference/typeAliasExport.symbols new file mode 100644 index 00000000000..1f580b03011 --- /dev/null +++ b/tests/baselines/reference/typeAliasExport.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/typeAliasExport.ts === +declare module "a" { + export default 0 + export var a; +>a : Symbol(a, Decl(typeAliasExport.ts, 2, 12), Decl(typeAliasExport.ts, 2, 15)) + + export type a = typeof a; +>a : Symbol(a, Decl(typeAliasExport.ts, 2, 12), Decl(typeAliasExport.ts, 2, 15)) +>a : Symbol(a, Decl(typeAliasExport.ts, 2, 12), Decl(typeAliasExport.ts, 2, 15)) +} diff --git a/tests/baselines/reference/typeAliasExport.types b/tests/baselines/reference/typeAliasExport.types new file mode 100644 index 00000000000..afa26073061 --- /dev/null +++ b/tests/baselines/reference/typeAliasExport.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/typeAliasExport.ts === +declare module "a" { + export default 0 + export var a; +>a : any + + export type a = typeof a; +>a : any +>a : any +} diff --git a/tests/cases/compiler/typeAliasExport.ts b/tests/cases/compiler/typeAliasExport.ts new file mode 100644 index 00000000000..706b731f0ab --- /dev/null +++ b/tests/cases/compiler/typeAliasExport.ts @@ -0,0 +1,5 @@ +declare module "a" { + export default 0 + export var a; + export type a = typeof a; +} \ No newline at end of file diff --git a/tests/cases/fourslash/thisPredicateFunctionCompletions.ts b/tests/cases/fourslash/thisPredicateFunctionCompletions.ts new file mode 100644 index 00000000000..3c93a859bf3 --- /dev/null +++ b/tests/cases/fourslash/thisPredicateFunctionCompletions.ts @@ -0,0 +1,80 @@ +/// + +//// class RoyalGuard { +//// isLeader(): this is LeadGuard { +//// return this instanceof LeadGuard; +//// } +//// isFollower(): this is FollowerGuard { +//// return this instanceof FollowerGuard; +//// } +//// } +//// +//// class LeadGuard extends RoyalGuard { +//// lead(): void {}; +//// } +//// +//// class FollowerGuard extends RoyalGuard { +//// follow(): void {}; +//// } +//// +//// let a: RoyalGuard = new FollowerGuard(); +//// if (a.is/*1*/Leader()) { +//// a./*2*/; +//// } +//// else if (a.is/*3*/Follower()) { +//// a./*4*/; +//// } +//// +//// interface GuardInterface { +//// isLeader(): this is LeadGuard; +//// isFollower(): this is FollowerGuard; +//// } +//// +//// let b: GuardInterface; +//// if (b.is/*5*/Leader()) { +//// b./*6*/; +//// } +//// else if (b.is/*7*/Follower()) { +//// b./*8*/; +//// } +//// +//// if (((a.isLeader)())) { +//// a./*9*/; +//// } +//// else if (((a).isFollower())) { +//// a./*10*/; +//// } +//// +//// if (((a["isLeader"])())) { +//// a./*11*/; +//// } +//// else if (((a)["isFollower"]())) { +//// a./*12*/; +//// } +//// +//// let leader/*13*/Status = a.isLeader(); +//// function isLeaderGuard(g: RoyalGuard) { +//// return g.isLeader(); +//// } +//// let checked/*14*/LeaderStatus = isLeader/*15*/Guard(a); + + +goTo.marker("2"); +verify.completionListContains("lead"); +goTo.marker("4"); +verify.completionListContains("follow"); + +goTo.marker("6"); +verify.completionListContains("lead"); +goTo.marker("8"); +verify.completionListContains("follow"); + +goTo.marker("9"); +verify.completionListContains("lead"); +goTo.marker("10"); +verify.completionListContains("follow"); + +goTo.marker("11"); +verify.completionListContains("lead"); +goTo.marker("12"); +verify.completionListContains("follow"); \ No newline at end of file diff --git a/tests/cases/fourslash/thisPredicateFunctionQuickInfo.ts b/tests/cases/fourslash/thisPredicateFunctionQuickInfo.ts new file mode 100644 index 00000000000..3b7adc460c5 --- /dev/null +++ b/tests/cases/fourslash/thisPredicateFunctionQuickInfo.ts @@ -0,0 +1,77 @@ +/// + +//// class RoyalGuard { +//// isLeader(): this is LeadGuard { +//// return this instanceof LeadGuard; +//// } +//// isFollower(): this is FollowerGuard { +//// return this instanceof FollowerGuard; +//// } +//// } +//// +//// class LeadGuard extends RoyalGuard { +//// lead(): void {}; +//// } +//// +//// class FollowerGuard extends RoyalGuard { +//// follow(): void {}; +//// } +//// +//// let a: RoyalGuard = new FollowerGuard(); +//// if (a.is/*1*/Leader()) { +//// a./*2*/; +//// } +//// else if (a.is/*3*/Follower()) { +//// a./*4*/; +//// } +//// +//// interface GuardInterface { +//// isLeader(): this is LeadGuard; +//// isFollower(): this is FollowerGuard; +//// } +//// +//// let b: GuardInterface; +//// if (b.is/*5*/Leader()) { +//// b./*6*/; +//// } +//// else if (b.is/*7*/Follower()) { +//// b./*8*/; +//// } +//// +//// if (((a.isLeader)())) { +//// a./*9*/; +//// } +//// else if (((a).isFollower())) { +//// a./*10*/; +//// } +//// +//// if (((a["isLeader"])())) { +//// a./*11*/; +//// } +//// else if (((a)["isFollower"]())) { +//// a./*12*/; +//// } +//// +//// let leader/*13*/Status = a.isLeader(); +//// function isLeaderGuard(g: RoyalGuard) { +//// return g.isLeader(); +//// } +//// let checked/*14*/LeaderStatus = isLeader/*15*/Guard(a); + + +goTo.marker("1"); +verify.quickInfoIs("(method) RoyalGuard.isLeader(): this is LeadGuard"); +goTo.marker("3"); +verify.quickInfoIs("(method) RoyalGuard.isFollower(): this is FollowerGuard"); + +goTo.marker("5"); +verify.quickInfoIs("(method) GuardInterface.isLeader(): this is LeadGuard"); +goTo.marker("7"); +verify.quickInfoIs("(method) GuardInterface.isFollower(): this is FollowerGuard"); + +goTo.marker("13"); +verify.quickInfoIs("let leaderStatus: boolean"); +goTo.marker("14"); +verify.quickInfoIs("let checkedLeaderStatus: boolean"); +goTo.marker("15"); +verify.quickInfoIs("function isLeaderGuard(g: RoyalGuard): boolean"); \ No newline at end of file diff --git a/tests/cases/fourslash/thisPredicateMemberCompletions.ts b/tests/cases/fourslash/thisPredicateMemberCompletions.ts new file mode 100644 index 00000000000..24ce742faac --- /dev/null +++ b/tests/cases/fourslash/thisPredicateMemberCompletions.ts @@ -0,0 +1,95 @@ +/// + +//// class FileSystemObject { +//// get is/*1*/File(): this is Item { +//// return this instanceof Item; +//// } +//// set is/*2*/File(param) { +//// // noop +//// } +//// get is/*3*/Directory(): this is Directory { +//// return this instanceof Directory; +//// } +//// is/*4*/Networked: this is (Networked & this); +//// constructor(public path: string) {} +//// } +//// +//// class Item extends FileSystemObject { +//// constructor(path: string, public content: string) { super(path); } +//// } +//// class Directory extends FileSystemObject { +//// children: FileSystemObject[]; +//// } +//// interface Networked { +//// host: string; +//// } +//// +//// interface Sundries { +//// broken: boolean; +//// } +//// +//// interface Supplies { +//// spoiled: boolean; +//// } +//// +//// interface Crate { +//// contents: T; +//// is/*5*/Sundries: this is Crate; +//// is/*6*/Supplies: this is Crate; +//// is/*7*/PackedTight: this is (this & {extraContents: T}); +//// } +//// +//// const obj: FileSystemObject = new Item("/foo", ""); +//// if (obj.is/*8*/File) { +//// obj./*9*/; +//// if (obj.is/*10*/Networked) { +//// obj./*11*/; +//// } +//// } +//// if (obj.is/*12*/Directory) { +//// obj./*13*/; +//// if (obj.is/*14*/Networked) { +//// obj./*15*/; +//// } +//// } +//// if (obj.is/*16*/Networked) { +//// obj./*17*/; +//// } +//// +//// const crate: Crate; +//// if (crate.is/*18*/PackedTight) { +//// crate./*19*/; +//// } +//// if (crate.is/*20*/Sundries) { +//// crate.contents./*21*/; +//// if (crate.is/*22*/PackedTight) { +//// crate./*23*/ +//// } +//// } +//// if (crate.is/*24*/Supplies) { +//// crate.contents./*25*/; +//// if (crate.is/*26*/PackedTight) { +//// crate./*27*/ +//// } +//// } + +goTo.marker("9"); +verify.completionListContains("content"); +goTo.marker("11"); +verify.completionListContains("host"); +goTo.marker("13"); +verify.completionListContains("children"); +goTo.marker("15"); +verify.completionListContains("host"); +goTo.marker("17"); +verify.completionListContains("host"); +goTo.marker("19"); +verify.completionListContains("extraContents"); +goTo.marker("21"); +verify.completionListContains("broken"); +goTo.marker("23"); +verify.completionListContains("extraContents"); +goTo.marker("25"); +verify.completionListContains("spoiled"); +goTo.marker("27"); +verify.completionListContains("extraContents"); \ No newline at end of file diff --git a/tests/cases/fourslash/thisPredicateMemberQuickInfo.ts b/tests/cases/fourslash/thisPredicateMemberQuickInfo.ts new file mode 100644 index 00000000000..20d519e0008 --- /dev/null +++ b/tests/cases/fourslash/thisPredicateMemberQuickInfo.ts @@ -0,0 +1,117 @@ +/// + +//// class FileSystemObject { +//// get is/*1*/File(): this is Item { +//// return this instanceof Item; +//// } +//// set is/*2*/File(param) { +//// // noop +//// } +//// get is/*3*/Directory(): this is Directory { +//// return this instanceof Directory; +//// } +//// is/*4*/Networked: this is (Networked & this); +//// constructor(public path: string) {} +//// } +//// +//// class Item extends FileSystemObject { +//// constructor(path: string, public content: string) { super(path); } +//// } +//// class Directory extends FileSystemObject { +//// children: FileSystemObject[]; +//// } +//// interface Networked { +//// host: string; +//// } +//// +//// interface Sundries { +//// broken: boolean; +//// } +//// +//// interface Supplies { +//// spoiled: boolean; +//// } +//// +//// interface Crate { +//// contents: T; +//// is/*5*/Sundries: this is Crate; +//// is/*6*/Supplies: this is Crate; +//// is/*7*/PackedTight: this is (this & {extraContents: T}); +//// } +//// +//// const obj: FileSystemObject = new Item("/foo", ""); +//// if (obj.is/*8*/File) { +//// obj./*9*/; +//// if (obj.is/*10*/Networked) { +//// obj./*11*/; +//// } +//// } +//// if (obj.is/*12*/Directory) { +//// obj./*13*/; +//// if (obj.is/*14*/Networked) { +//// obj./*15*/; +//// } +//// } +//// if (obj.is/*16*/Networked) { +//// obj./*17*/; +//// } +//// +//// const crate: Crate; +//// if (crate.is/*18*/PackedTight) { +//// crate./*19*/; +//// } +//// if (crate.is/*20*/Sundries) { +//// crate.contents./*21*/; +//// if (crate.is/*22*/PackedTight) { +//// crate./*23*/ +//// } +//// } +//// if (crate.is/*24*/Supplies) { +//// crate.contents./*25*/; +//// if (crate.is/*26*/PackedTight) { +//// crate./*27*/ +//// } +//// } + +goTo.marker("1"); +verify.quickInfoIs("(property) FileSystemObject.isFile: this is Item"); +goTo.marker("2"); +verify.quickInfoIs("(property) FileSystemObject.isFile: this is Item"); +goTo.marker("3"); +verify.quickInfoIs("(property) FileSystemObject.isDirectory: this is Directory"); +goTo.marker("4"); +verify.quickInfoIs("(property) FileSystemObject.isNetworked: this is Networked & this"); +goTo.marker("5"); +verify.quickInfoIs("(property) Crate.isSundries: this is Crate"); +goTo.marker("6"); +verify.quickInfoIs("(property) Crate.isSupplies: this is Crate"); +goTo.marker("7"); +verify.quickInfoIs(`(property) Crate.isPackedTight: this is this & { + extraContents: T; +}`); +goTo.marker("8"); +verify.quickInfoIs("(property) FileSystemObject.isFile: this is Item"); +goTo.marker("10"); +verify.quickInfoIs("(property) FileSystemObject.isNetworked: this is Networked & Item"); +goTo.marker("12"); +verify.quickInfoIs("(property) FileSystemObject.isDirectory: this is Directory"); +goTo.marker("14"); +verify.quickInfoIs("(property) FileSystemObject.isNetworked: this is Networked & Directory"); +goTo.marker("16"); +verify.quickInfoIs("(property) FileSystemObject.isNetworked: this is Networked & FileSystemObject"); +goTo.marker("18"); +verify.quickInfoIs(`(property) Crate.isPackedTight: this is Crate & { + extraContents: any; +}`); +goTo.marker("20"); +verify.quickInfoIs("(property) Crate.isSundries: this is Crate"); +goTo.marker("22"); +verify.quickInfoIs(`(property) Crate.isPackedTight: this is Crate & { + extraContents: Sundries; +}`); +goTo.marker("24"); +verify.quickInfoIs("(property) Crate.isSupplies: this is Crate"); +goTo.marker("26"); +verify.quickInfoIs(`(property) Crate.isPackedTight: this is Crate & { + extraContents: Supplies; +}`); \ No newline at end of file