1 var compiler_input = "//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\nmodule TypeScript {\n export class AstLogger {\n\n constructor (public logger: ILogger) { }\n\n public logScript(script: TypeScript.Script): void {\n this.logLinemap(script.locationInfo.lineMap);\n\n var stack: AST[]= [];\n\n var pre = (cur: TypeScript.AST, parent: TypeScript.AST) => {\n stack.push(cur);\n var indent = (stack.length - 1) * 2;\n this.logComments(script, cur.preComments, indent);\n this.logNode(script, cur, indent);\n this.logComments(script, cur.postComments, indent);\n return cur;\n }\n\n var post = (cur: TypeScript.AST, parent: TypeScript.AST) => {\n stack.pop();\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(script, pre, post);\n }\n\n\n public logNode(script: TypeScript.Script, cur: TypeScript.AST, indent: number) {\n var msg = this.addPadding(\"\", indent, \"| \", true);\n\n msg = msg.concat(\"+ \" + cur.treeViewLabel());\n msg = this.addPadding(msg, 70, \" \", false);\n\n msg = msg + this.addLineColumn(script, cur.minChar);\n msg = this.addPadding(msg, 80, \" \", false);\n\n msg = msg + \"=> \";\n msg = msg + this.addLineColumn(script, cur.limChar);\n msg = this.addPadding(msg, 102, \" \", false);\n\n msg = msg.concat(\"[\" + this.addPadding(cur.minChar.toString(), 1, \" \", true) + \", \" + this.addPadding(cur.limChar.toString(), 1, \" \", true) + \"]\");\n\n msg = this.addPadding(msg, 115, \" \", false);\n msg = msg.concat(\"sym=\" + (<any>cur).sym);\n\n msg = this.addPadding(msg, 135, \" \", false);\n msg = msg.concat(\"type=\" + (cur.type === null ? \"null\" : cur.type.getTypeName()));\n this.logger.log(msg);\n }\n\n private logComments(script: TypeScript.Script, comments: TypeScript.AST[], indent: number) {\n if (comments == null)\n return;\n\n for (var i = 0; i < comments.length; i++) {\n this.logNode(script, comments[i], indent);\n }\n }\n\n public logLinemap(linemap: number[]) {\n var result = \"[\";\n for (var i = 0; i < linemap.length; i++) {\n if (i > 0)\n result += \",\";\n result += linemap[i];\n }\n result += \"]\";\n this.logger.log(\"linemap: \" + result);\n }\n\n private addPadding(s: string, targetLength: number, paddingString: string, leftPadding: bool): string {\n var result = (leftPadding ? \"\" : s);\n for (var i = s.length; i < targetLength; i++) {\n result = result + paddingString;\n }\n result = result + (leftPadding ? s : \"\");\n return result;\n }\n\n private addLineColumn(script: TypeScript.Script, position: number): string {\n // just for calling getSourceLineColFromMap\n var lineInfo = {\n line: -1,\n col: -1\n }\n TypeScript.getSourceLineColFromMap(lineInfo, position, script.locationInfo.lineMap);\n\n if (lineInfo.col !== -1) {\n lineInfo.col++; //TODO: function above seems to consider line as 1-based, and column as 0-based\n }\n\n return \"(\" + lineInfo.line + \", \" + lineInfo.col + \")\";\n }\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export function lastOf(items: any[]): any {\n return (items === null || items.length === 0) ? null : items[items.length - 1];\n }\n\n export function max(a: number, b: number): number {\n return a >= b ? a : b;\n }\n\n export function min(a: number, b: number): number {\n return a <= b ? a : b;\n }\n\n //\n // Helper class representing a path from a root ast node to a (grand)child ast node.\n // This is helpful as our tree don't have parents.\n //\n export class AstPath {\n public asts: TypeScript.AST[] = [];\n public top: number = -1;\n\n static reverseIndexOf(items: any[], index: number): any {\n return (items === null || items.length <= index) ? null : items[items.length - index - 1];\n }\n\n public clone(): AstPath {\n var clone = new AstPath();\n clone.asts = this.asts.map((value) => { return value; });\n clone.top = this.top;\n return clone;\n }\n\n public pop(): TypeScript.AST {\n var head = this.ast();\n this.up();\n\n while (this.asts.length > this.count()) {\n this.asts.pop();\n }\n return head;\n }\n\n public push(ast: TypeScript.AST) {\n while (this.asts.length > this.count()) {\n this.asts.pop();\n }\n this.top = this.asts.length;\n this.asts.push(ast);\n }\n\n public up() {\n if (this.top <= -1)\n throw new Error(\"Invalid call to 'up'\");\n this.top--;\n }\n\n public down() {\n if (this.top == this.ast.length - 1)\n throw new Error(\"Invalid call to 'down'\");\n this.top++;\n }\n\n public nodeType(): TypeScript.NodeType {\n if (this.ast() == null)\n return TypeScript.NodeType.None;\n return this.ast().nodeType;\n }\n\n public ast() {\n return <TypeScript.AST>AstPath.reverseIndexOf(this.asts, this.asts.length - (this.top + 1));\n }\n\n public parent() {\n return <TypeScript.AST>AstPath.reverseIndexOf(this.asts, this.asts.length - this.top);\n }\n\n public count() {\n return this.top + 1;\n }\n\n public get(index: number): TypeScript.AST {\n return this.asts[index];\n }\n\n public isNameOfClass(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.ClassDeclaration) &&\n ((<TypeScript.InterfaceDeclaration>this.parent()).name === this.ast());\n }\n\n public isNameOfInterface(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.InterfaceDeclaration) &&\n ((<TypeScript.InterfaceDeclaration>this.parent()).name === this.ast());\n }\n\n public isNameOfArgument(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.ArgDecl) &&\n ((<TypeScript.ArgDecl>this.parent()).id === this.ast());\n }\n\n public isNameOfVariable(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.VarDecl) &&\n ((<TypeScript.VarDecl>this.parent()).id === this.ast());\n }\n\n public isNameOfModule(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.ModuleDeclaration) &&\n ((<TypeScript.ModuleDeclaration>this.parent()).name === this.ast());\n }\n\n public isNameOfFunction(): bool {\n if (this.ast() === null || this.parent() === null)\n return false;\n\n return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n (this.parent().nodeType === TypeScript.NodeType.FuncDecl) &&\n ((<TypeScript.FuncDecl>this.parent()).name === this.ast());\n }\n\n public isChildOfScript(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.Script;\n }\n\n public isChildOfModule(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.ModuleDeclaration;\n }\n\n public isChildOfClass(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.ClassDeclaration;\n }\n\n public isArgumentOfClassConstructor(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 5 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl &&\n this.asts[this.top - 3].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 4].nodeType === TypeScript.NodeType.ClassDeclaration &&\n ((<TypeScript.FuncDecl>this.asts[this.top - 2]).isConstructor) &&\n ((<TypeScript.FuncDecl>this.asts[this.top - 2]).arguments === this.asts[this.top - 1]) &&\n ((<TypeScript.ClassDeclaration>this.asts[this.top - 4]).constructorDecl === this.asts[this.top - 2]);\n }\n\n public isChildOfInterface(): bool {\n var ast = lastOf(this.asts);\n return this.count() >= 3 &&\n this.asts[this.top] === ast &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.InterfaceDeclaration;\n }\n\n public isTopLevelImplicitModule() {\n return this.count() >= 1 &&\n this.asts[this.top].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n TypeScript.hasFlag((<TypeScript.ModuleDeclaration>this.asts[this.top]).modFlags, TypeScript.ModuleFlags.IsWholeFile);\n }\n\n public isBodyOfTopLevelImplicitModule() {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n (<TypeScript.ModuleDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0] &&\n TypeScript.hasFlag((<TypeScript.ModuleDeclaration>this.asts[this.top - 1]).modFlags, TypeScript.ModuleFlags.IsWholeFile);\n }\n\n public isBodyOfScript(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Script &&\n (<TypeScript.Script>this.asts[this.top - 1]).bod == this.asts[this.top - 0];\n }\n\n public isBodyOfSwitch(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Switch &&\n (<TypeScript.SwitchStatement>this.asts[this.top - 1]).caseList == this.asts[this.top - 0];\n }\n\n public isBodyOfModule(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n (<TypeScript.ModuleDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0];\n }\n\n public isBodyOfClass(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ClassDeclaration &&\n (<TypeScript.ClassDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0];\n }\n\n public isBodyOfFunction(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl &&\n (<TypeScript.FuncDecl>this.asts[this.top - 1]).bod == this.asts[this.top - 0];\n }\n\n public isBodyOfInterface(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.InterfaceDeclaration &&\n (<TypeScript.InterfaceDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0];\n }\n\n public isBodyOfBlock(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Block &&\n (<TypeScript.Block>this.asts[this.top - 1]).statements == this.asts[this.top - 0];\n }\n\n public isBodyOfFor(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.For &&\n (<TypeScript.ForStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfCase(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Case &&\n (<TypeScript.CaseStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfTry(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Try &&\n (<TypeScript.Try>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfCatch(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Catch &&\n (<TypeScript.Catch>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfDoWhile(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.DoWhile &&\n (<TypeScript.DoWhileStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfWhile(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.While &&\n (<TypeScript.WhileStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfForIn(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ForIn &&\n (<TypeScript.ForInStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfWith(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.With &&\n (<TypeScript.WithStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isBodyOfFinally(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Finally &&\n (<TypeScript.Finally>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n }\n\n public isCaseOfSwitch(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n (<TypeScript.SwitchStatement>this.asts[this.top - 2]).caseList == this.asts[this.top - 1];\n }\n\n public isDefaultCaseOfSwitch(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n (<TypeScript.SwitchStatement>this.asts[this.top - 2]).caseList == this.asts[this.top - 1] &&\n (<TypeScript.SwitchStatement>this.asts[this.top - 2]).defaultCase == this.asts[this.top - 0];\n }\n\n public isListOfObjectLit(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n (<TypeScript.UnaryExpression>this.asts[this.top - 1]).operand == this.asts[this.top - 0];\n }\n\n public isBodyOfObjectLit(): bool {\n return this.isListOfObjectLit();\n }\n\n public isEmptyListOfObjectLit(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n (<TypeScript.UnaryExpression>this.asts[this.top - 1]).operand == this.asts[this.top - 0] &&\n (<TypeScript.ASTList>this.asts[this.top - 0]).members.length == 0;\n }\n\n public isMemberOfObjectLit(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.Member &&\n (<TypeScript.UnaryExpression>this.asts[this.top - 2]).operand == this.asts[this.top - 1];\n }\n\n public isNameOfMemberOfObjectLit(): bool {\n return this.count() >= 4 &&\n this.asts[this.top - 3].nodeType === TypeScript.NodeType.ObjectLit &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.Name &&\n (<TypeScript.UnaryExpression>this.asts[this.top - 3]).operand == this.asts[this.top - 2];\n }\n\n public isListOfArrayLit(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.ArrayLit &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n (<TypeScript.UnaryExpression>this.asts[this.top - 1]).operand == this.asts[this.top - 0];\n }\n\n public isTargetOfMember(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n (<TypeScript.BinaryExpression>this.asts[this.top - 1]).operand1 === this.asts[this.top - 0];\n }\n\n public isMemberOfMember(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n (<TypeScript.BinaryExpression>this.asts[this.top - 1]).operand2 === this.asts[this.top - 0];\n }\n\n public isItemOfList(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List;\n //(<Tools.ASTList>this.asts[this.top - 1]).operand2 === this.asts[this.top - 0];\n }\n\n public isThenOfIf(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.If &&\n (<TypeScript.IfStatement>this.asts[this.top - 1]).thenBod == this.asts[this.top - 0];\n }\n\n public isElseOfIf(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.If &&\n (<TypeScript.IfStatement>this.asts[this.top - 1]).elseBod == this.asts[this.top - 0];\n }\n\n public isBodyOfDefaultCase(): bool {\n return this.isBodyOfCase();\n }\n\n public isSingleStatementList(): bool {\n return this.count() >= 1 &&\n this.asts[this.top].nodeType === TypeScript.NodeType.List &&\n (<TypeScript.ASTList>this.asts[this.top]).members.length === 1;\n }\n\n public isArgumentListOfFunction(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl &&\n (<TypeScript.FuncDecl>this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n }\n\n public isArgumentOfFunction(): bool {\n return this.count() >= 3 &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl &&\n (<TypeScript.FuncDecl>this.asts[this.top - 2]).arguments === this.asts[this.top - 1];\n }\n\n public isArgumentListOfCall(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.Call &&\n (<TypeScript.CallExpression>this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n }\n\n public isArgumentListOfNew(): bool {\n return this.count() >= 2 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n this.asts[this.top - 1].nodeType === TypeScript.NodeType.New &&\n (<TypeScript.CallExpression>this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n }\n\n public isSynthesizedBlock(): bool {\n return this.count() >= 1 &&\n this.asts[this.top - 0].nodeType === TypeScript.NodeType.Block &&\n (<TypeScript.Block>this.asts[this.top - 0]).isStatementBlock === false;\n }\n }\n\n export function isValidAstNode(ast: TypeScript.ASTSpan): bool {\n if (ast === null)\n return false;\n\n if (ast.minChar === -1 || ast.limChar === -1)\n return false;\n\n return true;\n }\n\n export class AstPathContext {\n public path = new TypeScript.AstPath();\n }\n\n export enum GetAstPathOptions {\n Default = 0,\n EdgeInclusive = 1,\n //We need this options dealing with an AST coming from an incomplete AST. For example:\n // class foo { // r\n // If we ask for the AST at the position after the \"r\" character, we won't see we are \n // inside a comment, because the \"class\" AST node has a limChar corresponding to the position of \n // the \"{\" character, meaning we don't traverse the tree down to the stmt list of the class, meaning\n // we don't find the \"precomment\" attached to the errorneous empty stmt.\n //TODO: It would be nice to be able to get rid of this.\n DontPruneSearchBasedOnPosition = 1 << 1,\n }\n\n ///\n /// Return the stack of AST nodes containing \"position\"\n ///\n export function getAstPathToPosition(script: TypeScript.AST, pos: number, options = GetAstPathOptions.Default): TypeScript.AstPath {\n var lookInComments = (comments: TypeScript.Comment[]) => {\n if (comments && comments.length > 0) {\n for (var i = 0; i < comments.length; i++) {\n var minChar = comments[i].minChar;\n var limChar = comments[i].limChar;\n if (!comments[i].isBlockComment) {\n limChar++; // For single line comments, include 1 more character (for the newline)\n }\n if (pos >= minChar && pos < limChar) {\n ctx.path.push(comments[i]);\n }\n }\n }\n }\n\n var pre = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: IAstWalker) {\n if (isValidAstNode(cur)) {\n\n // Add \"cur\" to the stack if it contains our position\n // For \"identifier\" nodes, we need a special case: A position equal to \"limChar\" is\n // valid, since the position corresponds to a caret position (in between characters)\n // For example:\n // bar\n // 0123\n // If \"position == 3\", the caret is at the \"right\" of the \"r\" character, which should be considered valid\n var inclusive =\n hasFlag(options, GetAstPathOptions.EdgeInclusive) ||\n cur.nodeType === TypeScript.NodeType.Name ||\n pos === script.limChar; // Special \"EOF\" case\n\n var minChar = cur.minChar;\n var limChar = cur.limChar + (inclusive ? 1 : 0)\n if (pos >= minChar && pos < limChar) {\n\n // TODO: Since AST is sometimes not correct wrt to position, only add \"cur\" if it's better\n // than top of the stack.\n var previous = ctx.path.ast();\n if (previous == null || (cur.minChar >= previous.minChar && cur.limChar <= previous.limChar)) {\n ctx.path.push(cur);\n }\n else {\n //logger.log(\"TODO: Ignoring node because minChar, limChar not better than previous node in stack\");\n }\n }\n\n // The AST walker skips comments, but we might be in one, so check the pre/post comments for this node manually\n if (pos < limChar) {\n lookInComments(cur.preComments);\n }\n if (pos >= minChar) {\n lookInComments(cur.postComments);\n }\n\n if (!hasFlag(options, GetAstPathOptions.DontPruneSearchBasedOnPosition)) {\n // Don't go further down the tree if pos is outside of [minChar, limChar]\n walker.options.goChildren = (minChar <= pos && pos <= limChar);\n }\n }\n return cur;\n }\n\n var ctx = new AstPathContext();\n TypeScript.getAstWalkerFactory().walk(script, pre, null, null, ctx);\n return ctx.path;\n }\n\n //\n // Find a source text offset that is safe for lexing tokens at the given position.\n // This is used when \"position\" might be inside a comment or string, etc.\n //\n export function getTokenizationOffset(script: TypeScript.Script, position: number): number {\n var bestOffset = 0;\n var pre = (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker): TypeScript.AST => {\n if (TypeScript.isValidAstNode(cur)) {\n // Did we find a closer offset?\n if (cur.minChar <= position) {\n bestOffset = max(bestOffset, cur.minChar);\n }\n\n // Stop the walk if this node is not related to \"minChar\"\n if (cur.minChar > position || cur.limChar < bestOffset) {\n walker.options.goChildren = false;\n }\n }\n\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(script, pre);\n return bestOffset;\n }\n\n ///\n /// Simple function to Walk an AST using a simple callback function.\n ///\n export function walkAST(ast: TypeScript.AST, callback: (path: AstPath, walker: TypeScript.IAstWalker) => void ): void {\n var pre = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n var path: TypeScript.AstPath = walker.state;\n path.push(cur);\n callback(path, walker);\n return cur;\n }\n var post = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n var path: TypeScript.AstPath = walker.state;\n path.pop();\n return cur;\n }\n\n var path = new AstPath();\n TypeScript.getAstWalkerFactory().walk(ast, pre, post, null, path);\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class ASTSpan {\n public minChar: number = -1; // -1 = \"undefined\" or \"compiler generated\"\n public limChar: number = -1; // -1 = \"undefined\" or \"compiler generated\" \n }\n\n export class AST extends ASTSpan {\n public type: Type = null;\n public flags = ASTFlags.Writeable;\n\n // REVIEW: for diagnostic purposes\n public passCreated: number = CompilerDiagnostics.analysisPass;\n\n public preComments: Comment[] = null;\n public postComments: Comment[] = null;\n private docComments: Comment[] = null;\n\n public isParenthesized = false;\n\n constructor (public nodeType: NodeType) {\n super();\n }\n\n public isExpression() { return false; }\n\n public isStatementOrExpression() { return false; }\n\n public isCompoundStatement() { return false; }\n\n public isLeaf() { return this.isStatementOrExpression() && (!this.isCompoundStatement()); }\n \n public isDeclaration() { return false; }\n\n public typeCheck(typeFlow: TypeFlow) {\n switch (this.nodeType) {\n case NodeType.Error:\n case NodeType.EmptyExpr:\n this.type = typeFlow.anyType;\n break;\n case NodeType.This:\n return typeFlow.typeCheckThis(this);\n case NodeType.Null:\n this.type = typeFlow.nullType;\n break;\n case NodeType.False:\n case NodeType.True:\n this.type = typeFlow.booleanType;\n break;\n case NodeType.Super:\n return typeFlow.typeCheckSuper(this);\n case NodeType.EndCode:\n case NodeType.Empty:\n case NodeType.Void:\n this.type = typeFlow.voidType;\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n switch (this.nodeType) {\n case NodeType.This:\n emitter.recordSourceMappingStart(this);\n if (emitter.thisFnc && (hasFlag(emitter.thisFnc.fncFlags, FncFlags.IsFatArrowFunction))) {\n emitter.writeToOutput(\"_this\");\n }\n else {\n emitter.writeToOutput(\"this\");\n }\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.Null:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"null\");\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.False:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"false\");\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.True:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"true\");\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.Super:\n emitter.recordSourceMappingStart(this);\n emitter.emitSuperReference();\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.EndCode:\n case NodeType.Error:\n case NodeType.EmptyExpr:\n break;\n case NodeType.Empty:\n emitter.recordSourceMappingStart(this);\n emitter.recordSourceMappingEnd(this);\n break;\n case NodeType.Void:\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"void \");\n emitter.recordSourceMappingEnd(this);\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public print(context: PrintContext) {\n context.startLine();\n var lineCol = { line: -1, col: -1 };\n var limLineCol = { line: -1, col: -1 };\n if (context.parser !== null) {\n context.parser.getSourceLineCol(lineCol, this.minChar);\n context.parser.getSourceLineCol(limLineCol, this.limChar);\n context.write(\"(\" + lineCol.line + \",\" + lineCol.col + \")--\" +\n \"(\" + limLineCol.line + \",\" + limLineCol.col + \"): \");\n }\n var lab = this.printLabel();\n if (hasFlag(this.flags, ASTFlags.Error)) {\n lab += \" (Error)\";\n }\n context.writeLine(lab);\n }\n\n public printLabel() {\n if (nodeTypeTable[this.nodeType] !== undefined) {\n return nodeTypeTable[this.nodeType];\n }\n else {\n return (<any>NodeType)._map[this.nodeType];\n }\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n // by default, AST adds itself to current basic block and does not check its children\n context.walker.options.goChildren = false;\n context.addContent(this);\n }\n\n public netFreeUses(container: Symbol, freeUses: StringHashTable) {\n }\n\n public treeViewLabel() {\n return (<any>NodeType)._map[this.nodeType];\n }\n\n public static getResolvedIdentifierName(name: string): string {\n if (!name) return \"\";\n\n var resolved = \"\";\n var start = 0;\n var i = 0;\n while(i <= name.length - 6) {\n // Look for escape sequence \\uxxxx\n if (name.charAt(i) == '\\\\' && name.charAt(i+1) == 'u') {\n var charCode = parseInt(name.substr(i + 2, 4), 16);\n resolved += name.substr(start, i - start);\n resolved += String.fromCharCode(charCode);\n i += 6;\n start = i;\n continue;\n } \n i++;\n }\n // Append remaining string\n resolved += name.substring(start);\n return resolved;\n }\n\n public getDocComments() : Comment[] {\n if (!this.isDeclaration() || !this.preComments || this.preComments.length == 0) {\n return [];\n }\n\n if (!this.docComments) {\n var preCommentsLength = this.preComments.length;\n var docComments: Comment[] = [];\n for (var i = preCommentsLength - 1; i >= 0; i--) {\n if (this.preComments[i].isDocComment()) {\n var prevDocComment = docComments.length > 0 ? docComments[docComments.length - 1] : null;\n if (prevDocComment == null || // If the help comments were not yet set then this is the comment\n (this.preComments[i].limLine == prevDocComment.minLine ||\n this.preComments[i].limLine + 1 == prevDocComment.minLine)) { // On same line or next line\n docComments.push(this.preComments[i]);\n continue;\n }\n }\n break;\n }\n\n this.docComments = docComments.reverse();\n }\n\n return this.docComments;\n }\n }\n\n export class IncompleteAST extends AST {\n constructor (min: number, lim: number) {\n super(NodeType.Error);\n\n this.minChar = min;\n this.limChar = lim;\n }\n }\n\n export class ASTList extends AST {\n public enclosingScope: SymbolScope = null;\n public members: AST[] = new AST[];\n\n constructor () {\n super(NodeType.List);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var len = this.members.length;\n for (var i = 0; i < len; i++) {\n if (context.noContinuation) {\n context.addUnreachable(this.members[i]);\n break;\n }\n else {\n this.members[i] = context.walk(this.members[i], this);\n }\n }\n context.walker.options.goChildren = false;\n }\n\n public append(ast: AST) {\n this.members[this.members.length] = ast;\n return this;\n }\n\n public appendAll(ast: AST) {\n if (ast.nodeType == NodeType.List) {\n var list = <ASTList>ast;\n for (var i = 0, len = list.members.length; i < len; i++) {\n this.append(list.members[i]);\n }\n }\n else {\n this.append(ast);\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascriptList(this, null, TokenID.Semicolon, startLine, false, false);\n emitter.recordSourceMappingEnd(this);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var len = this.members.length;\n typeFlow.nestingLevel++;\n for (var i = 0; i < len; i++) {\n if (this.members[i]) {\n this.members[i] = this.members[i].typeCheck(typeFlow);\n }\n }\n typeFlow.nestingLevel--;\n return this;\n }\n }\n\n export class Identifier extends AST {\n public sym: Symbol = null;\n public cloId = -1;\n public text: string;\n\n // 'actualText' is the text that the user has entered for the identifier. the text might \n // include any Unicode escape sequences (e.g.: \\u0041 for 'A'). 'text', however, contains \n // the resolved value of any escape sequences in the actual text; so in the previous \n // example, actualText = '\\u0041', text = 'A'.\n //\n // For purposes of finding a symbol, use text, as this will allow you to match all \n // variations of the variable text. For full-fidelity translation of the user input, such\n // as emitting, use the actualText field.\n // \n // Note: \n // To change text, and to avoid running into a situation where 'actualText' does not \n // match 'text', always use setText.\n constructor (public actualText: string, public hasEscapeSequence?: bool) {\n super(NodeType.Name);\n this.setText(actualText, hasEscapeSequence);\n }\n\n public setText(actualText: string, hasEscapeSequence?: bool) {\n this.actualText = actualText;\n if (hasEscapeSequence) {\n this.text = AST.getResolvedIdentifierName(actualText);\n }\n else {\n this.text = actualText;\n }\n }\n\n public isMissing() { return false; }\n public isLeaf() { return true; }\n\n public treeViewLabel() {\n return \"id: \" + this.actualText;\n }\n\n public printLabel() {\n if (this.actualText) {\n return \"id: \" + this.actualText;\n }\n else {\n return \"name node\";\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckName(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptName(this, true);\n }\n\n public static fromToken(token: Token): Identifier {\n return new Identifier(token.getText(), (<IdentifierToken>token).hasEscapeSequence);\n }\n }\n\n export class MissingIdentifier extends Identifier {\n constructor () {\n super(\"__missing\");\n }\n\n public isMissing() {\n return true;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n // Emit nothing for a missing ID\n }\n }\n\n export class Label extends AST {\n constructor (public id: Identifier) {\n super(NodeType.Label);\n }\n\n public printLabel() { return this.id.actualText + \":\"; }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.voidType;\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.recordSourceMappingStart(this.id);\n emitter.writeToOutput(this.id.actualText);\n emitter.recordSourceMappingEnd(this.id);\n emitter.writeLineToOutput(\":\");\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class Expression extends AST {\n constructor (nodeType: NodeType) {\n super(nodeType);\n }\n\n public isExpression() { return true; }\n\n public isStatementOrExpression() { return true; }\n }\n\n export class UnaryExpression extends Expression {\n public targetType: Type = null; // Target type for an object literal (null if no target type)\n public castTerm: AST = null;\n\n constructor (nodeType: NodeType, public operand: AST) {\n super(nodeType);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n super.addToControlFlow(context);\n // TODO: add successor as catch block/finally block if present\n if (this.nodeType == NodeType.Throw) {\n context.returnStmt();\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n switch (this.nodeType) {\n case NodeType.Not:\n return typeFlow.typeCheckBitNot(this);\n\n case NodeType.LogNot:\n return typeFlow.typeCheckLogNot(this);\n\n case NodeType.Pos:\n case NodeType.Neg:\n return typeFlow.typeCheckUnaryNumberOperator(this);\n\n case NodeType.IncPost:\n case NodeType.IncPre:\n case NodeType.DecPost:\n case NodeType.DecPre:\n return typeFlow.typeCheckIncOrDec(this);\n\n case NodeType.ArrayLit:\n typeFlow.typeCheckArrayLit(this);\n return this;\n\n case NodeType.ObjectLit:\n typeFlow.typeCheckObjectLit(this);\n return this;\n\n case NodeType.Throw:\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.voidType;\n return this;\n\n case NodeType.Typeof:\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.stringType;\n return this;\n\n case NodeType.Delete:\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.booleanType;\n break;\n\n case NodeType.TypeAssertion:\n this.castTerm = typeFlow.typeCheck(this.castTerm);\n var applyTargetType = !this.operand.isParenthesized;\n\n var targetType = applyTargetType ? this.castTerm.type : null;\n\n typeFlow.checker.typeCheckWithContextualType(targetType, typeFlow.checker.inProvisionalTypecheckMode(), true, this.operand);\n typeFlow.castWithCoercion(this.operand, this.castTerm.type, false, true);\n this.type = this.castTerm.type;\n return this;\n\n case NodeType.Void:\n // REVIEW - Although this is good to do for completeness's sake,\n // this shouldn't be strictly necessary from the void operator's\n // point of view\n this.operand = typeFlow.typeCheck(this.operand);\n this.type = typeFlow.checker.undefinedType;\n break;\n\n default:\n throw new Error(\"please implement in derived class\");\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n switch (this.nodeType) {\n case NodeType.IncPost:\n emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);\n emitter.writeToOutput(\"++\");\n break;\n case NodeType.LogNot:\n emitter.writeToOutput(\"!\");\n emitter.emitJavascript(this.operand, TokenID.Exclamation, false);\n break;\n case NodeType.DecPost:\n emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);\n emitter.writeToOutput(\"--\");\n break;\n case NodeType.ObjectLit:\n emitter.emitObjectLiteral(<ASTList>this.operand);\n break;\n case NodeType.ArrayLit:\n emitter.emitArrayLiteral(<ASTList>this.operand);\n break;\n case NodeType.Not:\n emitter.writeToOutput(\"~\");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.Neg:\n emitter.writeToOutput(\"-\");\n if (this.operand.nodeType == NodeType.Neg) {\n this.operand.isParenthesized = true;\n }\n emitter.emitJavascript(this.operand, TokenID.Minus, false);\n break;\n case NodeType.Pos:\n emitter.writeToOutput(\"+\");\n if (this.operand.nodeType == NodeType.Pos) {\n this.operand.isParenthesized = true;\n }\n emitter.emitJavascript(this.operand, TokenID.Plus, false);\n break;\n case NodeType.IncPre:\n emitter.writeToOutput(\"++\");\n emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);\n break;\n case NodeType.DecPre:\n emitter.writeToOutput(\"--\");\n emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);\n break;\n case NodeType.Throw:\n emitter.writeToOutput(\"throw \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n emitter.writeToOutput(\";\");\n break;\n case NodeType.Typeof:\n emitter.writeToOutput(\"typeof \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.Delete:\n emitter.writeToOutput(\"delete \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.Void:\n emitter.writeToOutput(\"void \");\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n case NodeType.TypeAssertion:\n emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class CallExpression extends Expression {\n constructor (nodeType: NodeType,\n public target: AST,\n public arguments: ASTList) {\n super(nodeType);\n this.minChar = this.target.minChar;\n }\n\n public signature: Signature = null;\n\n public typeCheck(typeFlow: TypeFlow) {\n if (this.nodeType == NodeType.New) {\n return typeFlow.typeCheckNew(this);\n }\n else {\n return typeFlow.typeCheckCall(this);\n }\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n\n if (this.nodeType == NodeType.New) {\n emitter.emitNew(this.target, this.arguments);\n }\n else {\n emitter.emitCall(this, this.target, this.arguments);\n }\n\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class BinaryExpression extends Expression {\n constructor (nodeType: NodeType, public operand1: AST, public operand2: AST) {\n super(nodeType);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n switch (this.nodeType) {\n case NodeType.Dot:\n return typeFlow.typeCheckDotOperator(this);\n case NodeType.Asg:\n return typeFlow.typeCheckAsgOperator(this);\n case NodeType.Add:\n case NodeType.Sub:\n case NodeType.Mul:\n case NodeType.Div:\n case NodeType.Mod:\n case NodeType.Or:\n case NodeType.And:\n return typeFlow.typeCheckArithmeticOperator(this, false);\n case NodeType.Xor:\n return typeFlow.typeCheckBitwiseOperator(this, false);\n case NodeType.Ne:\n case NodeType.Eq:\n var text: string;\n if (typeFlow.checker.styleSettings.eqeqeq) {\n text = nodeTypeTable[this.nodeType];\n typeFlow.checker.errorReporter.styleError(this, \"use of \" + text);\n }\n else if (typeFlow.checker.styleSettings.eqnull) {\n text = nodeTypeTable[this.nodeType];\n if ((this.operand2 !== null) && (this.operand2.nodeType == NodeType.Null)) {\n typeFlow.checker.errorReporter.styleError(this, \"use of \" + text + \" to compare with null\");\n }\n }\n case NodeType.Eqv:\n case NodeType.NEqv:\n case NodeType.Lt:\n case NodeType.Le:\n case NodeType.Ge:\n case NodeType.Gt:\n return typeFlow.typeCheckBooleanOperator(this);\n case NodeType.Index:\n return typeFlow.typeCheckIndex(this);\n case NodeType.Member:\n this.type = typeFlow.voidType;\n return this;\n case NodeType.LogOr:\n return typeFlow.typeCheckLogOr(this);\n case NodeType.LogAnd:\n return typeFlow.typeCheckLogAnd(this);\n case NodeType.AsgAdd:\n case NodeType.AsgSub:\n case NodeType.AsgMul:\n case NodeType.AsgDiv:\n case NodeType.AsgMod:\n case NodeType.AsgOr:\n case NodeType.AsgAnd:\n return typeFlow.typeCheckArithmeticOperator(this, true);\n case NodeType.AsgXor:\n return typeFlow.typeCheckBitwiseOperator(this, true);\n case NodeType.Lsh:\n case NodeType.Rsh:\n case NodeType.Rs2:\n return typeFlow.typeCheckShift(this, false);\n case NodeType.AsgLsh:\n case NodeType.AsgRsh:\n case NodeType.AsgRs2:\n return typeFlow.typeCheckShift(this, true);\n case NodeType.Comma:\n return typeFlow.typeCheckCommaOperator(this);\n case NodeType.InstOf:\n return typeFlow.typeCheckInstOf(this);\n case NodeType.In:\n return typeFlow.typeCheckInOperator(this);\n case NodeType.From:\n typeFlow.checker.errorReporter.simpleError(this, \"Illegal use of 'from' keyword in binary expression\");\n break;\n default:\n throw new Error(\"please implement in derived class\");\n }\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n var binTokenId = nodeTypeToTokTable[this.nodeType];\n\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (binTokenId != undefined) {\n\n emitter.emitJavascript(this.operand1, binTokenId, false);\n\n if (tokenTable[binTokenId].text == \"instanceof\") {\n emitter.writeToOutput(\" instanceof \");\n }\n else if (tokenTable[binTokenId].text == \"in\") {\n emitter.writeToOutput(\" in \");\n }\n else {\n emitter.writeToOutputTrimmable(\" \" + tokenTable[binTokenId].text + \" \");\n }\n\n emitter.emitJavascript(this.operand2, binTokenId, false);\n }\n else {\n switch (this.nodeType) {\n case NodeType.Dot:\n if (!emitter.tryEmitConstant(this)) {\n emitter.emitJavascript(this.operand1, TokenID.Dot, false);\n emitter.writeToOutput(\".\");\n emitter.emitJavascriptName(<Identifier>this.operand2, false);\n }\n break;\n case NodeType.Index:\n emitter.emitIndex(this.operand1, this.operand2);\n break;\n\n case NodeType.Member:\n if (this.operand2.nodeType == NodeType.FuncDecl && (<FuncDecl>this.operand2).isAccessor()) {\n var funcDecl = <FuncDecl>this.operand2;\n if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n emitter.writeToOutput(\"get \");\n }\n else {\n emitter.writeToOutput(\"set \");\n }\n emitter.emitJavascript(this.operand1, TokenID.Colon, false);\n }\n else {\n emitter.emitJavascript(this.operand1, TokenID.Colon, false);\n emitter.writeToOutputTrimmable(\": \");\n }\n emitter.emitJavascript(this.operand2, TokenID.Comma, false);\n break;\n case NodeType.Comma:\n emitter.emitJavascript(this.operand1, TokenID.Comma, false);\n if (emitter.emitState.inObjectLiteral) {\n emitter.writeLineToOutput(\", \");\n }\n else {\n emitter.writeToOutput(\",\");\n }\n emitter.emitJavascript(this.operand2, TokenID.Comma, false);\n break;\n case NodeType.Is:\n throw new Error(\"should be de-sugared during type check\");\n default:\n throw new Error(\"please implement in derived class\");\n }\n }\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class ConditionalExpression extends Expression {\n constructor (public operand1: AST,\n public operand2: AST,\n public operand3: AST) {\n super(NodeType.ConditionalExpression);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckQMark(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascript(this.operand1, TokenID.Question, false);\n emitter.writeToOutput(\" ? \");\n emitter.emitJavascript(this.operand2, TokenID.Question, false);\n emitter.writeToOutput(\" : \");\n emitter.emitJavascript(this.operand3, TokenID.Question, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class NumberLiteral extends Expression {\n constructor (public value: number, public hasEmptyFraction?: bool) {\n super(NodeType.NumberLit);\n }\n\n public isNegativeZero = false;\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.doubleType;\n return this;\n }\n\n public treeViewLabel() {\n return \"num: \" + this.printLabel();\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.isNegativeZero) {\n emitter.writeToOutput(\"-\");\n }\n\n emitter.writeToOutput(this.value.toString());\n\n if (this.hasEmptyFraction)\n emitter.writeToOutput(\".0\");\n\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public printLabel() {\n if (Math.floor(this.value) != this.value) {\n return this.value.toFixed(2).toString();\n }\n else if (this.hasEmptyFraction) {\n return this.value.toString() + \".0\";\n }\n else {\n return this.value.toString();\n }\n }\n }\n\n export class RegexLiteral extends Expression {\n constructor (public regex) {\n super(NodeType.Regex);\n }\n \n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.regexType;\n return this;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(this.regex.toString());\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class StringLiteral extends Expression {\n constructor (public text: string) {\n super(NodeType.QString);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.emitStringLiteral(this.text);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.stringType;\n return this;\n }\n\n public treeViewLabel() {\n return \"st: \" + this.text;\n }\n\n public printLabel() {\n return this.text;\n }\n }\n\n export class ModuleElement extends AST {\n constructor (nodeType: NodeType) {\n super(nodeType);\n }\n }\n\n export class ImportDeclaration extends ModuleElement {\n public isStatementOrExpression() { return true; }\n public varFlags = VarFlags.None;\n public isDynamicImport = false;\n public isDeclaration() { return true; }\n\n constructor (public id: Identifier, public alias: AST) {\n super(NodeType.ImportDeclaration);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n var mod = <ModuleType>this.alias.type;\n // REVIEW: Only modules may be aliased for now, though there's no real\n // restriction on what the type symbol may be\n if (!this.isDynamicImport || (this.id.sym && !(<TypeSymbol>this.id.sym).onlyReferencedAsTypeRef)) {\n var prevModAliasId = emitter.modAliasId;\n var prevFirstModAlias = emitter.firstModAlias;\n\n emitter.recordSourceMappingStart(this);\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.writeToOutput(\"var \" + this.id.actualText + \" = \");\n emitter.modAliasId = this.id.actualText;\n emitter.firstModAlias = this.firstAliasedModToString();\n emitter.emitJavascript(this.alias, TokenID.Tilde, false);\n // the dynamic import case will insert the semi-colon automatically\n if (!this.isDynamicImport) {\n emitter.writeToOutput(\";\");\n }\n emitter.emitParensAndCommentsInPlace(this, false);\n emitter.recordSourceMappingEnd(this);\n\n emitter.modAliasId = prevModAliasId;\n emitter.firstModAlias = prevFirstModAlias;\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckImportDecl(this);\n }\n\n public getAliasName(aliasAST?: AST = this.alias) : string {\n if (aliasAST.nodeType == NodeType.Name) {\n return (<Identifier>aliasAST).actualText;\n } else {\n var dotExpr = <BinaryExpression>aliasAST;\n return this.getAliasName(dotExpr.operand1) + \".\" + this.getAliasName(dotExpr.operand2);\n }\n }\n\n public firstAliasedModToString() {\n if (this.alias.nodeType == NodeType.Name) {\n return (<Identifier>this.alias).actualText;\n }\n else {\n var dotExpr = <BinaryExpression>this.alias;\n var firstMod = <Identifier>dotExpr.operand1;\n return firstMod.actualText;\n }\n }\n }\n\n export class BoundDecl extends AST {\n public init: AST = null;\n public typeExpr: AST = null;\n public varFlags = VarFlags.None;\n public sym: Symbol = null;\n public isDeclaration() { return true; }\n\n constructor (public id: Identifier, nodeType: NodeType, public nestingLevel: number) {\n super(nodeType);\n }\n\n public isStatementOrExpression() { return true; }\n\n public isPrivate() { return hasFlag(this.varFlags, VarFlags.Private); }\n public isPublic() { return hasFlag(this.varFlags, VarFlags.Public); }\n public isProperty() { return hasFlag(this.varFlags, VarFlags.Property); }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckBoundDecl(this);\n }\n\n public printLabel() {\n return this.treeViewLabel();\n }\n }\n\n export class VarDecl extends BoundDecl {\n constructor (id: Identifier, nest: number) {\n super(id, NodeType.VarDecl, nest);\n }\n\n public isAmbient() { return hasFlag(this.varFlags, VarFlags.Ambient); }\n public isExported() { return hasFlag(this.varFlags, VarFlags.Exported); }\n public isStatic() { return hasFlag(this.varFlags, VarFlags.Static); }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptVarDecl(this, tokenId);\n }\n\n public treeViewLabel() {\n return \"var \" + this.id.actualText;\n }\n }\n\n export class ArgDecl extends BoundDecl {\n constructor (id: Identifier) {\n super(id, NodeType.ArgDecl, 0);\n }\n\n public isOptional = false;\n\n public isOptionalArg() { return this.isOptional || this.init; }\n\n public treeViewLabel() {\n return \"arg: \" + this.id.actualText;\n }\n\n public parameterPropertySym: FieldSymbol = null;\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(this.id.actualText);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n var internalId = 0;\n\n export class FuncDecl extends AST {\n public hint: string = null;\n public fncFlags = FncFlags.None;\n public returnTypeAnnotation: AST = null;\n public symbols: IHashTable;\n public variableArgList = false;\n public signature: Signature;\n public envids: Identifier[];\n public jumpRefs: Identifier[] = null;\n public internalNameCache: string = null;\n public tmp1Declared = false;\n public enclosingFnc: FuncDecl = null;\n public freeVariables: Symbol[] = [];\n public unitIndex = -1;\n public classDecl: NamedDeclaration = null;\n public boundToProperty: VarDecl = null;\n public isOverload = false;\n public innerStaticFuncs: FuncDecl[] = [];\n public isTargetTypedAsMethod = false;\n public isInlineCallLiteral = false;\n public accessorSymbol: Symbol = null;\n public leftCurlyCount = 0;\n public rightCurlyCount = 0;\n public returnStatementsWithExpressions: ReturnStatement[] = [];\n public scopeType: Type = null; // Type of the FuncDecl, before target typing\n public endingToken: ASTSpan = null;\n public isDeclaration() { return true; }\n\n constructor (public name: Identifier, public bod: ASTList, public isConstructor: bool,\n public arguments: ASTList, public vars: ASTList, public scopes: ASTList, public statics: ASTList,\n nodeType: number) {\n\n super(nodeType);\n }\n\n public internalName(): string {\n if (this.internalNameCache == null) {\n var extName = this.getNameText();\n if (extName) {\n this.internalNameCache = \"_internal_\" + extName;\n }\n else {\n this.internalNameCache = \"_internal_\" + internalId++;\n }\n }\n return this.internalNameCache;\n }\n\n public hasSelfReference() { return hasFlag(this.fncFlags, FncFlags.HasSelfReference); }\n public setHasSelfReference() { this.fncFlags |= FncFlags.HasSelfReference; }\n\n public hasSuperReferenceInFatArrowFunction() { return hasFlag(this.fncFlags, FncFlags.HasSuperReferenceInFatArrowFunction); }\n public setHasSuperReferenceInFatArrowFunction() { this.fncFlags |= FncFlags.HasSuperReferenceInFatArrowFunction; }\n\n public addCloRef(id: Identifier, sym: Symbol): number {\n if (this.envids == null) {\n this.envids = new Identifier[];\n }\n this.envids[this.envids.length] = id;\n var outerFnc = this.enclosingFnc;\n if (sym) {\n while (outerFnc && (outerFnc.type.symbol != sym.container)) {\n outerFnc.addJumpRef(sym);\n outerFnc = outerFnc.enclosingFnc;\n }\n }\n return this.envids.length - 1;\n }\n\n public addJumpRef(sym: Symbol): void {\n if (this.jumpRefs == null) {\n this.jumpRefs = new Identifier[];\n }\n var id = new Identifier(sym.name);\n this.jumpRefs[this.jumpRefs.length] = id;\n id.sym = sym;\n id.cloId = this.addCloRef(id, null);\n }\n\n public buildControlFlow(): ControlFlowContext {\n var entry = new BasicBlock();\n var exit = new BasicBlock();\n\n var context = new ControlFlowContext(entry, exit);\n\n var controlFlowPrefix = (ast: AST, parent: AST, walker: IAstWalker) => {\n ast.addToControlFlow(walker.state);\n return ast;\n }\n\n var walker = getAstWalkerFactory().getWalker(controlFlowPrefix, null, null, context);\n context.walker = walker;\n walker.walk(this.bod, this);\n\n return context;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckFunction(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptFunction(this);\n }\n\n public getNameText() {\n if (this.name) {\n return this.name.actualText;\n }\n else {\n return this.hint;\n }\n }\n\n public isMethod() {\n return (this.fncFlags & FncFlags.Method) != FncFlags.None;\n }\n\n public isCallMember() { return hasFlag(this.fncFlags, FncFlags.CallMember); }\n public isConstructMember() { return hasFlag(this.fncFlags, FncFlags.ConstructMember); }\n public isIndexerMember() { return hasFlag(this.fncFlags, FncFlags.IndexerMember); }\n public isSpecialFn() { return this.isCallMember() || this.isIndexerMember() || this.isConstructMember(); }\n public isAnonymousFn() { return this.name === null; }\n public isAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor) || hasFlag(this.fncFlags, FncFlags.SetAccessor); }\n public isGetAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor); }\n public isSetAccessor() { return hasFlag(this.fncFlags, FncFlags.SetAccessor); }\n public isAmbient() { return hasFlag(this.fncFlags, FncFlags.Ambient); }\n public isExported() { return hasFlag(this.fncFlags, FncFlags.Exported); }\n public isPrivate() { return hasFlag(this.fncFlags, FncFlags.Private); }\n public isPublic() { return hasFlag(this.fncFlags, FncFlags.Public); }\n public isStatic() { return hasFlag(this.fncFlags, FncFlags.Static); }\n\n public treeViewLabel() {\n if (this.name == null) {\n return \"funcExpr\";\n }\n else {\n return \"func: \" + this.name.actualText\n }\n }\n\n public ClearFlags(): void {\n this.fncFlags = FncFlags.None;\n }\n\n public isSignature() { return (this.fncFlags & FncFlags.Signature) != FncFlags.None; }\n }\n\n export class LocationInfo {\n constructor (public filename: string, public lineMap: number[], public unitIndex) { }\n }\n\n export var unknownLocationInfo = new LocationInfo(\"unknown\", null, -1);\n\n export class Script extends FuncDecl {\n public locationInfo: LocationInfo = null;\n public referencedFiles: IFileReference[] = [];\n public requiresGlobal = false;\n public requiresExtendsBlock = false;\n public isResident = false;\n public isDeclareFile = false;\n public hasBeenTypeChecked = false;\n public topLevelMod: ModuleDeclaration = null;\n public leftCurlyCount = 0;\n public rightCurlyCount = 0;\n public vars: ASTList;\n public scopes: ASTList;\n // Remember if the script contains Unicode chars, that is needed when generating code for this script object to decide the output file correct encoding.\n public containsUnicodeChar = false;\n public containsUnicodeCharInComment = false;\n public cachedEmitRequired: bool;\n\n private setCachedEmitRequired(value: bool) {\n this.cachedEmitRequired = value;\n return this.cachedEmitRequired;\n }\n\n constructor (vars: ASTList, scopes: ASTList) {\n super(new Identifier(\"script\"), null, false, null, vars, scopes, null, NodeType.Script);\n this.vars = vars;\n this.scopes = scopes;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckScript(this);\n }\n\n public treeViewLabel() {\n return \"Script\";\n }\n\n public emitRequired(emitOptions: EmitOptions) {\n if (this.cachedEmitRequired != undefined) {\n return this.cachedEmitRequired;\n }\n\n if (!this.isDeclareFile && !this.isResident && this.bod) {\n if (this.bod.members.length == 0) {\n // allow empty files that are not declare files \n return this.setCachedEmitRequired(true);\n }\n\n for (var i = 0, len = this.bod.members.length; i < len; i++) {\n var stmt = this.bod.members[i];\n if (stmt.nodeType == NodeType.ModuleDeclaration) {\n if (!hasFlag((<ModuleDeclaration>stmt).modFlags, ModuleFlags.ShouldEmitModuleDecl | ModuleFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.ClassDeclaration) {\n if (!hasFlag((<ClassDeclaration>stmt).varFlags, VarFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.VarDecl) {\n if (!hasFlag((<VarDecl>stmt).varFlags, VarFlags.Ambient)) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType == NodeType.FuncDecl) {\n if (!(<FuncDecl>stmt).isSignature()) {\n return this.setCachedEmitRequired(true);\n }\n }\n else if (stmt.nodeType != NodeType.InterfaceDeclaration && stmt.nodeType != NodeType.Empty) {\n return this.setCachedEmitRequired(true);\n }\n }\n\n if ( emitOptions.emitComments &&\n ((this.bod.preComments && this.bod.preComments.length > 0) || (this.bod.postComments && this.bod.postComments.length > 0))) {\n return this.setCachedEmitRequired(true);\n }\n }\n return this.setCachedEmitRequired(false);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n if (this.emitRequired(emitter.emitOptions)) {\n emitter.emitParensAndCommentsInPlace(this.bod, true);\n emitter.emitJavascriptList(this.bod, null, TokenID.Semicolon, true, false, false, true, this.requiresExtendsBlock);\n emitter.emitParensAndCommentsInPlace(this.bod, false);\n }\n }\n\n private externallyVisibleImportedSymbols: Symbol[] = [];\n\n public AddExternallyVisibleImportedSymbol(symbol: Symbol, checker: TypeChecker) {\n if (this.isExternallyVisibleSymbol(symbol)) {\n return;\n }\n\n // Before adding check if the external symbol is also marked for visibility\n if (!symbol.getType().symbol.isExternallyVisible(checker)) {\n // Report error\n var quotes = \"\";\n var moduleName = symbol.getType().symbol.prettyName;\n if (!isQuoted(moduleName)) {\n quotes = \"'\";\n }\n checker.errorReporter.simpleError(symbol.declAST, \"Externally visible import statement uses non exported module \" + quotes + moduleName + quotes);\n }\n this.externallyVisibleImportedSymbols.push(symbol);\n }\n\n public isExternallyVisibleSymbol(symbol: Symbol) {\n for (var i = 0 ; i < this.externallyVisibleImportedSymbols.length; i++) {\n if (this.externallyVisibleImportedSymbols[i] == symbol) {\n return true;\n }\n }\n return false;\n }\n }\n\n export class NamedDeclaration extends ModuleElement {\n public leftCurlyCount = 0;\n public rightCurlyCount = 0;\n public isDeclaration() { return true; }\n\n constructor (nodeType: NodeType,\n public name: Identifier,\n public members: ASTList) {\n super(nodeType);\n }\n }\n\n export class ModuleDeclaration extends NamedDeclaration {\n public modFlags = ModuleFlags.ShouldEmitModuleDecl;\n public mod: ModuleType;\n public prettyName: string;\n public amdDependencies: string[] = [];\n public vars: ASTList;\n public scopes: ASTList;\n // Remember if the module contains Unicode chars, that is needed for dynamic module as we will generate a file for each.\n public containsUnicodeChar = false;\n public containsUnicodeCharInComment = false;\n\n constructor (name: Identifier, members: ASTList, vars: ASTList, scopes: ASTList, public endingToken: ASTSpan) {\n super(NodeType.ModuleDeclaration, name, members);\n\n this.vars = vars;\n this.scopes = scopes;\n this.prettyName = this.name.actualText;\n }\n\n public isExported() { return hasFlag(this.modFlags, ModuleFlags.Exported); }\n public isAmbient() { return hasFlag(this.modFlags, ModuleFlags.Ambient); }\n public isEnum() { return hasFlag(this.modFlags, ModuleFlags.IsEnum); }\n\n public recordNonInterface() {\n this.modFlags &= ~ModuleFlags.ShouldEmitModuleDecl;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckModule(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n if (!hasFlag(this.modFlags, ModuleFlags.ShouldEmitModuleDecl)) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.emitJavascriptModule(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n }\n\n export class TypeDeclaration extends NamedDeclaration {\n public varFlags = VarFlags.None;\n\n constructor (nodeType: NodeType,\n name: Identifier,\n public extendsList: ASTList,\n public implementsList: ASTList,\n members: ASTList) {\n super(nodeType, name, members);\n }\n\n public isExported() { \n return hasFlag(this.varFlags, VarFlags.Exported);\n }\n\n public isAmbient() {\n return hasFlag(this.varFlags, VarFlags.Ambient);\n }\n }\n\n export class ClassDeclaration extends TypeDeclaration {\n public knownMemberNames: any = {};\n public constructorDecl: FuncDecl = null;\n public constructorNestingLevel = 0;\n public endingToken: ASTSpan = null;\n\n constructor (name: Identifier,\n members: ASTList,\n extendsList: ASTList,\n implementsList: ASTList) {\n super(NodeType.ClassDeclaration, name, extendsList, implementsList, members);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckClass(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitJavascriptClass(this);\n }\n }\n\n export class InterfaceDeclaration extends TypeDeclaration {\n constructor (name: Identifier,\n members: ASTList,\n extendsList: ASTList,\n implementsList: ASTList) {\n super(NodeType.InterfaceDeclaration, name, extendsList, implementsList, members);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckInterface(this);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n }\n }\n\n export class Statement extends ModuleElement {\n constructor (nodeType: NodeType) {\n super(nodeType);\n this.flags |= ASTFlags.IsStatement;\n }\n\n public isLoop() { return false; }\n\n public isStatementOrExpression() { return true; }\n\n public isCompoundStatement() { return this.isLoop(); }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.type = typeFlow.voidType;\n return this;\n }\n }\n\n export class LabeledStatement extends Statement {\n constructor (public labels: ASTList, public stmt: AST) {\n super(NodeType.LabeledStatement);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.labels) {\n var labelsLen = this.labels.members.length;\n for (var i = 0; i < labelsLen; i++) {\n this.labels.members[i].emit(emitter, tokenId, startLine);\n }\n }\n this.stmt.emit(emitter, tokenId, true);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n typeFlow.typeCheck(this.labels);\n this.stmt = this.stmt.typeCheck(typeFlow);\n return this;\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n var beforeBB = context.current;\n var bb = new BasicBlock();\n context.current = bb;\n beforeBB.addSuccessor(bb);\n }\n }\n\n export class Block extends Statement {\n constructor (public statements: ASTList,\n public isStatementBlock: bool) {\n super(NodeType.Block);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.isStatementBlock) {\n emitter.writeLineToOutput(\" {\");\n emitter.indenter.increaseIndent();\n } else {\n emitter.setInVarBlock(this.statements.members.length);\n }\n var temp = emitter.setInObjectLiteral(false);\n if (this.statements) {\n emitter.emitJavascriptList(this.statements, null, TokenID.Semicolon, true, false, false);\n }\n if (this.isStatementBlock) {\n emitter.indenter.decreaseIndent();\n emitter.emitIndent();\n emitter.writeToOutput(\"}\");\n }\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var afterIfNeeded = new BasicBlock();\n context.pushStatement(this, context.current, afterIfNeeded);\n if (this.statements) {\n context.walk(this.statements, this);\n }\n context.walker.options.goChildren = false;\n context.popStatement();\n if (afterIfNeeded.predecessors.length > 0) {\n context.current.addSuccessor(afterIfNeeded);\n context.current = afterIfNeeded;\n }\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n if (!typeFlow.checker.styleSettings.emptyBlocks) {\n if ((this.statements === null) || (this.statements.members.length == 0)) {\n typeFlow.checker.errorReporter.styleError(this, \"empty block\");\n }\n }\n\n typeFlow.typeCheck(this.statements);\n return this;\n }\n }\n\n export class Jump extends Statement {\n public target: string = null;\n public hasExplicitTarget() { return (this.target); }\n public resolvedTarget: Statement = null;\n\n constructor (nodeType: NodeType) {\n super(nodeType);\n }\n\n public setResolvedTarget(parser: Parser, stmt: Statement): bool {\n if (stmt.isLoop()) {\n this.resolvedTarget = stmt;\n return true;\n }\n if (this.nodeType === NodeType.Continue) {\n parser.reportParseError(\"continue statement applies only to loops\");\n return false;\n }\n else {\n if ((stmt.nodeType == NodeType.Switch) || this.hasExplicitTarget()) {\n this.resolvedTarget = stmt;\n return true;\n }\n else {\n parser.reportParseError(\"break statement with no label can apply only to a loop or switch statement\");\n return false;\n }\n }\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n super.addToControlFlow(context);\n context.unconditionalBranch(this.resolvedTarget, (this.nodeType == NodeType.Continue));\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.nodeType == NodeType.Break) {\n emitter.writeToOutput(\"break\");\n }\n else {\n emitter.writeToOutput(\"continue\");\n }\n if (this.hasExplicitTarget()) {\n emitter.writeToOutput(\" \" + this.target);\n }\n emitter.recordSourceMappingEnd(this);\n emitter.writeToOutput(\";\");\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n\n export class WhileStatement extends Statement {\n public body: AST = null;\n\n constructor (public cond: AST) {\n super(NodeType.While);\n }\n\n public isLoop() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.writeToOutput(\"while(\");\n emitter.emitJavascript(this.cond, TokenID.While, false);\n emitter.writeToOutput(\")\");\n emitter.emitJavascriptStatements(this.body, false);\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckWhile(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n context.addContent(this.cond);\n var condBlock = context.current;\n var targetInfo: ITargetInfo = null;\n if (this.body) {\n context.current = new BasicBlock();\n condBlock.addSuccessor(context.current);\n context.pushStatement(this, loopStart, afterLoop);\n context.walk(this.body, this);\n targetInfo = context.popStatement();\n }\n if (!(context.noContinuation)) {\n var loopEnd = context.current;\n loopEnd.addSuccessor(loopStart);\n }\n context.current = afterLoop;\n condBlock.addSuccessor(afterLoop);\n // TODO: check for while (true) and then only continue if afterLoop has predecessors\n context.noContinuation = false;\n context.walker.options.goChildren = false;\n }\n }\n\n export class DoWhileStatement extends Statement {\n public body: AST = null;\n public whileAST: AST = null;\n public cond: AST = null;\n public isLoop() { return true; }\n\n constructor () {\n super(NodeType.DoWhile);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.writeToOutput(\"do\");\n emitter.emitJavascriptStatements(this.body, true);\n emitter.recordSourceMappingStart(this.whileAST);\n emitter.writeToOutput(\"while\");\n emitter.recordSourceMappingEnd(this.whileAST);\n emitter.writeToOutput('(');\n emitter.emitJavascript(this.cond, TokenID.CloseParen, false);\n emitter.writeToOutput(\")\");\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.writeToOutput(\";\");\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckDoWhile(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n var targetInfo: ITargetInfo = null;\n if (this.body) {\n context.pushStatement(this, loopStart, afterLoop);\n context.walk(this.body, this);\n targetInfo = context.popStatement();\n }\n if (!(context.noContinuation)) {\n var loopEnd = context.current;\n loopEnd.addSuccessor(loopStart);\n context.addContent(this.cond);\n // TODO: check for while (true) \n context.current = afterLoop;\n loopEnd.addSuccessor(afterLoop);\n }\n else {\n context.addUnreachable(this.cond);\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class IfStatement extends Statement {\n public thenBod: AST;\n public elseBod: AST = null;\n public statement: ASTSpan = new ASTSpan();\n\n constructor (public cond: AST) {\n super(NodeType.If);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"if(\");\n emitter.emitJavascript(this.cond, TokenID.If, false);\n emitter.writeToOutput(\")\");\n emitter.recordSourceMappingEnd(this.statement);\n emitter.emitJavascriptStatements(this.thenBod, true);\n if (this.elseBod) {\n if (this.elseBod.nodeType === NodeType.If) {\n emitter.writeToOutput(\" else \");\n this.elseBod.emit(emitter, tokenId, /*startLine:*/ false);\n }\n else {\n emitter.writeToOutput(\" else\");\n emitter.emitJavascriptStatements(this.elseBod, true);\n }\n }\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckIf(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n this.cond.addToControlFlow(context);\n var afterIf = new BasicBlock();\n var beforeIf = context.current;\n context.pushStatement(this, beforeIf, afterIf);\n var hasContinuation = false;\n context.current = new BasicBlock();\n beforeIf.addSuccessor(context.current);\n context.walk(this.thenBod, this);\n if (!context.noContinuation) {\n hasContinuation = true;\n context.current.addSuccessor(afterIf);\n }\n if (this.elseBod) {\n // current block will be thenBod\n context.current = new BasicBlock();\n context.noContinuation = false;\n beforeIf.addSuccessor(context.current);\n context.walk(this.elseBod, this);\n if (!context.noContinuation) {\n hasContinuation = true;\n context.current.addSuccessor(afterIf);\n }\n else {\n // thenBod created continuation for if statement\n if (hasContinuation) {\n context.noContinuation = false;\n }\n }\n }\n else {\n beforeIf.addSuccessor(afterIf);\n context.noContinuation = false;\n hasContinuation = true;\n }\n var targetInfo = context.popStatement();\n if (afterIf.predecessors.length > 0) {\n context.noContinuation = false;\n hasContinuation = true;\n }\n if (hasContinuation) {\n context.current = afterIf;\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class ReturnStatement extends Statement {\n public returnExpression: AST = null;\n\n constructor () {\n super(NodeType.Return);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n if (this.returnExpression) {\n emitter.writeToOutput(\"return \");\n emitter.emitJavascript(this.returnExpression, TokenID.Semicolon, false);\n\n if (this.returnExpression.nodeType === NodeType.FuncDecl) {\n emitter.writeToOutput(\";\");\n }\n }\n else {\n emitter.writeToOutput(\"return;\");\n }\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n super.addToControlFlow(context);\n context.returnStmt();\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckReturn(this);\n }\n }\n\n export class EndCode extends AST {\n constructor () {\n super(NodeType.EndCode);\n }\n }\n\n export class ForInStatement extends Statement {\n constructor (public lval: AST, public obj: AST) {\n super(NodeType.ForIn);\n if (this.lval && (this.lval.nodeType == NodeType.VarDecl)) {\n (<BoundDecl>this.lval).varFlags |= VarFlags.AutoInit;\n }\n }\n public statement: ASTSpan = new ASTSpan();\n public body: AST;\n\n public isLoop() { return true; }\n\n public isFiltered() {\n if (this.body) {\n var singleItem: AST = null;\n if (this.body.nodeType == NodeType.List) {\n var stmts = <ASTList>this.body;\n if (stmts.members.length == 1) {\n singleItem = stmts.members[0];\n }\n }\n else {\n singleItem = this.body;\n }\n // match template for filtering 'own' properties from obj\n if (singleItem !== null) {\n if (singleItem.nodeType == NodeType.Block) {\n var block = <Block>singleItem;\n if ((block.statements !== null) && (block.statements.members.length == 1)) {\n singleItem = block.statements.members[0];\n }\n }\n if (singleItem.nodeType == NodeType.If) {\n var cond = (<IfStatement>singleItem).cond;\n if (cond.nodeType == NodeType.Call) {\n var target = (<CallExpression>cond).target;\n if (target.nodeType == NodeType.Dot) {\n var binex = <BinaryExpression>target;\n if ((binex.operand1.nodeType == NodeType.Name) &&\n (this.obj.nodeType == NodeType.Name) &&\n ((<Identifier>binex.operand1).actualText == (<Identifier>this.obj).actualText)) {\n var prop = <Identifier>binex.operand2;\n if (prop.actualText == \"hasOwnProperty\") {\n var args = (<CallExpression>cond).arguments;\n if ((args !== null) && (args.members.length == 1)) {\n var arg = args.members[0];\n if ((arg.nodeType == NodeType.Name) &&\n (this.lval.nodeType == NodeType.Name)) {\n if (((<Identifier>this.lval).actualText) == (<Identifier>arg).actualText) {\n return true;\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n return false;\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"for(\");\n emitter.emitJavascript(this.lval, TokenID.For, false);\n emitter.writeToOutput(\" in \");\n emitter.emitJavascript(this.obj, TokenID.For, false);\n emitter.writeToOutput(\")\");\n emitter.recordSourceMappingEnd(this.statement);\n emitter.emitJavascriptStatements(this.body, true);\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n if (typeFlow.checker.styleSettings.forin) {\n if (!this.isFiltered()) {\n typeFlow.checker.errorReporter.styleError(this, \"no hasOwnProperty filter\");\n }\n }\n return typeFlow.typeCheckForIn(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n if (this.lval) {\n context.addContent(this.lval);\n }\n if (this.obj) {\n context.addContent(this.obj);\n }\n\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n if (this.body) {\n context.pushStatement(this, loopStart, afterLoop);\n context.walk(this.body, this);\n context.popStatement();\n }\n if (!(context.noContinuation)) {\n var loopEnd = context.current;\n loopEnd.addSuccessor(loopStart);\n }\n context.current = afterLoop;\n context.noContinuation = false;\n loopHeader.addSuccessor(afterLoop);\n context.walker.options.goChildren = false;\n }\n }\n\n export class ForStatement extends Statement {\n public cond: AST;\n public body: AST;\n public incr: AST;\n\n constructor (public init: AST) {\n super(NodeType.For);\n }\n\n public isLoop() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.writeToOutput(\"for(\");\n if (this.init) {\n if (this.init.nodeType != NodeType.List) {\n emitter.emitJavascript(this.init, TokenID.For, false);\n }\n else {\n emitter.setInVarBlock((<ASTList>this.init).members.length); \n emitter.emitJavascriptList(this.init, null, TokenID.For, false, false, false);\n }\n }\n emitter.writeToOutput(\"; \");\n emitter.emitJavascript(this.cond, TokenID.For, false);\n emitter.writeToOutput(\"; \");\n emitter.emitJavascript(this.incr, TokenID.For, false);\n emitter.writeToOutput(\")\");\n emitter.emitJavascriptStatements(this.body, true);\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckFor(this);\n }\n\n public addToControlFlow(context: ControlFlowContext): void {\n if (this.init) {\n context.addContent(this.init);\n }\n var loopHeader = context.current;\n var loopStart = new BasicBlock();\n var afterLoop = new BasicBlock();\n\n loopHeader.addSuccessor(loopStart);\n context.current = loopStart;\n var condBlock: BasicBlock = null;\n var continueTarget = loopStart;\n var incrBB: BasicBlock = null;\n if (this.incr) {\n incrBB = new BasicBlock();\n continueTarget = incrBB;\n }\n if (this.cond) {\n condBlock = context.current;\n context.addContent(this.cond);\n context.current = new BasicBlock();\n condBlock.addSuccessor(context.current);\n }\n var targetInfo: ITargetInfo = null;\n if (this.body) {\n context.pushStatement(this, continueTarget, afterLoop);\n context.walk(this.body, this);\n targetInfo = context.popStatement();\n }\n if (this.incr) {\n if (context.noContinuation) {\n if (incrBB.predecessors.length == 0) {\n context.addUnreachable(this.incr);\n }\n }\n else {\n context.current.addSuccessor(incrBB);\n context.current = incrBB;\n context.addContent(this.incr);\n }\n }\n var loopEnd = context.current;\n if (!(context.noContinuation)) {\n loopEnd.addSuccessor(loopStart);\n\n }\n if (condBlock) {\n condBlock.addSuccessor(afterLoop);\n context.noContinuation = false;\n }\n if (afterLoop.predecessors.length > 0) {\n context.noContinuation = false;\n context.current = afterLoop;\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class WithStatement extends Statement {\n public body: AST;\n\n public isCompoundStatement() { return true; }\n\n public withSym: WithSymbol = null;\n\n constructor (public expr: AST) {\n super(NodeType.With);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"with (\");\n if (this.expr) {\n emitter.emitJavascript(this.expr, TokenID.With, false);\n }\n\n emitter.writeToOutput(\")\");\n emitter.emitJavascriptStatements(this.body, true);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n return typeFlow.typeCheckWith(this);\n }\n }\n\n export class SwitchStatement extends Statement {\n public caseList: ASTList;\n public defaultCase: CaseStatement = null;\n public statement: ASTSpan = new ASTSpan();\n\n constructor (public val: AST) {\n super(NodeType.Switch);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n var temp = emitter.setInObjectLiteral(false);\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"switch(\");\n emitter.emitJavascript(this.val, TokenID.Identifier, false);\n emitter.writeToOutput(\")\"); \n emitter.recordSourceMappingEnd(this.statement);\n emitter.writeLineToOutput(\" {\");\n emitter.indenter.increaseIndent();\n var casesLen = this.caseList.members.length;\n for (var i = 0; i < casesLen; i++) {\n var caseExpr = this.caseList.members[i];\n emitter.emitJavascript(caseExpr, TokenID.Case, true);\n }\n emitter.indenter.decreaseIndent();\n emitter.emitIndent();\n emitter.writeToOutput(\"}\");\n emitter.setInObjectLiteral(temp);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var len = this.caseList.members.length;\n this.val = typeFlow.typeCheck(this.val);\n for (var i = 0; i < len; i++) {\n this.caseList.members[i] = typeFlow.typeCheck(this.caseList.members[i]);\n }\n this.defaultCase = <CaseStatement>typeFlow.typeCheck(this.defaultCase);\n this.type = typeFlow.voidType;\n return this;\n }\n\n // if there are break statements that match this switch, then just link cond block with block after switch\n public addToControlFlow(context: ControlFlowContext) {\n var condBlock = context.current;\n context.addContent(this.val);\n var execBlock = new BasicBlock();\n var afterSwitch = new BasicBlock();\n\n condBlock.addSuccessor(execBlock);\n context.pushSwitch(execBlock);\n context.current = execBlock;\n context.pushStatement(this, execBlock, afterSwitch);\n context.walk(this.caseList, this);\n context.popSwitch();\n var targetInfo = context.popStatement();\n var hasCondContinuation = (this.defaultCase == null);\n if (this.defaultCase == null) {\n condBlock.addSuccessor(afterSwitch);\n }\n if (afterSwitch.predecessors.length > 0) {\n context.noContinuation = false;\n context.current = afterSwitch;\n }\n else {\n context.noContinuation = true;\n }\n context.walker.options.goChildren = false;\n }\n }\n\n export class CaseStatement extends Statement {\n public expr: AST = null;\n public body: ASTList;\n\n constructor () {\n super(NodeType.Case);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n if (this.expr) {\n emitter.writeToOutput(\"case \");\n emitter.emitJavascript(this.expr, TokenID.Identifier, false);\n }\n else {\n emitter.writeToOutput(\"default\");\n }\n emitter.writeToOutput(\":\");\n if (this.body.members.length == 1 && this.body.members[0].nodeType == NodeType.Block) {\n // The case statement was written with curly braces, so emit it with the appropriate formatting\n emitter.emitJavascriptStatements(this.body, false);\n }\n else {\n // No curly braces. Format in the expected way\n emitter.writeLineToOutput(\"\");\n emitter.indenter.increaseIndent();\n emitter.emitBareJavascriptStatements(this.body);\n emitter.indenter.decreaseIndent();\n }\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.expr = typeFlow.typeCheck(this.expr);\n typeFlow.typeCheck(this.body);\n this.type = typeFlow.voidType;\n return this;\n }\n\n // TODO: more reasoning about unreachable cases (such as duplicate literals as case expressions)\n // for now, assume all cases are reachable, regardless of whether some cases fall through\n public addToControlFlow(context: ControlFlowContext) {\n var execBlock = new BasicBlock();\n var sw = context.currentSwitch[context.currentSwitch.length - 1];\n // TODO: fall-through from previous (+ to end of switch)\n if (this.expr) {\n var exprBlock = new BasicBlock();\n context.current = exprBlock;\n sw.addSuccessor(exprBlock);\n context.addContent(this.expr);\n exprBlock.addSuccessor(execBlock);\n }\n else {\n sw.addSuccessor(execBlock);\n }\n context.current = execBlock;\n if (this.body) {\n context.walk(this.body, this);\n }\n context.noContinuation = false;\n context.walker.options.goChildren = false;\n }\n }\n\n export class TypeReference extends AST {\n constructor (public term: AST, public arrayCount: number) {\n super(NodeType.TypeRef);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n throw new Error(\"should not emit a type ref\");\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var prevInTCTR = typeFlow.inTypeRefTypeCheck;\n typeFlow.inTypeRefTypeCheck = true;\n var typeLink = getTypeLink(this, typeFlow.checker, true);\n typeFlow.checker.resolveTypeLink(typeFlow.scope, typeLink, false);\n\n if (this.term) {\n typeFlow.typeCheck(this.term);\n }\n\n typeFlow.checkForVoidConstructor(typeLink.type, this);\n\n this.type = typeLink.type;\n\n // in error recovery cases, there may not be a term\n if (this.term) {\n this.term.type = this.type;\n }\n\n typeFlow.inTypeRefTypeCheck = prevInTCTR;\n return this;\n }\n }\n\n export class TryFinally extends Statement {\n constructor (public tryNode: AST, public finallyNode: Finally) {\n super(NodeType.TryFinally);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascript(this.tryNode, TokenID.Try, false);\n emitter.emitJavascript(this.finallyNode, TokenID.Finally, false);\n emitter.recordSourceMappingEnd(this);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.tryNode = typeFlow.typeCheck(this.tryNode);\n this.finallyNode = <Finally>typeFlow.typeCheck(this.finallyNode);\n this.type = typeFlow.voidType;\n return this;\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var afterFinally = new BasicBlock();\n context.walk(this.tryNode, this);\n var finBlock = new BasicBlock();\n if (context.current) {\n context.current.addSuccessor(finBlock);\n }\n context.current = finBlock;\n context.pushStatement(this, null, afterFinally);\n context.walk(this.finallyNode, this);\n if (!context.noContinuation && context.current) {\n context.current.addSuccessor(afterFinally);\n }\n if (afterFinally.predecessors.length > 0) {\n context.current = afterFinally;\n }\n else {\n context.noContinuation = true;\n }\n context.popStatement();\n context.walker.options.goChildren = false;\n }\n }\n\n export class TryCatch extends Statement {\n constructor (public tryNode: Try, public catchNode: Catch) {\n super(NodeType.TryCatch);\n }\n\n public isCompoundStatement() { return true; }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.emitJavascript(this.tryNode, TokenID.Try, false);\n emitter.emitJavascript(this.catchNode, TokenID.Catch, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n var beforeTry = context.current;\n var tryBlock = new BasicBlock();\n beforeTry.addSuccessor(tryBlock);\n context.current = tryBlock;\n var afterTryCatch = new BasicBlock();\n context.pushStatement(this, null, afterTryCatch);\n context.walk(this.tryNode, this);\n if (!context.noContinuation) {\n if (context.current) {\n context.current.addSuccessor(afterTryCatch);\n }\n }\n context.current = new BasicBlock();\n beforeTry.addSuccessor(context.current);\n context.walk(this.catchNode, this);\n context.popStatement();\n if (!context.noContinuation) {\n if (context.current) {\n context.current.addSuccessor(afterTryCatch);\n }\n }\n context.current = afterTryCatch;\n context.walker.options.goChildren = false;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.tryNode = <Try>typeFlow.typeCheck(this.tryNode);\n this.catchNode = <Catch>typeFlow.typeCheck(this.catchNode);\n this.type = typeFlow.voidType;\n return this;\n }\n }\n\n export class Try extends Statement {\n constructor (public body: AST) {\n super(NodeType.Try);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"try \");\n emitter.emitJavascript(this.body, TokenID.Try, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.body = typeFlow.typeCheck(this.body);\n return this;\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n if (this.body) {\n context.walk(this.body, this);\n }\n context.walker.options.goChildren = false;\n context.noContinuation = false;\n }\n }\n\n export class Catch extends Statement {\n constructor (public param: VarDecl, public body: AST) {\n super(NodeType.Catch);\n if (this.param) {\n this.param.varFlags |= VarFlags.AutoInit;\n }\n }\n public statement: ASTSpan = new ASTSpan();\n public containedScope: SymbolScope = null;\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\" \");\n emitter.recordSourceMappingStart(this.statement);\n emitter.writeToOutput(\"catch (\");\n emitter.emitJavascript(this.param, TokenID.OpenParen, false);\n emitter.writeToOutput(\")\");\n emitter.recordSourceMappingEnd(this.statement);\n emitter.emitJavascript(this.body, TokenID.Catch, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n if (this.param) {\n context.addContent(this.param);\n var bodBlock = new BasicBlock();\n context.current.addSuccessor(bodBlock);\n context.current = bodBlock;\n }\n if (this.body) {\n context.walk(this.body, this);\n }\n context.noContinuation = false;\n context.walker.options.goChildren = false;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n var prevScope = typeFlow.scope;\n typeFlow.scope = this.containedScope;\n this.param = <VarDecl>typeFlow.typeCheck(this.param);\n var exceptVar = new ValueLocation();\n var varSym = new VariableSymbol((<VarDecl>this.param).id.text,\n this.param.minChar,\n typeFlow.checker.locationInfo.unitIndex,\n exceptVar);\n exceptVar.symbol = varSym;\n exceptVar.typeLink = new TypeLink();\n // var type for now (add syntax for type annotation)\n exceptVar.typeLink.type = typeFlow.anyType;\n var thisFnc = typeFlow.thisFnc;\n if (thisFnc && thisFnc.type) {\n exceptVar.symbol.container = thisFnc.type.symbol;\n }\n else {\n exceptVar.symbol.container = null;\n }\n this.param.sym = exceptVar.symbol;\n typeFlow.scope.enter(exceptVar.symbol.container, this.param, exceptVar.symbol,\n typeFlow.checker.errorReporter, false, false, false);\n this.body = typeFlow.typeCheck(this.body);\n\n // if we're in provisional typecheck mode, clean up the symbol entry\n // REVIEW: This is obviously bad form, since we're counting on the internal\n // layout of the symbol table, but this is also the only place where we insert\n // symbols during typecheck\n if (typeFlow.checker.inProvisionalTypecheckMode()) {\n var table = typeFlow.scope.getTable();\n (<any>table).secondaryTable.table[exceptVar.symbol.name] = undefined;\n }\n this.type = typeFlow.voidType;\n typeFlow.scope = prevScope;\n return this;\n }\n }\n\n export class Finally extends Statement {\n constructor (public body: AST) {\n super(NodeType.Finally);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeToOutput(\"finally\");\n emitter.emitJavascript(this.body, TokenID.Finally, false);\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n\n public addToControlFlow(context: ControlFlowContext) {\n if (this.body) {\n context.walk(this.body, this);\n }\n context.walker.options.goChildren = false;\n context.noContinuation = false;\n }\n\n public typeCheck(typeFlow: TypeFlow) {\n this.body = typeFlow.typeCheck(this.body);\n return this;\n }\n }\n\n export class Comment extends AST {\n\n public text: string[] = null;\n public minLine: number;\n public limLine: number;\n private docCommentText: string = null;\n\n constructor (public content: string, public isBlockComment: bool, public endsLine) {\n super(NodeType.Comment);\n }\n\n public getText(): string[] {\n if (this.text == null) {\n if (this.isBlockComment) {\n this.text = this.content.split(\"\\n\");\n for (var i = 0; i < this.text.length; i++) {\n this.text[i] = this.text[i].replace(/^\\s+|\\s+$/g, '');\n }\n }\n else {\n this.text = [(this.content.replace(/^\\s+|\\s+$/g, ''))];\n }\n }\n\n return this.text;\n }\n\n public isDocComment() {\n if (this.isBlockComment) {\n return this.content.charAt(2) == \"*\";\n }\n\n return false;\n }\n\n public getDocCommentText() {\n if (this.docCommentText == null) {\n this.docCommentText = Comment.cleanJSDocComment(this.content);\n }\n\n return this.docCommentText;\n }\n\n static consumeLeadingSpace(line: string, startIndex: number, maxSpacesToRemove?: number) {\n var endIndex = line.length;\n if (maxSpacesToRemove != undefined) {\n endIndex = min(startIndex + maxSpacesToRemove, endIndex);\n }\n\n for (; startIndex < endIndex; startIndex++) {\n var charCode = line.charCodeAt(startIndex);\n if (charCode != LexCodeSpace && charCode != LexCodeTAB) {\n return startIndex;\n }\n }\n \n if (endIndex != line.length) {\n return endIndex;\n }\n\n return -1;\n }\n\n static isSpaceChar(line: string, index: number) {\n var length = line.length;\n if (index < length) {\n var charCode = line.charCodeAt(index);\n // If the character is space\n return charCode == LexCodeSpace || charCode == LexCodeTAB;\n }\n\n // If the index is end of the line it is space\n return index == length;\n }\n\n static cleanDocCommentLine(line: string, jsDocStyleComment: bool, jsDocLineSpaceToRemove?: number) {\n var nonSpaceIndex = Comment.consumeLeadingSpace(line, 0);\n if (nonSpaceIndex != -1) {\n var jsDocSpacesRemoved = nonSpaceIndex;\n if (jsDocStyleComment && line.charAt(nonSpaceIndex) == '*') { // remove leading * in case of jsDocComment\n var startIndex = nonSpaceIndex + 1;\n nonSpaceIndex = Comment.consumeLeadingSpace(line, startIndex, jsDocLineSpaceToRemove);\n\n if (nonSpaceIndex != -1) {\n jsDocSpacesRemoved = nonSpaceIndex - startIndex;\n } else {\n return null;\n }\n }\n\n return {\n minChar: nonSpaceIndex,\n limChar: line.charAt(line.length - 1) == \"\\r\" ? line.length - 1 : line.length,\n jsDocSpacesRemoved: jsDocSpacesRemoved\n };\n }\n\n return null;\n }\n\n static cleanJSDocComment(content: string, spacesToRemove?: number) {\n var docCommentLines: string[] = [];\n content = content.replace(\"/**\", \"\"); // remove /**\n if (content.length >= 2 && content.charAt(content.length - 1) == \"/\" && content.charAt(content.length - 2) == \"*\") {\n content = content.substring(0, content.length - 2); // remove last */\n }\n var lines = content.split(\"\\n\");\n var inParamTag = false;\n for (var l = 0; l < lines.length; l++) {\n var line = lines[l];\n var cleanLinePos = Comment.cleanDocCommentLine(line, true, spacesToRemove);\n if (!cleanLinePos) {\n // Whole line empty, read next line\n continue;\n }\n\n var docCommentText = \"\";\n var prevPos = cleanLinePos.minChar;\n for (var i = line.indexOf(\"@\", cleanLinePos.minChar); 0 <= i && i < cleanLinePos.limChar; i = line.indexOf(\"@\", i + 1)) {\n // We have encoutered @. \n // If we were omitting param comment, we dont have to do anything\n // other wise the content of the text till @ tag goes as doc comment\n var wasInParamtag = inParamTag;\n\n // Parse contents next to @\n if (line.indexOf(\"param\", i + 1) == i + 1 && Comment.isSpaceChar(line, i + 6)) {\n // It is param tag. \n\n // If we were not in param tag earlier, push the contents from prev pos of the tag this tag start as docComment\n if (!wasInParamtag) {\n docCommentText += line.substring(prevPos, i);\n }\n\n // New start of contents \n prevPos = i;\n inParamTag = true;\n } else if (wasInParamtag) {\n // Non param tag start\n prevPos = i;\n inParamTag = false;\n }\n }\n\n if (!inParamTag) {\n docCommentText += line.substring(prevPos, cleanLinePos.limChar);\n }\n\n // Add line to comment text if it is not only white space line\n var newCleanPos = Comment.cleanDocCommentLine(docCommentText, false);\n if (newCleanPos) {\n if (spacesToRemove == undefined) {\n spacesToRemove = cleanLinePos.jsDocSpacesRemoved;\n }\n docCommentLines.push(docCommentText);\n }\n }\n \n return docCommentLines.join(\"\\n\");\n }\n\n static getDocCommentText(comments: Comment[]) {\n var docCommentText: string[] = [];\n for (var c = 0 ; c < comments.length; c++) {\n var commentText = comments[c].getDocCommentText();\n if (commentText != \"\") {\n docCommentText.push(commentText);\n }\n }\n return docCommentText.join(\"\\n\");\n }\n\n static getParameterDocCommentText(param: string, fncDocComments: Comment[]) {\n if (fncDocComments.length == 0 || !fncDocComments[0].isBlockComment) {\n // there were no fnc doc comments and the comment is not block comment then it cannot have \n // @param comment that can be parsed\n return \"\";\n }\n \n for (var i = 0; i < fncDocComments.length; i++) {\n var commentContents = fncDocComments[i].content;\n for (var j = commentContents.indexOf(\"@param\", 0); 0 <= j; j = commentContents.indexOf(\"@param\", j)) {\n j += 6;\n if (!Comment.isSpaceChar(commentContents, j)) {\n // This is not param tag but a tag line @paramxxxxx\n continue;\n }\n\n // This is param tag. Check if it is what we are looking for\n j = Comment.consumeLeadingSpace(commentContents, j);\n if (j == -1) {\n break;\n }\n \n // Ignore the type expression\n if (commentContents.charCodeAt(j) == LexCodeLC) {\n j++;\n // Consume the type\n var charCode = 0;\n for (var curlies = 1; j < commentContents.length; j++) {\n charCode = commentContents.charCodeAt(j);\n // { character means we need to find another } to match the found one\n if (charCode == LexCodeLC) {\n curlies++;\n continue;\n }\n\n // } char\n if (charCode == LexCodeRC) {\n curlies--;\n if (curlies == 0) {\n // We do not have any more } to match the type expression is ignored completely\n break;\n } else {\n // there are more { to be matched with }\n continue;\n }\n }\n\n // Found start of another tag\n if (charCode == LexCodeAtSign) {\n break;\n }\n }\n\n // End of the comment\n if (j == commentContents.length) {\n break;\n }\n\n // End of the tag, go onto looking for next tag\n if (charCode == LexCodeAtSign) {\n continue;\n }\n\n j = Comment.consumeLeadingSpace(commentContents, j + 1);\n if (j == -1) {\n break;\n }\n }\n\n // Parameter name\n if (param != commentContents.substr(j, param.length) || !Comment.isSpaceChar(commentContents, j + param.length)) {\n // this is not the parameter we are looking for\n continue;\n }\n\n // Found the parameter we were looking for\n j = Comment.consumeLeadingSpace(commentContents, j + param.length);\n if (j == -1) {\n return \"\";\n }\n \n var endOfParam = commentContents.indexOf(\"@\", j);\n var paramHelpString = commentContents.substring(j, endOfParam < 0 ? commentContents.length : endOfParam);\n\n // Find alignement spaces to remove\n var paramSpacesToRemove: number = undefined;\n var paramLineIndex = commentContents.substring(0, j).lastIndexOf(\"\\n\") + 1;\n if (paramLineIndex != 0) {\n if (paramLineIndex < j && commentContents.charAt(paramLineIndex + 1) == \"\\r\") {\n paramLineIndex++;\n }\n }\n var startSpaceRemovalIndex = Comment.consumeLeadingSpace(commentContents, paramLineIndex);\n if (startSpaceRemovalIndex != j && commentContents.charAt(startSpaceRemovalIndex) == \"*\") {\n paramSpacesToRemove = j - startSpaceRemovalIndex - 1;\n }\n\n // Clean jsDocComment and return\n return Comment.cleanJSDocComment(paramHelpString, paramSpacesToRemove);\n }\n }\n\n return \"\";\n }\n\n static getDocCommentTextOfSignatures(signatures: Signature[]) {\n var comments: string[] = [];\n for (var i = 0; i < signatures.length; i++) {\n var signatureDocComment = TypeScript.Comment.getDocCommentText(signatures[i].declAST.getDocComments());\n if (signatureDocComment != \"\") {\n comments.push(signatureDocComment);\n }\n }\n\n return comments.join(\"\\n\");\n }\n }\n\n export class DebuggerStatement extends Statement {\n constructor () {\n super(NodeType.Debugger);\n }\n\n public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n emitter.emitParensAndCommentsInPlace(this, true);\n emitter.recordSourceMappingStart(this);\n emitter.writeLineToOutput(\"debugger;\");\n emitter.recordSourceMappingEnd(this);\n emitter.emitParensAndCommentsInPlace(this, false);\n }\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript.AstWalkerWithDetailCallback {\n export interface AstWalkerDetailCallback {\n EmptyCallback? (pre, ast: AST): bool;\n EmptyExprCallback? (pre, ast: AST): bool;\n TrueCallback? (pre, ast: AST): bool;\n FalseCallback? (pre, ast: AST): bool;\n ThisCallback? (pre, ast: AST): bool;\n SuperCallback? (pre, ast: AST): bool;\n QStringCallback? (pre, ast: AST): bool;\n RegexCallback? (pre, ast: AST): bool;\n NullCallback? (pre, ast: AST): bool;\n ArrayLitCallback? (pre, ast: AST): bool;\n ObjectLitCallback? (pre, ast: AST): bool;\n VoidCallback? (pre, ast: AST): bool;\n CommaCallback? (pre, ast: AST): bool;\n PosCallback? (pre, ast: AST): bool;\n NegCallback? (pre, ast: AST): bool;\n DeleteCallback? (pre, ast: AST): bool;\n AwaitCallback? (pre, ast: AST): bool;\n InCallback? (pre, ast: AST): bool;\n DotCallback? (pre, ast: AST): bool;\n FromCallback? (pre, ast: AST): bool;\n IsCallback? (pre, ast: AST): bool;\n InstOfCallback? (pre, ast: AST): bool;\n TypeofCallback? (pre, ast: AST): bool;\n NumberLitCallback? (pre, ast: AST): bool;\n NameCallback? (pre, identifierAst: Identifier): bool;\n TypeRefCallback? (pre, ast: AST): bool;\n IndexCallback? (pre, ast: AST): bool;\n CallCallback? (pre, ast: AST): bool;\n NewCallback? (pre, ast: AST): bool;\n AsgCallback? (pre, ast: AST): bool;\n AsgAddCallback? (pre, ast: AST): bool;\n AsgSubCallback? (pre, ast: AST): bool;\n AsgDivCallback? (pre, ast: AST): bool;\n AsgMulCallback? (pre, ast: AST): bool;\n AsgModCallback? (pre, ast: AST): bool;\n AsgAndCallback? (pre, ast: AST): bool;\n AsgXorCallback? (pre, ast: AST): bool;\n AsgOrCallback? (pre, ast: AST): bool;\n AsgLshCallback? (pre, ast: AST): bool;\n AsgRshCallback? (pre, ast: AST): bool;\n AsgRs2Callback? (pre, ast: AST): bool;\n QMarkCallback? (pre, ast: AST): bool;\n LogOrCallback? (pre, ast: AST): bool;\n LogAndCallback? (pre, ast: AST): bool;\n OrCallback? (pre, ast: AST): bool;\n XorCallback? (pre, ast: AST): bool;\n AndCallback? (pre, ast: AST): bool;\n EqCallback? (pre, ast: AST): bool;\n NeCallback? (pre, ast: AST): bool;\n EqvCallback? (pre, ast: AST): bool;\n NEqvCallback? (pre, ast: AST): bool;\n LtCallback? (pre, ast: AST): bool;\n LeCallback? (pre, ast: AST): bool;\n GtCallback? (pre, ast: AST): bool;\n GeCallback? (pre, ast: AST): bool;\n AddCallback? (pre, ast: AST): bool;\n SubCallback? (pre, ast: AST): bool;\n MulCallback? (pre, ast: AST): bool;\n DivCallback? (pre, ast: AST): bool;\n ModCallback? (pre, ast: AST): bool;\n LshCallback? (pre, ast: AST): bool;\n RshCallback? (pre, ast: AST): bool;\n Rs2Callback? (pre, ast: AST): bool;\n NotCallback? (pre, ast: AST): bool;\n LogNotCallback? (pre, ast: AST): bool;\n IncPreCallback? (pre, ast: AST): bool;\n DecPreCallback? (pre, ast: AST): bool;\n IncPostCallback? (pre, ast: AST): bool;\n DecPostCallback? (pre, ast: AST): bool;\n TypeAssertionCallback? (pre, ast: AST): bool;\n FuncDeclCallback? (pre, funcDecl: FuncDecl): bool;\n MemberCallback? (pre, ast: AST): bool;\n VarDeclCallback? (pre, varDecl: VarDecl): bool;\n ArgDeclCallback? (pre, ast: AST): bool;\n ReturnCallback? (pre, ast: AST): bool;\n BreakCallback? (pre, ast: AST): bool;\n ContinueCallback? (pre, ast: AST): bool;\n ThrowCallback? (pre, ast: AST): bool;\n ForCallback? (pre, ast: AST): bool;\n ForInCallback? (pre, ast: AST): bool;\n IfCallback? (pre, ast: AST): bool;\n WhileCallback? (pre, ast: AST): bool;\n DoWhileCallback? (pre, ast: AST): bool;\n BlockCallback? (pre, block: Block): bool;\n CaseCallback? (pre, ast: AST): bool;\n SwitchCallback? (pre, ast: AST): bool;\n TryCallback? (pre, ast: AST): bool;\n TryCatchCallback? (pre, ast: AST): bool;\n TryFinallyCallback? (pre, ast: AST): bool;\n FinallyCallback? (pre, ast: AST): bool;\n CatchCallback? (pre, ast: AST): bool;\n ListCallback? (pre, astList: ASTList): bool;\n ScriptCallback? (pre, script: Script): bool;\n ClassDeclarationCallback? (pre, ast: AST): bool;\n InterfaceDeclarationCallback? (pre, interfaceDecl: InterfaceDeclaration): bool;\n ModuleDeclarationCallback? (pre, moduleDecl: ModuleDeclaration): bool;\n ImportDeclarationCallback? (pre, ast: AST): bool;\n WithCallback? (pre, ast: AST): bool;\n LabelCallback? (pre, labelAST: AST): bool;\n LabeledStatementCallback? (pre, ast: AST): bool;\n EBStartCallback? (pre, ast: AST): bool;\n GotoEBCallback? (pre, ast: AST): bool;\n EndCodeCallback? (pre, ast: AST): bool;\n ErrorCallback? (pre, ast: AST): bool;\n CommentCallback? (pre, ast: AST): bool;\n DebuggerCallback? (pre, ast: AST): bool;\n DefaultCallback? (pre, ast: AST): bool;\n }\n\n export function walk(script: Script, callback: AstWalkerDetailCallback): void {\n var pre = (cur: AST, parent: AST) => {\n walker.options.goChildren = AstWalkerCallback(true, cur, callback);\n return cur;\n }\n\n var post = (cur: AST, parent: AST) => {\n AstWalkerCallback(false, cur, callback);\n return cur;\n }\n\n var walker = TypeScript.getAstWalkerFactory().getWalker(pre, post);\n walker.walk(script, null);\n }\n\n function AstWalkerCallback(pre: bool, ast: AST, callback: AstWalkerDetailCallback): bool {\n // See if the Callback needs to be handled using specific one or default one\n var nodeType = ast.nodeType;\n var callbackString = (<any>NodeType)._map[nodeType] + \"Callback\";\n if (callback[callbackString]) {\n return callback[callbackString](pre, ast);\n }\n\n if (callback.DefaultCallback) {\n return callback.DefaultCallback(pre, ast);\n }\n\n return true;\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export interface IAstWalker {\n walk(ast: AST, parent: AST): AST;\n options: AstWalkOptions;\n state: any; // user state object\n }\n\n export class AstWalkOptions {\n public goChildren = true;\n public goNextSibling = true;\n public reverseSiblings = false; // visit siblings in reverse execution order\n\n public stopWalk(stop:bool = true) {\n this.goChildren = !stop;\n this.goNextSibling = !stop;\n }\n }\n\n export interface IAstWalkCallback {\n (ast: AST, parent: AST, walker: IAstWalker): AST;\n }\n\n export interface IAstWalkChildren {\n (preAst: AST, parent: AST, walker: IAstWalker): void;\n }\n\n class AstWalker implements IAstWalker {\n constructor (\n private childrenWalkers: IAstWalkChildren[],\n private pre: IAstWalkCallback,\n private post: IAstWalkCallback,\n public options: AstWalkOptions,\n public state: any) {\n }\n\n public walk(ast: AST, parent: AST): AST {\n var preAst = this.pre(ast, parent, this);\n if (preAst === undefined) {\n preAst = ast;\n }\n if (this.options.goChildren) {\n var svGoSib = this.options.goNextSibling;\n this.options.goNextSibling = true;\n // Call the \"walkChildren\" function corresponding to \"nodeType\".\n this.childrenWalkers[ast.nodeType](ast, parent, this);\n this.options.goNextSibling = svGoSib;\n }\n else {\n // no go only applies to children of node issuing it\n this.options.goChildren = true;\n }\n if (this.post) {\n var postAst = this.post(preAst, parent, this);\n if (postAst === undefined) {\n postAst = preAst;\n }\n return postAst;\n }\n else {\n return preAst;\n }\n }\n }\n\n export class AstWalkerFactory {\n private childrenWalkers: IAstWalkChildren[] = [];\n\n constructor () {\n this.initChildrenWalkers();\n }\n\n public walk(ast: AST, pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): AST {\n return this.getWalker(pre, post, options, state).walk(ast, null)\n }\n\n public getWalker(pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): IAstWalker {\n return this.getSlowWalker(pre, post, options, state);\n }\n\n private getSlowWalker(pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): IAstWalker {\n if (!options) {\n options = new AstWalkOptions();\n }\n\n return new AstWalker(this.childrenWalkers, pre, post, options, state);\n }\n\n private initChildrenWalkers(): void {\n this.childrenWalkers[NodeType.None] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Empty] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.EmptyExpr] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.True] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.False] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.This] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Super] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.QString] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Regex] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Null] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.ArrayLit] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.ObjectLit] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Void] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Comma] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Pos] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Neg] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Delete] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.Await] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.In] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Dot] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.From] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Is] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.InstOf] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Typeof] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.NumberLit] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Name] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.TypeRef] = ChildrenWalkers.walkTypeReferenceChildren;\n this.childrenWalkers[NodeType.Index] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Call] = ChildrenWalkers.walkCallExpressionChildren;\n this.childrenWalkers[NodeType.New] = ChildrenWalkers.walkCallExpressionChildren;\n this.childrenWalkers[NodeType.Asg] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgAdd] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgSub] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgDiv] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgMul] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgMod] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgAnd] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgXor] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgOr] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgLsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgRsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.AsgRs2] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.ConditionalExpression] = ChildrenWalkers.walkTrinaryExpressionChildren;\n this.childrenWalkers[NodeType.LogOr] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.LogAnd] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Or] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Xor] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.And] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Eq] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Ne] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Eqv] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.NEqv] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Lt] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Le] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Gt] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Ge] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Add] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Sub] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Mul] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Div] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Mod] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Lsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Rsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Rs2] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.Not] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.LogNot] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.IncPre] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.DecPre] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.IncPost] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.DecPost] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.TypeAssertion] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.FuncDecl] = ChildrenWalkers.walkFuncDeclChildren;\n this.childrenWalkers[NodeType.Member] = ChildrenWalkers.walkBinaryExpressionChildren;\n this.childrenWalkers[NodeType.VarDecl] = ChildrenWalkers.walkBoundDeclChildren;\n this.childrenWalkers[NodeType.ArgDecl] = ChildrenWalkers.walkBoundDeclChildren;\n this.childrenWalkers[NodeType.Return] = ChildrenWalkers.walkReturnStatementChildren;\n this.childrenWalkers[NodeType.Break] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Continue] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Throw] = ChildrenWalkers.walkUnaryExpressionChildren;\n this.childrenWalkers[NodeType.For] = ChildrenWalkers.walkForStatementChildren;\n this.childrenWalkers[NodeType.ForIn] = ChildrenWalkers.walkForInStatementChildren;\n this.childrenWalkers[NodeType.If] = ChildrenWalkers.walkIfStatementChildren;\n this.childrenWalkers[NodeType.While] = ChildrenWalkers.walkWhileStatementChildren;\n this.childrenWalkers[NodeType.DoWhile] = ChildrenWalkers.walkDoWhileStatementChildren;\n this.childrenWalkers[NodeType.Block] = ChildrenWalkers.walkBlockChildren;\n this.childrenWalkers[NodeType.Case] = ChildrenWalkers.walkCaseStatementChildren;\n this.childrenWalkers[NodeType.Switch] = ChildrenWalkers.walkSwitchStatementChildren;\n this.childrenWalkers[NodeType.Try] = ChildrenWalkers.walkTryChildren;\n this.childrenWalkers[NodeType.TryCatch] = ChildrenWalkers.walkTryCatchChildren;\n this.childrenWalkers[NodeType.TryFinally] = ChildrenWalkers.walkTryFinallyChildren;\n this.childrenWalkers[NodeType.Finally] = ChildrenWalkers.walkFinallyChildren;\n this.childrenWalkers[NodeType.Catch] = ChildrenWalkers.walkCatchChildren;\n this.childrenWalkers[NodeType.List] = ChildrenWalkers.walkListChildren;\n this.childrenWalkers[NodeType.Script] = ChildrenWalkers.walkScriptChildren;\n this.childrenWalkers[NodeType.ClassDeclaration] = ChildrenWalkers.walkClassDeclChildren;\n this.childrenWalkers[NodeType.InterfaceDeclaration] = ChildrenWalkers.walkTypeDeclChildren;\n this.childrenWalkers[NodeType.ModuleDeclaration] = ChildrenWalkers.walkModuleDeclChildren;\n this.childrenWalkers[NodeType.ImportDeclaration] = ChildrenWalkers.walkImportDeclChildren;\n this.childrenWalkers[NodeType.With] = ChildrenWalkers.walkWithStatementChildren;\n this.childrenWalkers[NodeType.Label] = ChildrenWalkers.walkLabelChildren;\n this.childrenWalkers[NodeType.LabeledStatement] = ChildrenWalkers.walkLabeledStatementChildren;\n this.childrenWalkers[NodeType.EBStart] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.GotoEB] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.EndCode] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Error] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Comment] = ChildrenWalkers.walkNone;\n this.childrenWalkers[NodeType.Debugger] = ChildrenWalkers.walkNone;\n\n // Verify the code is up to date with the enum\n for (var e in (<any>NodeType)._map) {\n if ((<any>this.childrenWalkers)[e] === undefined) {\n throw new Error(\"initWalkers function is not up to date with enum content!\");\n }\n }\n }\n }\n\n var globalAstWalkerFactory: AstWalkerFactory;\n\n export function getAstWalkerFactory(): AstWalkerFactory {\n if (!globalAstWalkerFactory) {\n globalAstWalkerFactory = new AstWalkerFactory();\n }\n return globalAstWalkerFactory;\n }\n\n module ChildrenWalkers {\n export function walkNone(preAst: ASTList, parent: AST, walker: IAstWalker): void {\n // Nothing to do\n }\n\n export function walkListChildren(preAst: ASTList, parent: AST, walker: IAstWalker): void {\n var len = preAst.members.length;\n if (walker.options.reverseSiblings) {\n for (var i = len - 1; i >= 0; i--) {\n if (walker.options.goNextSibling) {\n preAst.members[i] = walker.walk(preAst.members[i], preAst);\n }\n }\n }\n else {\n for (var i = 0; i < len; i++) {\n if (walker.options.goNextSibling) {\n preAst.members[i] = walker.walk(preAst.members[i], preAst);\n }\n }\n }\n }\n\n export function walkUnaryExpressionChildren(preAst: UnaryExpression, parent: AST, walker: IAstWalker): void {\n if (preAst.castTerm) {\n preAst.castTerm = walker.walk(preAst.castTerm, preAst);\n }\n if (preAst.operand) {\n preAst.operand = walker.walk(preAst.operand, preAst);\n }\n }\n\n export function walkBinaryExpressionChildren(preAst: BinaryExpression, parent: AST, walker: IAstWalker): void {\n if (walker.options.reverseSiblings) {\n if (preAst.operand2) {\n preAst.operand2 = walker.walk(preAst.operand2, preAst);\n }\n if ((preAst.operand1) && (walker.options.goNextSibling)) {\n preAst.operand1 = walker.walk(preAst.operand1, preAst);\n }\n } else {\n if (preAst.operand1) {\n preAst.operand1 = walker.walk(preAst.operand1, preAst);\n }\n if ((preAst.operand2) && (walker.options.goNextSibling)) {\n preAst.operand2 = walker.walk(preAst.operand2, preAst);\n }\n }\n }\n\n export function walkTypeReferenceChildren(preAst: TypeReference, parent: AST, walker: IAstWalker): void {\n if (preAst.term) {\n preAst.term = walker.walk(preAst.term, preAst);\n }\n }\n\n export function walkCallExpressionChildren(preAst: CallExpression, parent: AST, walker: IAstWalker): void {\n if (!walker.options.reverseSiblings) {\n preAst.target = walker.walk(preAst.target, preAst);\n }\n if (preAst.arguments && (walker.options.goNextSibling)) {\n preAst.arguments = <ASTList> walker.walk(preAst.arguments, preAst);\n }\n if ((walker.options.reverseSiblings) && (walker.options.goNextSibling)) {\n preAst.target = walker.walk(preAst.target, preAst);\n }\n }\n\n export function walkTrinaryExpressionChildren(preAst: ConditionalExpression, parent: AST, walker: IAstWalker): void {\n if (preAst.operand1) {\n preAst.operand1 = walker.walk(preAst.operand1, preAst);\n }\n if (preAst.operand2 && (walker.options.goNextSibling)) {\n preAst.operand2 = walker.walk(preAst.operand2, preAst);\n }\n if (preAst.operand3 && (walker.options.goNextSibling)) {\n preAst.operand3 = walker.walk(preAst.operand3, preAst);\n }\n }\n\n export function walkFuncDeclChildren(preAst: FuncDecl, parent: AST, walker: IAstWalker): void {\n if (preAst.name) {\n preAst.name = <Identifier>walker.walk(preAst.name, preAst);\n }\n if (preAst.arguments && (preAst.arguments.members.length > 0) && (walker.options.goNextSibling)) {\n preAst.arguments = <ASTList>walker.walk(preAst.arguments, preAst);\n }\n if (preAst.returnTypeAnnotation && (walker.options.goNextSibling)) {\n preAst.returnTypeAnnotation = walker.walk(preAst.returnTypeAnnotation, preAst);\n }\n if (preAst.bod && (preAst.bod.members.length > 0) && (walker.options.goNextSibling)) {\n preAst.bod = <ASTList>walker.walk(preAst.bod, preAst);\n }\n }\n\n export function walkBoundDeclChildren(preAst: BoundDecl, parent: AST, walker: IAstWalker): void {\n if (preAst.id) {\n preAst.id = <Identifier>walker.walk(preAst.id, preAst);\n }\n if (preAst.init) {\n preAst.init = walker.walk(preAst.init, preAst);\n }\n if ((preAst.typeExpr) && (walker.options.goNextSibling)) {\n preAst.typeExpr = walker.walk(preAst.typeExpr, preAst);\n }\n }\n\n export function walkReturnStatementChildren(preAst: ReturnStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.returnExpression) {\n preAst.returnExpression = walker.walk(preAst.returnExpression, preAst);\n }\n }\n\n export function walkForStatementChildren(preAst: ForStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.init) {\n preAst.init = walker.walk(preAst.init, preAst);\n }\n\n if (preAst.cond && walker.options.goNextSibling) {\n preAst.cond = walker.walk(preAst.cond, preAst);\n }\n\n if (preAst.incr && walker.options.goNextSibling) {\n preAst.incr = walker.walk(preAst.incr, preAst);\n }\n\n if (preAst.body && walker.options.goNextSibling) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkForInStatementChildren(preAst: ForInStatement, parent: AST, walker: IAstWalker): void {\n preAst.lval = walker.walk(preAst.lval, preAst);\n if (walker.options.goNextSibling) {\n preAst.obj = walker.walk(preAst.obj, preAst);\n }\n if (preAst.body && (walker.options.goNextSibling)) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkIfStatementChildren(preAst: IfStatement, parent: AST, walker: IAstWalker): void {\n preAst.cond = walker.walk(preAst.cond, preAst);\n if (preAst.thenBod && (walker.options.goNextSibling)) {\n preAst.thenBod = walker.walk(preAst.thenBod, preAst);\n }\n if (preAst.elseBod && (walker.options.goNextSibling)) {\n preAst.elseBod = walker.walk(preAst.elseBod, preAst);\n }\n }\n\n export function walkWhileStatementChildren(preAst: WhileStatement, parent: AST, walker: IAstWalker): void {\n preAst.cond = walker.walk(preAst.cond, preAst);\n if (preAst.body && (walker.options.goNextSibling)) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkDoWhileStatementChildren(preAst: DoWhileStatement, parent: AST, walker: IAstWalker): void {\n preAst.cond = walker.walk(preAst.cond, preAst);\n if (preAst.body && (walker.options.goNextSibling)) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkBlockChildren(preAst: Block, parent: AST, walker: IAstWalker): void {\n if (preAst.statements) {\n preAst.statements = <ASTList>walker.walk(preAst.statements, preAst);\n }\n }\n\n export function walkCaseStatementChildren(preAst: CaseStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.expr) {\n preAst.expr = walker.walk(preAst.expr, preAst);\n }\n\n if (preAst.body && walker.options.goNextSibling) {\n preAst.body = <ASTList>walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkSwitchStatementChildren(preAst: SwitchStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.val) {\n preAst.val = walker.walk(preAst.val, preAst);\n }\n\n if ((preAst.caseList) && walker.options.goNextSibling) {\n preAst.caseList = <ASTList>walker.walk(preAst.caseList, preAst);\n }\n }\n\n export function walkTryChildren(preAst: Try, parent: AST, walker: IAstWalker): void {\n if (preAst.body) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkTryCatchChildren(preAst: TryCatch, parent: AST, walker: IAstWalker): void {\n if (preAst.tryNode) {\n preAst.tryNode = <Try>walker.walk(preAst.tryNode, preAst);\n }\n\n if ((preAst.catchNode) && walker.options.goNextSibling) {\n preAst.catchNode = <Catch>walker.walk(preAst.catchNode, preAst);\n }\n }\n\n export function walkTryFinallyChildren(preAst: TryFinally, parent: AST, walker: IAstWalker): void {\n if (preAst.tryNode) {\n preAst.tryNode = walker.walk(preAst.tryNode, preAst);\n }\n\n if (preAst.finallyNode && walker.options.goNextSibling) {\n preAst.finallyNode = <Finally>walker.walk(preAst.finallyNode, preAst);\n }\n }\n\n export function walkFinallyChildren(preAst: Finally, parent: AST, walker: IAstWalker): void {\n if (preAst.body) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkCatchChildren(preAst: Catch, parent: AST, walker: IAstWalker): void {\n if (preAst.param) {\n preAst.param = <VarDecl>walker.walk(preAst.param, preAst);\n }\n\n if ((preAst.body) && walker.options.goNextSibling) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkRecordChildren(preAst: NamedDeclaration, parent: AST, walker: IAstWalker): void {\n preAst.name = <Identifier>walker.walk(preAst.name, preAst);\n if (walker.options.goNextSibling && preAst.members) {\n preAst.members = <ASTList>walker.walk(preAst.members, preAst);\n }\n\n }\n\n export function walkNamedTypeChildren(preAst: TypeDeclaration, parent: AST, walker: IAstWalker): void {\n walkRecordChildren(preAst, parent, walker);\n }\n\n export function walkClassDeclChildren(preAst: ClassDeclaration, parent: AST, walker: IAstWalker): void {\n walkNamedTypeChildren(preAst, parent, walker);\n\n if (walker.options.goNextSibling && preAst.extendsList) {\n preAst.extendsList = <ASTList>walker.walk(preAst.extendsList, preAst);\n }\n\n if (walker.options.goNextSibling && preAst.implementsList) {\n preAst.implementsList = <ASTList>walker.walk(preAst.implementsList, preAst);\n }\n }\n\n export function walkScriptChildren(preAst: Script, parent: AST, walker: IAstWalker): void {\n if (preAst.bod) {\n preAst.bod = <ASTList>walker.walk(preAst.bod, preAst);\n }\n }\n\n export function walkTypeDeclChildren(preAst: InterfaceDeclaration, parent: AST, walker: IAstWalker): void {\n walkNamedTypeChildren(preAst, parent, walker);\n\n // walked arguments as part of members\n if (walker.options.goNextSibling && preAst.extendsList) {\n preAst.extendsList = <ASTList>walker.walk(preAst.extendsList, preAst);\n }\n\n if (walker.options.goNextSibling && preAst.implementsList) {\n preAst.implementsList = <ASTList>walker.walk(preAst.implementsList, preAst);\n }\n }\n\n export function walkModuleDeclChildren(preAst: ModuleDeclaration, parent: AST, walker: IAstWalker): void {\n walkRecordChildren(preAst, parent, walker);\n }\n\n export function walkImportDeclChildren(preAst: ImportDeclaration, parent: AST, walker: IAstWalker): void {\n if (preAst.id) {\n preAst.id = <Identifier>walker.walk(preAst.id, preAst);\n }\n if (preAst.alias) {\n preAst.alias = walker.walk(preAst.alias, preAst);\n }\n }\n\n export function walkWithStatementChildren(preAst: WithStatement, parent: AST, walker: IAstWalker): void {\n if (preAst.expr) {\n preAst.expr = walker.walk(preAst.expr, preAst);\n }\n\n if (preAst.body && walker.options.goNextSibling) {\n preAst.body = walker.walk(preAst.body, preAst);\n }\n }\n\n export function walkLabelChildren(preAst: Label, parent: AST, walker: IAstWalker): void {\n //TODO: Walk \"id\"?\n }\n\n export function walkLabeledStatementChildren(preAst: LabeledStatement, parent: AST, walker: IAstWalker): void {\n preAst.labels = <ASTList>walker.walk(preAst.labels, preAst);\n if (walker.options.goNextSibling) {\n preAst.stmt = walker.walk(preAst.stmt, preAst);\n }\n }\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\nmodule TypeScript {\n class Base64Format {\n static encodedValues = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n static encode(inValue: number) {\n if (inValue < 64) {\n return encodedValues.charAt(inValue);\n }\n throw TypeError(inValue + \": not a 64 based value\");\n }\n\n static decodeChar(inChar: string) {\n if (inChar.length === 1) {\n return encodedValues.indexOf(inChar);\n } else {\n throw TypeError('\"' + inChar + '\" must have length 1');\n }\n }\n }\n\n export class Base64VLQFormat {\n static encode(inValue: number) {\n // Add a new least significant bit that has the sign of the value.\n // if negative number the least significant bit that gets added to the number has value 1\n // else least significant bit value that gets added is 0\n // eg. -1 changes to binary : 01 [1] => 3\n // +1 changes to binary : 01 [0] => 2\n if (inValue < 0) {\n inValue = ((-inValue) << 1) + 1;\n }\n else {\n inValue = inValue << 1;\n }\n\n // Encode 5 bits at a time starting from least significant bits\n var encodedStr = \"\";\n do {\n var currentDigit = inValue & 31; // 11111\n inValue = inValue >> 5;\n if (inValue > 0) {\n // There are still more digits to decode, set the msb (6th bit)\n currentDigit = currentDigit | 32; \n }\n encodedStr = encodedStr + Base64Format.encode(currentDigit);\n } while (inValue > 0);\n\n return encodedStr;\n }\n\n static decode(inString: string) {\n var result = 0;\n var negative = false;\n\n var shift = 0;\n for (var i = 0; i < inString.length; i++) {\n var byte = Base64Format.decodeChar(inString[i]);\n if (i === 0) {\n // Sign bit appears in the LSBit of the first value\n if ((byte & 1) === 1) {\n negative = true;\n }\n result = (byte >> 1) & 15; // 1111x\n } else {\n result = result | ((byte & 31) << shift); // 11111\n }\n\n shift += (i == 0) ? 4 : 5;\n\n if ((byte & 32) === 32) {\n // Continue\n } else {\n return { value: negative ? -(result) : result, rest: inString.substr(i + 1) };\n }\n }\n\n throw new Error('Base64 value \"' + inString + '\" finished with a continuation bit');\n }\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class Binder {\n constructor(public checker: TypeChecker) { }\n \n public resolveBaseTypeLinks(typeLinks: TypeLink[], scope: SymbolScope) {\n var extendsList: Type[] = null;\n if (typeLinks) {\n extendsList = new Type[];\n for (var i = 0, len = typeLinks.length; i < len; i++) {\n extendsList[i] = this.checker.resolveBaseTypeLink(typeLinks[i], scope);\n }\n }\n return extendsList;\n }\n\n public resolveBases(scope: SymbolScope, type: Type) {\n type.extendsList = this.resolveBaseTypeLinks(type.extendsTypeLinks, scope);\n\n var i = 0, len = type.extendsList.length;\n var derivedIsClass = type.isClassInstance();\n for (; i < len; i++) {\n var baseIsClass = type.extendsList[i].isClassInstance();\n if (type.extendsList[i] != this.checker.anyType) {\n var baseRef = type.extendsTypeLinks[i].ast;\n if (derivedIsClass) {\n if (!baseIsClass) {\n this.checker.errorReporter.simpleError(baseRef,\n \"A class may only extend other classes, \" + type.extendsList[i].symbol.fullName() + \" is not a class.\");\n }\n }\n else {\n if (baseIsClass) {\n this.checker.errorReporter.simpleError(baseRef,\n \"An interface may only extend other interfaces, \" + type.extendsList[i].symbol.fullName() + \" is a class.\");\n }\n }\n }\n }\n\n type.implementsList = this.resolveBaseTypeLinks(type.implementsTypeLinks, scope);\n\n if (type.implementsList) {\n for (i = 0, len = type.implementsList.length; i < len; i++) {\n var iface = type.implementsList[i];\n var baseRef = type.implementsTypeLinks[i].ast;\n if (iface.isClassInstance()) {\n if (derivedIsClass) {\n this.checker.errorReporter.simpleError(baseRef,\n \"A class may only implement an interface; \" + iface.symbol.fullName() + \" is a class.\");\n }\n }\n }\n }\n }\n\n public resolveSignatureGroup(signatureGroup: SignatureGroup, scope: SymbolScope, instanceType: Type) {\n var supplyVar = !(signatureGroup.hasImplementation);\n for (var i = 0, len = signatureGroup.signatures.length; i < len; i++) {\n var signature = signatureGroup.signatures[i];\n if (instanceType) {\n signature.returnType.type = instanceType;\n }\n else {\n this.checker.resolveTypeLink(scope, signature.returnType, supplyVar);\n }\n var paramLen = signature.parameters.length;\n for (var j = 0; j < paramLen; j++) {\n this.bindSymbol(scope, signature.parameters[j]);\n }\n if (signature.hasVariableArgList) {\n // check that last parameter has an array type\n var lastParam = <ParameterSymbol>signature.parameters[paramLen - 1];\n lastParam.argsOffset = paramLen - 1;\n if (!lastParam.getType().isArray()) {\n this.checker.errorReporter.simpleErrorFromSym(lastParam,\n \"... parameter must have array type\");\n lastParam.parameter.typeLink.type = this.checker.makeArrayType(lastParam.parameter.typeLink.type);\n }\n }\n }\n }\n\n public bindType(scope: SymbolScope, type: Type, instanceType: Type): void {\n if (instanceType) {\n this.bindType(scope, instanceType, null);\n }\n if (type.hasMembers()) {\n var members = type.members;\n var ambientMembers = type.ambientMembers;\n var typeMembers = type.getAllEnclosedTypes(); // REVIEW: Should only be getting exported types?\n var ambientTypeMembers = type.getAllAmbientEnclosedTypes(); // REVIEW: Should only be getting exported types?\n var memberScope = new SymbolTableScope(members, ambientMembers, typeMembers, ambientTypeMembers, type.symbol);\n var agg = new SymbolAggregateScope(type.symbol);\n var prevCurrentModDecl = this.checker.currentModDecl;\n var prevBindStatus = this.checker.inBind;\n agg.addParentScope(memberScope);\n agg.addParentScope(scope);\n if (type.isModuleType()) {\n this.checker.currentModDecl = <ModuleDeclaration>type.symbol.declAST;\n this.checker.inBind = true;\n }\n if (members) {\n this.bind(agg, type.members.allMembers); // REVIEW: Should only be getting exported types?\n }\n if (typeMembers) {\n this.bind(agg, typeMembers.allMembers);\n }\n if (ambientMembers) {\n this.bind(agg, ambientMembers.allMembers);\n }\n if (ambientTypeMembers) {\n this.bind(agg, ambientTypeMembers.allMembers);\n }\n this.checker.currentModDecl = prevCurrentModDecl;\n this.checker.inBind = prevBindStatus;\n }\n if (type.extendsTypeLinks) {\n this.resolveBases(scope, type);\n }\n if (type.construct) {\n this.resolveSignatureGroup(type.construct, scope, instanceType);\n }\n if (type.call) {\n this.resolveSignatureGroup(type.call, scope, null);\n }\n if (type.index) {\n this.resolveSignatureGroup(type.index, scope, null);\n }\n if (type.elementType) {\n this.bindType(scope, type.elementType, null);\n }\n }\n\n public bindSymbol(scope: SymbolScope, symbol: Symbol) {\n if (!symbol.bound) {\n var prevLocationInfo = this.checker.locationInfo;\n if ((this.checker.units) && (symbol.unitIndex >= 0) && (symbol.unitIndex < this.checker.units.length)) {\n this.checker.locationInfo = this.checker.units[symbol.unitIndex];\n }\n switch (symbol.kind()) {\n case SymbolKind.Type:\n\n if (symbol.flags & SymbolFlags.Bound) {\n break;\n }\n\n var typeSymbol = <TypeSymbol>symbol;\n typeSymbol.flags |= SymbolFlags.Bound;\n\n // Since type collection happens out of order, a dynamic module referenced by an import statement\n // may not yet be in scope when the import symbol is created. In that case, we need to search\n // out the module symbol now\n // Note that we'll also want to do this in resolveTypeMembers, in case the symbol is set outside the\n // context of a given module (E.g., an outer import statement)\n if (typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == NodeType.Name) {\n var modPath = (<Identifier>typeSymbol.aliasLink.alias).text;\n var modSym = this.checker.findSymbolForDynamicModule(modPath, this.checker.locationInfo.filename, (id) => scope.find(id, false, true));\n if (modSym) {\n typeSymbol.type = modSym.getType();\n }\n }\n\n if (typeSymbol.type && typeSymbol.type != this.checker.gloModType) {\n this.bindType(scope, typeSymbol.type, typeSymbol.instanceType);\n\n // bind expansions on the parent type symbol\n if (typeSymbol.type.isModuleType()) {\n for (var i = 0; i < typeSymbol.expansions.length; i++) {\n this.bindType(scope, typeSymbol.expansions[i], typeSymbol.instanceType);\n }\n }\n }\n break;\n case SymbolKind.Field:\n this.checker.resolveTypeLink(scope, (<FieldSymbol>symbol).field.typeLink,\n false);\n break;\n case SymbolKind.Parameter:\n this.checker.resolveTypeLink(scope,\n (<ParameterSymbol>symbol).parameter.typeLink,\n true);\n break;\n }\n this.checker.locationInfo = prevLocationInfo;\n }\n symbol.bound = true;\n }\n\n public bind(scope: SymbolScope, table: IHashTable) {\n table.map(\n (key, sym, binder) => {\n binder.bindSymbol(scope, sym);\n },\n this);\n }\n }\n\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export class DeclFileWriter {\n public onNewLine = true;\n constructor(private declFile: ITextWriter) {\n }\n\n public Write(s: string) {\n this.declFile.Write(s);\n this.onNewLine = false;\n }\n\n public WriteLine(s: string) {\n this.declFile.WriteLine(s);\n this.onNewLine = true;\n }\n\n public Close() {\n this.declFile.Close();\n }\n }\n\n export class DeclarationEmitter implements AstWalkerWithDetailCallback.AstWalkerDetailCallback {\n private declFile: DeclFileWriter = null;\n private indenter = new Indenter();\n private declarationContainerStack: AST[] = [];\n private isDottedModuleName: bool[] = [];\n private dottedModuleEmit: string;\n private ignoreCallbackAst: AST = null;\n private singleDeclFile: DeclFileWriter = null;\n private varListCount: number = 0;\n\n private getAstDeclarationContainer() {\n return this.declarationContainerStack[this.declarationContainerStack.length - 1];\n }\n\n private emitDottedModuleName() {\n return (this.isDottedModuleName.length == 0) ? false : this.isDottedModuleName[this.isDottedModuleName.length - 1];\n }\n\n constructor (public checker: TypeChecker, public emitOptions: EmitOptions, public errorReporter: ErrorReporter) {\n }\n\n public setDeclarationFile(file: ITextWriter) {\n this.declFile = new DeclFileWriter(file);\n }\n\n public Close() {\n try {\n // Closing files could result in exceptions, report them if they occur\n this.declFile.Close();\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n\n public emitDeclarations(script: TypeScript.Script): void {\n AstWalkerWithDetailCallback.walk(script, this);\n }\n\n private getIndentString(declIndent? = false) {\n if (this.emitOptions.minWhitespace) {\n return \"\";\n }\n else {\n return this.indenter.getIndent();\n }\n }\n\n private emitIndent() {\n this.declFile.Write(this.getIndentString());\n }\n\n private canEmitSignature(declFlags: DeclFlags, canEmitGlobalAmbientDecl?: bool = true, useDeclarationContainerTop?: bool = true) {\n var container: AST;\n if (useDeclarationContainerTop) {\n container = this.getAstDeclarationContainer();\n } else {\n container = this.declarationContainerStack[this.declarationContainerStack.length - 2];\n }\n\n if (container.nodeType == NodeType.ModuleDeclaration && !hasFlag(declFlags, DeclFlags.Exported)) {\n return false;\n }\n\n if (!canEmitGlobalAmbientDecl && container.nodeType == NodeType.Script && hasFlag(declFlags, DeclFlags.Ambient)) {\n return false;\n }\n\n return true;\n }\n\n private canEmitPrePostAstSignature(declFlags: DeclFlags, astWithPrePostCallback: AST, preCallback: bool) {\n if (this.ignoreCallbackAst) {\n CompilerDiagnostics.assert(this.ignoreCallbackAst != astWithPrePostCallback, \"Ignore Callback AST mismatch\");\n this.ignoreCallbackAst = null;\n return false;\n } else if (preCallback &&\n !this.canEmitSignature(declFlags, true, preCallback)) {\n this.ignoreCallbackAst = astWithPrePostCallback;\n return false;\n }\n\n return true;\n }\n\n private getDeclFlagsString(declFlags: DeclFlags, typeString: string) {\n var result = this.getIndentString();\n\n // Accessor strings\n var accessorString = \"\";\n if (hasFlag(declFlags, DeclFlags.GetAccessor)) {\n accessorString = \"get \";\n }\n else if (hasFlag(declFlags, DeclFlags.SetAccessor)) {\n accessorString = \"set \";\n }\n\n // Emit export only for global export statements. The container for this would be dynamic module which is whole file\n var container = this.getAstDeclarationContainer();\n if (container.nodeType == NodeType.ModuleDeclaration &&\n hasFlag((<ModuleDeclaration>container).modFlags, ModuleFlags.IsWholeFile) &&\n hasFlag(declFlags, DeclFlags.Exported)) {\n result += \"export \";\n }\n\n // Static/public/private/global declare\n if (hasFlag(declFlags, DeclFlags.LocalStatic) || hasFlag(declFlags, DeclFlags.Static)) {\n result += \"static \" + accessorString;\n }\n else {\n if (hasFlag(declFlags, DeclFlags.Private)) {\n result += \"private \" + accessorString;\n }\n else if (hasFlag(declFlags, DeclFlags.Public)) {\n result += \"public \" + accessorString;\n }\n else {\n if (accessorString == \"\") {\n result += typeString + \" \";\n } else {\n result += accessorString;\n }\n }\n }\n\n return result;\n }\n\n private emitDeclFlags(declFlags: DeclFlags, typeString: string) {\n this.declFile.Write(this.getDeclFlagsString(declFlags, typeString));\n }\n\n private canEmitTypeAnnotationSignature(declFlag: DeclFlags = DeclFlags.None) {\n // Private declaration, shouldnt emit type any time.\n return !hasFlag(declFlag, DeclFlags.Private);\n }\n\n private pushDeclarationContainer(ast: AST) {\n this.declarationContainerStack.push(ast);\n }\n\n private popDeclarationContainer(ast: AST) {\n CompilerDiagnostics.assert(ast != this.getAstDeclarationContainer(), 'Declaration container mismatch');\n this.declarationContainerStack.pop();\n }\n\n private emitTypeNamesMember(memberName: MemberName, emitIndent? : bool = false) {\n if (memberName.prefix == \"{ \") {\n if (emitIndent) {\n this.emitIndent();\n }\n this.declFile.WriteLine(\"{\");\n this.indenter.increaseIndent();\n emitIndent = true;\n } else if (memberName.prefix != \"\") {\n if (emitIndent) {\n this.emitIndent();\n }\n this.declFile.Write(memberName.prefix);\n emitIndent = false;\n }\n\n if (memberName.isString()) {\n if (emitIndent) {\n this.emitIndent();\n }\n this.declFile.Write((<MemberNameString>memberName).text);\n } else {\n var ar = <MemberNameArray>memberName;\n for (var index = 0; index < ar.entries.length; index++) {\n this.emitTypeNamesMember(ar.entries[index], emitIndent);\n if (ar.delim == \"; \") {\n this.declFile.WriteLine(\";\");\n }\n }\n }\n\n if (memberName.suffix == \"}\") {\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.declFile.Write(memberName.suffix);\n } else {\n this.declFile.Write(memberName.suffix);\n }\n }\n\n private emitTypeSignature(type: Type) {\n var containingScope: SymbolScope = null;\n var declarationContainerAst = this.getAstDeclarationContainer();\n switch (declarationContainerAst.nodeType) {\n case NodeType.ModuleDeclaration:\n case NodeType.InterfaceDeclaration:\n case NodeType.FuncDecl:\n if (declarationContainerAst.type) {\n containingScope = declarationContainerAst.type.containedScope;\n }\n break;\n\n case NodeType.Script:\n var script = <Script>declarationContainerAst;\n if (script.bod) {\n containingScope = script.bod.enclosingScope;\n }\n break;\n\n case NodeType.ClassDeclaration:\n if (declarationContainerAst.type) {\n containingScope = declarationContainerAst.type.instanceType.containedScope;\n }\n break;\n\n default:\n CompilerDiagnostics.debugPrint(\"Unknown containing scope\");\n }\n\n var typeNameMembers = type.getScopedTypeNameEx(containingScope);\n this.emitTypeNamesMember(typeNameMembers);\n }\n\n private emitComment(comment: Comment) {\n var text = comment.getText();\n if (this.declFile.onNewLine) {\n this.emitIndent();\n } else if (!comment.isBlockComment) {\n this.declFile.WriteLine(\"\");\n this.emitIndent();\n }\n \n this.declFile.Write(text[0]);\n\n for (var i = 1; i < text.length; i++) {\n this.declFile.WriteLine(\"\");\n this.emitIndent();\n this.declFile.Write(text[i]);\n }\n\n if (comment.endsLine || !comment.isBlockComment) {\n this.declFile.WriteLine(\"\");\n } else {\n this.declFile.Write(\" \");\n }\n }\n\n private emitDeclarationComments(ast: AST, endLine?: bool);\n private emitDeclarationComments(symbol: Symbol, endLine?: bool);\n private emitDeclarationComments(astOrSymbol, endLine = true) {\n if (!this.emitOptions.emitComments) {\n return;\n }\n\n var declComments = <Comment[]>astOrSymbol.getDocComments();\n if (declComments.length > 0) {\n for (var i = 0; i < declComments.length; i++) {\n this.emitComment(declComments[i]);\n }\n\n if (endLine) {\n if (!this.declFile.onNewLine) {\n this.declFile.WriteLine(\"\");\n }\n } else {\n if (this.declFile.onNewLine) {\n this.emitIndent();\n }\n }\n }\n }\n\n public VarDeclCallback(pre: bool, varDecl: VarDecl): bool {\n if (pre && this.canEmitSignature(ToDeclFlags(varDecl.varFlags), false)) {\n var interfaceMember = (this.getAstDeclarationContainer().nodeType == NodeType.InterfaceDeclaration);\n this.emitDeclarationComments(varDecl);\n if (!interfaceMember) {\n // If it is var list of form var a, b, c = emit it only if count > 0 - which will be when emitting first var\n // If it is var list of form var a = varList count will be 0\n if (this.varListCount >= 0) {\n this.emitDeclFlags(ToDeclFlags(varDecl.varFlags), \"var\");\n this.varListCount = -this.varListCount;\n }\n this.declFile.Write(varDecl.id.text);\n } else {\n this.emitIndent();\n this.declFile.Write(varDecl.id.text);\n if (hasFlag(varDecl.id.flags, ASTFlags.OptionalName)) {\n this.declFile.Write(\"?\");\n }\n }\n\n var type: Type = null;\n if (varDecl.typeExpr && varDecl.typeExpr.type) {\n type = varDecl.typeExpr.type;\n }\n else if (varDecl.sym) {\n type = (<FieldSymbol>varDecl.sym).getType();\n // Dont emit inferred any\n if (type == this.checker.anyType) {\n type = null;\n }\n }\n\n if (type && this.canEmitTypeAnnotationSignature(ToDeclFlags(varDecl.varFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(type);\n }\n \n // emitted one var decl\n if (this.varListCount > 0) { this.varListCount--; } else if (this.varListCount < 0) { this.varListCount++; }\n\n // Write ; or ,\n if (this.varListCount < 0) {\n this.declFile.Write(\", \");\n } else {\n this.declFile.WriteLine(\";\");\n }\n }\n return false;\n }\n\n public BlockCallback(pre: bool, block: Block): bool {\n if (!block.isStatementBlock) {\n if (pre) {\n this.varListCount = block.statements.members.length;\n } else {\n this.varListCount = 0;\n }\n return true;\n }\n return false;\n }\n\n private emitArgDecl(argDecl: ArgDecl, funcDecl: FuncDecl) {\n this.emitDeclarationComments(argDecl, false);\n this.declFile.Write(argDecl.id.text);\n if (argDecl.isOptionalArg()) {\n this.declFile.Write(\"?\");\n }\n if ((argDecl.typeExpr || argDecl.type != this.checker.anyType) &&\n this.canEmitTypeAnnotationSignature(ToDeclFlags(funcDecl.fncFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(argDecl.type);\n }\n }\n\n public FuncDeclCallback(pre: bool, funcDecl: FuncDecl): bool {\n if (!pre) {\n return false;\n }\n\n if (funcDecl.isAccessor()) {\n return this.emitPropertyAccessorSignature(funcDecl);\n }\n\n var isInterfaceMember = (this.getAstDeclarationContainer().nodeType == NodeType.InterfaceDeclaration);\n if (funcDecl.bod) {\n if (funcDecl.isConstructor) {\n if (funcDecl.type.construct && funcDecl.type.construct.signatures.length > 1) {\n return false;\n }\n } else {\n if (funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {\n // This means its implementation of overload signature. do not emit\n return false;\n }\n }\n } else if (!isInterfaceMember && hasFlag(funcDecl.fncFlags, FncFlags.Private) && funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {\n // Print only first overload of private function\n var signatures = funcDecl.type.call.signatures;\n var firstSignature = signatures[0].declAST;\n if (firstSignature.bod) {\n // Its a implementation, use next one\n firstSignature = signatures[1].declAST;\n }\n\n if (firstSignature != funcDecl) {\n return false;\n }\n }\n\n if (!this.canEmitSignature(ToDeclFlags(funcDecl.fncFlags), false)) {\n return false;\n }\n\n this.emitDeclarationComments(funcDecl);\n if (funcDecl.isConstructor) {\n this.emitIndent();\n this.declFile.Write(\"constructor\");\n }\n else {\n var id = funcDecl.getNameText();\n if (!isInterfaceMember) {\n this.emitDeclFlags(ToDeclFlags(funcDecl.fncFlags), \"function\");\n this.declFile.Write(id);\n } else {\n this.emitIndent();\n if (funcDecl.isConstructMember()) {\n this.declFile.Write(\"new\");\n } else if (!funcDecl.isCallMember() && !funcDecl.isIndexerMember()) {\n this.declFile.Write(id);\n if (hasFlag(funcDecl.name.flags, ASTFlags.OptionalName)) {\n this.declFile.Write(\"? \");\n }\n }\n }\n }\n\n if (!funcDecl.isIndexerMember()) {\n this.declFile.Write(\"(\");\n } else {\n this.declFile.Write(\"[\");\n }\n\n this.indenter.increaseIndent();\n\n if (funcDecl.arguments) {\n var argsLen = funcDecl.arguments.members.length;\n if (funcDecl.variableArgList) {\n argsLen--;\n }\n for (var i = 0; i < argsLen; i++) {\n var argDecl = <ArgDecl>funcDecl.arguments.members[i];\n this.emitArgDecl(argDecl, funcDecl);\n if (i < (argsLen - 1)) {\n this.declFile.Write(\", \");\n }\n }\n }\n\n if (funcDecl.variableArgList) {\n var lastArg = <ArgDecl>funcDecl.arguments.members[funcDecl.arguments.members.length - 1];\n if (funcDecl.arguments.members.length > 1) {\n this.declFile.Write(\", ...\");\n }\n else {\n this.declFile.Write(\"...\");\n }\n this.emitArgDecl(lastArg, funcDecl);\n }\n\n this.indenter.decreaseIndent();\n\n if (!funcDecl.isIndexerMember()) {\n this.declFile.Write(\")\");\n } else {\n this.declFile.Write(\"]\");\n }\n\n if (!funcDecl.isConstructor &&\n (funcDecl.returnTypeAnnotation || funcDecl.signature.returnType.type != this.checker.anyType) &&\n this.canEmitTypeAnnotationSignature(ToDeclFlags(funcDecl.fncFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(funcDecl.signature.returnType.type);\n }\n\n this.declFile.WriteLine(\";\");\n\n return false;\n }\n\n private emitBaseList(bases: ASTList, qual: string) {\n if (bases && (bases.members.length > 0)) {\n this.declFile.Write(\" \" + qual + \" \");\n var basesLen = bases.members.length;\n for (var i = 0; i < basesLen; i++) {\n var baseExpr = bases.members[i];\n var baseSymbol = baseExpr.type.symbol;\n var baseType = baseExpr.type;\n if (i > 0) {\n this.declFile.Write(\", \");\n }\n this.emitTypeSignature(baseType);\n }\n }\n }\n\n private emitPropertyAccessorSignature(funcDecl: FuncDecl) {\n var accessorSymbol = <FieldSymbol>funcDecl.accessorSymbol;\n if (accessorSymbol.getter && accessorSymbol.getter.declAST != funcDecl) {\n // Setter is being used to emit the type info. \n return false;\n }\n\n this.emitDeclarationComments(accessorSymbol);\n this.emitDeclFlags(ToDeclFlags(accessorSymbol.flags), \"var\");\n this.declFile.Write(funcDecl.name.text);\n var propertyType = accessorSymbol.getType();\n if (this.canEmitTypeAnnotationSignature(ToDeclFlags(accessorSymbol.flags))) {\n this.declFile.Write(\" : \");\n this.emitTypeSignature(propertyType);\n }\n this.declFile.WriteLine(\";\");\n\n return false;\n }\n\n private emitClassMembersFromConstructorDefinition(funcDecl: FuncDecl) {\n if (funcDecl.arguments) {\n var argsLen = funcDecl.arguments.members.length; if (funcDecl.variableArgList) { argsLen--; }\n\n for (var i = 0; i < argsLen; i++) {\n var argDecl = <ArgDecl>funcDecl.arguments.members[i];\n if (hasFlag(argDecl.varFlags, VarFlags.Property)) {\n this.emitDeclarationComments(argDecl);\n this.emitDeclFlags(ToDeclFlags(argDecl.varFlags), \"var\");\n this.declFile.Write(argDecl.id.text);\n\n if (argDecl.typeExpr && this.canEmitTypeAnnotationSignature(ToDeclFlags(argDecl.varFlags))) {\n this.declFile.Write(\": \");\n this.emitTypeSignature(argDecl.type);\n }\n this.declFile.WriteLine(\";\");\n }\n }\n }\n }\n\n public ClassDeclarationCallback(pre: bool, classDecl: ClassDeclaration): bool {\n if (!this.canEmitPrePostAstSignature(ToDeclFlags(classDecl.varFlags), classDecl, pre)) {\n return false;\n }\n\n if (pre) {\n var className = classDecl.name.text;\n this.emitDeclarationComments(classDecl);\n this.emitDeclFlags(ToDeclFlags(classDecl.varFlags), \"class\");\n this.declFile.Write(className);\n this.emitBaseList(classDecl.extendsList, \"extends\");\n this.emitBaseList(classDecl.implementsList, \"implements\");\n this.declFile.WriteLine(\" {\");\n\n this.pushDeclarationContainer(classDecl);\n this.indenter.increaseIndent();\n if (classDecl.constructorDecl) {\n this.emitClassMembersFromConstructorDefinition(classDecl.constructorDecl);\n }\n } else {\n this.indenter.decreaseIndent();\n this.popDeclarationContainer(classDecl);\n\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n }\n\n return true;\n }\n\n public InterfaceDeclarationCallback(pre: bool, interfaceDecl: InterfaceDeclaration): bool {\n if (!this.canEmitPrePostAstSignature(ToDeclFlags(interfaceDecl.varFlags), interfaceDecl, pre)) {\n return false;\n }\n\n if (pre) {\n var interfaceName = interfaceDecl.name.text;\n this.emitDeclarationComments(interfaceDecl);\n this.emitDeclFlags(ToDeclFlags(interfaceDecl.varFlags), \"interface\");\n this.declFile.Write(interfaceName);\n this.emitBaseList(interfaceDecl.extendsList, \"extends\");\n this.declFile.WriteLine(\" {\");\n\n this.indenter.increaseIndent();\n this.pushDeclarationContainer(interfaceDecl);\n } else {\n this.indenter.decreaseIndent();\n this.popDeclarationContainer(interfaceDecl);\n\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n }\n\n return true;\n }\n\n public ImportDeclarationCallback(pre: bool, importDecl: ImportDeclaration): bool {\n if (pre) {\n if ((<Script>this.declarationContainerStack[0]).isExternallyVisibleSymbol(importDecl.id.sym)) {\n this.emitDeclarationComments(importDecl);\n this.emitIndent();\n this.declFile.Write(\"import \");\n\n this.declFile.Write(importDecl.id.text + \" = \");\n if (importDecl.isDynamicImport) {\n this.declFile.WriteLine(\"module (\" + importDecl.getAliasName() + \");\");\n } else {\n this.declFile.WriteLine(importDecl.getAliasName() + \";\");\n }\n }\n }\n\n return false;\n }\n\n private emitEnumSignature(moduleDecl: ModuleDeclaration) {\n if (!this.canEmitSignature(ToDeclFlags(moduleDecl.modFlags))) {\n return false;\n }\n\n this.emitDeclarationComments(moduleDecl);\n this.emitDeclFlags(ToDeclFlags(moduleDecl.modFlags), \"enum\");\n this.declFile.WriteLine(moduleDecl.name.text + \" {\");\n\n this.indenter.increaseIndent();\n var membersLen = moduleDecl.members.members.length;\n for (var j = 1; j < membersLen; j++) {\n var memberDecl: AST = moduleDecl.members.members[j];\n if (memberDecl.nodeType == NodeType.VarDecl) {\n this.emitDeclarationComments(memberDecl);\n this.emitIndent();\n this.declFile.WriteLine((<VarDecl>memberDecl).id.text + \",\");\n } else {\n CompilerDiagnostics.assert(memberDecl.nodeType != NodeType.Asg, \"We want to catch this\");\n }\n }\n this.indenter.decreaseIndent();\n\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n\n return false;\n }\n\n public ModuleDeclarationCallback(pre: bool, moduleDecl: ModuleDeclaration): bool {\n if (hasFlag(moduleDecl.modFlags, ModuleFlags.IsWholeFile)) {\n // This is dynamic modules and we are going to outputing single file, \n // we need to change the declFile because dynamic modules are always emitted to their corresponding .d.ts\n if (hasFlag(moduleDecl.modFlags, ModuleFlags.IsDynamic)) {\n if (pre) {\n if (!this.emitOptions.outputMany) {\n this.singleDeclFile = this.declFile;\n CompilerDiagnostics.assert(this.indenter.indentAmt == 0, \"Indent has to be 0 when outputing new file\");\n // Create new file\n var declareFileName = this.emitOptions.mapOutputFileName(stripQuotes(moduleDecl.name.sym.name), TypeScriptCompiler.mapToDTSFileName);\n var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);\n try {\n // Creating files can cause exceptions, report them. \n this.declFile = new DeclFileWriter(this.emitOptions.ioHost.createFile(declareFileName, useUTF8InOutputfile));\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n this.pushDeclarationContainer(moduleDecl);\n } else {\n if (!this.emitOptions.outputMany) {\n CompilerDiagnostics.assert(this.singleDeclFile != this.declFile, \"singleDeclFile cannot be null as we are going to revert back to it\");\n CompilerDiagnostics.assert(this.indenter.indentAmt == 0, \"Indent has to be 0 when outputing new file\");\n try {\n // Closing files could result in exceptions, report them if they occur\n this.declFile.Close();\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n this.declFile = this.singleDeclFile;\n }\n this.popDeclarationContainer(moduleDecl);\n }\n }\n\n return true;\n }\n\n if (moduleDecl.isEnum()) {\n if (pre) {\n this.emitEnumSignature(moduleDecl);\n }\n return false;\n }\n\n if (!this.canEmitPrePostAstSignature(ToDeclFlags(moduleDecl.modFlags), moduleDecl, pre)) {\n return false;\n }\n\n if (pre) {\n if (this.emitDottedModuleName()) {\n this.dottedModuleEmit += \".\";\n } else {\n this.dottedModuleEmit = this.getDeclFlagsString(ToDeclFlags(moduleDecl.modFlags), \"module\");\n }\n this.dottedModuleEmit += moduleDecl.name.text;\n\n var isCurrentModuleDotted = (moduleDecl.members.members.length == 1 &&\n moduleDecl.members.members[0].nodeType == NodeType.ModuleDeclaration &&\n !(<ModuleDeclaration>moduleDecl.members.members[0]).isEnum() &&\n hasFlag((<ModuleDeclaration>moduleDecl.members.members[0]).modFlags, ModuleFlags.Exported));\n\n // Module is dotted only if it does not have doc comments for it\n var moduleDeclComments = moduleDecl.getDocComments();\n isCurrentModuleDotted = isCurrentModuleDotted && (moduleDeclComments == null || moduleDeclComments.length == 0);\n\n this.isDottedModuleName.push(isCurrentModuleDotted);\n this.pushDeclarationContainer(moduleDecl);\n\n if (!isCurrentModuleDotted) {\n this.emitDeclarationComments(moduleDecl);\n this.declFile.Write(this.dottedModuleEmit);\n this.declFile.WriteLine(\" {\");\n this.indenter.increaseIndent();\n }\n } else {\n if (!this.emitDottedModuleName()) {\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.declFile.WriteLine(\"}\");\n }\n this.popDeclarationContainer(moduleDecl);\n this.isDottedModuleName.pop();\n }\n\n return true;\n }\n\n public ScriptCallback(pre: bool, script: Script): bool {\n if (pre) {\n if (this.emitOptions.outputMany) {\n for (var i = 0; i < script.referencedFiles.length; i++) {\n var referencePath = script.referencedFiles[i].path;\n var declareFileName: string;\n if (isRooted(referencePath)) {\n declareFileName = this.emitOptions.mapOutputFileName(referencePath, TypeScriptCompiler.mapToDTSFileName)\n } else {\n declareFileName = getDeclareFilePath(script.referencedFiles[i].path);\n }\n this.declFile.WriteLine('/// <reference path=\"' + declareFileName + '\" />');\n }\n }\n this.pushDeclarationContainer(script);\n }\n else {\n this.popDeclarationContainer(script);\n }\n return true;\n }\n\n public DefaultCallback(pre: bool, ast: AST): bool {\n return !hasFlag(ast.flags, ASTFlags.IsStatement);\n }\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export module CompilerDiagnostics {\n export var debug = false;\n export interface IDiagnosticWriter {\n Alert(output: string): void;\n }\n\n export var diagnosticWriter: IDiagnosticWriter = null;\n\n export var analysisPass: number = 0;\n\n export function Alert(output: string) {\n if (diagnosticWriter) {\n diagnosticWriter.Alert(output);\n }\n }\n\n export function debugPrint(s: string) {\n if (debug) {\n Alert(s);\n }\n }\n\n export function assert(condition: bool, s: string) {\n if (debug) {\n if (!condition) {\n Alert(s);\n }\n }\n }\n\n }\n\n export interface ILogger {\n information(): bool;\n debug(): bool;\n warning(): bool;\n error(): bool;\n fatal(): bool;\n log(s: string): void;\n }\n\n export class NullLogger implements ILogger {\n public information(): bool { return false; }\n public debug(): bool { return false; }\n public warning(): bool { return false; }\n public error(): bool { return false; }\n public fatal(): bool { return false; }\n public log(s: string): void {\n }\n }\n\n export class LoggerAdapter implements ILogger {\n private _information: bool;\n private _debug: bool;\n private _warning: bool;\n private _error: bool;\n private _fatal: bool;\n\n constructor (public logger: ILogger) { \n this._information = this.logger.information();\n this._debug = this.logger.debug();\n this._warning = this.logger.warning();\n this._error = this.logger.error();\n this._fatal = this.logger.fatal();\n }\n\n\n public information(): bool { return this._information; }\n public debug(): bool { return this._debug; }\n public warning(): bool { return this._warning; }\n public error(): bool { return this._error; }\n public fatal(): bool { return this._fatal; }\n public log(s: string): void {\n this.logger.log(s);\n }\n }\n\n export class BufferedLogger implements ILogger {\n public logContents = [];\n\n public information(): bool { return false; }\n public debug(): bool { return false; }\n public warning(): bool { return false; }\n public error(): bool { return false; }\n public fatal(): bool { return false; }\n public log(s: string): void {\n this.logContents.push(s);\n }\n }\n\n export function timeFunction(logger: ILogger, funcDescription: string, func: () =>any): any {\n var start = +new Date();\n var result = func();\n var end = +new Date();\n logger.log(funcDescription + \" completed in \" + (end - start) + \" msec\");\n return result;\n }\n\n export function stringToLiteral(value: string, length: number): string {\n var result = \"\";\n\n var addChar = (index: number) => {\n var ch = value.charCodeAt(index);\n switch (ch) {\n case 0x09: // tab\n result += \"\\\\t\";\n break;\n case 0x0a: // line feed\n result += \"\\\\n\";\n break;\n case 0x0b: // vertical tab\n result += \"\\\\v\";\n break;\n case 0x0c: // form feed\n result += \"\\\\f\";\n break;\n case 0x0d: // carriage return\n result += \"\\\\r\";\n break;\n case 0x22: // double quote\n result += \"\\\\\\\"\";\n break;\n case 0x27: // single quote\n result += \"\\\\\\'\";\n break;\n case 0x5c: // Backslash\n result += \"\\\\\";\n break;\n default:\n result += value.charAt(index);\n }\n }\n\n var tooLong = (value.length > length);\n if (tooLong) {\n var mid = length >> 1;\n for (var i = 0; i < mid; i++) addChar(i);\n result += \"(...)\";\n for (var i = value.length - mid; i < value.length; i++) addChar(i);\n }\n else {\n length = value.length;\n for (var i = 0; i < length; i++) addChar(i);\n }\n return result;\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export enum EmitContainer {\n Prog,\n Module,\n DynamicModule,\n Class,\n Constructor,\n Function,\n Args,\n Interface,\n }\n\n export class EmitState {\n public column: number;\n public line: number;\n public pretty: bool;\n public inObjectLiteral: bool;\n public container: EmitContainer;\n\n constructor () {\n this.column = 0;\n this.line = 0;\n this.pretty = false;\n this.inObjectLiteral = false;\n this.container = EmitContainer.Prog;\n }\n }\n\n export class EmitOptions {\n public minWhitespace: bool;\n public propagateConstants: bool;\n public emitComments: bool;\n public outputOption: string;\n public ioHost: EmitterIOHost = null;\n public outputMany: bool = true;\n public commonDirectoryPath = \"\";\n\n constructor(settings: CompilationSettings) {\n this.minWhitespace = settings.minWhitespace;\n this.propagateConstants = settings.propagateConstants;\n this.emitComments = settings.emitComments;\n this.outputOption = settings.outputOption;\n }\n\n public mapOutputFileName(fileName: string, extensionChanger: (fname: string, wholeFileNameReplaced: bool) => string) {\n if (this.outputMany) {\n var updatedFileName = fileName;\n if (this.outputOption != \"\") {\n // Replace the common directory path with the option specified\n updatedFileName = fileName.replace(this.commonDirectoryPath, \"\");\n updatedFileName = this.outputOption + updatedFileName;\n }\n return extensionChanger(updatedFileName, false);\n } else {\n return extensionChanger(this.outputOption, true);\n }\n }\n }\n\n export class Indenter {\n static indentStep : number = 4;\n static indentStepString : string = \" \";\n static indentStrings: string[] = [];\n public indentAmt: number = 0;\n\n public increaseIndent() {\n this.indentAmt += Indenter.indentStep;\n }\n\n public decreaseIndent() {\n this.indentAmt -= Indenter.indentStep;\n }\n\n public getIndent() {\n var indentString = Indenter.indentStrings[this.indentAmt];\n if (indentString === undefined) {\n indentString = \"\";\n for (var i = 0; i < this.indentAmt; i = i + Indenter.indentStep) {\n indentString += Indenter.indentStepString;\n }\n Indenter.indentStrings[this.indentAmt] = indentString;\n }\n return indentString;\n }\n }\n\n export class Emitter {\n public prologueEmitted = false;\n public thisClassNode: TypeDeclaration = null;\n public thisFnc: FuncDecl = null;\n public moduleDeclList: ModuleDeclaration[] = [];\n public moduleName = \"\";\n public emitState = new EmitState();\n public indenter = new Indenter();\n public ambientModule = false;\n public modAliasId: string = null;\n public firstModAlias: string = null;\n public allSourceMappers: SourceMapper[] = [];\n public sourceMapper: SourceMapper = null;\n public captureThisStmtString = \"var _this = this;\";\n private varListCountStack: number[] = [0]; \n\n constructor(public checker: TypeChecker, public emittingFileName: string, public outfile: ITextWriter, public emitOptions: EmitOptions, public errorReporter: ErrorReporter) {\n }\n\n public setSourceMappings(mapper: SourceMapper) {\n this.allSourceMappers.push(mapper);\n this.sourceMapper = mapper;\n }\n\n public writeToOutput(s: string) {\n this.outfile.Write(s);\n // TODO: check s for newline\n this.emitState.column += s.length;\n }\n\n public writeToOutputTrimmable(s: string) {\n if (this.emitOptions.minWhitespace) {\n s = s.replace(/[\\s]*/g, '');\n }\n this.writeToOutput(s);\n }\n\n public writeLineToOutput(s: string) {\n if (this.emitOptions.minWhitespace) {\n this.writeToOutput(s);\n var c = s.charCodeAt(s.length - 1);\n if (!((c == LexCodeSpace) || (c == LexCodeSMC) || (c == LexCodeLBR))) {\n this.writeToOutput(' ');\n }\n }\n else {\n this.outfile.WriteLine(s);\n this.emitState.column = 0\n this.emitState.line++;\n }\n }\n\n public writeCaptureThisStatement(ast: AST) {\n this.emitIndent();\n this.recordSourceMappingStart(ast);\n this.writeToOutput(this.captureThisStmtString);\n this.recordSourceMappingEnd(ast);\n this.writeLineToOutput(\"\");\n }\n\n public setInVarBlock(count: number) {\n this.varListCountStack[this.varListCountStack.length - 1] = count;\n }\n\n public setInObjectLiteral(val: bool): bool {\n var temp = this.emitState.inObjectLiteral;\n this.emitState.inObjectLiteral = val;\n return temp;\n }\n\n public setContainer(c: number): number {\n var temp = this.emitState.container;\n this.emitState.container = c;\n return temp;\n }\n\n private getIndentString() {\n if (this.emitOptions.minWhitespace) {\n return \"\";\n }\n else {\n return this.indenter.getIndent();\n }\n }\n\n public emitIndent() {\n this.writeToOutput(this.getIndentString());\n }\n\n public emitCommentInPlace(comment: Comment) {\n var text = comment.getText();\n var hadNewLine = false;\n\n if (comment.isBlockComment) {\n if (this.emitState.column == 0) {\n this.emitIndent();\n }\n this.recordSourceMappingStart(comment);\n this.writeToOutput(text[0]);\n\n if (text.length > 1 || comment.endsLine) {\n for (var i = 1; i < text.length; i++) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n this.writeToOutput(text[i]);\n }\n this.recordSourceMappingEnd(comment);\n this.writeLineToOutput(\"\");\n hadNewLine = true;\n } else {\n this.recordSourceMappingEnd(comment);\n }\n }\n else {\n if (this.emitState.column == 0) {\n this.emitIndent();\n }\n this.recordSourceMappingStart(comment);\n this.writeToOutput(text[0]);\n this.recordSourceMappingEnd(comment);\n this.writeLineToOutput(\"\");\n hadNewLine = true;\n }\n\n if (hadNewLine) {\n this.emitIndent();\n }\n else {\n this.writeToOutput(\" \");\n }\n }\n\n public emitParensAndCommentsInPlace(ast: AST, pre: bool) {\n var comments = pre ? ast.preComments : ast.postComments;\n\n // comments should be printed before the LParen, but after the RParen\n if (ast.isParenthesized && !pre) {\n this.writeToOutput(\")\");\n }\n if (this.emitOptions.emitComments && comments && comments.length != 0) {\n for (var i = 0; i < comments.length; i++) {\n this.emitCommentInPlace(comments[i]);\n }\n }\n if (ast.isParenthesized && pre) {\n this.writeToOutput(\"(\");\n }\n }\n\n // TODO: emit accessor pattern\n public emitObjectLiteral(content: ASTList) {\n this.writeLineToOutput(\"{\");\n this.indenter.increaseIndent();\n var inObjectLiteral = this.setInObjectLiteral(true);\n this.emitJavascriptList(content, \",\", TokenID.Comma, true, false, false);\n this.setInObjectLiteral(inObjectLiteral);\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeToOutput(\"}\");\n }\n\n public emitArrayLiteral(content: ASTList) {\n this.writeToOutput(\"[\");\n if (content) {\n this.writeLineToOutput(\"\");\n this.indenter.increaseIndent();\n this.emitJavascriptList(content, \", \", TokenID.Comma, true, false, false);\n this.indenter.decreaseIndent();\n this.emitIndent();\n }\n this.writeToOutput(\"]\");\n }\n\n public emitNew(target: AST, args: ASTList) {\n this.writeToOutput(\"new \");\n if (target.nodeType == NodeType.TypeRef) {\n var typeRef = <TypeReference>target;\n if (typeRef.arrayCount) {\n this.writeToOutput(\"Array()\");\n }\n else {\n this.emitJavascript(typeRef.term, TokenID.Tilde, false);\n this.writeToOutput(\"()\");\n }\n }\n else {\n this.emitJavascript(target, TokenID.Tilde, false);\n this.recordSourceMappingStart(args);\n this.writeToOutput(\"(\");\n this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n this.writeToOutput(\")\");\n this.recordSourceMappingEnd(args);\n }\n }\n\n public tryEmitConstant(dotExpr: BinaryExpression) {\n if (!this.emitOptions.propagateConstants) {\n return false;\n }\n var propertyName = <Identifier>dotExpr.operand2;\n if (propertyName && propertyName.sym && propertyName.sym.isVariable()) {\n if (hasFlag(propertyName.sym.flags, SymbolFlags.Constant)) {\n if (propertyName.sym.declAST) {\n var boundDecl = <BoundDecl>propertyName.sym.declAST;\n if (boundDecl.init && (boundDecl.init.nodeType == NodeType.NumberLit)) {\n var numLit = <NumberLiteral>boundDecl.init;\n this.writeToOutput(numLit.value.toString());\n var comment = \" /* \";\n comment += propertyName.actualText;\n comment += \" */ \";\n this.writeToOutput(comment);\n return true;\n }\n }\n }\n }\n return false;\n }\n\n public emitCall(callNode: CallExpression, target: AST, args: ASTList) {\n if (!this.emitSuperCall(callNode)) {\n if (!hasFlag(callNode.flags, ASTFlags.ClassBaseConstructorCall)) {\n if (target.nodeType == NodeType.FuncDecl && !target.isParenthesized) {\n this.writeToOutput(\"(\");\n }\n if (callNode.target.nodeType == NodeType.Super && this.emitState.container == EmitContainer.Constructor) {\n this.writeToOutput(\"_super.call\");\n }\n else {\n this.emitJavascript(target, TokenID.OpenParen, false);\n }\n if (target.nodeType == NodeType.FuncDecl && !target.isParenthesized) {\n this.writeToOutput(\")\");\n }\n this.recordSourceMappingStart(args);\n this.writeToOutput(\"(\");\n if (callNode.target.nodeType == NodeType.Super && this.emitState.container == EmitContainer.Constructor) {\n this.writeToOutput(\"this\");\n if (args && args.members.length) {\n this.writeToOutput(\", \");\n }\n }\n this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n this.writeToOutput(\")\");\n this.recordSourceMappingEnd(args);\n }\n else {\n this.indenter.decreaseIndent();\n this.indenter.decreaseIndent();\n var constructorCall = new ASTList();\n constructorCall.members[0] = callNode;\n this.emitConstructorCalls(constructorCall, this.thisClassNode);\n this.indenter.increaseIndent();\n this.indenter.increaseIndent();\n }\n }\n }\n\n public emitConstructorCalls(bases: ASTList, classDecl: TypeDeclaration) {\n if (bases == null) {\n return;\n }\n var basesLen = bases.members.length;\n this.recordSourceMappingStart(classDecl);\n for (var i = 0; i < basesLen; i++) {\n var baseExpr = bases.members[i];\n var baseSymbol: Symbol = null;\n if (baseExpr.nodeType == NodeType.Call) {\n baseSymbol = (<CallExpression>baseExpr).target.type.symbol;\n }\n else {\n baseSymbol = baseExpr.type.symbol;\n }\n var baseName = baseSymbol.name;\n if (baseSymbol.declModule != classDecl.type.symbol.declModule) {\n baseName = baseSymbol.fullName();\n }\n if (baseExpr.nodeType == NodeType.Call) {\n this.emitIndent();\n this.writeToOutput(\"_super.call(this\");\n var args = (<CallExpression>baseExpr).arguments;\n if (args && (args.members.length > 0)) {\n this.writeToOutput(\", \");\n this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n }\n this.writeToOutput(\")\");\n }\n else {\n if (baseExpr.type && (baseExpr.type.isClassInstance())) {\n // parameterless constructor call;\n this.emitIndent();\n this.writeToOutput(classDecl.name.actualText + \"._super.constructor\");\n //emitJavascript(baseExpr,TokenID.LParen,false);\n this.writeToOutput(\".call(this)\");\n }\n }\n }\n this.recordSourceMappingEnd(classDecl);\n }\n\n public emitInnerFunction(funcDecl: FuncDecl, printName: bool, isMember: bool,\n bases: ASTList, hasSelfRef: bool, classDecl: TypeDeclaration) {\n /// REVIEW: The code below causes functions to get pushed to a newline in cases where they shouldn't\n /// such as: \n /// Foo.prototype.bar = \n /// function() {\n /// };\n /// Once we start emitting comments, we should pull this code out to place on the outer context where the function\n /// is used.\n //if (funcDecl.preComments!=null && funcDecl.preComments.length>0) {\n // this.writeLineToOutput(\"\");\n // this.increaseIndent();\n // emitIndent();\n //}\n\n var isClassConstructor = funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod);\n var hasNonObjectBaseType = isClassConstructor && hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeFlags.HasBaseType) && !hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeFlags.HasBaseTypeOfObject);\n var classPropertiesMustComeAfterSuperCall = hasNonObjectBaseType && hasFlag((<ClassDeclaration>this.thisClassNode).varFlags, VarFlags.ClassSuperMustBeFirstCallInConstructor);\n\n // We have no way of knowing if the current function is used as an expression or a statement, so as to enusre that the emitted\n // JavaScript is always valid, add an extra parentheses for unparenthesized function expressions\n var shouldParenthesize = hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression) && !funcDecl.isParenthesized && !funcDecl.isAccessor() && (hasFlag(funcDecl.flags, ASTFlags.ExplicitSemicolon) || hasFlag(funcDecl.flags, ASTFlags.AutomaticSemicolon));\n\n this.emitParensAndCommentsInPlace(funcDecl, true);\n if (shouldParenthesize) {\n this.writeToOutput(\"(\");\n }\n this.recordSourceMappingStart(funcDecl);\n if (!(funcDecl.isAccessor() && (<FieldSymbol>funcDecl.accessorSymbol).isObjectLitField)) {\n this.writeToOutput(\"function \");\n }\n if (printName) {\n var id = funcDecl.getNameText();\n if (id && !funcDecl.isAccessor()) {\n if (funcDecl.name) {\n this.recordSourceMappingStart(funcDecl.name);\n }\n this.writeToOutput(id);\n if (funcDecl.name) {\n this.recordSourceMappingEnd(funcDecl.name);\n }\n }\n }\n\n this.writeToOutput(\"(\");\n var argsLen = 0;\n var i = 0;\n var arg: ArgDecl;\n var defaultArgs: ArgDecl[] = [];\n if (funcDecl.arguments) {\n var tempContainer = this.setContainer(EmitContainer.Args);\n argsLen = funcDecl.arguments.members.length;\n var printLen = argsLen;\n if (funcDecl.variableArgList) {\n printLen--;\n }\n for (i = 0; i < printLen; i++) {\n arg = <ArgDecl>funcDecl.arguments.members[i];\n if (arg.init) {\n defaultArgs.push(arg);\n }\n this.emitJavascript(arg, TokenID.OpenParen, false);\n if (i < (printLen - 1)) {\n this.writeToOutput(\", \");\n }\n }\n this.setContainer(tempContainer);\n }\n this.writeLineToOutput(\") {\");\n\n if (funcDecl.isConstructor) {\n this.recordSourceMappingNameStart(\"constructor\");\n } else if (funcDecl.isGetAccessor()) {\n this.recordSourceMappingNameStart(\"get_\" + funcDecl.getNameText());\n } else if (funcDecl.isSetAccessor()) {\n this.recordSourceMappingNameStart(\"set_\" + funcDecl.getNameText());\n } else {\n this.recordSourceMappingNameStart(funcDecl.getNameText());\n }\n this.indenter.increaseIndent();\n\n // set default args first\n for (i = 0; i < defaultArgs.length; i++) {\n var arg = defaultArgs[i];\n this.emitIndent();\n this.recordSourceMappingStart(arg);\n this.writeToOutput(\"if (typeof \" + arg.id.actualText + \" === \\\"undefined\\\") { \");//\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeToOutput(\" = \");\n this.emitJavascript(arg.init, TokenID.OpenParen, false);\n this.writeLineToOutput(\"; }\")\n this.recordSourceMappingEnd(arg);\n }\n\n if (funcDecl.isConstructor && ((<ClassDeclaration>funcDecl.classDecl).varFlags & VarFlags.MustCaptureThis)) {\n this.writeCaptureThisStatement(funcDecl);\n }\n\n if (funcDecl.isConstructor && !classPropertiesMustComeAfterSuperCall) {\n if (funcDecl.arguments) {\n argsLen = funcDecl.arguments.members.length;\n for (i = 0; i < argsLen; i++) {\n arg = <ArgDecl>funcDecl.arguments.members[i];\n if ((arg.varFlags & VarFlags.Property) != VarFlags.None) {\n this.emitIndent();\n this.recordSourceMappingStart(arg);\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(\"this.\" + arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeToOutput(\" = \");\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(arg);\n }\n }\n }\n\n // For classes, the constructor needs to be explicitly called\n if (!hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n this.emitConstructorCalls(bases, classDecl);\n }\n }\n if (hasSelfRef) {\n this.writeCaptureThisStatement(funcDecl);\n }\n if (funcDecl.variableArgList) {\n argsLen = funcDecl.arguments.members.length;\n var lastArg = <ArgDecl>funcDecl.arguments.members[argsLen - 1];\n this.emitIndent();\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"var \");\n this.recordSourceMappingStart(lastArg.id);\n this.writeToOutput(lastArg.id.actualText);\n this.recordSourceMappingEnd(lastArg.id);\n this.writeLineToOutput(\" = [];\");\n this.recordSourceMappingEnd(lastArg);\n this.emitIndent();\n this.writeToOutput(\"for (\")\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"var _i = 0;\");\n this.recordSourceMappingEnd(lastArg);\n this.writeToOutput(\" \");\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"_i < (arguments.length - \" + (argsLen - 1) + \")\");\n this.recordSourceMappingEnd(lastArg);\n this.writeToOutput(\"; \");\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(\"_i++\");\n this.recordSourceMappingEnd(lastArg);\n this.writeLineToOutput(\") {\");\n this.indenter.increaseIndent();\n this.emitIndent();\n\n this.recordSourceMappingStart(lastArg);\n this.writeToOutput(lastArg.id.actualText + \"[_i] = arguments[_i + \" + (argsLen - 1) + \"];\");\n this.recordSourceMappingEnd(lastArg);\n this.writeLineToOutput(\"\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeLineToOutput(\"}\");\n }\n\n // if it's a class, emit the uninitializedMembers, first emit the non-proto class body members\n if (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod) && !classPropertiesMustComeAfterSuperCall) {\n\n var nProps = (<ASTList>this.thisClassNode.members).members.length;\n\n for (var i = 0; i < nProps; i++) {\n if ((<ASTList>this.thisClassNode.members).members[i].nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>(<ASTList>this.thisClassNode.members).members[i];\n if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n this.emitIndent();\n this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n this.writeLineToOutput(\"\");\n }\n }\n }\n //this.writeLineToOutput(\"\");\n }\n\n this.emitBareJavascriptStatements(funcDecl.bod, classPropertiesMustComeAfterSuperCall);\n\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl.endingToken);\n this.writeToOutput(\"}\");\n\n this.recordSourceMappingNameEnd();\n this.recordSourceMappingEnd(funcDecl.endingToken);\n this.recordSourceMappingEnd(funcDecl);\n\n if (shouldParenthesize) {\n this.writeToOutput(\")\");\n }\n\n // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it\n this.recordSourceMappingEnd(funcDecl);\n\n this.emitParensAndCommentsInPlace(funcDecl, false);\n\n if (!isMember &&\n //funcDecl.name != null &&\n !hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression) &&\n (hasFlag(funcDecl.fncFlags, FncFlags.Definition) || funcDecl.isConstructor)) {\n this.writeLineToOutput(\"\");\n } else if (hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression)) {\n if (hasFlag(funcDecl.flags, ASTFlags.ExplicitSemicolon) || hasFlag(funcDecl.flags, ASTFlags.AutomaticSemicolon)) {\n // If either of these two flags are set, then the function expression is a statement. Terminate it.\n this.writeLineToOutput(\";\");\n }\n }\n /// TODO: See the other part of this at the beginning of function\n //if (funcDecl.preComments!=null && funcDecl.preComments.length>0) {\n // this.decreaseIndent();\n //} \n }\n\n public emitJavascriptModule(moduleDecl: ModuleDeclaration) {\n var modName = moduleDecl.name.actualText;\n if (isTSFile(modName)) {\n moduleDecl.name.setText(modName.substring(0, modName.length - 3));\n }\n else if (isSTRFile(modName)) {\n moduleDecl.name.setText(modName.substring(0, modName.length - 4));\n }\n\n if (!hasFlag(moduleDecl.modFlags, ModuleFlags.Ambient)) {\n var isDynamicMod = hasFlag(moduleDecl.modFlags, ModuleFlags.IsDynamic);\n var prevOutFile = this.outfile;\n var prevOutFileName = this.emittingFileName;\n var prevAllSourceMappers = this.allSourceMappers;\n var prevSourceMapper = this.sourceMapper;\n var prevColumn = this.emitState.column;\n var prevLine = this.emitState.line;\n var temp = this.setContainer(EmitContainer.Module);\n var svModuleName = this.moduleName;\n var isExported = hasFlag(moduleDecl.modFlags, ModuleFlags.Exported);\n this.moduleDeclList[this.moduleDeclList.length] = moduleDecl;\n var isWholeFile = hasFlag(moduleDecl.modFlags, ModuleFlags.IsWholeFile);\n this.moduleName = moduleDecl.name.actualText;\n\n // prologue\n if (isDynamicMod) {\n // create the new outfile for this module\n var tsModFileName = stripQuotes(moduleDecl.name.actualText);\n var modFilePath = trimModName(tsModFileName) + \".js\";\n modFilePath = this.emitOptions.mapOutputFileName(modFilePath, TypeScriptCompiler.mapToJSFileName);\n\n if (this.emitOptions.ioHost) {\n // Ensure that the slashes are normalized so that the comparison is fair\n // REVIEW: Note that modFilePath is normalized to forward slashes in Parser.parse, so the \n // first call to switchToForwardSlashes is technically a no-op, but it will prevent us from\n // regressing if the parser changes\n if (switchToForwardSlashes(modFilePath) != switchToForwardSlashes(this.emittingFileName)) {\n this.emittingFileName = modFilePath;\n var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);\n this.outfile = this.createFile(this.emittingFileName, useUTF8InOutputfile);\n if (prevSourceMapper != null) {\n this.allSourceMappers = [];\n var sourceMappingFile = this.createFile(this.emittingFileName + SourceMapper.MapFileExtension, false);\n this.setSourceMappings(new TypeScript.SourceMapper(tsModFileName, this.emittingFileName, this.outfile, sourceMappingFile, this.errorReporter));\n this.emitState.column = 0;\n this.emitState.line = 0;\n }\n } else {\n CompilerDiagnostics.assert(this.emitOptions.outputMany, \"Cannot have dynamic modules compiling into single file\");\n }\n }\n\n this.setContainer(EmitContainer.DynamicModule); // discard the previous 'Module' container\n\n this.recordSourceMappingStart(moduleDecl);\n if (moduleGenTarget == ModuleGenTarget.Asynchronous) { // AMD\n var dependencyList = \"[\\\"require\\\", \\\"exports\\\"\";\n var importList = \"require, exports\";\n var importStatement: ImportDeclaration = null;\n\n // all dependencies are quoted\n for (var i = 0; i < (<ModuleType>moduleDecl.mod).importedModules.length; i++) {\n importStatement = (<ModuleType>moduleDecl.mod).importedModules[i]\n\n // if the imported module is only used in a type position, do not add it as a requirement\n if (importStatement.id.sym &&\n !(<TypeSymbol>importStatement.id.sym).onlyReferencedAsTypeRef) {\n if (i <= (<ModuleType>moduleDecl.mod).importedModules.length - 1) {\n dependencyList += \", \";\n importList += \", \";\n }\n\n importList += \"__\" + importStatement.id.actualText + \"__\";\n dependencyList += importStatement.firstAliasedModToString();\n }\n }\n\n // emit any potential amd dependencies\n for (var i = 0; i < moduleDecl.amdDependencies.length; i++) {\n dependencyList += \", \\\"\" + moduleDecl.amdDependencies[i] + \"\\\"\";\n }\n\n dependencyList += \"]\";\n\n this.writeLineToOutput(\"define(\" + dependencyList + \",\" + \" function(\" + importList + \") {\");\n }\n else { // Node\n\n }\n }\n else {\n\n if (!isExported) {\n this.recordSourceMappingStart(moduleDecl);\n this.writeToOutput(\"var \");\n this.recordSourceMappingStart(moduleDecl.name);\n this.writeToOutput(this.moduleName);\n this.recordSourceMappingEnd(moduleDecl.name);\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(moduleDecl);\n this.emitIndent();\n }\n\n this.writeToOutput(\"(\");\n this.recordSourceMappingStart(moduleDecl);\n this.writeToOutput(\"function (\");\n this.recordSourceMappingStart(moduleDecl.name);\n this.writeToOutput(this.moduleName);\n this.recordSourceMappingEnd(moduleDecl.name);\n this.writeLineToOutput(\") {\");\n }\n\n if (!isWholeFile) {\n this.recordSourceMappingNameStart(this.moduleName);\n }\n\n // body - don't indent for Node\n if (!isDynamicMod || moduleGenTarget == ModuleGenTarget.Asynchronous) {\n this.indenter.increaseIndent();\n }\n\n if (moduleDecl.modFlags & ModuleFlags.MustCaptureThis) {\n this.writeCaptureThisStatement(moduleDecl);\n }\n\n this.emitJavascriptList(moduleDecl.members, null, TokenID.Semicolon, true, false, false);\n if (!isDynamicMod || moduleGenTarget == ModuleGenTarget.Asynchronous) {\n this.indenter.decreaseIndent();\n }\n this.emitIndent();\n\n // epilogue\n if (isDynamicMod) {\n if (moduleGenTarget == ModuleGenTarget.Asynchronous) { // AMD\n this.writeLineToOutput(\"})\");\n }\n else { // Node\n }\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl);\n\n // close the module outfile, and restore the old one\n if (this.outfile != prevOutFile) {\n this.Close();\n if (prevSourceMapper != null) {\n this.allSourceMappers = prevAllSourceMappers;\n this.sourceMapper = prevSourceMapper;\n this.emitState.column = prevColumn;\n this.emitState.line = prevLine;\n }\n this.outfile = prevOutFile;\n this.emittingFileName = prevOutFileName;\n }\n }\n else {\n var containingMod: ModuleDeclaration = null;\n if (moduleDecl.type && moduleDecl.type.symbol.container && moduleDecl.type.symbol.container.declAST) {\n containingMod = <ModuleDeclaration>moduleDecl.type.symbol.container.declAST;\n }\n var parentIsDynamic = containingMod && hasFlag(containingMod.modFlags, ModuleFlags.IsDynamic);\n\n this.recordSourceMappingStart(moduleDecl.endingToken);\n if (temp == EmitContainer.Prog && isExported) {\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")(this.\" + this.moduleName + \" || (this.\" + this.moduleName + \" = {}));\");\n }\n else if (isExported || temp == EmitContainer.Prog) {\n var dotMod = svModuleName != \"\" ? (parentIsDynamic ? \"exports\" : svModuleName) + \".\" : svModuleName;\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")(\" + dotMod + this.moduleName + \" || (\" + dotMod + this.moduleName + \" = {}));\");\n }\n else if (!isExported && temp != EmitContainer.Prog) {\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")(\" + this.moduleName + \" || (\" + this.moduleName + \" = {}));\");\n }\n else {\n this.writeToOutput(\"}\");\n if (!isWholeFile) {\n this.recordSourceMappingNameEnd();\n }\n this.recordSourceMappingEnd(moduleDecl.endingToken);\n this.writeToOutput(\")();\");\n }\n this.recordSourceMappingEnd(moduleDecl);\n this.writeLineToOutput(\"\");\n if (temp != EmitContainer.Prog && isExported) {\n this.emitIndent();\n this.recordSourceMappingStart(moduleDecl);\n if (parentIsDynamic) {\n this.writeLineToOutput(\"var \" + this.moduleName + \" = exports.\" + this.moduleName + \";\");\n } else {\n this.writeLineToOutput(\"var \" + this.moduleName + \" = \" + svModuleName + \".\" + this.moduleName + \";\");\n }\n this.recordSourceMappingEnd(moduleDecl);\n }\n }\n\n this.setContainer(temp);\n this.moduleName = svModuleName;\n this.moduleDeclList.length--;\n }\n }\n\n public emitIndex(operand1: AST, operand2: AST) {\n var temp = this.setInObjectLiteral(false);\n this.emitJavascript(operand1, TokenID.Tilde, false);\n this.writeToOutput(\"[\");\n this.emitJavascriptList(operand2, \", \", TokenID.Comma, false, false, false);\n this.writeToOutput(\"]\");\n this.setInObjectLiteral(temp);\n }\n\n public emitStringLiteral(text: string) {\n // should preserve escape etc.\n // TODO: simplify object literal simple name\n this.writeToOutput(text);\n }\n\n public emitJavascriptFunction(funcDecl: FuncDecl) {\n if (hasFlag(funcDecl.fncFlags, FncFlags.Signature) || funcDecl.isOverload) {\n return;\n }\n var temp: number;\n var tempFnc = this.thisFnc;\n this.thisFnc = funcDecl;\n\n if (funcDecl.isConstructor) {\n temp = this.setContainer(EmitContainer.Constructor);\n }\n else {\n temp = this.setContainer(EmitContainer.Function);\n }\n\n var bases: ASTList = null;\n var hasSelfRef = false;\n var funcName = funcDecl.getNameText();\n\n if ((this.emitState.inObjectLiteral || !funcDecl.isAccessor()) &&\n ((temp != EmitContainer.Constructor) ||\n ((funcDecl.fncFlags & FncFlags.Method) == FncFlags.None))) {\n var tempLit = this.setInObjectLiteral(false);\n if (this.thisClassNode) {\n bases = this.thisClassNode.extendsList;\n }\n hasSelfRef = Emitter.shouldCaptureThis(funcDecl);\n this.recordSourceMappingStart(funcDecl);\n if (hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported) && funcDecl.type.symbol.container == this.checker.gloMod && !funcDecl.isConstructor) {\n this.writeToOutput(\"this.\" + funcName + \" = \");\n this.emitInnerFunction(funcDecl, false, false, bases, hasSelfRef, this.thisClassNode);\n }\n else {\n this.emitInnerFunction(funcDecl, (funcDecl.name && !funcDecl.name.isMissing()), false, bases, hasSelfRef, this.thisClassNode);\n }\n this.setInObjectLiteral(tempLit);\n }\n this.setContainer(temp);\n this.thisFnc = tempFnc;\n\n if (hasFlag(funcDecl.fncFlags, FncFlags.Definition)) {\n if (hasFlag(funcDecl.fncFlags, FncFlags.Static)) {\n if (this.thisClassNode) {\n if (funcDecl.isAccessor()) {\n this.emitPropertyAccessor(funcDecl, this.thisClassNode.name.actualText, false);\n }\n else {\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl);\n this.writeLineToOutput(this.thisClassNode.name.actualText + \".\" + funcName +\n \" = \" + funcName + \";\");\n this.recordSourceMappingEnd(funcDecl);\n }\n }\n }\n else if ((this.emitState.container == EmitContainer.Module || this.emitState.container == EmitContainer.DynamicModule) && hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported)) {\n this.emitIndent();\n var modName = this.emitState.container == EmitContainer.Module ? this.moduleName : \"exports\";\n this.recordSourceMappingStart(funcDecl);\n this.writeLineToOutput(modName + \".\" + funcName +\n \" = \" + funcName + \";\");\n this.recordSourceMappingEnd(funcDecl);\n }\n }\n }\n\n public emitAmbientVarDecl(varDecl: VarDecl) {\n if (varDecl.init) {\n this.emitParensAndCommentsInPlace(varDecl, true);\n this.recordSourceMappingStart(varDecl);\n this.recordSourceMappingStart(varDecl.id);\n this.writeToOutput(varDecl.id.actualText);\n this.recordSourceMappingEnd(varDecl.id);\n this.writeToOutput(\" = \");\n this.emitJavascript(varDecl.init, TokenID.Comma, false);\n this.recordSourceMappingEnd(varDecl);\n this.writeToOutput(\";\");\n this.emitParensAndCommentsInPlace(varDecl, false);\n }\n }\n\n private varListCount(): number {\n return this.varListCountStack[this.varListCountStack.length - 1];\n }\n\n // Emits \"var \" if it is allowed\n private emitVarDeclVar() {\n // If it is var list of form var a, b, c = emit it only if count > 0 - which will be when emitting first var\n // If it is var list of form var a = varList count will be 0\n if (this.varListCount() >= 0) {\n this.writeToOutput(\"var \");\n this.setInVarBlock(-this.varListCount());\n }\n return true;\n }\n\n private onEmitVar() {\n if (this.varListCount() > 0) {\n this.setInVarBlock(this.varListCount() - 1);\n }\n else if (this.varListCount() < 0) {\n this.setInVarBlock(this.varListCount() + 1);\n }\n }\n\n public emitJavascriptVarDecl(varDecl: VarDecl, tokenId: TokenID) {\n if ((varDecl.varFlags & VarFlags.Ambient) == VarFlags.Ambient) {\n this.emitAmbientVarDecl(varDecl);\n this.onEmitVar();\n }\n else {\n var sym = varDecl.sym;\n var hasInitializer = (varDecl.init != null);\n this.emitParensAndCommentsInPlace(varDecl, true);\n this.recordSourceMappingStart(varDecl);\n if (sym && sym.isMember() && sym.container &&\n (sym.container.kind() == SymbolKind.Type)) {\n var type = (<TypeSymbol>sym.container).type;\n if (type.isClass() && (!hasFlag(sym.flags, SymbolFlags.ModuleMember))) {\n // class\n if (this.emitState.container != EmitContainer.Args) {\n if (hasFlag(sym.flags, SymbolFlags.Static)) {\n this.writeToOutput(sym.container.name + \".\");\n }\n else {\n this.writeToOutput(\"this.\");\n }\n }\n }\n else if (type.hasImplementation()) {\n // module\n if (!hasFlag(sym.flags, SymbolFlags.Exported) && (sym.container == this.checker.gloMod || !hasFlag(sym.flags, SymbolFlags.Property))) {\n this.emitVarDeclVar();\n }\n else if (hasFlag(varDecl.varFlags, VarFlags.LocalStatic)) {\n this.writeToOutput(\".\");\n }\n else {\n if (this.emitState.container == EmitContainer.DynamicModule) {\n this.writeToOutput(\"exports.\");\n }\n else {\n this.writeToOutput(this.moduleName + \".\");\n }\n }\n }\n else {\n // function, constructor, method etc.\n if (tokenId != TokenID.OpenParen) {\n if (hasFlag(sym.flags, SymbolFlags.Exported) && sym.container == this.checker.gloMod) {\n this.writeToOutput(\"this.\");\n }\n else {\n this.emitVarDeclVar();\n }\n }\n }\n }\n else {\n if (tokenId != TokenID.OpenParen) {\n this.emitVarDeclVar();\n }\n }\n this.recordSourceMappingStart(varDecl.id);\n this.writeToOutput(varDecl.id.actualText);\n this.recordSourceMappingEnd(varDecl.id);\n if (hasInitializer) {\n this.writeToOutputTrimmable(\" = \");\n\n // Ensure we have a fresh var list count when recursing into the variable \n // initializer. We don't want our current list of variables to affect how we\n // emit nested variable lists.\n this.varListCountStack.push(0);\n this.emitJavascript(varDecl.init, TokenID.Comma, false);\n this.varListCountStack.pop();\n }\n this.onEmitVar();\n if ((tokenId != TokenID.OpenParen)) {\n if (this.varListCount() < 0) {\n this.writeToOutput(\", \");\n } else if (tokenId != TokenID.For) {\n this.writeToOutputTrimmable(\";\");\n }\n }\n this.recordSourceMappingEnd(varDecl);\n this.emitParensAndCommentsInPlace(varDecl, false);\n }\n }\n\n public declEnclosed(moduleDecl: ModuleDeclaration): bool {\n if (moduleDecl == null) {\n return true;\n }\n for (var i = 0, len = this.moduleDeclList.length; i < len; i++) {\n if (this.moduleDeclList[i] == moduleDecl) {\n return true;\n }\n }\n return false;\n }\n\n public emitJavascriptName(name: Identifier, addThis: bool) {\n var sym = name.sym;\n this.emitParensAndCommentsInPlace(name, true);\n this.recordSourceMappingStart(name);\n if (!name.isMissing()) {\n if (addThis && (this.emitState.container != EmitContainer.Args) && sym) {\n // TODO: flag global module with marker other than string name\n if (sym.container && (sym.container.name != globalId)) {\n if (hasFlag(sym.flags, SymbolFlags.Static) && (hasFlag(sym.flags, SymbolFlags.Property))) {\n if (sym.declModule && hasFlag(sym.declModule.modFlags, ModuleFlags.IsDynamic)) {\n this.writeToOutput(\"exports.\");\n }\n else {\n this.writeToOutput(sym.container.name + \".\");\n }\n }\n else if (sym.kind() == SymbolKind.Field) {\n var fieldSym = <FieldSymbol>sym;\n if (hasFlag(fieldSym.flags, SymbolFlags.ModuleMember)) {\n if ((sym.container != this.checker.gloMod) && ((hasFlag(sym.flags, SymbolFlags.Property)) || hasFlag(sym.flags, SymbolFlags.Exported))) {\n if (hasFlag(sym.declModule.modFlags, ModuleFlags.IsDynamic)) {\n this.writeToOutput(\"exports.\");\n }\n else {\n this.writeToOutput(sym.container.name + \".\");\n }\n }\n }\n else {\n if (sym.isInstanceProperty()) {\n this.emitThis();\n this.writeToOutput(\".\");\n }\n }\n }\n else if (sym.kind() == SymbolKind.Type) {\n if (sym.isInstanceProperty()) {\n var typeSym = <TypeSymbol>sym;\n var type = typeSym.type;\n if (type.call && !hasFlag(sym.flags, SymbolFlags.ModuleMember)) {\n this.emitThis();\n this.writeToOutput(\".\");\n }\n }\n else if ((sym.unitIndex != this.checker.locationInfo.unitIndex) || (!this.declEnclosed(sym.declModule))) {\n this.writeToOutput(sym.container.name + \".\")\n }\n }\n }\n else if (sym.container == this.checker.gloMod &&\n hasFlag(sym.flags, SymbolFlags.Exported) &&\n !hasFlag(sym.flags, SymbolFlags.Ambient) &&\n // check that it's a not a member of an ambient module...\n !((sym.isType() || sym.isMember()) &&\n sym.declModule &&\n hasFlag(sym.declModule.modFlags, ModuleFlags.Ambient)) &&\n this.emitState.container == EmitContainer.Prog &&\n sym.declAST.nodeType != NodeType.FuncDecl) {\n this.writeToOutput(\"this.\");\n }\n }\n\n // If it's a dynamic module, we need to print the \"require\" invocation\n if (sym &&\n sym.declAST &&\n sym.declAST.nodeType == NodeType.ModuleDeclaration &&\n (hasFlag((<ModuleDeclaration>sym.declAST).modFlags, ModuleFlags.IsDynamic))) {\n var moduleDecl: ModuleDeclaration = <ModuleDeclaration>sym.declAST;\n\n if (moduleGenTarget == ModuleGenTarget.Asynchronous) {\n this.writeLineToOutput(\"__\" + this.modAliasId + \"__;\");\n }\n else {\n var modPath = name.actualText;//(<ModuleDecl>moduleDecl.mod.symbol.declAST).name.actualText;\n var isAmbient = moduleDecl.mod.symbol.declAST && hasFlag((<ModuleDeclaration>moduleDecl.mod.symbol.declAST).modFlags, ModuleFlags.Ambient);\n modPath = isAmbient ? modPath : this.firstModAlias ? this.firstModAlias : quoteBaseName(modPath);\n modPath = isAmbient ? modPath : (!isRelative(stripQuotes(modPath)) ? quoteStr(\"./\" + stripQuotes(modPath)) : modPath);\n this.writeToOutput(\"require(\" + modPath + \")\");\n }\n }\n else {\n this.writeToOutput(name.actualText);\n }\n }\n this.recordSourceMappingEnd(name);\n this.emitParensAndCommentsInPlace(name, false);\n }\n\n public emitJavascriptStatements(stmts: AST, emitEmptyBod: bool) {\n if (stmts) {\n if (stmts.nodeType != NodeType.Block) {\n var hasContents = (stmts && (stmts.nodeType != NodeType.List || ((<ASTList>stmts).members.length > 0)));\n if (emitEmptyBod || hasContents) {\n var hasOnlyBlockStatement = ((stmts.nodeType == NodeType.Block) ||\n ((stmts.nodeType == NodeType.List) && ((<ASTList>stmts).members.length == 1) && ((<ASTList>stmts).members[0].nodeType == NodeType.Block)));\n\n this.recordSourceMappingStart(stmts);\n if (!hasOnlyBlockStatement) {\n this.writeLineToOutput(\" {\");\n this.indenter.increaseIndent();\n }\n this.emitJavascriptList(stmts, null, TokenID.Semicolon, true, false, false);\n if (!hasOnlyBlockStatement) {\n this.writeLineToOutput(\"\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeToOutput(\"}\");\n }\n this.recordSourceMappingEnd(stmts);\n }\n }\n else {\n this.emitJavascript(stmts, TokenID.Semicolon, true);\n }\n }\n else if (emitEmptyBod) {\n this.writeToOutput(\"{ }\");\n }\n }\n\n public emitBareJavascriptStatements(stmts: AST, emitClassPropertiesAfterSuperCall: bool = false) {\n // just the statements without enclosing curly braces\n if (stmts.nodeType != NodeType.Block) {\n if (stmts.nodeType == NodeType.List) {\n var stmtList = <ASTList>stmts;\n if ((stmtList.members.length == 2) &&\n (stmtList.members[0].nodeType == NodeType.Block) &&\n (stmtList.members[1].nodeType == NodeType.EndCode)) {\n this.emitJavascript(stmtList.members[0], TokenID.Semicolon, true);\n this.writeLineToOutput(\"\");\n }\n else {\n this.emitJavascriptList(stmts, null, TokenID.Semicolon, true, false, emitClassPropertiesAfterSuperCall);\n }\n }\n else {\n this.emitJavascript(stmts, TokenID.Semicolon, true);\n }\n }\n else {\n this.emitJavascript(stmts, TokenID.Semicolon, true);\n }\n }\n\n public recordSourceMappingNameStart(name: string) {\n if (this.sourceMapper) {\n var finalName = name;\n if (!name) {\n finalName = \"\";\n } else if (this.sourceMapper.currentNameIndex.length > 0) {\n finalName = this.sourceMapper.names[this.sourceMapper.currentNameIndex.length - 1] + \".\" + name;\n }\n\n // We are currently not looking for duplicate but that is possible.\n this.sourceMapper.names.push(finalName);\n this.sourceMapper.currentNameIndex.push(this.sourceMapper.names.length - 1);\n }\n }\n\n public recordSourceMappingNameEnd() {\n if (this.sourceMapper) {\n this.sourceMapper.currentNameIndex.pop();\n }\n }\n\n public recordSourceMappingStart(ast: ASTSpan) {\n if (this.sourceMapper && isValidAstNode(ast)) {\n var lineCol = { line: -1, col: -1 };\n var sourceMapping = new SourceMapping();\n sourceMapping.start.emittedColumn = this.emitState.column;\n sourceMapping.start.emittedLine = this.emitState.line;\n // REVIEW: check time consumed by this binary search (about two per leaf statement)\n getSourceLineColFromMap(lineCol, ast.minChar, this.checker.locationInfo.lineMap);\n sourceMapping.start.sourceColumn = lineCol.col;\n sourceMapping.start.sourceLine = lineCol.line;\n getSourceLineColFromMap(lineCol, ast.limChar, this.checker.locationInfo.lineMap);\n sourceMapping.end.sourceColumn = lineCol.col;\n sourceMapping.end.sourceLine = lineCol.line;\n if (this.sourceMapper.currentNameIndex.length > 0) {\n sourceMapping.nameIndex = this.sourceMapper.currentNameIndex[this.sourceMapper.currentNameIndex.length - 1];\n }\n // Set parent and child relationship\n var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];\n siblings.push(sourceMapping);\n this.sourceMapper.currentMappings.push(sourceMapping.childMappings);\n }\n }\n\n public recordSourceMappingEnd(ast: ASTSpan) {\n if (this.sourceMapper && isValidAstNode(ast)) {\n // Pop source mapping childs\n this.sourceMapper.currentMappings.pop();\n\n // Get the last source mapping from sibling list = which is the one we are recording end for\n var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];\n var sourceMapping = siblings[siblings.length - 1];\n\n sourceMapping.end.emittedColumn = this.emitState.column;\n sourceMapping.end.emittedLine = this.emitState.line;\n }\n }\n\n public Close() {\n if (this.sourceMapper != null) {\n SourceMapper.EmitSourceMapping(this.allSourceMappers);\n }\n try {\n // Closing files could result in exceptions, report them if they occur\n this.outfile.Close();\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n\n public emitJavascriptList(ast: AST, delimiter: string, tokenId: TokenID, startLine: bool, onlyStatics: bool, emitClassPropertiesAfterSuperCall: bool = false, emitPrologue? = false, requiresExtendsBlock?: bool) {\n if (ast == null) {\n return;\n }\n else if (ast.nodeType != NodeType.List) {\n this.emitPrologue(emitPrologue);\n this.emitJavascript(ast, tokenId, startLine);\n }\n else {\n var list = <ASTList>ast;\n if (list.members.length == 0) {\n return;\n }\n\n this.emitParensAndCommentsInPlace(ast, true);\n var len = list.members.length;\n for (var i = 0; i < len; i++) {\n if (emitPrologue) {\n // If the list has Strict mode flags, emit prologue after first statement\n // otherwise emit before first statement\n if (i == 1 || !hasFlag(list.flags, ASTFlags.StrictMode)) {\n this.emitPrologue(requiresExtendsBlock);\n emitPrologue = false;\n }\n }\n\n // In some circumstances, class property initializers must be emitted immediately after the 'super' constructor\n // call which, in these cases, must be the first statement in the constructor body\n if (i == 1 && emitClassPropertiesAfterSuperCall) {\n\n // emit any parameter properties first\n var constructorDecl = (<ClassDeclaration>this.thisClassNode).constructorDecl;\n\n if (constructorDecl && constructorDecl.arguments) {\n var argsLen = constructorDecl.arguments.members.length;\n for (var iArg = 0; iArg < argsLen; iArg++) {\n var arg = <BoundDecl>constructorDecl.arguments.members[iArg];\n if ((arg.varFlags & VarFlags.Property) != VarFlags.None) {\n this.emitIndent();\n this.recordSourceMappingStart(arg);\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(\"this.\" + arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeToOutput(\" = \");\n this.recordSourceMappingStart(arg.id);\n this.writeToOutput(arg.id.actualText);\n this.recordSourceMappingEnd(arg.id);\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(arg);\n }\n }\n }\n\n var nProps = (<ASTList>this.thisClassNode.members).members.length;\n\n for (var iMember = 0; iMember < nProps; iMember++) {\n if ((<ASTList>this.thisClassNode.members).members[iMember].nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>(<ASTList>this.thisClassNode.members).members[iMember];\n if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n this.emitIndent();\n this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n this.writeLineToOutput(\"\");\n }\n }\n }\n }\n\n var emitNode = list.members[i];\n\n var isStaticDecl =\n (emitNode.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>emitNode).fncFlags, FncFlags.Static)) ||\n (emitNode.nodeType == NodeType.VarDecl && hasFlag((<VarDecl>emitNode).varFlags, VarFlags.Static))\n\n if (onlyStatics ? !isStaticDecl : isStaticDecl) {\n continue;\n }\n this.emitJavascript(emitNode, tokenId, startLine);\n\n if (delimiter && (i < (len - 1))) {\n if (startLine) {\n this.writeLineToOutput(delimiter);\n }\n else {\n this.writeToOutput(delimiter);\n }\n }\n else if (startLine &&\n (emitNode.nodeType != NodeType.ModuleDeclaration) &&\n (emitNode.nodeType != NodeType.InterfaceDeclaration) &&\n (!((emitNode.nodeType == NodeType.VarDecl) &&\n ((((<VarDecl>emitNode).varFlags) & VarFlags.Ambient) == VarFlags.Ambient) &&\n (((<VarDecl>emitNode).init) == null)) && this.varListCount() >= 0) &&\n (emitNode.nodeType != NodeType.Block || (<Block>emitNode).isStatementBlock) &&\n (emitNode.nodeType != NodeType.EndCode) &&\n (emitNode.nodeType != NodeType.FuncDecl)) {\n this.writeLineToOutput(\"\");\n }\n }\n this.emitParensAndCommentsInPlace(ast, false);\n }\n }\n\n // tokenId is the id the preceding token\n public emitJavascript(ast: AST, tokenId: TokenID, startLine: bool) {\n if (ast == null) {\n return;\n }\n\n // REVIEW: simplify rules for indenting\n if (startLine && (this.indenter.indentAmt > 0) && (ast.nodeType != NodeType.List) &&\n (ast.nodeType != NodeType.Block)) {\n if ((ast.nodeType != NodeType.InterfaceDeclaration) &&\n (!((ast.nodeType == NodeType.VarDecl) &&\n ((((<VarDecl>ast).varFlags) & VarFlags.Ambient) == VarFlags.Ambient) &&\n (((<VarDecl>ast).init) == null)) && this.varListCount() >= 0) &&\n (ast.nodeType != NodeType.EndCode) &&\n ((ast.nodeType != NodeType.FuncDecl) ||\n (this.emitState.container != EmitContainer.Constructor))) {\n this.emitIndent();\n }\n }\n\n ast.emit(this, tokenId, startLine);\n\n if ((tokenId == TokenID.Semicolon) && (ast.nodeType < NodeType.GeneralNode)) {\n this.writeToOutput(\";\");\n }\n }\n\n public emitPropertyAccessor(funcDecl: FuncDecl, className: string, isProto: bool) {\n if (!(<FieldSymbol>funcDecl.accessorSymbol).hasBeenEmitted) {\n var accessorSymbol = <FieldSymbol>funcDecl.accessorSymbol;\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl);\n this.writeLineToOutput(\"Object.defineProperty(\" + className + (isProto ? \".prototype, \\\"\" : \", \\\"\") + funcDecl.name.actualText + \"\\\"\" + \", {\");\n this.indenter.increaseIndent();\n\n if (accessorSymbol.getter) {\n var getter: FuncDecl = <FuncDecl>accessorSymbol.getter.declAST;\n\n this.emitIndent();\n this.recordSourceMappingStart(getter);\n this.writeToOutput(\"get: \");\n this.emitInnerFunction(getter, false, isProto, null, Emitter.shouldCaptureThis(getter), null);\n this.writeLineToOutput(\",\");\n }\n\n if (accessorSymbol.setter) {\n var setter: FuncDecl = <FuncDecl>accessorSymbol.setter.declAST;\n\n this.emitIndent();\n this.recordSourceMappingStart(setter);\n this.writeToOutput(\"set: \");\n this.emitInnerFunction(setter, false, isProto, null, Emitter.shouldCaptureThis(setter), null);\n this.writeLineToOutput(\",\");\n }\n\n this.emitIndent();\n this.writeLineToOutput(\"enumerable: true,\");\n this.emitIndent();\n this.writeLineToOutput(\"configurable: true\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeLineToOutput(\"});\");\n this.recordSourceMappingEnd(funcDecl);\n\n accessorSymbol.hasBeenEmitted = true;\n }\n }\n\n public emitPrototypeMember(member: AST, className: string) {\n if (member.nodeType == NodeType.FuncDecl) {\n var funcDecl = <FuncDecl>member;\n if (funcDecl.isAccessor()) {\n this.emitPropertyAccessor(funcDecl, className, true);\n }\n else {\n this.emitIndent();\n this.recordSourceMappingStart(funcDecl);\n this.writeToOutput(className + \".prototype.\" + funcDecl.getNameText() + \" = \");\n this.emitInnerFunction(funcDecl, false, true, null, Emitter.shouldCaptureThis(funcDecl), null);\n this.writeLineToOutput(\";\");\n }\n }\n else if (member.nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>member;\n\n if (varDecl.init) {\n this.emitIndent();\n this.recordSourceMappingStart(varDecl);\n this.recordSourceMappingStart(varDecl.id);\n this.writeToOutput(className + \".prototype.\" + varDecl.id.actualText);\n this.recordSourceMappingEnd(varDecl.id);\n this.writeToOutput(\" = \");\n this.emitJavascript(varDecl.init, TokenID.Equals, false);\n this.recordSourceMappingEnd(varDecl);\n this.writeLineToOutput(\";\");\n }\n }\n }\n\n public emitAddBaseMethods(className: string, base: Type, classDecl: TypeDeclaration): void {\n if (base.members) {\n var baseSymbol = base.symbol;\n var baseName = baseSymbol.name;\n if (baseSymbol.declModule != classDecl.type.symbol.declModule) {\n baseName = baseSymbol.fullName();\n }\n base.members.allMembers.map(function(key, s, c) {\n var sym = <Symbol>s;\n if ((sym.kind() == SymbolKind.Type) && (<TypeSymbol>sym).type.call) {\n this.recordSourceMappingStart(sym.declAST);\n this.writeLineToOutput(className + \".prototype.\" + sym.name + \" = \" +\n baseName + \".prototype.\" + sym.name + \";\");\n this.recordSourceMappingEnd(sym.declAST);\n }\n }, null);\n }\n if (base.extendsList) {\n for (var i = 0, len = base.extendsList.length; i < len; i++) {\n this.emitAddBaseMethods(className, base.extendsList[i], classDecl);\n }\n }\n }\n\n public emitJavascriptClass(classDecl: ClassDeclaration) {\n if (!hasFlag(classDecl.varFlags, VarFlags.Ambient)) {\n var svClassNode = this.thisClassNode;\n var i = 0;\n this.thisClassNode = classDecl;\n var className = classDecl.name.actualText;\n this.emitParensAndCommentsInPlace(classDecl, true);\n var temp = this.setContainer(EmitContainer.Class);\n\n this.recordSourceMappingStart(classDecl);\n if (hasFlag(classDecl.varFlags, VarFlags.Exported) && classDecl.type.symbol.container == this.checker.gloMod) {\n this.writeToOutput(\"this.\" + className);\n }\n else {\n this.writeToOutput(\"var \" + className);\n }\n\n //if (hasFlag(classDecl.varFlags, VarFlags.Exported) && (temp == EmitContainer.Module || temp == EmitContainer.DynamicModule)) {\n // var modName = temp == EmitContainer.Module ? this.moduleName : \"exports\";\n // this.writeToOutput(\" = \" + modName + \".\" + className);\n //}\n\n var hasBaseClass = classDecl.extendsList && classDecl.extendsList.members.length;\n var baseNameDecl: AST = null;\n var baseName: AST = null;\n\n if (hasBaseClass) {\n this.writeLineToOutput(\" = (function (_super) {\");\n } else {\n this.writeLineToOutput(\" = (function () {\");\n }\n\n this.recordSourceMappingNameStart(className);\n this.indenter.increaseIndent();\n\n if (hasBaseClass) {\n baseNameDecl = classDecl.extendsList.members[0];\n baseName = baseNameDecl.nodeType == NodeType.Call ? (<CallExpression>baseNameDecl).target : baseNameDecl;\n this.emitIndent();\n this.writeLineToOutput(\"__extends(\" + className + \", _super);\");\n }\n\n this.emitIndent();\n\n var constrDecl = classDecl.constructorDecl;\n\n // output constructor\n if (constrDecl) {\n // declared constructor\n this.emitJavascript(classDecl.constructorDecl, TokenID.OpenParen, false);\n\n }\n else {\n var wroteProps = 0;\n\n this.recordSourceMappingStart(classDecl);\n // default constructor\n this.indenter.increaseIndent();\n this.writeToOutput(\"function \" + classDecl.name.actualText + \"() {\");\n this.recordSourceMappingNameStart(\"constructor\");\n if (hasBaseClass) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n this.writeLineToOutput(\"_super.apply(this, arguments);\");\n wroteProps++;\n }\n\n if (classDecl.varFlags & VarFlags.MustCaptureThis) {\n this.writeCaptureThisStatement(classDecl);\n }\n\n var members = (<ASTList>this.thisClassNode.members).members\n\n // output initialized properties\n for (var i = 0; i < members.length; i++) {\n if (members[i].nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>members[i];\n if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n wroteProps++;\n }\n }\n }\n if (wroteProps) {\n this.writeLineToOutput(\"\");\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.writeLineToOutput(\"}\");\n }\n else {\n this.writeLineToOutput(\" }\");\n this.indenter.decreaseIndent();\n }\n this.recordSourceMappingNameEnd();\n this.recordSourceMappingEnd(classDecl);\n }\n\n var membersLen = classDecl.members.members.length;\n for (var j = 0; j < membersLen; j++) {\n\n var memberDecl: AST = classDecl.members.members[j];\n\n if (memberDecl.nodeType == NodeType.FuncDecl) {\n var fn = <FuncDecl>memberDecl;\n\n if (hasFlag(fn.fncFlags, FncFlags.Method) && !fn.isSignature()) {\n if (!hasFlag(fn.fncFlags, FncFlags.Static)) {\n this.emitPrototypeMember(fn, className);\n }\n else { // static functions\n if (fn.isAccessor()) {\n this.emitPropertyAccessor(fn, this.thisClassNode.name.actualText, false);\n }\n else {\n this.emitIndent();\n this.recordSourceMappingStart(fn)\n this.writeToOutput(classDecl.name.actualText + \".\" + fn.name.actualText + \" = \");\n this.emitInnerFunction(fn, (fn.name && !fn.name.isMissing()), true,\n null, Emitter.shouldCaptureThis(fn), null);\n this.writeLineToOutput(\";\");\n }\n }\n }\n }\n else if (memberDecl.nodeType == NodeType.VarDecl) {\n var varDecl = <VarDecl>memberDecl;\n if (hasFlag(varDecl.varFlags, VarFlags.Static)) {\n\n if (varDecl.init) {\n // EMITREVIEW\n this.emitIndent();\n this.recordSourceMappingStart(varDecl);\n this.writeToOutput(classDecl.name.actualText + \".\" + varDecl.id.actualText + \" = \");\n this.emitJavascript(varDecl.init, TokenID.Equals, false);\n // EMITREVIEW\n\n this.writeLineToOutput(\";\");\n this.recordSourceMappingEnd(varDecl);\n }\n }\n }\n else {\n throw Error(\"We want to catch this\");\n }\n }\n\n this.emitIndent();\n this.recordSourceMappingStart(classDecl.endingToken);\n this.writeLineToOutput(\"return \" + className + \";\");\n this.recordSourceMappingEnd(classDecl.endingToken);\n this.indenter.decreaseIndent();\n this.emitIndent();\n this.recordSourceMappingStart(classDecl.endingToken);\n this.writeToOutput(\"}\");\n this.recordSourceMappingNameEnd();\n this.recordSourceMappingEnd(classDecl.endingToken);\n this.recordSourceMappingStart(classDecl);\n this.writeToOutput(\")(\");\n if (hasBaseClass)\n this.emitJavascript(baseName, TokenID.Tilde, false);\n this.writeToOutput(\");\");\n this.recordSourceMappingEnd(classDecl);\n\n if ((temp == EmitContainer.Module || temp == EmitContainer.DynamicModule) && hasFlag(classDecl.varFlags, VarFlags.Exported)) {\n this.writeLineToOutput(\"\");\n this.emitIndent();\n var modName = temp == EmitContainer.Module ? this.moduleName : \"exports\";\n this.recordSourceMappingStart(classDecl);\n this.writeToOutput(modName + \".\" + className + \" = \" + className + \";\");\n this.recordSourceMappingEnd(classDecl);\n }\n\n this.emitIndent();\n this.recordSourceMappingEnd(classDecl);\n this.emitParensAndCommentsInPlace(classDecl, false);\n this.setContainer(temp);\n this.thisClassNode = svClassNode;\n }\n }\n\n public emitPrologue(reqInherits: bool) {\n if (!this.prologueEmitted) {\n if (reqInherits) {\n this.prologueEmitted = true;\n this.writeLineToOutput(\"var __extends = this.__extends || function (d, b) {\");\n this.writeLineToOutput(\" function __() { this.constructor = d; }\");\n this.writeLineToOutput(\" __.prototype = b.prototype;\");\n this.writeLineToOutput(\" d.prototype = new __();\");\n this.writeLineToOutput(\"};\");\n }\n if (this.checker.mustCaptureGlobalThis) {\n this.prologueEmitted = true;\n this.writeLineToOutput(this.captureThisStmtString);\n }\n }\n }\n\n public emitSuperReference() {\n this.writeToOutput(\"_super.prototype\");\n }\n\n public emitSuperCall(callEx: CallExpression): bool {\n if (callEx.target.nodeType == NodeType.Dot) {\n var dotNode = <BinaryExpression>callEx.target;\n if (dotNode.operand1.nodeType == NodeType.Super) {\n this.emitJavascript(dotNode, TokenID.OpenParen, false);\n this.writeToOutput(\".call(\");\n this.emitThis();\n if (callEx.arguments && callEx.arguments.members.length > 0) {\n this.writeToOutput(\", \");\n this.emitJavascriptList(callEx.arguments, \", \", TokenID.Comma, false, false, false);\n }\n this.writeToOutput(\")\");\n return true;\n }\n }\n return false;\n }\n\n public emitThis() {\n if (this.thisFnc && !this.thisFnc.isMethod() && (!this.thisFnc.isConstructor)) {\n this.writeToOutput(\"_this\");\n }\n else {\n this.writeToOutput(\"this\");\n }\n }\n\n private static shouldCaptureThis(func: FuncDecl): bool {\n // Super calls use 'this' reference. If super call is in a lambda, 'this' value needs to be captured in the parent.\n return func.hasSelfReference() || func.hasSuperReferenceInFatArrowFunction();\n }\n\n private createFile(fileName: string, useUTF8: bool): ITextWriter {\n try {\n return this.emitOptions.ioHost.createFile(fileName, useUTF8);\n } catch (ex) {\n this.errorReporter.emitterError(null, ex.message);\n }\n }\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n export interface ILineCol {\n line: number;\n col: number;\n }\n\n export class ErrorReporter {\n public parser: Parser = null;\n public checker: TypeChecker = null;\n public lineCol = { line: 0, col: 0 };\n public emitAsComments = true;\n public hasErrors = false;\n public pushToErrorSink = false;\n public errorSink: string[] = [];\n\n constructor (public outfile: ITextWriter) { }\n\n public getCapturedErrors() { return this.errorSink; }\n public freeCapturedErrors() { this.errorSink = []; }\n public captureError(emsg: string) { this.errorSink[this.errorSink.length] = emsg; }\n\n public setErrOut(outerr) {\n this.outfile = outerr;\n this.emitAsComments = false;\n }\n\n public emitPrefix() {\n if (this.emitAsComments) {\n this.outfile.Write(\"// \");\n }\n this.outfile.Write(this.checker.locationInfo.filename + \"(\" + this.lineCol.line + \",\" + this.lineCol.col + \"): \");\n }\n\n public writePrefix(ast: AST): void {\n if (ast) {\n this.setError(ast);\n }\n else {\n this.lineCol.line = 0;\n this.lineCol.col = 0;\n }\n this.emitPrefix();\n }\n\n public writePrefixFromSym(symbol: Symbol): void {\n if (symbol && this.checker.locationInfo.lineMap) {\n getSourceLineColFromMap(this.lineCol, symbol.location,\n this.checker.locationInfo.lineMap);\n }\n else {\n this.lineCol.line = -1;\n this.lineCol.col = -1;\n }\n this.emitPrefix();\n }\n\n public setError(ast: AST) {\n if (ast) {\n ast.flags |= ASTFlags.Error;\n if (this.checker.locationInfo.lineMap) {\n getSourceLineColFromMap(this.lineCol, ast.minChar, this.checker.locationInfo.lineMap);\n }\n }\n }\n\n public reportError(ast: AST, message: string) {\n if (this.pushToErrorSink) {\n this.captureError(message);\n return;\n }\n\n this.hasErrors = true;\n if (ast && this.parser.errorRecovery && this.parser.errorCallback) {\n var len = (ast.limChar - ast.minChar);\n this.parser.errorCallback(ast.minChar, len, message, this.checker.locationInfo.unitIndex);\n }\n else {\n this.writePrefix(ast);\n this.outfile.WriteLine(message); // Right after the semi-colon\n }\n }\n\n public reportErrorFromSym(symbol: Symbol, message: string) {\n if (this.pushToErrorSink) {\n this.captureError(message);\n return;\n }\n\n this.hasErrors = true;\n if (this.parser.errorRecovery && this.parser.errorCallback) {\n this.parser.errorCallback(symbol.location, symbol.length, message, this.checker.locationInfo.unitIndex);\n }\n else {\n this.writePrefixFromSym(symbol);\n this.outfile.WriteLine(message);\n }\n }\n\n public emitterError(ast: AST, message: string) {\n this.reportError(ast, message);\n // Emitter errors are not recoverable, stop immediately\n throw Error(\"EmitError\");\n }\n\n public duplicateIdentifier(ast: AST, name: string) {\n this.reportError(ast, \"Duplicate identifier '\" + name + \"'\");\n }\n\n public showRef(ast: AST, text: string, symbol: Symbol) {\n var defLineCol = { line: -1, col: -1 };\n // TODO: multiple def locations\n this.parser.getSourceLineCol(defLineCol, symbol.location);\n this.reportError(ast, \"symbol \" + text + \" defined at (\" + defLineCol.line + \",\" +\n defLineCol.col + \")\");\n }\n\n public unresolvedSymbol(ast: AST, name: string) {\n this.reportError(ast, \"The name '\" + name + \"' does not exist in the current scope\");\n }\n\n public symbolDoesNotReferToAValue(ast: AST, name: string): void {\n this.reportError(ast, \"The name '\" + name + \"' does not refer to a value\");\n }\n\n public styleError(ast: AST, msg: string): void {\n var bkThrow = this.pushToErrorSink;\n this.pushToErrorSink = false;\n this.reportError(ast, \"STYLE: \" + msg);\n this.pushToErrorSink = bkThrow;\n }\n\n public simpleError(ast: AST, msg: string): void {\n this.reportError(ast, msg);\n }\n\n public simpleErrorFromSym(sym: Symbol, msg: string): void {\n this.reportErrorFromSym(sym, msg);\n }\n\n public invalidSuperReference(ast: AST) {\n this.simpleError(ast, \"Keyword 'super' can only be used inside a class instance method\");\n }\n\n public valueCannotBeModified(ast: AST) {\n this.simpleError(ast, \"The left-hand side of an assignment expression must be a variable, property or indexer\");\n }\n\n public invalidCall(ast: CallExpression, nodeType: number, scope: SymbolScope): void {\n var targetType = ast.target.type;\n var typeName = targetType.getScopedTypeName(scope);\n if (targetType.construct && (nodeType == NodeType.Call)) {\n this.reportError(ast, \"Value of type '\" + typeName + \"' is not callable. Did you mean to include 'new'?\");\n } else {\n var catString = (nodeType == NodeType.Call) ? \"callable\" : \"newable\";\n\n this.reportError(ast, \"Value of type '\" + typeName + \"' is not \" + catString);\n }\n }\n\n public indexLHS(ast: BinaryExpression, scope: SymbolScope): void {\n var targetType = ast.operand1.type.getScopedTypeName(scope);\n var indexType = ast.operand2.type.getScopedTypeName(scope);\n this.simpleError(ast, \"Value of type '\" + targetType + \"' is not indexable by type '\" + indexType + \"'\");\n }\n\n public incompatibleTypes(ast: AST, t1: Type, t2: Type, op: string, scope: SymbolScope, comparisonInfo?:TypeComparisonInfo) {\n if (!t1) {\n t1 = this.checker.anyType;\n }\n if (!t2) {\n t2 = this.checker.anyType;\n }\n\n var reason = comparisonInfo ? comparisonInfo.message : \"\";\n if (op) {\n this.reportError(ast, \"Operator '\" + op + \"' cannot be applied to types '\" + t1.getScopedTypeName(scope) +\n \"' and '\" + t2.getScopedTypeName(scope) + \"'\" + (reason ? \": \" + reason : \"\"));\n }\n else {\n this.reportError(ast, \"Cannot convert '\" + t1.getScopedTypeName(scope) +\n \"' to '\" + t2.getScopedTypeName(scope) + \"'\" + (reason ? \": \" + reason : \"\"));\n }\n }\n\n public expectedClassOrInterface(ast: AST): void {\n this.simpleError(ast, \"Expected var, class, interface, or module\");\n }\n\n public unaryOperatorTypeError(ast: AST, op: string, type: Type) {\n this.reportError(ast, \"Operator '\" + op + \"' cannot be applied to type '\" + type.getTypeName() + \"'\");\n }\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export function hasFlag(val: number, flag: number) {\n return (val & flag) != 0;\n }\n\n export enum ErrorRecoverySet {\n None = 0,\n Comma = 1, // Comma\n SColon = 1 << 1, // SColon\n Asg = 1 << 2, // Asg\n BinOp = 1 << 3, // Lsh, Rsh, Rs2, Le, Ge, INSTANCEOF, EQ, NE, Eqv, NEqv, LogAnd, LogOr, AsgMul, AsgDiv\n // AsgMod, AsgAdd, AsgSub, AsgLsh, AsgRsh, AsgRs2, AsgAnd, AsgXor, AsgOr, QMark, Mult, Div, \n // Pct, GT, LT, And, Xor, Or\n RBrack = 1 << 4, // RBrack\n RCurly = 1 << 5, // RCurly\n RParen = 1 << 6, // RParen\n Dot = 1 << 7, // Dot\n Colon = 1 << 8, // Colon\n PrimType = 1 << 9, // number, string, bool\n AddOp = 1 << 10, // Add, Sub\n LCurly = 1 << 11, // LCurly\n PreOp = 1 << 12, // Tilde, Bang, Inc, Dec\n RegExp = 1 << 13, // RegExp\n LParen = 1 << 14, // LParen\n LBrack = 1 << 15, // LBrack\n Scope = 1 << 16, // Scope\n In = 1 << 17, // IN\n SCase = 1 << 18, // CASE, DEFAULT\n Else = 1 << 19, // ELSE\n Catch = 1 << 20, // CATCH, FINALLY\n Var = 1 << 21, // \n Stmt = 1 << 22, // BREAK, RETURN, THROW, DEBUGGER, FOR, SWITCH, DO, IF, TRY, WITH\n While = 1 << 23, // WHILE\n ID = 1 << 24, // ID\n Prefix = 1 << 25, // VOID, DELETE, TYPEOF, AWAIT\n Literal = 1 << 26, // IntCon, FltCon, StrCon\n RLit = 1 << 27, // THIS, TRUE, FALSE, NULL\n Func = 1 << 28, // FUNCTION\n EOF = 1 << 29, // EOF\n\n // REVIEW: Name this something clearer.\n TypeScriptS = 1 << 30, // PROPERTY, PRIVATE, STATIC, INTERFACE, CLASS, MODULE, EXPORT, IMPORT\n ExprStart = SColon | AddOp | LCurly | PreOp | RegExp | LParen | LBrack | ID | Prefix | RLit | Func | Literal,\n StmtStart = ExprStart | SColon | Var | Stmt | While | TypeScriptS,\n Postfix = Dot | LParen | LBrack,\n }\n\n export enum AllowedElements {\n None = 0,\n ModuleDeclarations = 1 << 2,\n ClassDeclarations = 1 << 3,\n InterfaceDeclarations = 1 << 4,\n AmbientDeclarations = 1 << 10,\n Properties = 1 << 11,\n\n Global = ModuleDeclarations | ClassDeclarations | InterfaceDeclarations | AmbientDeclarations,\n QuickParse = Global | Properties,\n }\n\n export enum Modifiers {\n None = 0,\n Private = 1,\n Public = 1 << 1,\n Readonly = 1 << 2,\n Ambient = 1 << 3,\n Exported = 1 << 4,\n Getter = 1 << 5,\n Setter = 1 << 6,\n Static = 1 << 7,\n }\n\n export enum ASTFlags {\n None = 0,\n ExplicitSemicolon = 1, // statment terminated by an explicit semicolon\n AutomaticSemicolon = 1 << 1, // statment terminated by an automatic semicolon\n Writeable = 1 << 2, // node is lhs that can be modified\n Error = 1 << 3, // node has an error\n DotLHSPartial = 1 << 4, // node is the lhs of an incomplete dot expr at cursor\n DotLHS = 1 << 5, // node is the lhs of a dot expr\n IsStatement = 1 << 6, // node is a statement\n StrictMode = 1 << 7, // node is in the strict mode environment\n PossibleOptionalParameter = 1 << 8,\n ClassBaseConstructorCall = 1 << 9,\n OptionalName = 1 << 10,\n // REVIEW: This flag is to mark lambda nodes to note that the LParen of an expression has already been matched in the lambda header.\n // The flag is used to communicate this piece of information to the calling parseTerm, which intern will remove it.\n // Once we have a better way to associate information with nodes, this flag should not be used.\n SkipNextRParen = 1 << 11, \n }\n\n export enum DeclFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n }\n\n export enum ModuleFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n IsEnum = 1 << 8,\n ShouldEmitModuleDecl = 1 << 9,\n IsWholeFile = 1 << 10,\n IsDynamic = 1 << 11,\n MustCaptureThis = 1 << 12,\n }\n\n export enum SymbolFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n Property = 1 << 8,\n Readonly = 1 << 9,\n ModuleMember = 1 << 10,\n InterfaceMember = 1 << 11,\n ClassMember = 1 << 12,\n BuiltIn = 1 << 13,\n TypeSetDuringScopeAssignment = 1 << 14,\n Constant = 1 << 15,\n Optional = 1 << 16,\n RecursivelyReferenced = 1 << 17,\n Bound = 1 << 18,\n CompilerGenerated = 1 << 19,\n }\n\n export enum VarFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n AutoInit = 1 << 8,\n Property = 1 << 9,\n Readonly = 1 << 10,\n Class = 1 << 11,\n ClassProperty = 1 << 12,\n ClassBodyProperty = 1 << 13,\n ClassConstructorProperty = 1 << 14,\n ClassSuperMustBeFirstCallInConstructor = 1 << 15,\n Constant = 1 << 16,\n MustCaptureThis = 1 << 17,\n }\n\n export enum FncFlags {\n None = 0,\n Exported = 1,\n Private = 1 << 1,\n Public = 1 << 2,\n Ambient = 1 << 3,\n Static = 1 << 4,\n LocalStatic = 1 << 5,\n GetAccessor = 1 << 6,\n SetAccessor = 1 << 7,\n Definition = 1 << 8,\n Signature = 1 << 9,\n Method = 1 << 10,\n HasReturnExpression = 1 << 11,\n CallMember = 1 << 12,\n ConstructMember = 1 << 13,\n HasSelfReference = 1 << 14,\n IsFatArrowFunction = 1 << 15,\n IndexerMember = 1 << 16,\n IsFunctionExpression = 1 << 17,\n ClassMethod = 1 << 18,\n ClassPropertyMethodExported = 1 << 19,\n HasSuperReferenceInFatArrowFunction = 1 << 20,\n IsPropertyBound = 1 << 21,\n }\n\n export enum SignatureFlags {\n None = 0,\n IsIndexer = 1,\n IsStringIndexer = 1 << 1,\n IsNumberIndexer = 1 << 2,\n }\n\n export function ToDeclFlags(fncFlags: FncFlags) : DeclFlags;\n export function ToDeclFlags(varFlags: VarFlags) : DeclFlags;\n export function ToDeclFlags(symFlags: SymbolFlags): DeclFlags;\n export function ToDeclFlags(moduleFlags: ModuleFlags): DeclFlags;\n export function ToDeclFlags(fncOrVarOrSymbolOrModuleFlags: any) {\n return <DeclFlags>fncOrVarOrSymbolOrModuleFlags;\n }\n\n export enum TypeFlags {\n None = 0,\n HasImplementation = 1,\n HasSelfReference = 1 << 1,\n MergeResult = 1 << 2,\n IsEnum = 1 << 3,\n BuildingName = 1 << 4,\n HasBaseType = 1 << 5,\n HasBaseTypeOfObject = 1 << 6,\n IsClass = 1 << 7,\n }\n\n export enum TypeRelationshipFlags {\n SuccessfulComparison = 0,\n SourceIsNullTargetIsVoidOrUndefined = 1,\n RequiredPropertyIsMissing = 1 << 1,\n IncompatibleSignatures = 1 << 2,\n SourceSignatureHasTooManyParameters = 3,\n IncompatibleReturnTypes = 1 << 4,\n IncompatiblePropertyTypes = 1 << 5,\n IncompatibleParameterTypes = 1 << 6,\n }\n\n export enum CodeGenTarget {\n ES3 = 0,\n ES5 = 1,\n }\n\n export enum ModuleGenTarget {\n Synchronous = 0,\n Asynchronous = 1,\n Local = 1 << 1,\n }\n\n // Compiler defaults to generating ES5-compliant code for\n // - getters and setters\n export var codeGenTarget: CodeGenTarget = CodeGenTarget.ES3;\n\n export var moduleGenTarget: ModuleGenTarget = ModuleGenTarget.Synchronous;\n\n export var optimizeModuleCodeGen = true;\n\n export function flagsToString(e, flags: number): string {\n var builder = \"\";\n for (var i = 1; i < (1 << 31) ; i = i << 1) {\n if ((flags & i) != 0) {\n for (var k in e) {\n if (e[k] == i) {\n if (builder.length > 0) {\n builder += \"|\";\n }\n builder += k;\n break;\n }\n }\n }\n }\n return builder;\n }\n\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export class BlockIntrinsics {\n public prototype = undefined;\n public toString = undefined;\n public toLocaleString = undefined;\n public valueOf = undefined;\n public hasOwnProperty = undefined;\n public propertyIsEnumerable = undefined;\n public isPrototypeOf = undefined;\n\n constructor () {\n // initialize the 'constructor' field\n this[\"constructor\"] = undefined;\n }\n }\n\n export interface IHashTable {\n getAllKeys(): string[];\n add(key: string, data): bool;\n addOrUpdate(key: string, data): bool;\n map(fn: (k: string, v, c) => void , context): void;\n every(fn: (k: string, v, c) => bool, context): bool;\n some(fn: (k: string, v, c) => bool, context): bool;\n count(): number;\n lookup(key: string): any;\n }\n\n export class StringHashTable implements IHashTable {\n public itemCount = 0;\n public table = <any>(<any> new BlockIntrinsics());\n\n public getAllKeys(): string[]{\n var result: string[] = [];\n for (var k in this.table) {\n if (this.table[k] != undefined) {\n result[result.length] = k;\n }\n }\n return result;\n }\n\n public add(key: string, data): bool {\n if (this.table[key] != undefined) {\n return false;\n }\n this.table[key] = data;\n this.itemCount++;\n return true;\n }\n\n public addOrUpdate(key: string, data): bool {\n if (this.table[key] != undefined) {\n this.table[key] = data;\n return false;\n }\n this.table[key] = data;\n this.itemCount++;\n return true;\n }\n\n public map(fn: (k: string, v, c) => void , context) {\n for (var k in this.table) {\n var data = this.table[k];\n if (data != undefined) {\n fn(k, this.table[k], context);\n }\n }\n }\n\n public every(fn: (k: string, v, c) => bool, context) {\n for (var k in this.table) {\n var data = this.table[k];\n if (data != undefined) {\n if (!fn(k, this.table[k], context)) {\n return false;\n }\n }\n }\n return true;\n }\n\n public some(fn: (k: string, v, c) => bool, context) {\n for (var k in this.table) {\n var data = this.table[k];\n if (data != undefined) {\n if (fn(k, this.table[k], context)) {\n return true;\n }\n }\n }\n return false;\n }\n\n public count(): number { return this.itemCount; }\n\n public lookup(key: string) {\n var data = this.table[key];\n if (data != undefined) {\n return data;\n }\n else {\n return (null);\n }\n }\n }\n\n // The resident table is expected to reference the same table object, whereas the \n // transientTable may reference different objects over time\n // REVIEW: WARNING: For performance reasons, neither the primary nor secondary table may be null\n export class DualStringHashTable implements IHashTable {\n\n public insertPrimary = true;\n\n constructor (public primaryTable: IHashTable,\n public secondaryTable: IHashTable) { }\n\n public getAllKeys(): string[]{\n return this.primaryTable.getAllKeys().concat(this.secondaryTable.getAllKeys());\n }\n\n public add(key: string, data): bool {\n if (this.insertPrimary) {\n return this.primaryTable.add(key, data);\n }\n else {\n return this.secondaryTable.add(key, data);\n }\n }\n\n public addOrUpdate(key: string, data): bool {\n if (this.insertPrimary) {\n return this.primaryTable.addOrUpdate(key, data);\n }\n else {\n return this.secondaryTable.addOrUpdate(key, data);\n }\n }\n\n public map(fn: (k: string, v, c) => void , context) {\n this.primaryTable.map(fn, context);\n this.secondaryTable.map(fn, context);\n }\n\n public every(fn: (k: string, v, c) => bool, context) {\n return this.primaryTable.every(fn, context) && this.secondaryTable.every(fn, context);\n }\n\n public some(fn: (k: string, v, c) => bool, context) {\n return this.primaryTable.some(fn, context) || this.secondaryTable.some(fn, context);\n }\n\n public count() {\n return this.primaryTable.count() + this.secondaryTable.count();\n }\n\n public lookup(key: string) {\n var data = this.primaryTable.lookup(key);\n if (data != undefined) {\n return data;\n }\n else {\n return this.secondaryTable.lookup(key);\n }\n }\n }\n\n export function numberHashFn(key: number): number {\n var c2 = 0x27d4eb2d; // a prime or an odd constant\n key = (key ^ 61) ^ (key >>> 16);\n key = key + (key << 3);\n key = key ^ (key >>> 4);\n key = key * c2;\n key = key ^ (key >>> 15);\n return key;\n }\n\n export function combineHashes(key1: number, key2: number) {\n return key2 ^ ((key1 >> 5) + key1);\n }\n\n export class HashEntry {\n public next: HashEntry;\n\n constructor (public key, public data) { }\n }\n\n export class HashTable {\n public itemCount: number = 0;\n public table = new HashEntry[];\n\n constructor (public size: number, public hashFn: (key) =>number,\n public equalsFn: (key1, key2) =>bool) {\n for (var i: number = 0; i < this.size; i++) {\n this.table[i] = null;\n }\n }\n\n public add(key, data): bool {\n var current: HashEntry;\n var entry: HashEntry = new HashEntry(key, data);\n var val: number = this.hashFn(key);\n val = val % this.size;\n\n for (current = this.table[val]; current != null ; current = current.next) {\n if (this.equalsFn(key, current.key)) {\n return false;\n }\n }\n entry.next = this.table[val];\n this.table[val] = entry;\n this.itemCount++;\n return true;\n }\n\n public remove(key) {\n var current: HashEntry;\n var val: number = this.hashFn(key);\n val = val % this.size;\n var result = null;\n var prevEntry: HashEntry = null;\n\n for (current = this.table[val]; current != null ; current = current.next) {\n if (this.equalsFn(key, current.key)) {\n result = current.data;\n this.itemCount--;\n if (prevEntry) {\n prevEntry.next = current.next;\n }\n else {\n this.table[val] = current.next;\n }\n break;\n }\n prevEntry = current;\n }\n return result;\n }\n\n public count(): number { return this.itemCount; }\n\n public lookup(key) {\n var current: HashEntry;\n var val: number = this.hashFn(key);\n val = val % this.size;\n for (current = this.table[val]; current != null ; current = current.next) {\n if (this.equalsFn(key, current.key)) {\n return (current.data);\n }\n }\n return (null);\n }\n }\n\n // Simple Hash table with list of keys and values matching each other at the given index\n export class SimpleHashTable {\n private keys = [];\n private values = [];\n\n public lookup(key, findValue?: bool) {\n var searchArray = this.keys;\n if (findValue) {\n searchArray = this.values;\n }\n\n for (var i = 0; i < searchArray.length; i++) {\n if (searchArray[i] == key) {\n return {\n key: this.keys[i],\n data: this.values[i],\n };\n }\n }\n return null;\n }\n\n public add(key, data): bool {\n var lookupData = this.lookup(key);\n if (lookupData) {\n return false;\n }\n\n this.keys[this.keys.length] = key;\n this.values[this.values.length] = data;\n\n return true;\n }\n }\n\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n export class IncrementalParser {\n \n private astLogger: AstLogger;\n\n constructor (private logger: TypeScript.ILogger) {\n this.astLogger = new AstLogger(this.logger);\n }\n\n //\n // Return \"null\" if \"editRange\" cannot be safely determined to be inside a single scope.\n //\n public getEnclosingScopeContextIfSingleScopeEdit(previousScript: Script, scriptId: string, newSourceText: ISourceText, editRange: ScriptEditRange): EnclosingScopeContext {\n this.logger.log(\"checkEditsInsideSingleScope(\\\"\" + scriptId + \"\\\")\");\n\n if (editRange === null) {\n throw new Error(\"editRange should be valid\");\n }\n\n if (editRange.isUnknown()) {\n this.logger.log(\" Bailing out because edit range is unknown\");\n return null;\n }\n\n var scope1 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.minChar, false/*isMemberCompletion*/);\n var scope2 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.limChar, false/*isMemberCompletion*/);\n if (scope1 == null || scope2 == null) {\n this.logger.log(\" Bailing out because containing scopes cannot be determined\");\n return null;\n }\n\n // We only support changes within a single containing scope\n if (scope1.scopeStartAST !== scope2.scopeStartAST) {\n this.logger.log(\" Bailing out because edit overlaps 2 disctint scopes\");\n return null;\n }\n\n var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;\n if (newScopeLength <= 0) {\n this.logger.log(\" Bailing out because scope has been entirely removed from new source text\");\n return null;\n }\n\n return scope1;\n }\n\n public attemptIncrementalUpdateUnit(previousScript: Script, scriptId: string, newSourceText: ISourceText, editRange: ScriptEditRange): UpdateUnitResult {\n this.logger.log(\"attemptIncrementalUpdateUnit(\\\"\" + scriptId + \"\\\")\");\n\n if (editRange === null) {\n throw new Error(\"editRange should be valid\");\n }\n\n var scope1 = this.getEnclosingScopeContextIfSingleScopeEdit(previousScript, scriptId, newSourceText, editRange);\n if (scope1 === null) {\n return null;\n }\n\n var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;\n\n // Heuristic: if the range to reparse is too big, bail out. \n // This is because a full parse will be faster than an incremental parse followed by all the necessary fix-ups \n if (newScopeLength >= newSourceText.getLength() / 2) {\n this.logger.log(\" Bailing out because range of scope to reparse (\" + newScopeLength + \" characters) is greater than half the size of the source text\");\n return null;\n }\n\n // Capture parsing errors so that they are part of \"updateResult\"\n var parseErrors: TypeScript.ErrorEntry[] = [];\n var errorCapture = function(minChar: number, charLen: number, message: string, unitIndex: number): void {\n parseErrors.push(new TypeScript.ErrorEntry(unitIndex, minChar, minChar + charLen, message));\n };\n\n var quickParseResult = TypeScript.quickParse(this.logger, scope1.scopeStartAST, newSourceText, scope1.scopeStartAST.minChar, scope1.scopeStartAST.minChar + newScopeLength, errorCapture);\n if (quickParseResult.endLexState != TypeScript.LexState.Start) {\n this.logger.log(\" Bailing out because scope contains unterminated comment\");\n return null;\n }\n\n var scriptFragment = quickParseResult.Script;\n if (scriptFragment.vars.members.length !== 0) {\n this.logger.log(\" Bailing out because new source text defines variables\");\n return null;\n }\n\n //if (scriptFragment.scopes.members.length !== 1) {\n // logger.log(\" Bailing out because new source text defines more than one scope (or none)\");\n // return null;\n //}\n\n // This detects adding close curlies, since they have the side effect of having the parser \n // parse more members in the scope range.\n if (scriptFragment.bod.members.length !== 1) {\n this.logger.log(\" Bailing out because new source text defines more than one scope (or none)\");\n return null;\n }\n\n var oldScope = scope1.scopeStartAST;\n var newScope = scriptFragment.bod.members[0];\n\n if (oldScope.nodeType != newScope.nodeType) {\n this.logger.log(\" Bailing out because new source text does not define the same scope type as the existing scope\");\n return null;\n }\n\n if (!(<any>oldScope).leftCurlyCount || !(<any>oldScope).rightCurlyCount) {\n this.logger.log(\" Bailing out because sopce doesn't have left/right curly count\");\n return null;\n }\n\n if ((<any>oldScope).leftCurlyCount !== (<any>newScope).leftCurlyCount) {\n this.logger.log(\" Bailing out because new source text contains more (or fewer) left curly braces\");\n return null;\n }\n\n if ((<any>oldScope).rightCurlyCount !== (<any>newScope).rightCurlyCount) {\n this.logger.log(\" Bailing out because new source text contains more (or fewer) right curly braces\");\n return null;\n }\n\n if (newScope.minChar !== 0) {\n this.logger.log(\" Bailing out because new function declaration does not start at position 0\");\n return null;\n }\n\n if (newScope.limChar !== newScopeLength) {\n this.logger.log(\" Bailing out because new function declaration does not end at the new end position\");\n return null;\n }\n\n return TypeScript.UpdateUnitResult.singleScopeEdits(previousScript, scriptFragment, oldScope, newScope, editRange, parseErrors);\n }\n\n public mergeTrees(updateResult: UpdateUnitResult): void {\n TypeScript.timeFunction(this.logger, \"mergeTrees()\", () => {\n var editRange = new ScriptEditRange(updateResult.scope1.minChar, updateResult.scope1.limChar, updateResult.editRange.delta);\n // Update positions in current ast\n this.applyDeltaPosition(updateResult.script1, editRange.limChar, editRange.delta);\n // Update positions in new (partial) ast\n this.applyDeltaPosition(updateResult.script2, 0, editRange.minChar);\n // Merge linemaps\n this.mergeLocationInfo(updateResult.script1, updateResult.script2, editRange);\n // Replace old AST for scope with new one\n this.replaceAST(updateResult.script1, updateResult.scope1, updateResult.scope2);\n });\n }\n\n private replaceAST(script: TypeScript.AST, oldAst: TypeScript.AST, newAst: TypeScript.AST) {\n var pre = (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) => {\n if (cur === oldAst) {\n // Transfer comments ownership to new AST. We need this because when \"quick parsing\" the\n // new AST, we don't take into account the text before and after the \"minChar/limChar\" pair\n // of the scope, which don't include pre/post-comments.\n newAst.preComments = cur.preComments;\n newAst.postComments = cur.postComments;\n\n this.logger.log(\"replaced old AST node with new one in script AST\");\n walker.options.stopWalk();\n return newAst;\n }\n\n // Avoid visiting sub-trees outside of the edit range\n if (TypeScript.isValidAstNode(cur)) {\n if (cur.limChar < oldAst.minChar || cur.minChar > oldAst.limChar) {\n walker.options.goChildren = false;\n }\n }\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(script, pre);\n }\n\n private mergeLocationInfo(script: TypeScript.Script, partial: TypeScript.Script, editRange: ScriptEditRange) {\n // Don't merger these fields, as the original script has the right values\n //script.locationInfo.unitIndex = partial.locationInfo.unitIndex;\n //script.locationInfo.filename = partial.locationInfo.filename;\n\n var lineMap1 = script.locationInfo.lineMap;\n var lineMap2 = partial.locationInfo.lineMap;\n\n if (this.logger.information()) {\n this.logger.log(\"lineMap1 (before):\");\n this.astLogger.logLinemap(lineMap1);\n this.logger.log(\"lineMap2 (quick parse):\");\n this.astLogger.logLinemap(lineMap2);\n this.logger.log(\"EditRange=\" + editRange);\n }\n\n // Skip entries < minChar\n var i1 = 2; // lineMap[0] is always undefined, lineMap[1] is always 0.\n var i2 = 2; // lineMap[0] is always undefined, lineMap[1] is always 0.\n var len1 = lineMap1.length;\n var len2 = lineMap2.length;\n while (i1 < len1) {\n if (lineMap1[i1] <= editRange.minChar) {\n // Nothing to do for this entry, since it's before the range of the change\n i1++;\n } else if (lineMap1[i1] >= editRange.limChar) {\n // Apply delta to this entry, since it's outside the range of the change\n lineMap1[i1] += editRange.delta;\n i1++;\n }\n else {\n if (i2 < len2) {\n // Add a new entry to lineMap1 corresponding to lineMap2 in new range\n lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);\n i1++;\n len1++;\n i2++;\n }\n else { /* i2 >= len 2 */\n // Remove this entry, since there is no corresponding entry in the new map\n lineMap1.splice(i1, 1);\n len1--;\n }\n }\n }\n // Merge the remaining entries in lineMap2 while maintaing the constraint that a lineMap is sorted\n if (i2 < len2) {\n // i1 >= len1 && i2 < len2 \n if (lineMap1[len1 - 1] >= (lineMap2[i2] + editRange.minChar)) {\n // lineMap2 needs to be merged within lineMap1\n i1 = 2;\n while (i1 < len1 && i2 < len2) {\n if (lineMap1[i1] < (lineMap2[i2] + editRange.minChar)) {\n i1++;\n }\n else {\n lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);\n i1++;\n len1++;\n i2++;\n }\n }\n }\n\n // Append all the remaining entries in lineMap2 to the end of lineMap1\n for (; i2 < len2; i2++) {\n lineMap1.push(lineMap2[i2] + editRange.minChar);\n }\n }\n\n if (this.logger.information()) {\n this.logger.log(\"lineMap1 (after merge):\");\n this.astLogger.logLinemap(lineMap1);\n }\n }\n\n private applyDeltaPosition(ast: TypeScript.AST, start: number, delta: number) {\n var applyDelta = (ast: TypeScript.AST) => {\n if (ast.minChar !== -1 && ast.minChar >= start) {\n ast.minChar += delta;\n }\n if (ast.limChar !== -1 && ast.limChar >= start) {\n ast.limChar += delta;\n }\n }\n\n var applyDeltaToComments = (comments: TypeScript.Comment[]) => {\n if (comments && comments.length > 0) {\n for (var i = 0; i < comments.length; i++) {\n applyDelta(comments[i]);\n }\n }\n }\n\n var pre = function(cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n // *Before* applying delta to this, check if we need to go to children\n if (cur.limChar !== -1 && cur.limChar < start) {\n walker.options.goChildren = false; // Done with applying Delta for this sub-tree\n }\n\n // Apply delta to this node\n applyDelta(cur);\n applyDeltaToComments(cur.preComments);\n applyDeltaToComments(cur.postComments);\n\n return cur;\n }\n\n TypeScript.getAstWalkerFactory().walk(ast, pre);\n }\n }\n}\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\ninterface IResolvedFile {\n content: string;\n path: string;\n}\n\ninterface IFileWatcher {\n close(): void;\n}\n\ninterface IIO {\n readFile(path: string): string;\n writeFile(path: string, contents: string): void;\n createFile(path: string, useUTF8?: bool): ITextWriter;\n deleteFile(path: string): void;\n dir(path: string, re?: RegExp, options?: { recursive?: bool; }): string[];\n fileExists(path: string): bool;\n directoryExists(path: string): bool;\n createDirectory(path: string): void;\n resolvePath(path: string): string;\n dirName(path: string): string;\n findFile(rootPath: string, partialFilePath: string): IResolvedFile;\n print(str: string): void;\n printLine(str: string): void;\n arguments: string[];\n stderr: ITextWriter;\n stdout: ITextWriter;\n watchFile(filename: string, callback: (string) => void ): IFileWatcher;\n run(source: string, filename: string): void;\n getExecutingFilePath(): string;\n quit(exitCode?: number);\n}\n\nmodule IOUtils {\n // Creates the directory including its parent if not already present\n function createDirectoryStructure(ioHost: IIO, dirName: string) {\n if (ioHost.directoryExists(dirName)) {\n return;\n }\n\n var parentDirectory = ioHost.dirName(dirName);\n if (parentDirectory != \"\") {\n createDirectoryStructure(ioHost, parentDirectory);\n }\n ioHost.createDirectory(dirName);\n }\n\n // Creates a file including its directory structure if not already present\n export function createFileAndFolderStructure(ioHost: IIO, fileName: string, useUTF8?: bool) {\n var path = ioHost.resolvePath(fileName);\n var dirName = ioHost.dirName(path);\n createDirectoryStructure(ioHost, dirName);\n return ioHost.createFile(path, useUTF8);\n }\n\n export function throwIOError(message: string, error: Error) {\n var errorMessage = message;\n if (error && error.message) {\n errorMessage += (\" \" + error.message);\n }\n throw new Error(errorMessage);\n }\n}\n\n// Declare dependencies needed for all supported hosts\ndeclare class Enumerator {\n public atEnd(): bool;\n public moveNext();\n public item(): any;\n constructor (o: any);\n}\ndeclare function setTimeout(callback: () =>void , ms?: number);\ndeclare var require: any;\ndeclare module process {\n export var argv: string[];\n export var platform: string;\n export function on(event: string, handler: (any) => void ): void;\n export module stdout {\n export function write(str: string);\n }\n export module stderr {\n export function write(str: string);\n }\n export module mainModule {\n export var filename: string;\n }\n export function exit(exitCode?: number);\n}\n\nvar IO = (function() {\n\n // Create an IO object for use inside WindowsScriptHost hosts\n // Depends on WSCript and FileSystemObject\n function getWindowsScriptHostIO(): IIO {\n var fso = new ActiveXObject(\"Scripting.FileSystemObject\");\n var streamObjectPool = [];\n\n function getStreamObject(): any { \n if (streamObjectPool.length > 0) {\n return streamObjectPool.pop();\n } else {\n return new ActiveXObject(\"ADODB.Stream\");\n }\n }\n\n function releaseStreamObject(obj: any) { \n streamObjectPool.push(obj);\n }\n\n var args = [];\n for (var i = 0; i < WScript.Arguments.length; i++) {\n args[i] = WScript.Arguments.Item(i);\n }\n\n return {\n readFile: function(path) {\n try {\n var streamObj = getStreamObject();\n streamObj.Open();\n streamObj.Type = 2; // Text data\n streamObj.Charset = 'x-ansi'; // Assume we are reading ansi text\n streamObj.LoadFromFile(path);\n var bomChar = streamObj.ReadText(2); // Read the BOM char\n streamObj.Position = 0; // Position has to be at 0 before changing the encoding\n if ((bomChar.charCodeAt(0) == 0xFE && bomChar.charCodeAt(1) == 0xFF)\n || (bomChar.charCodeAt(0) == 0xFF && bomChar.charCodeAt(1) == 0xFE)) {\n streamObj.Charset = 'unicode';\n } else if (bomChar.charCodeAt(0) == 0xEF && bomChar.charCodeAt(1) == 0xBB) {\n streamObj.Charset = 'utf-8'; \n }\n\n // Read the whole file\n var str = streamObj.ReadText(-1 /* read from the current position to EOS */);\n streamObj.Close();\n releaseStreamObject(streamObj);\n return <string>str;\n }\n catch (err) {\n IOUtils.throwIOError(\"Error reading file \\\"\" + path + \"\\\".\", err);\n }\n },\n\n writeFile: function(path, contents) {\n var file = this.createFile(path);\n file.Write(contents);\n file.Close();\n },\n\n fileExists: function(path: string): bool {\n return fso.FileExists(path);\n },\n\n resolvePath: function(path: string): string {\n return fso.GetAbsolutePathName(path);\n },\n\n dirName: function(path: string): string {\n return fso.GetParentFolderName(path);\n },\n\n findFile: function(rootPath: string, partialFilePath: string): IResolvedFile {\n var path = fso.GetAbsolutePathName(rootPath) + \"/\" + partialFilePath;\n\n while (true) {\n if (fso.FileExists(path)) {\n try {\n var content = this.readFile(path);\n return { content: content, path: path };\n }\n catch (err) {\n //Tools.CompilerDiagnostics.debugPrint(\"Could not find \" + path + \", trying parent\");\n }\n }\n else {\n rootPath = fso.GetParentFolderName(fso.GetAbsolutePathName(rootPath));\n\n if (rootPath == \"\") {\n return null;\n }\n else {\n path = fso.BuildPath(rootPath, partialFilePath);\n }\n }\n }\n },\n\n deleteFile: function(path: string): void {\n try {\n if (fso.FileExists(path)) {\n fso.DeleteFile(path, true); // true: delete read-only files\n }\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't delete file '\" + path + \"'.\", e);\n }\n },\n\n createFile: function (path, useUTF8?) {\n try {\n var streamObj = getStreamObject();\n streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi';\n streamObj.Open();\n return {\n Write: function (str) { streamObj.WriteText(str, 0); },\n WriteLine: function (str) { streamObj.WriteText(str, 1); },\n Close: function() {\n try {\n streamObj.SaveToFile(path, 2);\n } catch (saveError) {\n IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", saveError);\n }\n finally {\n if (streamObj.State != 0 /*adStateClosed*/) {\n streamObj.Close();\n }\n releaseStreamObject(streamObj);\n }\n }\n };\n } catch (creationError) {\n IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", creationError);\n }\n },\n\n directoryExists: function(path) {\n return <bool>fso.FolderExists(path);\n },\n\n createDirectory: function(path) {\n try {\n if (!this.directoryExists(path)) {\n fso.CreateFolder(path);\n }\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't create directory '\" + path + \"'.\", e);\n }\n },\n\n dir: function(path, spec?, options?) {\n options = options || <{ recursive?: bool; }>{};\n function filesInFolder(folder, root): string[]{\n var paths = [];\n var fc: Enumerator;\n\n if (options.recursive) {\n fc = new Enumerator(folder.subfolders);\n\n for (; !fc.atEnd() ; fc.moveNext()) {\n paths = paths.concat(filesInFolder(fc.item(), root + \"/\" + fc.item().Name));\n }\n }\n\n fc = new Enumerator(folder.files);\n\n for (; !fc.atEnd() ; fc.moveNext()) {\n if (!spec || fc.item().Name.match(spec)) {\n paths.push(root + \"/\" + fc.item().Name);\n }\n }\n\n return paths;\n }\n\n var folder = fso.GetFolder(path);\n var paths = [];\n\n return filesInFolder(folder, path);\n },\n\n print: function(str) {\n WScript.StdOut.Write(str);\n },\n\n printLine: function(str) {\n WScript.Echo(str);\n },\n\n arguments: <string[]>args,\n stderr: WScript.StdErr,\n stdout: WScript.StdOut,\n watchFile: null,\n run: function(source, filename) {\n try {\n eval(source);\n } catch (e) {\n IOUtils.throwIOError(\"Error while executing file '\" + filename + \"'.\", e);\n }\n },\n getExecutingFilePath: function () {\n return WScript.ScriptFullName;\n },\n quit: function (exitCode? : number = 0) {\n try {\n WScript.Quit(exitCode);\n } catch (e) {\n }\n }\n }\n\n };\n\n // Create an IO object for use inside Node.js hosts\n // Depends on 'fs' and 'path' modules\n function getNodeIO(): IIO {\n\n var _fs = require('fs');\n var _path = require('path');\n var _module = require('module');\n\n return {\n readFile: function(file) {\n try {\n var buffer = _fs.readFileSync(file);\n switch (buffer[0]) {\n case 0xFE:\n if (buffer[1] == 0xFF) {\n // utf16-be. Reading the buffer as big endian is not supported, so convert it to \n // Little Endian first\n var i = 0;\n while ((i + 1) < buffer.length) {\n var temp = buffer[i]\n buffer[i] = buffer[i + 1];\n buffer[i + 1] = temp;\n i += 2;\n }\n return buffer.toString(\"ucs2\", 2);\n }\n break;\n case 0xFF:\n if (buffer[1] == 0xFE) {\n // utf16-le \n return buffer.toString(\"ucs2\", 2);\n }\n break;\n case 0xEF:\n if (buffer[1] == 0xBB) {\n // utf-8\n return buffer.toString(\"utf8\", 3);\n }\n }\n // Default behaviour\n return buffer.toString();\n } catch (e) {\n IOUtils.throwIOError(\"Error reading file \\\"\" + file + \"\\\".\", e);\n }\n },\n writeFile: <(path: string, contents: string) => void >_fs.writeFileSync,\n deleteFile: function(path) {\n try {\n _fs.unlinkSync(path);\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't delete file '\" + path + \"'.\", e);\n }\n },\n fileExists: function(path): bool {\n return _fs.existsSync(path);\n },\n createFile: function(path, useUTF8?) {\n function mkdirRecursiveSync(path) {\n var stats = _fs.statSync(path);\n if (stats.isFile()) {\n IOUtils.throwIOError(\"\\\"\" + path + \"\\\" exists but isn't a directory.\", null);\n } else if (stats.isDirectory()) {\n return;\n } else {\n mkdirRecursiveSync(_path.dirname(path));\n _fs.mkdirSync(path, 0775);\n }\n }\n\n mkdirRecursiveSync(_path.dirname(path));\n\n try {\n var fd = _fs.openSync(path, 'w');\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", e);\n }\n return {\n Write: function(str) { _fs.writeSync(fd, str); },\n WriteLine: function(str) { _fs.writeSync(fd, str + '\\r\\n'); },\n Close: function() { _fs.closeSync(fd); fd = null; }\n };\n },\n dir: function dir(path, spec?, options?) {\n options = options || <{ recursive?: bool; }>{};\n\n function filesInFolder(folder: string): string[]{\n var paths = [];\n\n var files = _fs.readdirSync(folder);\n for (var i = 0; i < files.length; i++) {\n var stat = _fs.statSync(folder + \"/\" + files[i]);\n if (options.recursive && stat.isDirectory()) {\n paths = paths.concat(filesInFolder(folder + \"/\" + files[i]));\n } else if (stat.isFile() && (!spec || files[i].match(spec))) {\n paths.push(folder + \"/\" + files[i]);\n }\n }\n\n return paths;\n }\n\n return filesInFolder(path);\n },\n createDirectory: function(path: string): void {\n try {\n if (!this.directoryExists(path)) {\n _fs.mkdirSync(path);\n }\n } catch (e) {\n IOUtils.throwIOError(\"Couldn't create directory '\" + path + \"'.\", e);\n }\n },\n\n directoryExists: function(path: string): bool {\n return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory();\n },\n resolvePath: function(path: string): string {\n return _path.resolve(path);\n },\n dirName: function(path: string): string {\n return _path.dirname(path);\n },\n findFile: function(rootPath: string, partialFilePath): IResolvedFile {\n var path = rootPath + \"/\" + partialFilePath;\n\n while (true) {\n if (_fs.existsSync(path)) {\n try {\n var content = this.readFile(path);\n return { content: content, path: path };\n } catch (err) {\n //Tools.CompilerDiagnostics.debugPrint((\"Could not find \" + path) + \", trying parent\");\n }\n }\n else {\n var parentPath = _path.resolve(rootPath, \"..\");\n\n // Node will just continue to repeat the root path, rather than return null\n if (rootPath === parentPath) {\n return null;\n }\n else {\n rootPath = parentPath;\n path = _path.resolve(rootPath, partialFilePath);\n }\n }\n }\n },\n print: function(str) { process.stdout.write(str) },\n printLine: function(str) { process.stdout.write(str + '\\n') },\n arguments: process.argv.slice(2),\n stderr: {\n Write: function(str) { process.stderr.write(str); },\n WriteLine: function(str) { process.stderr.write(str + '\\n'); },\n Close: function() { }\n },\n stdout: {\n Write: function(str) { process.stdout.write(str); },\n WriteLine: function(str) { process.stdout.write(str + '\\n'); },\n Close: function() { }\n },\n watchFile: function(filename: string, callback: (string) => void ): IFileWatcher {\n var firstRun = true;\n var processingChange = false;\n\n var fileChanged: any = function(curr, prev) {\n if (!firstRun) {\n if (curr.mtime < prev.mtime) {\n return;\n }\n\n _fs.unwatchFile(filename, fileChanged);\n if (!processingChange) {\n processingChange = true;\n callback(filename);\n setTimeout(function() { processingChange = false; }, 100);\n }\n }\n firstRun = false;\n _fs.watchFile(filename, { persistent: true, interval: 500 }, fileChanged);\n };\n\n fileChanged();\n return {\n filename: filename,\n close: function() {\n _fs.unwatchFile(filename, fileChanged);\n }\n };\n },\n run: function(source, filename) {\n require.main.filename = filename;\n require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename)));\n require.main._compile(source, filename);\n }, \n getExecutingFilePath: function () {\n return process.mainModule.filename;\n },\n quit: process.exit\n }\n };\n\n if (typeof ActiveXObject === \"function\")\n return getWindowsScriptHostIO();\n else if (typeof require === \"function\")\n return getNodeIO();\n else\n return null; // Unsupported host\n})();\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n // Note: Any addition to the NodeType should also be supported with addition to AstWalkerDetailCallback\n export enum NodeType {\n None,\n Empty,\n EmptyExpr,\n True,\n False,\n This,\n Super,\n QString,\n Regex,\n Null,\n ArrayLit,\n ObjectLit,\n Void,\n Comma,\n Pos,\n Neg,\n Delete,\n Await,\n In,\n Dot,\n From,\n Is,\n InstOf,\n Typeof,\n NumberLit,\n Name,\n TypeRef,\n Index,\n Call,\n New,\n Asg,\n AsgAdd,\n AsgSub,\n AsgDiv,\n AsgMul,\n AsgMod,\n AsgAnd,\n AsgXor,\n AsgOr,\n AsgLsh,\n AsgRsh,\n AsgRs2,\n ConditionalExpression,\n LogOr,\n LogAnd,\n Or,\n Xor,\n And,\n Eq,\n Ne,\n Eqv,\n NEqv,\n Lt,\n Le,\n Gt,\n Ge,\n Add,\n Sub,\n Mul,\n Div,\n Mod,\n Lsh,\n Rsh,\n Rs2,\n Not,\n LogNot,\n IncPre,\n DecPre,\n IncPost,\n DecPost,\n TypeAssertion,\n FuncDecl,\n Member,\n VarDecl,\n ArgDecl,\n Return,\n Break,\n Continue,\n Throw,\n For,\n ForIn,\n If,\n While,\n DoWhile,\n Block,\n Case,\n Switch,\n Try,\n TryCatch,\n TryFinally,\n Finally,\n Catch,\n List,\n Script,\n ClassDeclaration,\n InterfaceDeclaration,\n ModuleDeclaration,\n ImportDeclaration,\n With,\n Label,\n LabeledStatement,\n EBStart,\n GotoEB,\n EndCode,\n Error,\n Comment,\n Debugger,\n GeneralNode = FuncDecl,\n LastAsg = AsgRs2,\n }\n}//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path=\"io.ts\" />\n\ninterface IOptions {\n name?: string;\n flag?: bool;\n short?: string;\n usage?: string;\n set?: (s: string) => void;\n type?: string;\n experimental?: bool;\n}\n\nclass OptionsParser {\n private DEFAULT_SHORT_FLAG = \"-\";\n private DEFAULT_LONG_FLAG = \"--\";\n\n // Find the option record for the given string. Returns null if not found.\n private findOption(arg: string) {\n\n for (var i = 0; i < this.options.length; i++) {\n\n if (arg === this.options[i].short || arg === this.options[i].name) {\n return this.options[i];\n }\n }\n\n return null;\n }\n\n public unnamed: string[] = [];\n\n public options: IOptions[] = [];\n\n constructor (public host: IIO) {\n }\n\n public printUsage() {\n this.host.printLine(\"Syntax: tsc [options] [file ..]\");\n this.host.printLine(\"\");\n this.host.printLine(\"Examples: tsc hello.ts\");\n this.host.printLine(\" tsc --out foo.js foo.ts\");\n this.host.printLine(\" tsc @args.txt\");\n this.host.printLine(\"\");\n this.host.printLine(\"Options:\");\n\n var output = [];\n var maxLength = 0;\n\n this.options = this.options.sort(function(a, b) {\n var aName = a.name.toLowerCase();\n var bName = b.name.toLowerCase();\n\n if (aName > bName) {\n return 1;\n } else if (aName < bName) {\n return -1;\n } else {\n return 0;\n }\n });\n\n // Build up output array\n for (var i = 0; i < this.options.length; i++) {\n var option = this.options[i];\n\n if (option.experimental) {\n continue;\n }\n\n if (!option.usage) {\n break;\n }\n\n var usageString = \" \";\n var type = option.type ? \" \" + option.type.toUpperCase() : \"\";\n\n if (option.short) {\n usageString += this.DEFAULT_SHORT_FLAG + option.short + type + \", \";\n }\n\n usageString += this.DEFAULT_LONG_FLAG + option.name + type;\n\n output.push([usageString, option.usage]);\n\n if (usageString.length > maxLength) {\n maxLength = usageString.length;\n }\n }\n\n output.push([\" @<file>\", \"Insert command line options and files from a file.\"]);\n\n // Print padded output\n for (var i = 0; i < output.length; i++) {\n this.host.printLine(output[i][0] + (new Array(maxLength - output[i][0].length + 3)).join(\" \") + output[i][1]);\n }\n }\n\n public option(name: string, config: IOptions, short?: string) {\n if (!config) {\n config = <any>short;\n short = null;\n }\n\n config.name = name;\n config.short = short;\n config.flag = false;\n\n this.options.push(config);\n }\n\n public flag(name: string, config: IOptions, short?: string) {\n if (!config) {\n config = <any>short;\n short = null;\n }\n\n config.name = name;\n config.short = short;\n config.flag = true\n\n this.options.push(config);\n }\n\n // Parse an arguments string\n public parseString(argString: string) {\n&nbs