diff --git a/Gruntfile.js b/Gruntfile.js
index 72307c001..7070a514d 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -9,7 +9,7 @@ module.exports = function (grunt) {
                 target: 'es5',
                 module: 'commonjs',
                 sourceMap: false,
-                preserveConstEnums: false,
+                preserveConstEnums: true,
                 compiler: './node_modules/typescript/bin/tsc'
             },
             dev: {
diff --git a/dist/globals.js b/dist/globals.js
index d3812f64a..8e7b82c4a 100644
--- a/dist/globals.js
+++ b/dist/globals.js
@@ -1,6 +1,4 @@
 /// <reference path="./typings/tsd.d.ts"/>
-/// <reference path="../node_modules/typescript/bin/typescript.d.ts"/>
-/// <reference path="../node_modules/typescript/bin/typescript_internal.d.ts"/>
 /// <reference path="./typings/bluebird.d.ts"/>
 /// <reference path="./typings/codemirror.d.ts"/>
 /// <reference path="./typings/brackets.d.ts"/>
diff --git a/dist/linter.js b/dist/linter.js
index 638b20e8c..f09c2441c 100644
--- a/dist/linter.js
+++ b/dist/linter.js
@@ -1,5 +1,8 @@
 // This file is only called from linter
 // See : https://github.com/AtomLinter/Linter/issues/337
+/// <reference path="./globals.ts"/> ///ts:ref:generated
+var makeTypeScriptGlobal_1 = require("./typescript/makeTypeScriptGlobal");
+makeTypeScriptGlobal_1.makeTsGlobal();
 var parent = require('./worker/parent');
 var fs = require('fs');
 var linterPath = atom.packages.getLoadedPackage("linter").path;
diff --git a/dist/main/atom/typescriptGrammar.js b/dist/main/atom/typescriptGrammar.js
index 92495a9a4..f1b6e4dc2 100644
--- a/dist/main/atom/typescriptGrammar.js
+++ b/dist/main/atom/typescriptGrammar.js
@@ -6,7 +6,6 @@ var __extends = this.__extends || function (d, b) {
     __.prototype = b.prototype;
     d.prototype = new __();
 };
-var ts = require('typescript');
 var TokenClass = ts.TokenClass;
 global.AtomTSBaseGrammar = require(atom.config.resourcePath + "/node_modules/first-mate/lib/grammar.js");
 var TypeScriptSemanticGrammar = (function (_super) {
diff --git a/dist/main/atomts.js b/dist/main/atomts.js
index 3aa894d5d..8451176e3 100644
--- a/dist/main/atomts.js
+++ b/dist/main/atomts.js
@@ -1,5 +1,7 @@
 ///ts:ref=globals
 /// <reference path="../globals.ts"/> ///ts:ref:generated
+var makeTypeScriptGlobal_1 = require("../typescript/makeTypeScriptGlobal");
+makeTypeScriptGlobal_1.makeTsGlobal();
 var path = require('path');
 var fs = require('fs');
 var apd = require('atom-package-dependencies');
diff --git a/dist/main/lang/core/languageServiceHost2.js b/dist/main/lang/core/languageServiceHost2.js
index 73e65a01a..41b8f6a59 100644
--- a/dist/main/lang/core/languageServiceHost2.js
+++ b/dist/main/lang/core/languageServiceHost2.js
@@ -1,4 +1,3 @@
-var ts = require('typescript');
 var path = require('path');
 var fs = require('fs');
 var textBuffer = require('basarat-text-buffer');
diff --git a/dist/main/lang/core/project.js b/dist/main/lang/core/project.js
index ba85ac2f8..fd0ee7481 100644
--- a/dist/main/lang/core/project.js
+++ b/dist/main/lang/core/project.js
@@ -1,6 +1,5 @@
 ///ts:ref=globals
 /// <reference path="../../../globals.ts"/> ///ts:ref:generated
-var ts = require('typescript');
 exports.languageServiceHost = require('./languageServiceHost2');
 var Project = (function () {
     function Project(projectFile) {
diff --git a/dist/main/lang/fixmyts/addClassMember.js b/dist/main/lang/fixmyts/addClassMember.js
index 870ae7cbf..cb71e203d 100644
--- a/dist/main/lang/fixmyts/addClassMember.js
+++ b/dist/main/lang/fixmyts/addClassMember.js
@@ -1,7 +1,5 @@
-var ts = require("typescript");
 var ast = require("./astUtils");
 var os_1 = require("os");
-var typescript_1 = require("typescript");
 function getIdentifierAndClassNames(error) {
     var errorText = error.messageText;
     if (typeof errorText !== 'string') {
@@ -42,7 +40,7 @@ var AddClassMember = (function () {
             && parentOfParent.operatorToken.getText().trim() == '=') {
             var binaryExpression = parentOfParent;
             var type = info.typeChecker.getTypeAtLocation(binaryExpression.right);
-            typeString = typescript_1.displayPartsToString(typescript_1.typeToDisplayParts(info.typeChecker, type)).replace(/\s+/g, ' ');
+            typeString = ts.displayPartsToString(ts.typeToDisplayParts(info.typeChecker, type)).replace(/\s+/g, ' ');
         }
         var memberTarget = ast.getNodeByKindAndName(info.program, 201, className);
         if (!memberTarget) {
diff --git a/dist/main/lang/fixmyts/astUtils.js b/dist/main/lang/fixmyts/astUtils.js
index e5888780f..06866d9eb 100644
--- a/dist/main/lang/fixmyts/astUtils.js
+++ b/dist/main/lang/fixmyts/astUtils.js
@@ -1,4 +1,3 @@
-var ts = require("typescript");
 exports.forEachChild = ts.forEachChild;
 function forEachChildRecursive(node, cbNode, depth) {
     if (depth === void 0) { depth = 0; }
diff --git a/dist/main/lang/modules/astToText.js b/dist/main/lang/modules/astToText.js
index 54e436d17..b563bfe30 100644
--- a/dist/main/lang/modules/astToText.js
+++ b/dist/main/lang/modules/astToText.js
@@ -4,7 +4,6 @@
  */
 // Inspired by `ts.forEachChild`:
 // https://github.com/Microsoft/TypeScript/blob/65cbd91667acf890f21a3527b3647c7bc994ca32/src/compiler/parser.ts#L43-L320
-var ts = require("typescript");
 function astToText(srcFile) {
     //// A useful function for debugging
     // aggregate(srcFile, 0);
diff --git a/dist/main/lang/modules/building.js b/dist/main/lang/modules/building.js
index 97010e478..79a32c62f 100644
--- a/dist/main/lang/modules/building.js
+++ b/dist/main/lang/modules/building.js
@@ -1,4 +1,3 @@
-var ts = require('typescript');
 var mkdirp = require('mkdirp');
 var path = require('path');
 var fs = require('fs');
diff --git a/dist/main/lang/modules/getExternalModules.js b/dist/main/lang/modules/getExternalModules.js
index e319c1fca..9559ade06 100644
--- a/dist/main/lang/modules/getExternalModules.js
+++ b/dist/main/lang/modules/getExternalModules.js
@@ -1,8 +1,8 @@
-var typescript_1 = require("typescript");
+// From https://github.com/Microsoft/TypeScript/pull/2173/files
 function getExternalModuleNames(program) {
     var entries = [];
     program.getSourceFiles().forEach(function (sourceFile) {
-        typescript_1.forEachChild(sourceFile, function (child) {
+        ts.forEachChild(sourceFile, function (child) {
             if (child.kind === 205 && child.name.kind === 8) {
                 entries.push(child.name.text);
             }
diff --git a/dist/main/lang/modules/programDependencies.js b/dist/main/lang/modules/programDependencies.js
index 3288ca4a7..2ca1dd72a 100644
--- a/dist/main/lang/modules/programDependencies.js
+++ b/dist/main/lang/modules/programDependencies.js
@@ -1,5 +1,4 @@
 var tsconfig_1 = require("../../tsconfig/tsconfig");
-var ts = require("typescript");
 var path = require("path");
 var fs = require("fs");
 function getDependencies(projectFile, program) {
diff --git a/dist/main/lang/projectService.js b/dist/main/lang/projectService.js
index 1a8c7ce19..6b09c4656 100644
--- a/dist/main/lang/projectService.js
+++ b/dist/main/lang/projectService.js
@@ -2,7 +2,6 @@
 /// <reference path="../../globals.ts"/> ///ts:ref:generated
 var fs = require('fs');
 var path = require('path');
-var ts = require('typescript');
 var fuzzaldrin = require('fuzzaldrin');
 var tsconfig = require('../tsconfig/tsconfig');
 var utils = require('./utils');
diff --git a/dist/main/tsconfig/tsconfig.js b/dist/main/tsconfig/tsconfig.js
index f915fe920..cb04182d4 100644
--- a/dist/main/tsconfig/tsconfig.js
+++ b/dist/main/tsconfig/tsconfig.js
@@ -49,7 +49,6 @@ function errorWithDetails(error, details) {
 var fs = require('fs');
 var path = require('path');
 var expand = require('glob-expand');
-var ts = require('typescript');
 var os = require('os');
 var formatting = require('./formatting');
 var projectFileName = 'tsconfig.json';
diff --git a/dist/typescript/compiler/binder.js b/dist/typescript/compiler/binder.js
new file mode 100644
index 000000000..37c48f5ba
--- /dev/null
+++ b/dist/typescript/compiler/binder.js
@@ -0,0 +1,519 @@
+/// <reference path="parser.ts"/>
+var ts;
+(function (ts) {
+    ts.bindTime = 0;
+    (function (ModuleInstanceState) {
+        ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated";
+        ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated";
+        ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly";
+    })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {}));
+    var ModuleInstanceState = ts.ModuleInstanceState;
+    function getModuleInstanceState(node) {
+        if (node.kind === 202 || node.kind === 203) {
+            return 0;
+        }
+        else if (ts.isConstEnumDeclaration(node)) {
+            return 2;
+        }
+        else if ((node.kind === 209 || node.kind === 208) && !(node.flags & 1)) {
+            return 0;
+        }
+        else if (node.kind === 206) {
+            var state = 0;
+            ts.forEachChild(node, function (n) {
+                switch (getModuleInstanceState(n)) {
+                    case 0:
+                        return false;
+                    case 2:
+                        state = 2;
+                        return false;
+                    case 1:
+                        state = 1;
+                        return true;
+                }
+            });
+            return state;
+        }
+        else if (node.kind === 205) {
+            return getModuleInstanceState(node.body);
+        }
+        else {
+            return 1;
+        }
+    }
+    ts.getModuleInstanceState = getModuleInstanceState;
+    function bindSourceFile(file) {
+        var start = new Date().getTime();
+        bindSourceFileWorker(file);
+        ts.bindTime += new Date().getTime() - start;
+    }
+    ts.bindSourceFile = bindSourceFile;
+    function bindSourceFileWorker(file) {
+        var parent;
+        var container;
+        var blockScopeContainer;
+        var lastContainer;
+        var symbolCount = 0;
+        var Symbol = ts.objectAllocator.getSymbolConstructor();
+        if (!file.locals) {
+            file.locals = {};
+            container = file;
+            setBlockScopeContainer(file, false);
+            bind(file);
+            file.symbolCount = symbolCount;
+        }
+        function createSymbol(flags, name) {
+            symbolCount++;
+            return new Symbol(flags, name);
+        }
+        function setBlockScopeContainer(node, cleanLocals) {
+            blockScopeContainer = node;
+            if (cleanLocals) {
+                blockScopeContainer.locals = undefined;
+            }
+        }
+        function addDeclarationToSymbol(symbol, node, symbolKind) {
+            symbol.flags |= symbolKind;
+            if (!symbol.declarations)
+                symbol.declarations = [];
+            symbol.declarations.push(node);
+            if (symbolKind & 1952 && !symbol.exports)
+                symbol.exports = {};
+            if (symbolKind & 6240 && !symbol.members)
+                symbol.members = {};
+            node.symbol = symbol;
+            if (symbolKind & 107455 && !symbol.valueDeclaration)
+                symbol.valueDeclaration = node;
+        }
+        function getDeclarationName(node) {
+            if (node.name) {
+                if (node.kind === 205 && node.name.kind === 8) {
+                    return '"' + node.name.text + '"';
+                }
+                if (node.name.kind === 127) {
+                    var nameExpression = node.name.expression;
+                    ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression));
+                    return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text);
+                }
+                return node.name.text;
+            }
+            switch (node.kind) {
+                case 143:
+                case 135:
+                    return "__constructor";
+                case 142:
+                case 138:
+                    return "__call";
+                case 139:
+                    return "__new";
+                case 140:
+                    return "__index";
+                case 215:
+                    return "__export";
+                case 214:
+                    return node.isExportEquals ? "export=" : "default";
+                case 200:
+                case 201:
+                    return node.flags & 256 ? "default" : undefined;
+            }
+        }
+        function getDisplayName(node) {
+            return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node);
+        }
+        function declareSymbol(symbols, parent, node, includes, excludes) {
+            ts.Debug.assert(!ts.hasDynamicName(node));
+            var name = node.flags & 256 && parent ? "default" : getDeclarationName(node);
+            var symbol;
+            if (name !== undefined) {
+                symbol = ts.hasProperty(symbols, name) ? symbols[name] : (symbols[name] = createSymbol(0, name));
+                if (symbol.flags & excludes) {
+                    if (node.name) {
+                        node.name.parent = node;
+                    }
+                    var message = symbol.flags & 2
+                        ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0
+                        : ts.Diagnostics.Duplicate_identifier_0;
+                    ts.forEach(symbol.declarations, function (declaration) {
+                        file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
+                    });
+                    file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
+                    symbol = createSymbol(0, name);
+                }
+            }
+            else {
+                symbol = createSymbol(0, "__missing");
+            }
+            addDeclarationToSymbol(symbol, node, includes);
+            symbol.parent = parent;
+            if ((node.kind === 201 || node.kind === 174) && symbol.exports) {
+                var prototypeSymbol = createSymbol(4 | 134217728, "prototype");
+                if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) {
+                    if (node.name) {
+                        node.name.parent = node;
+                    }
+                    file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name));
+                }
+                symbol.exports[prototypeSymbol.name] = prototypeSymbol;
+                prototypeSymbol.parent = symbol;
+            }
+            return symbol;
+        }
+        function declareModuleMember(node, symbolKind, symbolExcludes) {
+            var hasExportModifier = ts.getCombinedNodeFlags(node) & 1;
+            if (symbolKind & 8388608) {
+                if (node.kind === 217 || (node.kind === 208 && hasExportModifier)) {
+                    declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                }
+                else {
+                    declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
+                }
+            }
+            else {
+                if (hasExportModifier || container.flags & 32768) {
+                    var exportKind = (symbolKind & 107455 ? 1048576 : 0) |
+                        (symbolKind & 793056 ? 2097152 : 0) |
+                        (symbolKind & 1536 ? 4194304 : 0);
+                    var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
+                    local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                    node.localSymbol = local;
+                }
+                else {
+                    declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
+                }
+            }
+        }
+        function bindChildren(node, symbolKind, isBlockScopeContainer) {
+            if (symbolKind & 255504) {
+                node.locals = {};
+            }
+            var saveParent = parent;
+            var saveContainer = container;
+            var savedBlockScopeContainer = blockScopeContainer;
+            parent = node;
+            if (symbolKind & 262128) {
+                container = node;
+                addToContainerChain(container);
+            }
+            if (isBlockScopeContainer) {
+                setBlockScopeContainer(node, (symbolKind & 255504) === 0 && node.kind !== 227);
+            }
+            ts.forEachChild(node, bind);
+            container = saveContainer;
+            parent = saveParent;
+            blockScopeContainer = savedBlockScopeContainer;
+        }
+        function addToContainerChain(node) {
+            if (lastContainer) {
+                lastContainer.nextContainer = node;
+            }
+            lastContainer = node;
+        }
+        function bindDeclaration(node, symbolKind, symbolExcludes, isBlockScopeContainer) {
+            switch (container.kind) {
+                case 205:
+                    declareModuleMember(node, symbolKind, symbolExcludes);
+                    break;
+                case 227:
+                    if (ts.isExternalModule(container)) {
+                        declareModuleMember(node, symbolKind, symbolExcludes);
+                        break;
+                    }
+                case 142:
+                case 143:
+                case 138:
+                case 139:
+                case 140:
+                case 134:
+                case 133:
+                case 135:
+                case 136:
+                case 137:
+                case 200:
+                case 162:
+                case 163:
+                    declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
+                    break;
+                case 174:
+                case 201:
+                    if (node.flags & 128) {
+                        declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                        break;
+                    }
+                case 145:
+                case 154:
+                case 202:
+                    declareSymbol(container.symbol.members, container.symbol, node, symbolKind, symbolExcludes);
+                    break;
+                case 204:
+                    declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                    break;
+            }
+            bindChildren(node, symbolKind, isBlockScopeContainer);
+        }
+        function isAmbientContext(node) {
+            while (node) {
+                if (node.flags & 2)
+                    return true;
+                node = node.parent;
+            }
+            return false;
+        }
+        function hasExportDeclarations(node) {
+            var body = node.kind === 227 ? node : node.body;
+            if (body.kind === 227 || body.kind === 206) {
+                for (var _i = 0, _a = body.statements; _i < _a.length; _i++) {
+                    var stat = _a[_i];
+                    if (stat.kind === 215 || stat.kind === 214) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        function setExportContextFlag(node) {
+            if (isAmbientContext(node) && !hasExportDeclarations(node)) {
+                node.flags |= 32768;
+            }
+            else {
+                node.flags &= ~32768;
+            }
+        }
+        function bindModuleDeclaration(node) {
+            setExportContextFlag(node);
+            if (node.name.kind === 8) {
+                bindDeclaration(node, 512, 106639, true);
+            }
+            else {
+                var state = getModuleInstanceState(node);
+                if (state === 0) {
+                    bindDeclaration(node, 1024, 0, true);
+                }
+                else {
+                    bindDeclaration(node, 512, 106639, true);
+                    var currentModuleIsConstEnumOnly = state === 2;
+                    if (node.symbol.constEnumOnlyModule === undefined) {
+                        node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
+                    }
+                    else {
+                        node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
+                    }
+                }
+            }
+        }
+        function bindFunctionOrConstructorType(node) {
+            // For a given function symbol "<...>(...) => T" we want to generate a symbol identical
+            // to the one we would get for: { <...>(...): T }
+            //
+            // We do that by making an anonymous type literal symbol, and then setting the function 
+            // symbol as its sole member. To the rest of the system, this symbol will be  indistinguishable 
+            // from an actual type literal symbol you would have gotten had you used the long form.
+            var symbol = createSymbol(131072, getDeclarationName(node));
+            addDeclarationToSymbol(symbol, node, 131072);
+            bindChildren(node, 131072, false);
+            var typeLiteralSymbol = createSymbol(2048, "__type");
+            addDeclarationToSymbol(typeLiteralSymbol, node, 2048);
+            typeLiteralSymbol.members = {};
+            typeLiteralSymbol.members[node.kind === 142 ? "__call" : "__new"] = symbol;
+        }
+        function bindAnonymousDeclaration(node, symbolKind, name, isBlockScopeContainer) {
+            var symbol = createSymbol(symbolKind, name);
+            addDeclarationToSymbol(symbol, node, symbolKind);
+            bindChildren(node, symbolKind, isBlockScopeContainer);
+        }
+        function bindCatchVariableDeclaration(node) {
+            bindChildren(node, 0, true);
+        }
+        function bindBlockScopedDeclaration(node, symbolKind, symbolExcludes) {
+            switch (blockScopeContainer.kind) {
+                case 205:
+                    declareModuleMember(node, symbolKind, symbolExcludes);
+                    break;
+                case 227:
+                    if (ts.isExternalModule(container)) {
+                        declareModuleMember(node, symbolKind, symbolExcludes);
+                        break;
+                    }
+                default:
+                    if (!blockScopeContainer.locals) {
+                        blockScopeContainer.locals = {};
+                        addToContainerChain(blockScopeContainer);
+                    }
+                    declareSymbol(blockScopeContainer.locals, undefined, node, symbolKind, symbolExcludes);
+            }
+            bindChildren(node, symbolKind, false);
+        }
+        function bindBlockScopedVariableDeclaration(node) {
+            bindBlockScopedDeclaration(node, 2, 107455);
+        }
+        function getDestructuringParameterName(node) {
+            return "__" + ts.indexOf(node.parent.parameters, node);
+        }
+        function bind(node) {
+            node.parent = parent;
+            switch (node.kind) {
+                case 128:
+                    bindDeclaration(node, 262144, 530912, false);
+                    break;
+                case 129:
+                    bindParameter(node);
+                    break;
+                case 198:
+                case 152:
+                    if (ts.isBindingPattern(node.name)) {
+                        bindChildren(node, 0, false);
+                    }
+                    else if (ts.isBlockOrCatchScoped(node)) {
+                        bindBlockScopedVariableDeclaration(node);
+                    }
+                    else {
+                        bindDeclaration(node, 1, 107454, false);
+                    }
+                    break;
+                case 132:
+                case 131:
+                    bindPropertyOrMethodOrAccessor(node, 4 | (node.questionToken ? 536870912 : 0), 107455, false);
+                    break;
+                case 224:
+                case 225:
+                    bindPropertyOrMethodOrAccessor(node, 4, 107455, false);
+                    break;
+                case 226:
+                    bindPropertyOrMethodOrAccessor(node, 8, 107455, false);
+                    break;
+                case 138:
+                case 139:
+                case 140:
+                    bindDeclaration(node, 131072, 0, false);
+                    break;
+                case 134:
+                case 133:
+                    bindPropertyOrMethodOrAccessor(node, 8192 | (node.questionToken ? 536870912 : 0), ts.isObjectLiteralMethod(node) ? 107455 : 99263, true);
+                    break;
+                case 200:
+                    bindDeclaration(node, 16, 106927, true);
+                    break;
+                case 135:
+                    bindDeclaration(node, 16384, 0, true);
+                    break;
+                case 136:
+                    bindPropertyOrMethodOrAccessor(node, 32768, 41919, true);
+                    break;
+                case 137:
+                    bindPropertyOrMethodOrAccessor(node, 65536, 74687, true);
+                    break;
+                case 142:
+                case 143:
+                    bindFunctionOrConstructorType(node);
+                    break;
+                case 145:
+                    bindAnonymousDeclaration(node, 2048, "__type", false);
+                    break;
+                case 154:
+                    bindAnonymousDeclaration(node, 4096, "__object", false);
+                    break;
+                case 162:
+                case 163:
+                    bindAnonymousDeclaration(node, 16, "__function", true);
+                    break;
+                case 174:
+                    bindAnonymousDeclaration(node, 32, "__class", false);
+                    break;
+                case 223:
+                    bindCatchVariableDeclaration(node);
+                    break;
+                case 201:
+                    bindBlockScopedDeclaration(node, 32, 899583);
+                    break;
+                case 202:
+                    bindDeclaration(node, 64, 792992, false);
+                    break;
+                case 203:
+                    bindDeclaration(node, 524288, 793056, false);
+                    break;
+                case 204:
+                    if (ts.isConst(node)) {
+                        bindDeclaration(node, 128, 899967, false);
+                    }
+                    else {
+                        bindDeclaration(node, 256, 899327, false);
+                    }
+                    break;
+                case 205:
+                    bindModuleDeclaration(node);
+                    break;
+                case 208:
+                case 211:
+                case 213:
+                case 217:
+                    bindDeclaration(node, 8388608, 8388608, false);
+                    break;
+                case 210:
+                    if (node.name) {
+                        bindDeclaration(node, 8388608, 8388608, false);
+                    }
+                    else {
+                        bindChildren(node, 0, false);
+                    }
+                    break;
+                case 215:
+                    if (!node.exportClause) {
+                        declareSymbol(container.symbol.exports, container.symbol, node, 1073741824, 0);
+                    }
+                    bindChildren(node, 0, false);
+                    break;
+                case 214:
+                    if (node.expression.kind === 65) {
+                        declareSymbol(container.symbol.exports, container.symbol, node, 8388608, 107455 | 8388608);
+                    }
+                    else {
+                        declareSymbol(container.symbol.exports, container.symbol, node, 4, 107455 | 8388608);
+                    }
+                    bindChildren(node, 0, false);
+                    break;
+                case 227:
+                    setExportContextFlag(node);
+                    if (ts.isExternalModule(node)) {
+                        bindAnonymousDeclaration(node, 512, '"' + ts.removeFileExtension(node.fileName) + '"', true);
+                        break;
+                    }
+                case 179:
+                    bindChildren(node, 0, !ts.isFunctionLike(node.parent));
+                    break;
+                case 223:
+                case 186:
+                case 187:
+                case 188:
+                case 207:
+                    bindChildren(node, 0, true);
+                    break;
+                default:
+                    var saveParent = parent;
+                    parent = node;
+                    ts.forEachChild(node, bind);
+                    parent = saveParent;
+            }
+        }
+        function bindParameter(node) {
+            if (ts.isBindingPattern(node.name)) {
+                bindAnonymousDeclaration(node, 1, getDestructuringParameterName(node), false);
+            }
+            else {
+                bindDeclaration(node, 1, 107455, false);
+            }
+            if (node.flags & 112 &&
+                node.parent.kind === 135 &&
+                (node.parent.parent.kind === 201 || node.parent.parent.kind === 174)) {
+                var classDeclaration = node.parent.parent;
+                declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4, 107455);
+            }
+        }
+        function bindPropertyOrMethodOrAccessor(node, symbolKind, symbolExcludes, isBlockScopeContainer) {
+            if (ts.hasDynamicName(node)) {
+                bindAnonymousDeclaration(node, symbolKind, "__computed", isBlockScopeContainer);
+            }
+            else {
+                bindDeclaration(node, symbolKind, symbolExcludes, isBlockScopeContainer);
+            }
+        }
+    }
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/checker.js b/dist/typescript/compiler/checker.js
new file mode 100644
index 000000000..258cbe234
--- /dev/null
+++ b/dist/typescript/compiler/checker.js
@@ -0,0 +1,10413 @@
+/// <reference path="binder.ts"/>
+var ts;
+(function (ts) {
+    var nextSymbolId = 1;
+    var nextNodeId = 1;
+    var nextMergeId = 1;
+    function getNodeId(node) {
+        if (!node.id)
+            node.id = nextNodeId++;
+        return node.id;
+    }
+    ts.getNodeId = getNodeId;
+    ts.checkTime = 0;
+    function getSymbolId(symbol) {
+        if (!symbol.id) {
+            symbol.id = nextSymbolId++;
+        }
+        return symbol.id;
+    }
+    ts.getSymbolId = getSymbolId;
+    function createTypeChecker(host, produceDiagnostics) {
+        var Symbol = ts.objectAllocator.getSymbolConstructor();
+        var Type = ts.objectAllocator.getTypeConstructor();
+        var Signature = ts.objectAllocator.getSignatureConstructor();
+        var typeCount = 0;
+        var emptyArray = [];
+        var emptySymbols = {};
+        var compilerOptions = host.getCompilerOptions();
+        var languageVersion = compilerOptions.target || 0;
+        var emitResolver = createResolver();
+        var undefinedSymbol = createSymbol(4 | 67108864, "undefined");
+        var argumentsSymbol = createSymbol(4 | 67108864, "arguments");
+        var checker = {
+            getNodeCount: function () { return ts.sum(host.getSourceFiles(), "nodeCount"); },
+            getIdentifierCount: function () { return ts.sum(host.getSourceFiles(), "identifierCount"); },
+            getSymbolCount: function () { return ts.sum(host.getSourceFiles(), "symbolCount"); },
+            getTypeCount: function () { return typeCount; },
+            isUndefinedSymbol: function (symbol) { return symbol === undefinedSymbol; },
+            isArgumentsSymbol: function (symbol) { return symbol === argumentsSymbol; },
+            getDiagnostics: getDiagnostics,
+            getGlobalDiagnostics: getGlobalDiagnostics,
+            getTypeOfSymbolAtLocation: getTypeOfSymbolAtLocation,
+            getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
+            getPropertiesOfType: getPropertiesOfType,
+            getPropertyOfType: getPropertyOfType,
+            getSignaturesOfType: getSignaturesOfType,
+            getIndexTypeOfType: getIndexTypeOfType,
+            getReturnTypeOfSignature: getReturnTypeOfSignature,
+            getSymbolsInScope: getSymbolsInScope,
+            getSymbolAtLocation: getSymbolAtLocation,
+            getShorthandAssignmentValueSymbol: getShorthandAssignmentValueSymbol,
+            getTypeAtLocation: getTypeAtLocation,
+            typeToString: typeToString,
+            getSymbolDisplayBuilder: getSymbolDisplayBuilder,
+            symbolToString: symbolToString,
+            getAugmentedPropertiesOfType: getAugmentedPropertiesOfType,
+            getRootSymbols: getRootSymbols,
+            getContextualType: getContextualType,
+            getFullyQualifiedName: getFullyQualifiedName,
+            getResolvedSignature: getResolvedSignature,
+            getConstantValue: getConstantValue,
+            isValidPropertyAccess: isValidPropertyAccess,
+            getSignatureFromDeclaration: getSignatureFromDeclaration,
+            isImplementationOfOverload: isImplementationOfOverload,
+            getAliasedSymbol: resolveAlias,
+            getEmitResolver: getEmitResolver,
+            getExportsOfModule: getExportsOfModuleAsArray,
+        };
+        var unknownSymbol = createSymbol(4 | 67108864, "unknown");
+        var resolvingSymbol = createSymbol(67108864, "__resolving__");
+        var anyType = createIntrinsicType(1, "any");
+        var stringType = createIntrinsicType(2, "string");
+        var numberType = createIntrinsicType(4, "number");
+        var booleanType = createIntrinsicType(8, "boolean");
+        var esSymbolType = createIntrinsicType(1048576, "symbol");
+        var voidType = createIntrinsicType(16, "void");
+        var undefinedType = createIntrinsicType(32 | 262144, "undefined");
+        var nullType = createIntrinsicType(64 | 262144, "null");
+        var unknownType = createIntrinsicType(1, "unknown");
+        var resolvingType = createIntrinsicType(1, "__resolving__");
+        var emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+        var anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+        var noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+        var anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false);
+        var unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false);
+        var globals = {};
+        var globalArraySymbol;
+        var globalESSymbolConstructorSymbol;
+        var globalObjectType;
+        var globalFunctionType;
+        var globalArrayType;
+        var globalStringType;
+        var globalNumberType;
+        var globalBooleanType;
+        var globalRegExpType;
+        var globalTemplateStringsArrayType;
+        var globalESSymbolType;
+        var globalIterableType;
+        var anyArrayType;
+        var getGlobalClassDecoratorType;
+        var getGlobalParameterDecoratorType;
+        var getGlobalPropertyDecoratorType;
+        var getGlobalMethodDecoratorType;
+        var tupleTypes = {};
+        var unionTypes = {};
+        var stringLiteralTypes = {};
+        var emitExtends = false;
+        var emitDecorate = false;
+        var emitParam = false;
+        var mergedSymbols = [];
+        var symbolLinks = [];
+        var nodeLinks = [];
+        var potentialThisCollisions = [];
+        var diagnostics = ts.createDiagnosticCollection();
+        var primitiveTypeInfo = {
+            "string": {
+                type: stringType,
+                flags: 258
+            },
+            "number": {
+                type: numberType,
+                flags: 132
+            },
+            "boolean": {
+                type: booleanType,
+                flags: 8
+            },
+            "symbol": {
+                type: esSymbolType,
+                flags: 1048576
+            }
+        };
+        function getEmitResolver(sourceFile) {
+            getDiagnostics(sourceFile);
+            return emitResolver;
+        }
+        function error(location, message, arg0, arg1, arg2) {
+            var diagnostic = location
+                ? ts.createDiagnosticForNode(location, message, arg0, arg1, arg2)
+                : ts.createCompilerDiagnostic(message, arg0, arg1, arg2);
+            diagnostics.add(diagnostic);
+        }
+        function createSymbol(flags, name) {
+            return new Symbol(flags, name);
+        }
+        function getExcludedSymbolFlags(flags) {
+            var result = 0;
+            if (flags & 2)
+                result |= 107455;
+            if (flags & 1)
+                result |= 107454;
+            if (flags & 4)
+                result |= 107455;
+            if (flags & 8)
+                result |= 107455;
+            if (flags & 16)
+                result |= 106927;
+            if (flags & 32)
+                result |= 899583;
+            if (flags & 64)
+                result |= 792992;
+            if (flags & 256)
+                result |= 899327;
+            if (flags & 128)
+                result |= 899967;
+            if (flags & 512)
+                result |= 106639;
+            if (flags & 8192)
+                result |= 99263;
+            if (flags & 32768)
+                result |= 41919;
+            if (flags & 65536)
+                result |= 74687;
+            if (flags & 262144)
+                result |= 530912;
+            if (flags & 524288)
+                result |= 793056;
+            if (flags & 8388608)
+                result |= 8388608;
+            return result;
+        }
+        function recordMergedSymbol(target, source) {
+            if (!source.mergeId)
+                source.mergeId = nextMergeId++;
+            mergedSymbols[source.mergeId] = target;
+        }
+        function cloneSymbol(symbol) {
+            var result = createSymbol(symbol.flags | 33554432, symbol.name);
+            result.declarations = symbol.declarations.slice(0);
+            result.parent = symbol.parent;
+            if (symbol.valueDeclaration)
+                result.valueDeclaration = symbol.valueDeclaration;
+            if (symbol.constEnumOnlyModule)
+                result.constEnumOnlyModule = true;
+            if (symbol.members)
+                result.members = cloneSymbolTable(symbol.members);
+            if (symbol.exports)
+                result.exports = cloneSymbolTable(symbol.exports);
+            recordMergedSymbol(result, symbol);
+            return result;
+        }
+        function mergeSymbol(target, source) {
+            if (!(target.flags & getExcludedSymbolFlags(source.flags))) {
+                if (source.flags & 512 && target.flags & 512 && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
+                    target.constEnumOnlyModule = false;
+                }
+                target.flags |= source.flags;
+                if (!target.valueDeclaration && source.valueDeclaration)
+                    target.valueDeclaration = source.valueDeclaration;
+                ts.forEach(source.declarations, function (node) {
+                    target.declarations.push(node);
+                });
+                if (source.members) {
+                    if (!target.members)
+                        target.members = {};
+                    mergeSymbolTable(target.members, source.members);
+                }
+                if (source.exports) {
+                    if (!target.exports)
+                        target.exports = {};
+                    mergeSymbolTable(target.exports, source.exports);
+                }
+                recordMergedSymbol(target, source);
+            }
+            else {
+                var message = target.flags & 2 || source.flags & 2
+                    ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0;
+                ts.forEach(source.declarations, function (node) {
+                    error(node.name ? node.name : node, message, symbolToString(source));
+                });
+                ts.forEach(target.declarations, function (node) {
+                    error(node.name ? node.name : node, message, symbolToString(source));
+                });
+            }
+        }
+        function cloneSymbolTable(symbolTable) {
+            var result = {};
+            for (var id in symbolTable) {
+                if (ts.hasProperty(symbolTable, id)) {
+                    result[id] = symbolTable[id];
+                }
+            }
+            return result;
+        }
+        function mergeSymbolTable(target, source) {
+            for (var id in source) {
+                if (ts.hasProperty(source, id)) {
+                    if (!ts.hasProperty(target, id)) {
+                        target[id] = source[id];
+                    }
+                    else {
+                        var symbol = target[id];
+                        if (!(symbol.flags & 33554432)) {
+                            target[id] = symbol = cloneSymbol(symbol);
+                        }
+                        mergeSymbol(symbol, source[id]);
+                    }
+                }
+            }
+        }
+        function getSymbolLinks(symbol) {
+            if (symbol.flags & 67108864)
+                return symbol;
+            var id = getSymbolId(symbol);
+            return symbolLinks[id] || (symbolLinks[id] = {});
+        }
+        function getNodeLinks(node) {
+            var nodeId = getNodeId(node);
+            return nodeLinks[nodeId] || (nodeLinks[nodeId] = {});
+        }
+        function getSourceFile(node) {
+            return ts.getAncestor(node, 227);
+        }
+        function isGlobalSourceFile(node) {
+            return node.kind === 227 && !ts.isExternalModule(node);
+        }
+        function getSymbol(symbols, name, meaning) {
+            if (meaning && ts.hasProperty(symbols, name)) {
+                var symbol = symbols[name];
+                ts.Debug.assert((symbol.flags & 16777216) === 0, "Should never get an instantiated symbol here.");
+                if (symbol.flags & meaning) {
+                    return symbol;
+                }
+                if (symbol.flags & 8388608) {
+                    var target = resolveAlias(symbol);
+                    if (target === unknownSymbol || target.flags & meaning) {
+                        return symbol;
+                    }
+                }
+            }
+        }
+        function isDefinedBefore(node1, node2) {
+            var file1 = ts.getSourceFileOfNode(node1);
+            var file2 = ts.getSourceFileOfNode(node2);
+            if (file1 === file2) {
+                return node1.pos <= node2.pos;
+            }
+            if (!compilerOptions.out) {
+                return true;
+            }
+            var sourceFiles = host.getSourceFiles();
+            return sourceFiles.indexOf(file1) <= sourceFiles.indexOf(file2);
+        }
+        function resolveName(location, name, meaning, nameNotFoundMessage, nameArg) {
+            var result;
+            var lastLocation;
+            var propertyWithInvalidInitializer;
+            var errorLocation = location;
+            var grandparent;
+            loop: while (location) {
+                if (location.locals && !isGlobalSourceFile(location)) {
+                    if (result = getSymbol(location.locals, name, meaning)) {
+                        break loop;
+                    }
+                }
+                switch (location.kind) {
+                    case 227:
+                        if (!ts.isExternalModule(location))
+                            break;
+                    case 205:
+                        if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & 8914931)) {
+                            if (result.flags & meaning || !(result.flags & 8388608 && getDeclarationOfAliasSymbol(result).kind === 217)) {
+                                break loop;
+                            }
+                            result = undefined;
+                        }
+                        else if (location.kind === 227 ||
+                            (location.kind === 205 && location.name.kind === 8)) {
+                            result = getSymbol(getSymbolOfNode(location).exports, "default", meaning & 8914931);
+                            var localSymbol = ts.getLocalSymbolForExportDefault(result);
+                            if (result && (result.flags & meaning) && localSymbol && localSymbol.name === name) {
+                                break loop;
+                            }
+                            result = undefined;
+                        }
+                        break;
+                    case 204:
+                        if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & 8)) {
+                            break loop;
+                        }
+                        break;
+                    case 132:
+                    case 131:
+                        if (location.parent.kind === 201 && !(location.flags & 128)) {
+                            var ctor = findConstructorDeclaration(location.parent);
+                            if (ctor && ctor.locals) {
+                                if (getSymbol(ctor.locals, name, meaning & 107455)) {
+                                    propertyWithInvalidInitializer = location;
+                                }
+                            }
+                        }
+                        break;
+                    case 201:
+                    case 202:
+                        if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & 793056)) {
+                            if (lastLocation && lastLocation.flags & 128) {
+                                error(errorLocation, ts.Diagnostics.Static_members_cannot_reference_class_type_parameters);
+                                return undefined;
+                            }
+                            break loop;
+                        }
+                        break;
+                    case 127:
+                        grandparent = location.parent.parent;
+                        if (grandparent.kind === 201 || grandparent.kind === 202) {
+                            if (result = getSymbol(getSymbolOfNode(grandparent).members, name, meaning & 793056)) {
+                                error(errorLocation, ts.Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type);
+                                return undefined;
+                            }
+                        }
+                        break;
+                    case 134:
+                    case 133:
+                    case 135:
+                    case 136:
+                    case 137:
+                    case 200:
+                    case 163:
+                        if (name === "arguments") {
+                            result = argumentsSymbol;
+                            break loop;
+                        }
+                        break;
+                    case 162:
+                        if (name === "arguments") {
+                            result = argumentsSymbol;
+                            break loop;
+                        }
+                        var functionName = location.name;
+                        if (functionName && name === functionName.text) {
+                            result = location.symbol;
+                            break loop;
+                        }
+                        break;
+                    case 174:
+                        var className = location.name;
+                        if (className && name === className.text) {
+                            result = location.symbol;
+                            break loop;
+                        }
+                        break;
+                    case 130:
+                        if (location.parent && location.parent.kind === 129) {
+                            location = location.parent;
+                        }
+                        if (location.parent && ts.isClassElement(location.parent)) {
+                            location = location.parent;
+                        }
+                        break;
+                }
+                lastLocation = location;
+                location = location.parent;
+            }
+            if (!result) {
+                result = getSymbol(globals, name, meaning);
+            }
+            if (!result) {
+                if (nameNotFoundMessage) {
+                    error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg));
+                }
+                return undefined;
+            }
+            if (nameNotFoundMessage) {
+                if (propertyWithInvalidInitializer) {
+                    var propertyName = propertyWithInvalidInitializer.name;
+                    error(errorLocation, ts.Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, ts.declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg));
+                    return undefined;
+                }
+                if (result.flags & 2) {
+                    checkResolvedBlockScopedVariable(result, errorLocation);
+                }
+            }
+            return result;
+        }
+        function checkResolvedBlockScopedVariable(result, errorLocation) {
+            ts.Debug.assert((result.flags & 2) !== 0);
+            var declaration = ts.forEach(result.declarations, function (d) { return ts.isBlockOrCatchScoped(d) ? d : undefined; });
+            ts.Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
+            var isUsedBeforeDeclaration = !isDefinedBefore(declaration, errorLocation);
+            if (!isUsedBeforeDeclaration) {
+                var variableDeclaration = ts.getAncestor(declaration, 198);
+                var container = ts.getEnclosingBlockScopeContainer(variableDeclaration);
+                if (variableDeclaration.parent.parent.kind === 180 ||
+                    variableDeclaration.parent.parent.kind === 186) {
+                    isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, variableDeclaration, container);
+                }
+                else if (variableDeclaration.parent.parent.kind === 188 ||
+                    variableDeclaration.parent.parent.kind === 187) {
+                    var expression = variableDeclaration.parent.parent.expression;
+                    isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, expression, container);
+                }
+            }
+            if (isUsedBeforeDeclaration) {
+                error(errorLocation, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, ts.declarationNameToString(declaration.name));
+            }
+        }
+        function isSameScopeDescendentOf(initial, parent, stopAt) {
+            if (!parent) {
+                return false;
+            }
+            for (var current = initial; current && current !== stopAt && !ts.isFunctionLike(current); current = current.parent) {
+                if (current === parent) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        function getAnyImportSyntax(node) {
+            if (ts.isAliasSymbolDeclaration(node)) {
+                if (node.kind === 208) {
+                    return node;
+                }
+                while (node && node.kind !== 209) {
+                    node = node.parent;
+                }
+                return node;
+            }
+        }
+        function getDeclarationOfAliasSymbol(symbol) {
+            return ts.forEach(symbol.declarations, function (d) { return ts.isAliasSymbolDeclaration(d) ? d : undefined; });
+        }
+        function getTargetOfImportEqualsDeclaration(node) {
+            if (node.moduleReference.kind === 219) {
+                return resolveExternalModuleSymbol(resolveExternalModuleName(node, ts.getExternalModuleImportEqualsDeclarationExpression(node)));
+            }
+            return getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, node);
+        }
+        function getTargetOfImportClause(node) {
+            var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier);
+            if (moduleSymbol) {
+                var exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]);
+                if (!exportDefaultSymbol) {
+                    error(node.name, ts.Diagnostics.External_module_0_has_no_default_export, symbolToString(moduleSymbol));
+                }
+                return exportDefaultSymbol;
+            }
+        }
+        function getTargetOfNamespaceImport(node) {
+            var moduleSpecifier = node.parent.parent.moduleSpecifier;
+            return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier);
+        }
+        function getMemberOfModuleVariable(moduleSymbol, name) {
+            if (moduleSymbol.flags & 3) {
+                var typeAnnotation = moduleSymbol.valueDeclaration.type;
+                if (typeAnnotation) {
+                    return getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name);
+                }
+            }
+        }
+        function combineValueAndTypeSymbols(valueSymbol, typeSymbol) {
+            if (valueSymbol.flags & (793056 | 1536)) {
+                return valueSymbol;
+            }
+            var result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.name);
+            result.declarations = ts.concatenate(valueSymbol.declarations, typeSymbol.declarations);
+            result.parent = valueSymbol.parent || typeSymbol.parent;
+            if (valueSymbol.valueDeclaration)
+                result.valueDeclaration = valueSymbol.valueDeclaration;
+            if (typeSymbol.members)
+                result.members = typeSymbol.members;
+            if (valueSymbol.exports)
+                result.exports = valueSymbol.exports;
+            return result;
+        }
+        function getExportOfModule(symbol, name) {
+            if (symbol.flags & 1536) {
+                var exports_1 = getExportsOfSymbol(symbol);
+                if (ts.hasProperty(exports_1, name)) {
+                    return resolveSymbol(exports_1[name]);
+                }
+            }
+        }
+        function getPropertyOfVariable(symbol, name) {
+            if (symbol.flags & 3) {
+                var typeAnnotation = symbol.valueDeclaration.type;
+                if (typeAnnotation) {
+                    return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name));
+                }
+            }
+        }
+        function getExternalModuleMember(node, specifier) {
+            var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
+            var targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier);
+            if (targetSymbol) {
+                var name_1 = specifier.propertyName || specifier.name;
+                if (name_1.text) {
+                    var symbolFromModule = getExportOfModule(targetSymbol, name_1.text);
+                    var symbolFromVariable = getPropertyOfVariable(targetSymbol, name_1.text);
+                    var symbol = symbolFromModule && symbolFromVariable ?
+                        combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) :
+                        symbolFromModule || symbolFromVariable;
+                    if (!symbol) {
+                        error(name_1, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), ts.declarationNameToString(name_1));
+                    }
+                    return symbol;
+                }
+            }
+        }
+        function getTargetOfImportSpecifier(node) {
+            return getExternalModuleMember(node.parent.parent.parent, node);
+        }
+        function getTargetOfExportSpecifier(node) {
+            return node.parent.parent.moduleSpecifier ?
+                getExternalModuleMember(node.parent.parent, node) :
+                resolveEntityName(node.propertyName || node.name, 107455 | 793056 | 1536);
+        }
+        function getTargetOfExportAssignment(node) {
+            return resolveEntityName(node.expression, 107455 | 793056 | 1536);
+        }
+        function getTargetOfAliasDeclaration(node) {
+            switch (node.kind) {
+                case 208:
+                    return getTargetOfImportEqualsDeclaration(node);
+                case 210:
+                    return getTargetOfImportClause(node);
+                case 211:
+                    return getTargetOfNamespaceImport(node);
+                case 213:
+                    return getTargetOfImportSpecifier(node);
+                case 217:
+                    return getTargetOfExportSpecifier(node);
+                case 214:
+                    return getTargetOfExportAssignment(node);
+            }
+        }
+        function resolveSymbol(symbol) {
+            return symbol && symbol.flags & 8388608 && !(symbol.flags & (107455 | 793056 | 1536)) ? resolveAlias(symbol) : symbol;
+        }
+        function resolveAlias(symbol) {
+            ts.Debug.assert((symbol.flags & 8388608) !== 0, "Should only get Alias here.");
+            var links = getSymbolLinks(symbol);
+            if (!links.target) {
+                links.target = resolvingSymbol;
+                var node = getDeclarationOfAliasSymbol(symbol);
+                var target = getTargetOfAliasDeclaration(node);
+                if (links.target === resolvingSymbol) {
+                    links.target = target || unknownSymbol;
+                }
+                else {
+                    error(node, ts.Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol));
+                }
+            }
+            else if (links.target === resolvingSymbol) {
+                links.target = unknownSymbol;
+            }
+            return links.target;
+        }
+        function markExportAsReferenced(node) {
+            var symbol = getSymbolOfNode(node);
+            var target = resolveAlias(symbol);
+            if (target) {
+                var markAlias = (target === unknownSymbol && compilerOptions.separateCompilation) ||
+                    (target !== unknownSymbol && (target.flags & 107455) && !isConstEnumOrConstEnumOnlyModule(target));
+                if (markAlias) {
+                    markAliasSymbolAsReferenced(symbol);
+                }
+            }
+        }
+        function markAliasSymbolAsReferenced(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.referenced) {
+                links.referenced = true;
+                var node = getDeclarationOfAliasSymbol(symbol);
+                if (node.kind === 214) {
+                    checkExpressionCached(node.expression);
+                }
+                else if (node.kind === 217) {
+                    checkExpressionCached(node.propertyName || node.name);
+                }
+                else if (ts.isInternalModuleImportEqualsDeclaration(node)) {
+                    checkExpressionCached(node.moduleReference);
+                }
+            }
+        }
+        function getSymbolOfPartOfRightHandSideOfImportEquals(entityName, importDeclaration) {
+            if (!importDeclaration) {
+                importDeclaration = ts.getAncestor(entityName, 208);
+                ts.Debug.assert(importDeclaration !== undefined);
+            }
+            if (entityName.kind === 65 && ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
+                entityName = entityName.parent;
+            }
+            if (entityName.kind === 65 || entityName.parent.kind === 126) {
+                return resolveEntityName(entityName, 1536);
+            }
+            else {
+                ts.Debug.assert(entityName.parent.kind === 208);
+                return resolveEntityName(entityName, 107455 | 793056 | 1536);
+            }
+        }
+        function getFullyQualifiedName(symbol) {
+            return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
+        }
+        function resolveEntityName(name, meaning) {
+            if (ts.nodeIsMissing(name)) {
+                return undefined;
+            }
+            var symbol;
+            if (name.kind === 65) {
+                symbol = resolveName(name, name.text, meaning, ts.Diagnostics.Cannot_find_name_0, name);
+                if (!symbol) {
+                    return undefined;
+                }
+            }
+            else if (name.kind === 126 || name.kind === 155) {
+                var left = name.kind === 126 ? name.left : name.expression;
+                var right = name.kind === 126 ? name.right : name.name;
+                var namespace = resolveEntityName(left, 1536);
+                if (!namespace || namespace === unknownSymbol || ts.nodeIsMissing(right)) {
+                    return undefined;
+                }
+                symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning);
+                if (!symbol) {
+                    error(right, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), ts.declarationNameToString(right));
+                    return undefined;
+                }
+            }
+            else {
+                ts.Debug.fail("Unknown entity name kind.");
+            }
+            ts.Debug.assert((symbol.flags & 16777216) === 0, "Should never get an instantiated symbol here.");
+            return symbol.flags & meaning ? symbol : resolveAlias(symbol);
+        }
+        function isExternalModuleNameRelative(moduleName) {
+            return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\";
+        }
+        function resolveExternalModuleName(location, moduleReferenceExpression) {
+            if (moduleReferenceExpression.kind !== 8) {
+                return;
+            }
+            var moduleReferenceLiteral = moduleReferenceExpression;
+            var searchPath = ts.getDirectoryPath(getSourceFile(location).fileName);
+            var moduleName = ts.escapeIdentifier(moduleReferenceLiteral.text);
+            if (!moduleName)
+                return;
+            var isRelative = isExternalModuleNameRelative(moduleName);
+            if (!isRelative) {
+                var symbol = getSymbol(globals, '"' + moduleName + '"', 512);
+                if (symbol) {
+                    return symbol;
+                }
+            }
+            var sourceFile;
+            while (true) {
+                var fileName = ts.normalizePath(ts.combinePaths(searchPath, moduleName));
+                sourceFile = host.getSourceFile(fileName + ".ts") || host.getSourceFile(fileName + ".d.ts");
+                if (sourceFile || isRelative) {
+                    break;
+                }
+                var parentPath = ts.getDirectoryPath(searchPath);
+                if (parentPath === searchPath) {
+                    break;
+                }
+                searchPath = parentPath;
+            }
+            if (sourceFile) {
+                if (sourceFile.symbol) {
+                    return sourceFile.symbol;
+                }
+                error(moduleReferenceLiteral, ts.Diagnostics.File_0_is_not_an_external_module, sourceFile.fileName);
+                return;
+            }
+            error(moduleReferenceLiteral, ts.Diagnostics.Cannot_find_external_module_0, moduleName);
+        }
+        function resolveExternalModuleSymbol(moduleSymbol) {
+            return moduleSymbol && resolveSymbol(moduleSymbol.exports["export="]) || moduleSymbol;
+        }
+        function resolveESModuleSymbol(moduleSymbol, moduleReferenceExpression) {
+            var symbol = resolveExternalModuleSymbol(moduleSymbol);
+            if (symbol && !(symbol.flags & (1536 | 3))) {
+                error(moduleReferenceExpression, ts.Diagnostics.External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
+                symbol = undefined;
+            }
+            return symbol;
+        }
+        function getExportAssignmentSymbol(moduleSymbol) {
+            return moduleSymbol.exports["export="];
+        }
+        function getExportsOfModuleAsArray(moduleSymbol) {
+            return symbolsToArray(getExportsOfModule(moduleSymbol));
+        }
+        function getExportsOfSymbol(symbol) {
+            return symbol.flags & 1536 ? getExportsOfModule(symbol) : symbol.exports || emptySymbols;
+        }
+        function getExportsOfModule(moduleSymbol) {
+            var links = getSymbolLinks(moduleSymbol);
+            return links.resolvedExports || (links.resolvedExports = getExportsForModule(moduleSymbol));
+        }
+        function extendExportSymbols(target, source) {
+            for (var id in source) {
+                if (id !== "default" && !ts.hasProperty(target, id)) {
+                    target[id] = source[id];
+                }
+            }
+        }
+        function getExportsForModule(moduleSymbol) {
+            var result;
+            var visitedSymbols = [];
+            visit(moduleSymbol);
+            return result || moduleSymbol.exports;
+            function visit(symbol) {
+                if (symbol && symbol.flags & 1952 && !ts.contains(visitedSymbols, symbol)) {
+                    visitedSymbols.push(symbol);
+                    if (symbol !== moduleSymbol) {
+                        if (!result) {
+                            result = cloneSymbolTable(moduleSymbol.exports);
+                        }
+                        extendExportSymbols(result, symbol.exports);
+                    }
+                    var exportStars = symbol.exports["__export"];
+                    if (exportStars) {
+                        for (var _i = 0, _a = exportStars.declarations; _i < _a.length; _i++) {
+                            var node = _a[_i];
+                            visit(resolveExternalModuleName(node, node.moduleSpecifier));
+                        }
+                    }
+                }
+            }
+        }
+        function getMergedSymbol(symbol) {
+            var merged;
+            return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol;
+        }
+        function getSymbolOfNode(node) {
+            return getMergedSymbol(node.symbol);
+        }
+        function getParentOfSymbol(symbol) {
+            return getMergedSymbol(symbol.parent);
+        }
+        function getExportSymbolOfValueSymbolIfExported(symbol) {
+            return symbol && (symbol.flags & 1048576) !== 0
+                ? getMergedSymbol(symbol.exportSymbol)
+                : symbol;
+        }
+        function symbolIsValue(symbol) {
+            if (symbol.flags & 16777216) {
+                return symbolIsValue(getSymbolLinks(symbol).target);
+            }
+            if (symbol.flags & 107455) {
+                return true;
+            }
+            if (symbol.flags & 8388608) {
+                return (resolveAlias(symbol).flags & 107455) !== 0;
+            }
+            return false;
+        }
+        function findConstructorDeclaration(node) {
+            var members = node.members;
+            for (var _i = 0; _i < members.length; _i++) {
+                var member = members[_i];
+                if (member.kind === 135 && ts.nodeIsPresent(member.body)) {
+                    return member;
+                }
+            }
+        }
+        function createType(flags) {
+            var result = new Type(checker, flags);
+            result.id = typeCount++;
+            return result;
+        }
+        function createIntrinsicType(kind, intrinsicName) {
+            var type = createType(kind);
+            type.intrinsicName = intrinsicName;
+            return type;
+        }
+        function createObjectType(kind, symbol) {
+            var type = createType(kind);
+            type.symbol = symbol;
+            return type;
+        }
+        function isReservedMemberName(name) {
+            return name.charCodeAt(0) === 95 &&
+                name.charCodeAt(1) === 95 &&
+                name.charCodeAt(2) !== 95 &&
+                name.charCodeAt(2) !== 64;
+        }
+        function getNamedMembers(members) {
+            var result;
+            for (var id in members) {
+                if (ts.hasProperty(members, id)) {
+                    if (!isReservedMemberName(id)) {
+                        if (!result)
+                            result = [];
+                        var symbol = members[id];
+                        if (symbolIsValue(symbol)) {
+                            result.push(symbol);
+                        }
+                    }
+                }
+            }
+            return result || emptyArray;
+        }
+        function setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType) {
+            type.members = members;
+            type.properties = getNamedMembers(members);
+            type.callSignatures = callSignatures;
+            type.constructSignatures = constructSignatures;
+            if (stringIndexType)
+                type.stringIndexType = stringIndexType;
+            if (numberIndexType)
+                type.numberIndexType = numberIndexType;
+            return type;
+        }
+        function createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexType, numberIndexType) {
+            return setObjectTypeMembers(createObjectType(32768, symbol), members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+        function forEachSymbolTableInScope(enclosingDeclaration, callback) {
+            var result;
+            for (var location_1 = enclosingDeclaration; location_1; location_1 = location_1.parent) {
+                if (location_1.locals && !isGlobalSourceFile(location_1)) {
+                    if (result = callback(location_1.locals)) {
+                        return result;
+                    }
+                }
+                switch (location_1.kind) {
+                    case 227:
+                        if (!ts.isExternalModule(location_1)) {
+                            break;
+                        }
+                    case 205:
+                        if (result = callback(getSymbolOfNode(location_1).exports)) {
+                            return result;
+                        }
+                        break;
+                    case 201:
+                    case 202:
+                        if (result = callback(getSymbolOfNode(location_1).members)) {
+                            return result;
+                        }
+                        break;
+                }
+            }
+            return callback(globals);
+        }
+        function getQualifiedLeftMeaning(rightMeaning) {
+            return rightMeaning === 107455 ? 107455 : 1536;
+        }
+        function getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, useOnlyExternalAliasing) {
+            function getAccessibleSymbolChainFromSymbolTable(symbols) {
+                function canQualifySymbol(symbolFromSymbolTable, meaning) {
+                    if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
+                        return true;
+                    }
+                    var accessibleParent = getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
+                    return !!accessibleParent;
+                }
+                function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) {
+                    if (symbol === (resolvedAliasSymbol || symbolFromSymbolTable)) {
+                        return !ts.forEach(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) &&
+                            canQualifySymbol(symbolFromSymbolTable, meaning);
+                    }
+                }
+                if (isAccessible(ts.lookUp(symbols, symbol.name))) {
+                    return [symbol];
+                }
+                return ts.forEachValue(symbols, function (symbolFromSymbolTable) {
+                    if (symbolFromSymbolTable.flags & 8388608 && symbolFromSymbolTable.name !== "export=") {
+                        if (!useOnlyExternalAliasing ||
+                            ts.forEach(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration)) {
+                            var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
+                            if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
+                                return [symbolFromSymbolTable];
+                            }
+                            var accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTable(resolvedImportedSymbol.exports) : undefined;
+                            if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
+                                return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
+                            }
+                        }
+                    }
+                });
+            }
+            if (symbol) {
+                return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
+            }
+        }
+        function needsQualification(symbol, enclosingDeclaration, meaning) {
+            var qualify = false;
+            forEachSymbolTableInScope(enclosingDeclaration, function (symbolTable) {
+                if (!ts.hasProperty(symbolTable, symbol.name)) {
+                    return false;
+                }
+                var symbolFromSymbolTable = symbolTable[symbol.name];
+                if (symbolFromSymbolTable === symbol) {
+                    return true;
+                }
+                symbolFromSymbolTable = (symbolFromSymbolTable.flags & 8388608) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable;
+                if (symbolFromSymbolTable.flags & meaning) {
+                    qualify = true;
+                    return true;
+                }
+                return false;
+            });
+            return qualify;
+        }
+        function isSymbolAccessible(symbol, enclosingDeclaration, meaning) {
+            if (symbol && enclosingDeclaration && !(symbol.flags & 262144)) {
+                var initialSymbol = symbol;
+                var meaningToLook = meaning;
+                while (symbol) {
+                    var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, false);
+                    if (accessibleSymbolChain) {
+                        var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]);
+                        if (!hasAccessibleDeclarations) {
+                            return {
+                                accessibility: 1,
+                                errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
+                                errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, 1536) : undefined,
+                            };
+                        }
+                        return hasAccessibleDeclarations;
+                    }
+                    meaningToLook = getQualifiedLeftMeaning(meaning);
+                    symbol = getParentOfSymbol(symbol);
+                }
+                var symbolExternalModule = ts.forEach(initialSymbol.declarations, getExternalModuleContainer);
+                if (symbolExternalModule) {
+                    var enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration);
+                    if (symbolExternalModule !== enclosingExternalModule) {
+                        return {
+                            accessibility: 2,
+                            errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
+                            errorModuleName: symbolToString(symbolExternalModule)
+                        };
+                    }
+                }
+                return {
+                    accessibility: 1,
+                    errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
+                };
+            }
+            return { accessibility: 0 };
+            function getExternalModuleContainer(declaration) {
+                for (; declaration; declaration = declaration.parent) {
+                    if (hasExternalModuleSymbol(declaration)) {
+                        return getSymbolOfNode(declaration);
+                    }
+                }
+            }
+        }
+        function hasExternalModuleSymbol(declaration) {
+            return (declaration.kind === 205 && declaration.name.kind === 8) ||
+                (declaration.kind === 227 && ts.isExternalModule(declaration));
+        }
+        function hasVisibleDeclarations(symbol) {
+            var aliasesToMakeVisible;
+            if (ts.forEach(symbol.declarations, function (declaration) { return !getIsDeclarationVisible(declaration); })) {
+                return undefined;
+            }
+            return { accessibility: 0, aliasesToMakeVisible: aliasesToMakeVisible };
+            function getIsDeclarationVisible(declaration) {
+                if (!isDeclarationVisible(declaration)) {
+                    var anyImportSyntax = getAnyImportSyntax(declaration);
+                    if (anyImportSyntax &&
+                        !(anyImportSyntax.flags & 1) &&
+                        isDeclarationVisible(anyImportSyntax.parent)) {
+                        getNodeLinks(declaration).isVisible = true;
+                        if (aliasesToMakeVisible) {
+                            if (!ts.contains(aliasesToMakeVisible, anyImportSyntax)) {
+                                aliasesToMakeVisible.push(anyImportSyntax);
+                            }
+                        }
+                        else {
+                            aliasesToMakeVisible = [anyImportSyntax];
+                        }
+                        return true;
+                    }
+                    return false;
+                }
+                return true;
+            }
+        }
+        function isEntityNameVisible(entityName, enclosingDeclaration) {
+            var meaning;
+            if (entityName.parent.kind === 144) {
+                meaning = 107455 | 1048576;
+            }
+            else if (entityName.kind === 126 || entityName.kind === 155 ||
+                entityName.parent.kind === 208) {
+                meaning = 1536;
+            }
+            else {
+                meaning = 793056;
+            }
+            var firstIdentifier = getFirstIdentifier(entityName);
+            var symbol = resolveName(enclosingDeclaration, firstIdentifier.text, meaning, undefined, undefined);
+            return (symbol && hasVisibleDeclarations(symbol)) || {
+                accessibility: 1,
+                errorSymbolName: ts.getTextOfNode(firstIdentifier),
+                errorNode: firstIdentifier
+            };
+        }
+        function writeKeyword(writer, kind) {
+            writer.writeKeyword(ts.tokenToString(kind));
+        }
+        function writePunctuation(writer, kind) {
+            writer.writePunctuation(ts.tokenToString(kind));
+        }
+        function writeSpace(writer) {
+            writer.writeSpace(" ");
+        }
+        function symbolToString(symbol, enclosingDeclaration, meaning) {
+            var writer = ts.getSingleLineStringWriter();
+            getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning);
+            var result = writer.string();
+            ts.releaseStringWriter(writer);
+            return result;
+        }
+        function typeToString(type, enclosingDeclaration, flags) {
+            var writer = ts.getSingleLineStringWriter();
+            getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+            var result = writer.string();
+            ts.releaseStringWriter(writer);
+            var maxLength = compilerOptions.noErrorTruncation || flags & 4 ? undefined : 100;
+            if (maxLength && result.length >= maxLength) {
+                result = result.substr(0, maxLength - "...".length) + "...";
+            }
+            return result;
+        }
+        function getTypeAliasForTypeLiteral(type) {
+            if (type.symbol && type.symbol.flags & 2048) {
+                var node = type.symbol.declarations[0].parent;
+                while (node.kind === 149) {
+                    node = node.parent;
+                }
+                if (node.kind === 203) {
+                    return getSymbolOfNode(node);
+                }
+            }
+            return undefined;
+        }
+        var _displayBuilder;
+        function getSymbolDisplayBuilder() {
+            function appendSymbolNameOnly(symbol, writer) {
+                if (symbol.declarations && symbol.declarations.length > 0) {
+                    var declaration = symbol.declarations[0];
+                    if (declaration.name) {
+                        writer.writeSymbol(ts.declarationNameToString(declaration.name), symbol);
+                        return;
+                    }
+                }
+                writer.writeSymbol(symbol.name, symbol);
+            }
+            function buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags, typeFlags) {
+                var parentSymbol;
+                function appendParentTypeArgumentsAndSymbolName(symbol) {
+                    if (parentSymbol) {
+                        if (flags & 1) {
+                            if (symbol.flags & 16777216) {
+                                buildDisplayForTypeArgumentsAndDelimiters(getTypeParametersOfClassOrInterface(parentSymbol), symbol.mapper, writer, enclosingDeclaration);
+                            }
+                            else {
+                                buildTypeParameterDisplayFromSymbol(parentSymbol, writer, enclosingDeclaration);
+                            }
+                        }
+                        writePunctuation(writer, 20);
+                    }
+                    parentSymbol = symbol;
+                    appendSymbolNameOnly(symbol, writer);
+                }
+                writer.trackSymbol(symbol, enclosingDeclaration, meaning);
+                function walkSymbol(symbol, meaning) {
+                    if (symbol) {
+                        var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & 2));
+                        if (!accessibleSymbolChain ||
+                            needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
+                            walkSymbol(getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol), getQualifiedLeftMeaning(meaning));
+                        }
+                        if (accessibleSymbolChain) {
+                            for (var _i = 0; _i < accessibleSymbolChain.length; _i++) {
+                                var accessibleSymbol = accessibleSymbolChain[_i];
+                                appendParentTypeArgumentsAndSymbolName(accessibleSymbol);
+                            }
+                        }
+                        else {
+                            if (!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) {
+                                return;
+                            }
+                            if (symbol.flags & 2048 || symbol.flags & 4096) {
+                                return;
+                            }
+                            appendParentTypeArgumentsAndSymbolName(symbol);
+                        }
+                    }
+                }
+                var isTypeParameter = symbol.flags & 262144;
+                var typeFormatFlag = 128 & typeFlags;
+                if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) {
+                    walkSymbol(symbol, meaning);
+                    return;
+                }
+                return appendParentTypeArgumentsAndSymbolName(symbol);
+            }
+            function buildTypeDisplay(type, writer, enclosingDeclaration, globalFlags, typeStack) {
+                var globalFlagsToPass = globalFlags & 16;
+                return writeType(type, globalFlags);
+                function writeType(type, flags) {
+                    if (type.flags & 1048703) {
+                        writer.writeKeyword(!(globalFlags & 16) &&
+                            (type.flags & 1) ? "any" : type.intrinsicName);
+                    }
+                    else if (type.flags & 4096) {
+                        writeTypeReference(type, flags);
+                    }
+                    else if (type.flags & (1024 | 2048 | 128 | 512)) {
+                        buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 793056, 0, flags);
+                    }
+                    else if (type.flags & 8192) {
+                        writeTupleType(type);
+                    }
+                    else if (type.flags & 16384) {
+                        writeUnionType(type, flags);
+                    }
+                    else if (type.flags & 32768) {
+                        writeAnonymousType(type, flags);
+                    }
+                    else if (type.flags & 256) {
+                        writer.writeStringLiteral(type.text);
+                    }
+                    else {
+                        writePunctuation(writer, 14);
+                        writeSpace(writer);
+                        writePunctuation(writer, 21);
+                        writeSpace(writer);
+                        writePunctuation(writer, 15);
+                    }
+                }
+                function writeTypeList(types, union) {
+                    for (var i = 0; i < types.length; i++) {
+                        if (i > 0) {
+                            if (union) {
+                                writeSpace(writer);
+                            }
+                            writePunctuation(writer, union ? 44 : 23);
+                            writeSpace(writer);
+                        }
+                        writeType(types[i], union ? 64 : 0);
+                    }
+                }
+                function writeTypeReference(type, flags) {
+                    if (type.target === globalArrayType && !(flags & 1)) {
+                        writeType(type.typeArguments[0], 64);
+                        writePunctuation(writer, 18);
+                        writePunctuation(writer, 19);
+                    }
+                    else {
+                        buildSymbolDisplay(type.target.symbol, writer, enclosingDeclaration, 793056);
+                        writePunctuation(writer, 24);
+                        writeTypeList(type.typeArguments, false);
+                        writePunctuation(writer, 25);
+                    }
+                }
+                function writeTupleType(type) {
+                    writePunctuation(writer, 18);
+                    writeTypeList(type.elementTypes, false);
+                    writePunctuation(writer, 19);
+                }
+                function writeUnionType(type, flags) {
+                    if (flags & 64) {
+                        writePunctuation(writer, 16);
+                    }
+                    writeTypeList(type.types, true);
+                    if (flags & 64) {
+                        writePunctuation(writer, 17);
+                    }
+                }
+                function writeAnonymousType(type, flags) {
+                    if (type.symbol && type.symbol.flags & (32 | 384 | 512)) {
+                        writeTypeofSymbol(type, flags);
+                    }
+                    else if (shouldWriteTypeOfFunctionSymbol()) {
+                        writeTypeofSymbol(type, flags);
+                    }
+                    else if (typeStack && ts.contains(typeStack, type)) {
+                        var typeAlias = getTypeAliasForTypeLiteral(type);
+                        if (typeAlias) {
+                            buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, 793056, 0, flags);
+                        }
+                        else {
+                            writeKeyword(writer, 112);
+                        }
+                    }
+                    else {
+                        if (!typeStack) {
+                            typeStack = [];
+                        }
+                        typeStack.push(type);
+                        writeLiteralType(type, flags);
+                        typeStack.pop();
+                    }
+                    function shouldWriteTypeOfFunctionSymbol() {
+                        if (type.symbol) {
+                            var isStaticMethodSymbol = !!(type.symbol.flags & 8192 &&
+                                ts.forEach(type.symbol.declarations, function (declaration) { return declaration.flags & 128; }));
+                            var isNonLocalFunctionSymbol = !!(type.symbol.flags & 16) &&
+                                (type.symbol.parent ||
+                                    ts.forEach(type.symbol.declarations, function (declaration) {
+                                        return declaration.parent.kind === 227 || declaration.parent.kind === 206;
+                                    }));
+                            if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
+                                return !!(flags & 2) ||
+                                    (typeStack && ts.contains(typeStack, type));
+                            }
+                        }
+                    }
+                }
+                function writeTypeofSymbol(type, typeFormatFlags) {
+                    writeKeyword(writer, 97);
+                    writeSpace(writer);
+                    buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 107455, 0, typeFormatFlags);
+                }
+                function getIndexerParameterName(type, indexKind, fallbackName) {
+                    var declaration = getIndexDeclarationOfSymbol(type.symbol, indexKind);
+                    if (!declaration) {
+                        return fallbackName;
+                    }
+                    ts.Debug.assert(declaration.parameters.length !== 0);
+                    return ts.declarationNameToString(declaration.parameters[0].name);
+                }
+                function writeLiteralType(type, flags) {
+                    var resolved = resolveObjectOrUnionTypeMembers(type);
+                    if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) {
+                        if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
+                            writePunctuation(writer, 14);
+                            writePunctuation(writer, 15);
+                            return;
+                        }
+                        if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
+                            if (flags & 64) {
+                                writePunctuation(writer, 16);
+                            }
+                            buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | 8, typeStack);
+                            if (flags & 64) {
+                                writePunctuation(writer, 17);
+                            }
+                            return;
+                        }
+                        if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
+                            if (flags & 64) {
+                                writePunctuation(writer, 16);
+                            }
+                            writeKeyword(writer, 88);
+                            writeSpace(writer);
+                            buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | 8, typeStack);
+                            if (flags & 64) {
+                                writePunctuation(writer, 17);
+                            }
+                            return;
+                        }
+                    }
+                    writePunctuation(writer, 14);
+                    writer.writeLine();
+                    writer.increaseIndent();
+                    for (var _i = 0, _a = resolved.callSignatures; _i < _a.length; _i++) {
+                        var signature = _a[_i];
+                        buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
+                        writePunctuation(writer, 22);
+                        writer.writeLine();
+                    }
+                    for (var _b = 0, _c = resolved.constructSignatures; _b < _c.length; _b++) {
+                        var signature = _c[_b];
+                        writeKeyword(writer, 88);
+                        writeSpace(writer);
+                        buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
+                        writePunctuation(writer, 22);
+                        writer.writeLine();
+                    }
+                    if (resolved.stringIndexType) {
+                        writePunctuation(writer, 18);
+                        writer.writeParameter(getIndexerParameterName(resolved, 0, "x"));
+                        writePunctuation(writer, 51);
+                        writeSpace(writer);
+                        writeKeyword(writer, 121);
+                        writePunctuation(writer, 19);
+                        writePunctuation(writer, 51);
+                        writeSpace(writer);
+                        writeType(resolved.stringIndexType, 0);
+                        writePunctuation(writer, 22);
+                        writer.writeLine();
+                    }
+                    if (resolved.numberIndexType) {
+                        writePunctuation(writer, 18);
+                        writer.writeParameter(getIndexerParameterName(resolved, 1, "x"));
+                        writePunctuation(writer, 51);
+                        writeSpace(writer);
+                        writeKeyword(writer, 119);
+                        writePunctuation(writer, 19);
+                        writePunctuation(writer, 51);
+                        writeSpace(writer);
+                        writeType(resolved.numberIndexType, 0);
+                        writePunctuation(writer, 22);
+                        writer.writeLine();
+                    }
+                    for (var _d = 0, _e = resolved.properties; _d < _e.length; _d++) {
+                        var p = _e[_d];
+                        var t = getTypeOfSymbol(p);
+                        if (p.flags & (16 | 8192) && !getPropertiesOfObjectType(t).length) {
+                            var signatures = getSignaturesOfType(t, 0);
+                            for (var _f = 0; _f < signatures.length; _f++) {
+                                var signature = signatures[_f];
+                                buildSymbolDisplay(p, writer);
+                                if (p.flags & 536870912) {
+                                    writePunctuation(writer, 50);
+                                }
+                                buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
+                                writePunctuation(writer, 22);
+                                writer.writeLine();
+                            }
+                        }
+                        else {
+                            buildSymbolDisplay(p, writer);
+                            if (p.flags & 536870912) {
+                                writePunctuation(writer, 50);
+                            }
+                            writePunctuation(writer, 51);
+                            writeSpace(writer);
+                            writeType(t, 0);
+                            writePunctuation(writer, 22);
+                            writer.writeLine();
+                        }
+                    }
+                    writer.decreaseIndent();
+                    writePunctuation(writer, 15);
+                }
+            }
+            function buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaraiton, flags) {
+                var targetSymbol = getTargetSymbol(symbol);
+                if (targetSymbol.flags & 32 || targetSymbol.flags & 64) {
+                    buildDisplayForTypeParametersAndDelimiters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
+                }
+            }
+            function buildTypeParameterDisplay(tp, writer, enclosingDeclaration, flags, typeStack) {
+                appendSymbolNameOnly(tp.symbol, writer);
+                var constraint = getConstraintOfTypeParameter(tp);
+                if (constraint) {
+                    writeSpace(writer);
+                    writeKeyword(writer, 79);
+                    writeSpace(writer);
+                    buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, typeStack);
+                }
+            }
+            function buildParameterDisplay(p, writer, enclosingDeclaration, flags, typeStack) {
+                if (ts.hasDotDotDotToken(p.valueDeclaration)) {
+                    writePunctuation(writer, 21);
+                }
+                appendSymbolNameOnly(p, writer);
+                if (ts.hasQuestionToken(p.valueDeclaration) || p.valueDeclaration.initializer) {
+                    writePunctuation(writer, 50);
+                }
+                writePunctuation(writer, 51);
+                writeSpace(writer);
+                buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
+            }
+            function buildDisplayForTypeParametersAndDelimiters(typeParameters, writer, enclosingDeclaration, flags, typeStack) {
+                if (typeParameters && typeParameters.length) {
+                    writePunctuation(writer, 24);
+                    for (var i = 0; i < typeParameters.length; i++) {
+                        if (i > 0) {
+                            writePunctuation(writer, 23);
+                            writeSpace(writer);
+                        }
+                        buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, typeStack);
+                    }
+                    writePunctuation(writer, 25);
+                }
+            }
+            function buildDisplayForTypeArgumentsAndDelimiters(typeParameters, mapper, writer, enclosingDeclaration, flags, typeStack) {
+                if (typeParameters && typeParameters.length) {
+                    writePunctuation(writer, 24);
+                    for (var i = 0; i < typeParameters.length; i++) {
+                        if (i > 0) {
+                            writePunctuation(writer, 23);
+                            writeSpace(writer);
+                        }
+                        buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, 0);
+                    }
+                    writePunctuation(writer, 25);
+                }
+            }
+            function buildDisplayForParametersAndDelimiters(parameters, writer, enclosingDeclaration, flags, typeStack) {
+                writePunctuation(writer, 16);
+                for (var i = 0; i < parameters.length; i++) {
+                    if (i > 0) {
+                        writePunctuation(writer, 23);
+                        writeSpace(writer);
+                    }
+                    buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack);
+                }
+                writePunctuation(writer, 17);
+            }
+            function buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack) {
+                if (flags & 8) {
+                    writeSpace(writer);
+                    writePunctuation(writer, 32);
+                }
+                else {
+                    writePunctuation(writer, 51);
+                }
+                writeSpace(writer);
+                buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack);
+            }
+            function buildSignatureDisplay(signature, writer, enclosingDeclaration, flags, typeStack) {
+                if (signature.target && (flags & 32)) {
+                    buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
+                }
+                else {
+                    buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
+                }
+                buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack);
+                buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack);
+            }
+            return _displayBuilder || (_displayBuilder = {
+                symbolToString: symbolToString,
+                typeToString: typeToString,
+                buildSymbolDisplay: buildSymbolDisplay,
+                buildTypeDisplay: buildTypeDisplay,
+                buildTypeParameterDisplay: buildTypeParameterDisplay,
+                buildParameterDisplay: buildParameterDisplay,
+                buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
+                buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
+                buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
+                buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
+                buildSignatureDisplay: buildSignatureDisplay,
+                buildReturnTypeDisplay: buildReturnTypeDisplay
+            });
+        }
+        function isDeclarationVisible(node) {
+            function getContainingExternalModule(node) {
+                for (; node; node = node.parent) {
+                    if (node.kind === 205) {
+                        if (node.name.kind === 8) {
+                            return node;
+                        }
+                    }
+                    else if (node.kind === 227) {
+                        return ts.isExternalModule(node) ? node : undefined;
+                    }
+                }
+                ts.Debug.fail("getContainingModule cant reach here");
+            }
+            function isUsedInExportAssignment(node) {
+                var externalModule = getContainingExternalModule(node);
+                var exportAssignmentSymbol;
+                var resolvedExportSymbol;
+                if (externalModule) {
+                    var externalModuleSymbol = getSymbolOfNode(externalModule);
+                    exportAssignmentSymbol = getExportAssignmentSymbol(externalModuleSymbol);
+                    var symbolOfNode = getSymbolOfNode(node);
+                    if (isSymbolUsedInExportAssignment(symbolOfNode)) {
+                        return true;
+                    }
+                    if (symbolOfNode.flags & 8388608) {
+                        return isSymbolUsedInExportAssignment(resolveAlias(symbolOfNode));
+                    }
+                }
+                function isSymbolUsedInExportAssignment(symbol) {
+                    if (exportAssignmentSymbol === symbol) {
+                        return true;
+                    }
+                    if (exportAssignmentSymbol && !!(exportAssignmentSymbol.flags & 8388608)) {
+                        resolvedExportSymbol = resolvedExportSymbol || resolveAlias(exportAssignmentSymbol);
+                        if (resolvedExportSymbol === symbol) {
+                            return true;
+                        }
+                        return ts.forEach(resolvedExportSymbol.declarations, function (current) {
+                            while (current) {
+                                if (current === node) {
+                                    return true;
+                                }
+                                current = current.parent;
+                            }
+                        });
+                    }
+                }
+            }
+            function determineIfDeclarationIsVisible() {
+                switch (node.kind) {
+                    case 152:
+                        return isDeclarationVisible(node.parent.parent);
+                    case 198:
+                        if (ts.isBindingPattern(node.name) &&
+                            !node.name.elements.length) {
+                            return false;
+                        }
+                    case 205:
+                    case 201:
+                    case 202:
+                    case 203:
+                    case 200:
+                    case 204:
+                    case 208:
+                        var parent_1 = getDeclarationContainer(node);
+                        if (!(ts.getCombinedNodeFlags(node) & 1) &&
+                            !(node.kind !== 208 && parent_1.kind !== 227 && ts.isInAmbientContext(parent_1))) {
+                            return isGlobalSourceFile(parent_1);
+                        }
+                        return isDeclarationVisible(parent_1);
+                    case 132:
+                    case 131:
+                    case 136:
+                    case 137:
+                    case 134:
+                    case 133:
+                        if (node.flags & (32 | 64)) {
+                            return false;
+                        }
+                    case 135:
+                    case 139:
+                    case 138:
+                    case 140:
+                    case 129:
+                    case 206:
+                    case 142:
+                    case 143:
+                    case 145:
+                    case 141:
+                    case 146:
+                    case 147:
+                    case 148:
+                    case 149:
+                        return isDeclarationVisible(node.parent);
+                    case 210:
+                    case 211:
+                    case 213:
+                        return false;
+                    case 128:
+                    case 227:
+                        return true;
+                    case 214:
+                        return false;
+                    default:
+                        ts.Debug.fail("isDeclarationVisible unknown: SyntaxKind: " + node.kind);
+                }
+            }
+            if (node) {
+                var links = getNodeLinks(node);
+                if (links.isVisible === undefined) {
+                    links.isVisible = !!determineIfDeclarationIsVisible();
+                }
+                return links.isVisible;
+            }
+        }
+        function collectLinkedAliases(node) {
+            var exportSymbol;
+            if (node.parent && node.parent.kind === 214) {
+                exportSymbol = resolveName(node.parent, node.text, 107455 | 793056 | 1536, ts.Diagnostics.Cannot_find_name_0, node);
+            }
+            else if (node.parent.kind === 217) {
+                exportSymbol = getTargetOfExportSpecifier(node.parent);
+            }
+            var result = [];
+            if (exportSymbol) {
+                buildVisibleNodeList(exportSymbol.declarations);
+            }
+            return result;
+            function buildVisibleNodeList(declarations) {
+                ts.forEach(declarations, function (declaration) {
+                    getNodeLinks(declaration).isVisible = true;
+                    var resultNode = getAnyImportSyntax(declaration) || declaration;
+                    if (!ts.contains(result, resultNode)) {
+                        result.push(resultNode);
+                    }
+                    if (ts.isInternalModuleImportEqualsDeclaration(declaration)) {
+                        var internalModuleReference = declaration.moduleReference;
+                        var firstIdentifier = getFirstIdentifier(internalModuleReference);
+                        var importSymbol = resolveName(declaration, firstIdentifier.text, 107455 | 793056 | 1536, ts.Diagnostics.Cannot_find_name_0, firstIdentifier);
+                        buildVisibleNodeList(importSymbol.declarations);
+                    }
+                });
+            }
+        }
+        function getRootDeclaration(node) {
+            while (node.kind === 152) {
+                node = node.parent.parent;
+            }
+            return node;
+        }
+        function getDeclarationContainer(node) {
+            node = getRootDeclaration(node);
+            return node.kind === 198 ? node.parent.parent.parent : node.parent;
+        }
+        function getTypeOfPrototypeProperty(prototype) {
+            var classType = getDeclaredTypeOfSymbol(prototype.parent);
+            return classType.typeParameters ? createTypeReference(classType, ts.map(classType.typeParameters, function (_) { return anyType; })) : classType;
+        }
+        function getTypeOfPropertyOfType(type, name) {
+            var prop = getPropertyOfType(type, name);
+            return prop ? getTypeOfSymbol(prop) : undefined;
+        }
+        function getTypeForBindingElement(declaration) {
+            var pattern = declaration.parent;
+            var parentType = getTypeForVariableLikeDeclaration(pattern.parent);
+            if (parentType === unknownType) {
+                return unknownType;
+            }
+            if (!parentType || parentType === anyType) {
+                if (declaration.initializer) {
+                    return checkExpressionCached(declaration.initializer);
+                }
+                return parentType;
+            }
+            var type;
+            if (pattern.kind === 150) {
+                var name_2 = declaration.propertyName || declaration.name;
+                type = getTypeOfPropertyOfType(parentType, name_2.text) ||
+                    isNumericLiteralName(name_2.text) && getIndexTypeOfType(parentType, 1) ||
+                    getIndexTypeOfType(parentType, 0);
+                if (!type) {
+                    error(name_2, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_2));
+                    return unknownType;
+                }
+            }
+            else {
+                var elementType = checkIteratedTypeOrElementType(parentType, pattern, false);
+                if (!declaration.dotDotDotToken) {
+                    if (elementType.flags & 1) {
+                        return elementType;
+                    }
+                    var propName = "" + ts.indexOf(pattern.elements, declaration);
+                    type = isTupleLikeType(parentType)
+                        ? getTypeOfPropertyOfType(parentType, propName)
+                        : elementType;
+                    if (!type) {
+                        if (isTupleType(parentType)) {
+                            error(declaration, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), parentType.elementTypes.length, pattern.elements.length);
+                        }
+                        else {
+                            error(declaration, ts.Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName);
+                        }
+                        return unknownType;
+                    }
+                }
+                else {
+                    type = createArrayType(elementType);
+                }
+            }
+            return type;
+        }
+        function getTypeForVariableLikeDeclaration(declaration) {
+            if (declaration.parent.parent.kind === 187) {
+                return anyType;
+            }
+            if (declaration.parent.parent.kind === 188) {
+                return checkRightHandSideOfForOf(declaration.parent.parent.expression) || anyType;
+            }
+            if (ts.isBindingPattern(declaration.parent)) {
+                return getTypeForBindingElement(declaration);
+            }
+            if (declaration.type) {
+                return getTypeFromTypeNode(declaration.type);
+            }
+            if (declaration.kind === 129) {
+                var func = declaration.parent;
+                if (func.kind === 137 && !ts.hasDynamicName(func)) {
+                    var getter = ts.getDeclarationOfKind(declaration.parent.symbol, 136);
+                    if (getter) {
+                        return getReturnTypeOfSignature(getSignatureFromDeclaration(getter));
+                    }
+                }
+                var type = getContextuallyTypedParameterType(declaration);
+                if (type) {
+                    return type;
+                }
+            }
+            if (declaration.initializer) {
+                return checkExpressionCached(declaration.initializer);
+            }
+            if (declaration.kind === 225) {
+                return checkIdentifier(declaration.name);
+            }
+            return undefined;
+        }
+        function getTypeFromBindingElement(element) {
+            if (element.initializer) {
+                return getWidenedType(checkExpressionCached(element.initializer));
+            }
+            if (ts.isBindingPattern(element.name)) {
+                return getTypeFromBindingPattern(element.name);
+            }
+            return anyType;
+        }
+        function getTypeFromObjectBindingPattern(pattern) {
+            var members = {};
+            ts.forEach(pattern.elements, function (e) {
+                var flags = 4 | 67108864 | (e.initializer ? 536870912 : 0);
+                var name = e.propertyName || e.name;
+                var symbol = createSymbol(flags, name.text);
+                symbol.type = getTypeFromBindingElement(e);
+                members[symbol.name] = symbol;
+            });
+            return createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
+        }
+        function getTypeFromArrayBindingPattern(pattern) {
+            var hasSpreadElement = false;
+            var elementTypes = [];
+            ts.forEach(pattern.elements, function (e) {
+                elementTypes.push(e.kind === 175 || e.dotDotDotToken ? anyType : getTypeFromBindingElement(e));
+                if (e.dotDotDotToken) {
+                    hasSpreadElement = true;
+                }
+            });
+            if (!elementTypes.length) {
+                return languageVersion >= 2 ? createIterableType(anyType) : anyArrayType;
+            }
+            else if (hasSpreadElement) {
+                var unionOfElements = getUnionType(elementTypes);
+                return languageVersion >= 2 ? createIterableType(unionOfElements) : createArrayType(unionOfElements);
+            }
+            return createTupleType(elementTypes);
+        }
+        function getTypeFromBindingPattern(pattern) {
+            return pattern.kind === 150
+                ? getTypeFromObjectBindingPattern(pattern)
+                : getTypeFromArrayBindingPattern(pattern);
+        }
+        function getWidenedTypeForVariableLikeDeclaration(declaration, reportErrors) {
+            var type = getTypeForVariableLikeDeclaration(declaration);
+            if (type) {
+                if (reportErrors) {
+                    reportErrorsFromWidening(declaration, type);
+                }
+                return declaration.kind !== 224 ? getWidenedType(type) : type;
+            }
+            if (ts.isBindingPattern(declaration.name)) {
+                return getTypeFromBindingPattern(declaration.name);
+            }
+            type = declaration.dotDotDotToken ? anyArrayType : anyType;
+            if (reportErrors && compilerOptions.noImplicitAny) {
+                var root = getRootDeclaration(declaration);
+                if (!isPrivateWithinAmbient(root) && !(root.kind === 129 && isPrivateWithinAmbient(root.parent))) {
+                    reportImplicitAnyError(declaration, type);
+                }
+            }
+            return type;
+        }
+        function getTypeOfVariableOrParameterOrProperty(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.type) {
+                if (symbol.flags & 134217728) {
+                    return links.type = getTypeOfPrototypeProperty(symbol);
+                }
+                var declaration = symbol.valueDeclaration;
+                if (declaration.parent.kind === 223) {
+                    return links.type = anyType;
+                }
+                if (declaration.kind === 214) {
+                    return links.type = checkExpression(declaration.expression);
+                }
+                links.type = resolvingType;
+                var type = getWidenedTypeForVariableLikeDeclaration(declaration, true);
+                if (links.type === resolvingType) {
+                    links.type = type;
+                }
+            }
+            else if (links.type === resolvingType) {
+                links.type = anyType;
+                if (compilerOptions.noImplicitAny) {
+                    var diagnostic = symbol.valueDeclaration.type ?
+                        ts.Diagnostics._0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation :
+                        ts.Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer;
+                    error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
+                }
+            }
+            return links.type;
+        }
+        function getSetAccessorTypeAnnotationNode(accessor) {
+            return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
+        }
+        function getAnnotatedAccessorType(accessor) {
+            if (accessor) {
+                if (accessor.kind === 136) {
+                    return accessor.type && getTypeFromTypeNode(accessor.type);
+                }
+                else {
+                    var setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor);
+                    return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
+                }
+            }
+            return undefined;
+        }
+        function getTypeOfAccessors(symbol) {
+            var links = getSymbolLinks(symbol);
+            checkAndStoreTypeOfAccessors(symbol, links);
+            return links.type;
+        }
+        function checkAndStoreTypeOfAccessors(symbol, links) {
+            links = links || getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = resolvingType;
+                var getter = ts.getDeclarationOfKind(symbol, 136);
+                var setter = ts.getDeclarationOfKind(symbol, 137);
+                var type;
+                var getterReturnType = getAnnotatedAccessorType(getter);
+                if (getterReturnType) {
+                    type = getterReturnType;
+                }
+                else {
+                    var setterParameterType = getAnnotatedAccessorType(setter);
+                    if (setterParameterType) {
+                        type = setterParameterType;
+                    }
+                    else {
+                        if (getter && getter.body) {
+                            type = getReturnTypeFromBody(getter);
+                        }
+                        else {
+                            if (compilerOptions.noImplicitAny) {
+                                error(setter, ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
+                            }
+                            type = anyType;
+                        }
+                    }
+                }
+                if (links.type === resolvingType) {
+                    links.type = type;
+                }
+            }
+            else if (links.type === resolvingType) {
+                links.type = anyType;
+                if (compilerOptions.noImplicitAny) {
+                    var getter = ts.getDeclarationOfKind(symbol, 136);
+                    error(getter, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
+                }
+            }
+        }
+        function getTypeOfFuncClassEnumModule(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = createObjectType(32768, symbol);
+            }
+            return links.type;
+        }
+        function getTypeOfEnumMember(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = getDeclaredTypeOfEnum(getParentOfSymbol(symbol));
+            }
+            return links.type;
+        }
+        function getTypeOfAlias(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = getTypeOfSymbol(resolveAlias(symbol));
+            }
+            return links.type;
+        }
+        function getTypeOfInstantiatedSymbol(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
+            }
+            return links.type;
+        }
+        function getTypeOfSymbol(symbol) {
+            if (symbol.flags & 16777216) {
+                return getTypeOfInstantiatedSymbol(symbol);
+            }
+            if (symbol.flags & (3 | 4)) {
+                return getTypeOfVariableOrParameterOrProperty(symbol);
+            }
+            if (symbol.flags & (16 | 8192 | 32 | 384 | 512)) {
+                return getTypeOfFuncClassEnumModule(symbol);
+            }
+            if (symbol.flags & 8) {
+                return getTypeOfEnumMember(symbol);
+            }
+            if (symbol.flags & 98304) {
+                return getTypeOfAccessors(symbol);
+            }
+            if (symbol.flags & 8388608) {
+                return getTypeOfAlias(symbol);
+            }
+            return unknownType;
+        }
+        function getTargetType(type) {
+            return type.flags & 4096 ? type.target : type;
+        }
+        function hasBaseType(type, checkBase) {
+            return check(type);
+            function check(type) {
+                var target = getTargetType(type);
+                return target === checkBase || ts.forEach(getBaseTypes(target), check);
+            }
+        }
+        function getTypeParametersOfClassOrInterface(symbol) {
+            var result;
+            ts.forEach(symbol.declarations, function (node) {
+                if (node.kind === 202 || node.kind === 201) {
+                    var declaration = node;
+                    if (declaration.typeParameters && declaration.typeParameters.length) {
+                        ts.forEach(declaration.typeParameters, function (node) {
+                            var tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
+                            if (!result) {
+                                result = [tp];
+                            }
+                            else if (!ts.contains(result, tp)) {
+                                result.push(tp);
+                            }
+                        });
+                    }
+                }
+            });
+            return result;
+        }
+        function getBaseTypes(type) {
+            var typeWithBaseTypes = type;
+            if (!typeWithBaseTypes.baseTypes) {
+                if (type.symbol.flags & 32) {
+                    resolveBaseTypesOfClass(typeWithBaseTypes);
+                }
+                else if (type.symbol.flags & 64) {
+                    resolveBaseTypesOfInterface(typeWithBaseTypes);
+                }
+                else {
+                    ts.Debug.fail("type must be class or interface");
+                }
+            }
+            return typeWithBaseTypes.baseTypes;
+        }
+        function resolveBaseTypesOfClass(type) {
+            type.baseTypes = [];
+            var declaration = ts.getDeclarationOfKind(type.symbol, 201);
+            var baseTypeNode = ts.getClassExtendsHeritageClauseElement(declaration);
+            if (baseTypeNode) {
+                var baseType = getTypeFromHeritageClauseElement(baseTypeNode);
+                if (baseType !== unknownType) {
+                    if (getTargetType(baseType).flags & 1024) {
+                        if (type !== baseType && !hasBaseType(baseType, type)) {
+                            type.baseTypes.push(baseType);
+                        }
+                        else {
+                            error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 1));
+                        }
+                    }
+                    else {
+                        error(baseTypeNode, ts.Diagnostics.A_class_may_only_extend_another_class);
+                    }
+                }
+            }
+        }
+        function resolveBaseTypesOfInterface(type) {
+            type.baseTypes = [];
+            for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) {
+                var declaration = _a[_i];
+                if (declaration.kind === 202 && ts.getInterfaceBaseTypeNodes(declaration)) {
+                    for (var _b = 0, _c = ts.getInterfaceBaseTypeNodes(declaration); _b < _c.length; _b++) {
+                        var node = _c[_b];
+                        var baseType = getTypeFromHeritageClauseElement(node);
+                        if (baseType !== unknownType) {
+                            if (getTargetType(baseType).flags & (1024 | 2048)) {
+                                if (type !== baseType && !hasBaseType(baseType, type)) {
+                                    type.baseTypes.push(baseType);
+                                }
+                                else {
+                                    error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 1));
+                                }
+                            }
+                            else {
+                                error(node, ts.Diagnostics.An_interface_may_only_extend_a_class_or_another_interface);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        function getDeclaredTypeOfClassOrInterface(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                var kind = symbol.flags & 32 ? 1024 : 2048;
+                var type = links.declaredType = createObjectType(kind, symbol);
+                var typeParameters = getTypeParametersOfClassOrInterface(symbol);
+                if (typeParameters) {
+                    type.flags |= 4096;
+                    type.typeParameters = typeParameters;
+                    type.instantiations = {};
+                    type.instantiations[getTypeListId(type.typeParameters)] = type;
+                    type.target = type;
+                    type.typeArguments = type.typeParameters;
+                }
+            }
+            return links.declaredType;
+        }
+        function getDeclaredTypeOfTypeAlias(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                links.declaredType = resolvingType;
+                var declaration = ts.getDeclarationOfKind(symbol, 203);
+                var type = getTypeFromTypeNode(declaration.type);
+                if (links.declaredType === resolvingType) {
+                    links.declaredType = type;
+                }
+            }
+            else if (links.declaredType === resolvingType) {
+                links.declaredType = unknownType;
+                var declaration = ts.getDeclarationOfKind(symbol, 203);
+                error(declaration.name, ts.Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
+            }
+            return links.declaredType;
+        }
+        function getDeclaredTypeOfEnum(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                var type = createType(128);
+                type.symbol = symbol;
+                links.declaredType = type;
+            }
+            return links.declaredType;
+        }
+        function getDeclaredTypeOfTypeParameter(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                var type = createType(512);
+                type.symbol = symbol;
+                if (!ts.getDeclarationOfKind(symbol, 128).constraint) {
+                    type.constraint = noConstraintType;
+                }
+                links.declaredType = type;
+            }
+            return links.declaredType;
+        }
+        function getDeclaredTypeOfAlias(symbol) {
+            var links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol));
+            }
+            return links.declaredType;
+        }
+        function getDeclaredTypeOfSymbol(symbol) {
+            ts.Debug.assert((symbol.flags & 16777216) === 0);
+            if (symbol.flags & (32 | 64)) {
+                return getDeclaredTypeOfClassOrInterface(symbol);
+            }
+            if (symbol.flags & 524288) {
+                return getDeclaredTypeOfTypeAlias(symbol);
+            }
+            if (symbol.flags & 384) {
+                return getDeclaredTypeOfEnum(symbol);
+            }
+            if (symbol.flags & 262144) {
+                return getDeclaredTypeOfTypeParameter(symbol);
+            }
+            if (symbol.flags & 8388608) {
+                return getDeclaredTypeOfAlias(symbol);
+            }
+            return unknownType;
+        }
+        function createSymbolTable(symbols) {
+            var result = {};
+            for (var _i = 0; _i < symbols.length; _i++) {
+                var symbol = symbols[_i];
+                result[symbol.name] = symbol;
+            }
+            return result;
+        }
+        function createInstantiatedSymbolTable(symbols, mapper) {
+            var result = {};
+            for (var _i = 0; _i < symbols.length; _i++) {
+                var symbol = symbols[_i];
+                result[symbol.name] = instantiateSymbol(symbol, mapper);
+            }
+            return result;
+        }
+        function addInheritedMembers(symbols, baseSymbols) {
+            for (var _i = 0; _i < baseSymbols.length; _i++) {
+                var s = baseSymbols[_i];
+                if (!ts.hasProperty(symbols, s.name)) {
+                    symbols[s.name] = s;
+                }
+            }
+        }
+        function addInheritedSignatures(signatures, baseSignatures) {
+            if (baseSignatures) {
+                for (var _i = 0; _i < baseSignatures.length; _i++) {
+                    var signature = baseSignatures[_i];
+                    signatures.push(signature);
+                }
+            }
+        }
+        function resolveDeclaredMembers(type) {
+            if (!type.declaredProperties) {
+                var symbol = type.symbol;
+                type.declaredProperties = getNamedMembers(symbol.members);
+                type.declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]);
+                type.declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]);
+                type.declaredStringIndexType = getIndexTypeOfSymbol(symbol, 0);
+                type.declaredNumberIndexType = getIndexTypeOfSymbol(symbol, 1);
+            }
+            return type;
+        }
+        function resolveClassOrInterfaceMembers(type) {
+            var target = resolveDeclaredMembers(type);
+            var members = target.symbol.members;
+            var callSignatures = target.declaredCallSignatures;
+            var constructSignatures = target.declaredConstructSignatures;
+            var stringIndexType = target.declaredStringIndexType;
+            var numberIndexType = target.declaredNumberIndexType;
+            var baseTypes = getBaseTypes(target);
+            if (baseTypes.length) {
+                members = createSymbolTable(target.declaredProperties);
+                for (var _i = 0; _i < baseTypes.length; _i++) {
+                    var baseType = baseTypes[_i];
+                    addInheritedMembers(members, getPropertiesOfObjectType(baseType));
+                    callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(baseType, 0));
+                    constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(baseType, 1));
+                    stringIndexType = stringIndexType || getIndexTypeOfType(baseType, 0);
+                    numberIndexType = numberIndexType || getIndexTypeOfType(baseType, 1);
+                }
+            }
+            setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+        function resolveTypeReferenceMembers(type) {
+            var target = resolveDeclaredMembers(type.target);
+            var mapper = createTypeMapper(target.typeParameters, type.typeArguments);
+            var members = createInstantiatedSymbolTable(target.declaredProperties, mapper);
+            var callSignatures = instantiateList(target.declaredCallSignatures, mapper, instantiateSignature);
+            var constructSignatures = instantiateList(target.declaredConstructSignatures, mapper, instantiateSignature);
+            var stringIndexType = target.declaredStringIndexType ? instantiateType(target.declaredStringIndexType, mapper) : undefined;
+            var numberIndexType = target.declaredNumberIndexType ? instantiateType(target.declaredNumberIndexType, mapper) : undefined;
+            ts.forEach(getBaseTypes(target), function (baseType) {
+                var instantiatedBaseType = instantiateType(baseType, mapper);
+                addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
+                callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, 0));
+                constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, 1));
+                stringIndexType = stringIndexType || getIndexTypeOfType(instantiatedBaseType, 0);
+                numberIndexType = numberIndexType || getIndexTypeOfType(instantiatedBaseType, 1);
+            });
+            setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+        function createSignature(declaration, typeParameters, parameters, resolvedReturnType, minArgumentCount, hasRestParameter, hasStringLiterals) {
+            var sig = new Signature(checker);
+            sig.declaration = declaration;
+            sig.typeParameters = typeParameters;
+            sig.parameters = parameters;
+            sig.resolvedReturnType = resolvedReturnType;
+            sig.minArgumentCount = minArgumentCount;
+            sig.hasRestParameter = hasRestParameter;
+            sig.hasStringLiterals = hasStringLiterals;
+            return sig;
+        }
+        function cloneSignature(sig) {
+            return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
+        }
+        function getDefaultConstructSignatures(classType) {
+            var baseTypes = getBaseTypes(classType);
+            if (baseTypes.length) {
+                var baseType = baseTypes[0];
+                var baseSignatures = getSignaturesOfType(getTypeOfSymbol(baseType.symbol), 1);
+                return ts.map(baseSignatures, function (baseSignature) {
+                    var signature = baseType.flags & 4096 ?
+                        getSignatureInstantiation(baseSignature, baseType.typeArguments) : cloneSignature(baseSignature);
+                    signature.typeParameters = classType.typeParameters;
+                    signature.resolvedReturnType = classType;
+                    return signature;
+                });
+            }
+            return [createSignature(undefined, classType.typeParameters, emptyArray, classType, 0, false, false)];
+        }
+        function createTupleTypeMemberSymbols(memberTypes) {
+            var members = {};
+            for (var i = 0; i < memberTypes.length; i++) {
+                var symbol = createSymbol(4 | 67108864, "" + i);
+                symbol.type = memberTypes[i];
+                members[i] = symbol;
+            }
+            return members;
+        }
+        function resolveTupleTypeMembers(type) {
+            var arrayType = resolveObjectOrUnionTypeMembers(createArrayType(getUnionType(type.elementTypes)));
+            var members = createTupleTypeMemberSymbols(type.elementTypes);
+            addInheritedMembers(members, arrayType.properties);
+            setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
+        }
+        function signatureListsIdentical(s, t) {
+            if (s.length !== t.length) {
+                return false;
+            }
+            for (var i = 0; i < s.length; i++) {
+                if (!compareSignatures(s[i], t[i], false, compareTypes)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        function getUnionSignatures(types, kind) {
+            var signatureLists = ts.map(types, function (t) { return getSignaturesOfType(t, kind); });
+            var signatures = signatureLists[0];
+            for (var _i = 0; _i < signatures.length; _i++) {
+                var signature = signatures[_i];
+                if (signature.typeParameters) {
+                    return emptyArray;
+                }
+            }
+            for (var i_1 = 1; i_1 < signatureLists.length; i_1++) {
+                if (!signatureListsIdentical(signatures, signatureLists[i_1])) {
+                    return emptyArray;
+                }
+            }
+            var result = ts.map(signatures, cloneSignature);
+            for (var i = 0; i < result.length; i++) {
+                var s = result[i];
+                s.resolvedReturnType = undefined;
+                s.unionSignatures = ts.map(signatureLists, function (signatures) { return signatures[i]; });
+            }
+            return result;
+        }
+        function getUnionIndexType(types, kind) {
+            var indexTypes = [];
+            for (var _i = 0; _i < types.length; _i++) {
+                var type = types[_i];
+                var indexType = getIndexTypeOfType(type, kind);
+                if (!indexType) {
+                    return undefined;
+                }
+                indexTypes.push(indexType);
+            }
+            return getUnionType(indexTypes);
+        }
+        function resolveUnionTypeMembers(type) {
+            var callSignatures = getUnionSignatures(type.types, 0);
+            var constructSignatures = getUnionSignatures(type.types, 1);
+            var stringIndexType = getUnionIndexType(type.types, 0);
+            var numberIndexType = getUnionIndexType(type.types, 1);
+            setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+        function resolveAnonymousTypeMembers(type) {
+            var symbol = type.symbol;
+            var members;
+            var callSignatures;
+            var constructSignatures;
+            var stringIndexType;
+            var numberIndexType;
+            if (symbol.flags & 2048) {
+                members = symbol.members;
+                callSignatures = getSignaturesOfSymbol(members["__call"]);
+                constructSignatures = getSignaturesOfSymbol(members["__new"]);
+                stringIndexType = getIndexTypeOfSymbol(symbol, 0);
+                numberIndexType = getIndexTypeOfSymbol(symbol, 1);
+            }
+            else {
+                members = emptySymbols;
+                callSignatures = emptyArray;
+                constructSignatures = emptyArray;
+                if (symbol.flags & 1952) {
+                    members = getExportsOfSymbol(symbol);
+                }
+                if (symbol.flags & (16 | 8192)) {
+                    callSignatures = getSignaturesOfSymbol(symbol);
+                }
+                if (symbol.flags & 32) {
+                    var classType = getDeclaredTypeOfClassOrInterface(symbol);
+                    constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
+                    if (!constructSignatures.length) {
+                        constructSignatures = getDefaultConstructSignatures(classType);
+                    }
+                    var baseTypes = getBaseTypes(classType);
+                    if (baseTypes.length) {
+                        members = createSymbolTable(getNamedMembers(members));
+                        addInheritedMembers(members, getPropertiesOfObjectType(getTypeOfSymbol(baseTypes[0].symbol)));
+                    }
+                }
+                stringIndexType = undefined;
+                numberIndexType = (symbol.flags & 384) ? stringType : undefined;
+            }
+            setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+        function resolveObjectOrUnionTypeMembers(type) {
+            if (!type.members) {
+                if (type.flags & (1024 | 2048)) {
+                    resolveClassOrInterfaceMembers(type);
+                }
+                else if (type.flags & 32768) {
+                    resolveAnonymousTypeMembers(type);
+                }
+                else if (type.flags & 8192) {
+                    resolveTupleTypeMembers(type);
+                }
+                else if (type.flags & 16384) {
+                    resolveUnionTypeMembers(type);
+                }
+                else {
+                    resolveTypeReferenceMembers(type);
+                }
+            }
+            return type;
+        }
+        function getPropertiesOfObjectType(type) {
+            if (type.flags & 48128) {
+                return resolveObjectOrUnionTypeMembers(type).properties;
+            }
+            return emptyArray;
+        }
+        function getPropertyOfObjectType(type, name) {
+            if (type.flags & 48128) {
+                var resolved = resolveObjectOrUnionTypeMembers(type);
+                if (ts.hasProperty(resolved.members, name)) {
+                    var symbol = resolved.members[name];
+                    if (symbolIsValue(symbol)) {
+                        return symbol;
+                    }
+                }
+            }
+        }
+        function getPropertiesOfUnionType(type) {
+            var result = [];
+            ts.forEach(getPropertiesOfType(type.types[0]), function (prop) {
+                var unionProp = getPropertyOfUnionType(type, prop.name);
+                if (unionProp) {
+                    result.push(unionProp);
+                }
+            });
+            return result;
+        }
+        function getPropertiesOfType(type) {
+            type = getApparentType(type);
+            return type.flags & 16384 ? getPropertiesOfUnionType(type) : getPropertiesOfObjectType(type);
+        }
+        function getApparentType(type) {
+            if (type.flags & 16384) {
+                type = getReducedTypeOfUnionType(type);
+            }
+            if (type.flags & 512) {
+                do {
+                    type = getConstraintOfTypeParameter(type);
+                } while (type && type.flags & 512);
+                if (!type) {
+                    type = emptyObjectType;
+                }
+            }
+            if (type.flags & 258) {
+                type = globalStringType;
+            }
+            else if (type.flags & 132) {
+                type = globalNumberType;
+            }
+            else if (type.flags & 8) {
+                type = globalBooleanType;
+            }
+            else if (type.flags & 1048576) {
+                type = globalESSymbolType;
+            }
+            return type;
+        }
+        function createUnionProperty(unionType, name) {
+            var types = unionType.types;
+            var props;
+            for (var _i = 0; _i < types.length; _i++) {
+                var current = types[_i];
+                var type = getApparentType(current);
+                if (type !== unknownType) {
+                    var prop = getPropertyOfType(type, name);
+                    if (!prop || getDeclarationFlagsFromSymbol(prop) & (32 | 64)) {
+                        return undefined;
+                    }
+                    if (!props) {
+                        props = [prop];
+                    }
+                    else {
+                        props.push(prop);
+                    }
+                }
+            }
+            var propTypes = [];
+            var declarations = [];
+            for (var _a = 0; _a < props.length; _a++) {
+                var prop = props[_a];
+                if (prop.declarations) {
+                    declarations.push.apply(declarations, prop.declarations);
+                }
+                propTypes.push(getTypeOfSymbol(prop));
+            }
+            var result = createSymbol(4 | 67108864 | 268435456, name);
+            result.unionType = unionType;
+            result.declarations = declarations;
+            result.type = getUnionType(propTypes);
+            return result;
+        }
+        function getPropertyOfUnionType(type, name) {
+            var properties = type.resolvedProperties || (type.resolvedProperties = {});
+            if (ts.hasProperty(properties, name)) {
+                return properties[name];
+            }
+            var property = createUnionProperty(type, name);
+            if (property) {
+                properties[name] = property;
+            }
+            return property;
+        }
+        function getPropertyOfType(type, name) {
+            type = getApparentType(type);
+            if (type.flags & 48128) {
+                var resolved = resolveObjectOrUnionTypeMembers(type);
+                if (ts.hasProperty(resolved.members, name)) {
+                    var symbol = resolved.members[name];
+                    if (symbolIsValue(symbol)) {
+                        return symbol;
+                    }
+                }
+                if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
+                    var symbol = getPropertyOfObjectType(globalFunctionType, name);
+                    if (symbol) {
+                        return symbol;
+                    }
+                }
+                return getPropertyOfObjectType(globalObjectType, name);
+            }
+            if (type.flags & 16384) {
+                return getPropertyOfUnionType(type, name);
+            }
+            return undefined;
+        }
+        function getSignaturesOfObjectOrUnionType(type, kind) {
+            if (type.flags & (48128 | 16384)) {
+                var resolved = resolveObjectOrUnionTypeMembers(type);
+                return kind === 0 ? resolved.callSignatures : resolved.constructSignatures;
+            }
+            return emptyArray;
+        }
+        function getSignaturesOfType(type, kind) {
+            return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
+        }
+        function typeHasCallOrConstructSignatures(type) {
+            var apparentType = getApparentType(type);
+            if (apparentType.flags & (48128 | 16384)) {
+                var resolved = resolveObjectOrUnionTypeMembers(type);
+                return resolved.callSignatures.length > 0
+                    || resolved.constructSignatures.length > 0;
+            }
+            return false;
+        }
+        function getIndexTypeOfObjectOrUnionType(type, kind) {
+            if (type.flags & (48128 | 16384)) {
+                var resolved = resolveObjectOrUnionTypeMembers(type);
+                return kind === 0 ? resolved.stringIndexType : resolved.numberIndexType;
+            }
+        }
+        function getIndexTypeOfType(type, kind) {
+            return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind);
+        }
+        function getTypeParametersFromDeclaration(typeParameterDeclarations) {
+            var result = [];
+            ts.forEach(typeParameterDeclarations, function (node) {
+                var tp = getDeclaredTypeOfTypeParameter(node.symbol);
+                if (!ts.contains(result, tp)) {
+                    result.push(tp);
+                }
+            });
+            return result;
+        }
+        function symbolsToArray(symbols) {
+            var result = [];
+            for (var id in symbols) {
+                if (!isReservedMemberName(id)) {
+                    result.push(symbols[id]);
+                }
+            }
+            return result;
+        }
+        function getSignatureFromDeclaration(declaration) {
+            var links = getNodeLinks(declaration);
+            if (!links.resolvedSignature) {
+                var classType = declaration.kind === 135 ? getDeclaredTypeOfClassOrInterface(declaration.parent.symbol) : undefined;
+                var typeParameters = classType ? classType.typeParameters :
+                    declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined;
+                var parameters = [];
+                var hasStringLiterals = false;
+                var minArgumentCount = -1;
+                for (var i = 0, n = declaration.parameters.length; i < n; i++) {
+                    var param = declaration.parameters[i];
+                    parameters.push(param.symbol);
+                    if (param.type && param.type.kind === 8) {
+                        hasStringLiterals = true;
+                    }
+                    if (minArgumentCount < 0) {
+                        if (param.initializer || param.questionToken || param.dotDotDotToken) {
+                            minArgumentCount = i;
+                        }
+                    }
+                }
+                if (minArgumentCount < 0) {
+                    minArgumentCount = declaration.parameters.length;
+                }
+                var returnType;
+                if (classType) {
+                    returnType = classType;
+                }
+                else if (declaration.type) {
+                    returnType = getTypeFromTypeNode(declaration.type);
+                }
+                else {
+                    if (declaration.kind === 136 && !ts.hasDynamicName(declaration)) {
+                        var setter = ts.getDeclarationOfKind(declaration.symbol, 137);
+                        returnType = getAnnotatedAccessorType(setter);
+                    }
+                    if (!returnType && ts.nodeIsMissing(declaration.body)) {
+                        returnType = anyType;
+                    }
+                }
+                links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, minArgumentCount, ts.hasRestParameters(declaration), hasStringLiterals);
+            }
+            return links.resolvedSignature;
+        }
+        function getSignaturesOfSymbol(symbol) {
+            if (!symbol)
+                return emptyArray;
+            var result = [];
+            for (var i = 0, len = symbol.declarations.length; i < len; i++) {
+                var node = symbol.declarations[i];
+                switch (node.kind) {
+                    case 142:
+                    case 143:
+                    case 200:
+                    case 134:
+                    case 133:
+                    case 135:
+                    case 138:
+                    case 139:
+                    case 140:
+                    case 136:
+                    case 137:
+                    case 162:
+                    case 163:
+                        if (i > 0 && node.body) {
+                            var previous = symbol.declarations[i - 1];
+                            if (node.parent === previous.parent && node.kind === previous.kind && node.pos === previous.end) {
+                                break;
+                            }
+                        }
+                        result.push(getSignatureFromDeclaration(node));
+                }
+            }
+            return result;
+        }
+        function getReturnTypeOfSignature(signature) {
+            if (!signature.resolvedReturnType) {
+                signature.resolvedReturnType = resolvingType;
+                var type;
+                if (signature.target) {
+                    type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper);
+                }
+                else if (signature.unionSignatures) {
+                    type = getUnionType(ts.map(signature.unionSignatures, getReturnTypeOfSignature));
+                }
+                else {
+                    type = getReturnTypeFromBody(signature.declaration);
+                }
+                if (signature.resolvedReturnType === resolvingType) {
+                    signature.resolvedReturnType = type;
+                }
+            }
+            else if (signature.resolvedReturnType === resolvingType) {
+                signature.resolvedReturnType = anyType;
+                if (compilerOptions.noImplicitAny) {
+                    var declaration = signature.declaration;
+                    if (declaration.name) {
+                        error(declaration.name, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, ts.declarationNameToString(declaration.name));
+                    }
+                    else {
+                        error(declaration, ts.Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
+                    }
+                }
+            }
+            return signature.resolvedReturnType;
+        }
+        function getRestTypeOfSignature(signature) {
+            if (signature.hasRestParameter) {
+                var type = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
+                if (type.flags & 4096 && type.target === globalArrayType) {
+                    return type.typeArguments[0];
+                }
+            }
+            return anyType;
+        }
+        function getSignatureInstantiation(signature, typeArguments) {
+            return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), true);
+        }
+        function getErasedSignature(signature) {
+            if (!signature.typeParameters)
+                return signature;
+            if (!signature.erasedSignatureCache) {
+                if (signature.target) {
+                    signature.erasedSignatureCache = instantiateSignature(getErasedSignature(signature.target), signature.mapper);
+                }
+                else {
+                    signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), true);
+                }
+            }
+            return signature.erasedSignatureCache;
+        }
+        function getOrCreateTypeFromSignature(signature) {
+            if (!signature.isolatedSignatureType) {
+                var isConstructor = signature.declaration.kind === 135 || signature.declaration.kind === 139;
+                var type = createObjectType(32768 | 65536);
+                type.members = emptySymbols;
+                type.properties = emptyArray;
+                type.callSignatures = !isConstructor ? [signature] : emptyArray;
+                type.constructSignatures = isConstructor ? [signature] : emptyArray;
+                signature.isolatedSignatureType = type;
+            }
+            return signature.isolatedSignatureType;
+        }
+        function getIndexSymbol(symbol) {
+            return symbol.members["__index"];
+        }
+        function getIndexDeclarationOfSymbol(symbol, kind) {
+            var syntaxKind = kind === 1 ? 119 : 121;
+            var indexSymbol = getIndexSymbol(symbol);
+            if (indexSymbol) {
+                var len = indexSymbol.declarations.length;
+                for (var _i = 0, _a = indexSymbol.declarations; _i < _a.length; _i++) {
+                    var decl = _a[_i];
+                    var node = decl;
+                    if (node.parameters.length === 1) {
+                        var parameter = node.parameters[0];
+                        if (parameter && parameter.type && parameter.type.kind === syntaxKind) {
+                            return node;
+                        }
+                    }
+                }
+            }
+            return undefined;
+        }
+        function getIndexTypeOfSymbol(symbol, kind) {
+            var declaration = getIndexDeclarationOfSymbol(symbol, kind);
+            return declaration
+                ? declaration.type ? getTypeFromTypeNode(declaration.type) : anyType
+                : undefined;
+        }
+        function getConstraintOfTypeParameter(type) {
+            if (!type.constraint) {
+                if (type.target) {
+                    var targetConstraint = getConstraintOfTypeParameter(type.target);
+                    type.constraint = targetConstraint ? instantiateType(targetConstraint, type.mapper) : noConstraintType;
+                }
+                else {
+                    type.constraint = getTypeFromTypeNode(ts.getDeclarationOfKind(type.symbol, 128).constraint);
+                }
+            }
+            return type.constraint === noConstraintType ? undefined : type.constraint;
+        }
+        function getTypeListId(types) {
+            switch (types.length) {
+                case 1:
+                    return "" + types[0].id;
+                case 2:
+                    return types[0].id + "," + types[1].id;
+                default:
+                    var result = "";
+                    for (var i = 0; i < types.length; i++) {
+                        if (i > 0) {
+                            result += ",";
+                        }
+                        result += types[i].id;
+                    }
+                    return result;
+            }
+        }
+        function getWideningFlagsOfTypes(types) {
+            var result = 0;
+            for (var _i = 0; _i < types.length; _i++) {
+                var type = types[_i];
+                result |= type.flags;
+            }
+            return result & 786432;
+        }
+        function createTypeReference(target, typeArguments) {
+            var id = getTypeListId(typeArguments);
+            var type = target.instantiations[id];
+            if (!type) {
+                var flags = 4096 | getWideningFlagsOfTypes(typeArguments);
+                type = target.instantiations[id] = createObjectType(flags, target.symbol);
+                type.target = target;
+                type.typeArguments = typeArguments;
+            }
+            return type;
+        }
+        function isTypeParameterReferenceIllegalInConstraint(typeReferenceNode, typeParameterSymbol) {
+            var links = getNodeLinks(typeReferenceNode);
+            if (links.isIllegalTypeReferenceInConstraint !== undefined) {
+                return links.isIllegalTypeReferenceInConstraint;
+            }
+            var currentNode = typeReferenceNode;
+            while (!ts.forEach(typeParameterSymbol.declarations, function (d) { return d.parent === currentNode.parent; })) {
+                currentNode = currentNode.parent;
+            }
+            links.isIllegalTypeReferenceInConstraint = currentNode.kind === 128;
+            return links.isIllegalTypeReferenceInConstraint;
+        }
+        function checkTypeParameterHasIllegalReferencesInConstraint(typeParameter) {
+            var typeParameterSymbol;
+            function check(n) {
+                if (n.kind === 141 && n.typeName.kind === 65) {
+                    var links = getNodeLinks(n);
+                    if (links.isIllegalTypeReferenceInConstraint === undefined) {
+                        var symbol = resolveName(typeParameter, n.typeName.text, 793056, undefined, undefined);
+                        if (symbol && (symbol.flags & 262144)) {
+                            links.isIllegalTypeReferenceInConstraint = ts.forEach(symbol.declarations, function (d) { return d.parent == typeParameter.parent; });
+                        }
+                    }
+                    if (links.isIllegalTypeReferenceInConstraint) {
+                        error(typeParameter, ts.Diagnostics.Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list);
+                    }
+                }
+                ts.forEachChild(n, check);
+            }
+            if (typeParameter.constraint) {
+                typeParameterSymbol = getSymbolOfNode(typeParameter);
+                check(typeParameter.constraint);
+            }
+        }
+        function getTypeFromTypeReference(node) {
+            return getTypeFromTypeReferenceOrHeritageClauseElement(node);
+        }
+        function getTypeFromHeritageClauseElement(node) {
+            return getTypeFromTypeReferenceOrHeritageClauseElement(node);
+        }
+        function getTypeFromTypeReferenceOrHeritageClauseElement(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                var type;
+                if (node.kind !== 177 || ts.isSupportedHeritageClauseElement(node)) {
+                    var typeNameOrExpression = node.kind === 141
+                        ? node.typeName
+                        : node.expression;
+                    var symbol = resolveEntityName(typeNameOrExpression, 793056);
+                    if (symbol) {
+                        if ((symbol.flags & 262144) && isTypeParameterReferenceIllegalInConstraint(node, symbol)) {
+                            type = unknownType;
+                        }
+                        else {
+                            type = getDeclaredTypeOfSymbol(symbol);
+                            if (type.flags & (1024 | 2048) && type.flags & 4096) {
+                                var typeParameters = type.typeParameters;
+                                if (node.typeArguments && node.typeArguments.length === typeParameters.length) {
+                                    type = createTypeReference(type, ts.map(node.typeArguments, getTypeFromTypeNode));
+                                }
+                                else {
+                                    error(node, ts.Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, undefined, 1), typeParameters.length);
+                                    type = undefined;
+                                }
+                            }
+                            else {
+                                if (node.typeArguments) {
+                                    error(node, ts.Diagnostics.Type_0_is_not_generic, typeToString(type));
+                                    type = undefined;
+                                }
+                            }
+                        }
+                    }
+                }
+                links.resolvedType = type || unknownType;
+            }
+            return links.resolvedType;
+        }
+        function getTypeFromTypeQueryNode(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = getWidenedType(checkExpressionOrQualifiedName(node.exprName));
+            }
+            return links.resolvedType;
+        }
+        function getTypeOfGlobalSymbol(symbol, arity) {
+            function getTypeDeclaration(symbol) {
+                var declarations = symbol.declarations;
+                for (var _i = 0; _i < declarations.length; _i++) {
+                    var declaration = declarations[_i];
+                    switch (declaration.kind) {
+                        case 201:
+                        case 202:
+                        case 204:
+                            return declaration;
+                    }
+                }
+            }
+            if (!symbol) {
+                return emptyObjectType;
+            }
+            var type = getDeclaredTypeOfSymbol(symbol);
+            if (!(type.flags & 48128)) {
+                error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbol.name);
+                return emptyObjectType;
+            }
+            if ((type.typeParameters ? type.typeParameters.length : 0) !== arity) {
+                error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbol.name, arity);
+                return emptyObjectType;
+            }
+            return type;
+        }
+        function getGlobalValueSymbol(name) {
+            return getGlobalSymbol(name, 107455, ts.Diagnostics.Cannot_find_global_value_0);
+        }
+        function getGlobalTypeSymbol(name) {
+            return getGlobalSymbol(name, 793056, ts.Diagnostics.Cannot_find_global_type_0);
+        }
+        function getGlobalSymbol(name, meaning, diagnostic) {
+            return resolveName(undefined, name, meaning, diagnostic, name);
+        }
+        function getGlobalType(name, arity) {
+            if (arity === void 0) { arity = 0; }
+            return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity);
+        }
+        function getGlobalESSymbolConstructorSymbol() {
+            return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"));
+        }
+        function createIterableType(elementType) {
+            return globalIterableType !== emptyObjectType ? createTypeReference(globalIterableType, [elementType]) : emptyObjectType;
+        }
+        function createArrayType(elementType) {
+            var arrayType = globalArrayType || getDeclaredTypeOfSymbol(globalArraySymbol);
+            return arrayType !== emptyObjectType ? createTypeReference(arrayType, [elementType]) : emptyObjectType;
+        }
+        function getTypeFromArrayTypeNode(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
+            }
+            return links.resolvedType;
+        }
+        function createTupleType(elementTypes) {
+            var id = getTypeListId(elementTypes);
+            var type = tupleTypes[id];
+            if (!type) {
+                type = tupleTypes[id] = createObjectType(8192);
+                type.elementTypes = elementTypes;
+            }
+            return type;
+        }
+        function getTypeFromTupleTypeNode(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = createTupleType(ts.map(node.elementTypes, getTypeFromTypeNode));
+            }
+            return links.resolvedType;
+        }
+        function addTypeToSortedSet(sortedSet, type) {
+            if (type.flags & 16384) {
+                addTypesToSortedSet(sortedSet, type.types);
+            }
+            else {
+                var i = 0;
+                var id = type.id;
+                while (i < sortedSet.length && sortedSet[i].id < id) {
+                    i++;
+                }
+                if (i === sortedSet.length || sortedSet[i].id !== id) {
+                    sortedSet.splice(i, 0, type);
+                }
+            }
+        }
+        function addTypesToSortedSet(sortedTypes, types) {
+            for (var _i = 0; _i < types.length; _i++) {
+                var type = types[_i];
+                addTypeToSortedSet(sortedTypes, type);
+            }
+        }
+        function isSubtypeOfAny(candidate, types) {
+            for (var _i = 0; _i < types.length; _i++) {
+                var type = types[_i];
+                if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        function removeSubtypes(types) {
+            var i = types.length;
+            while (i > 0) {
+                i--;
+                if (isSubtypeOfAny(types[i], types)) {
+                    types.splice(i, 1);
+                }
+            }
+        }
+        function containsAnyType(types) {
+            for (var _i = 0; _i < types.length; _i++) {
+                var type = types[_i];
+                if (type.flags & 1) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        function removeAllButLast(types, typeToRemove) {
+            var i = types.length;
+            while (i > 0 && types.length > 1) {
+                i--;
+                if (types[i] === typeToRemove) {
+                    types.splice(i, 1);
+                }
+            }
+        }
+        function getUnionType(types, noSubtypeReduction) {
+            if (types.length === 0) {
+                return emptyObjectType;
+            }
+            var sortedTypes = [];
+            addTypesToSortedSet(sortedTypes, types);
+            if (noSubtypeReduction) {
+                if (containsAnyType(sortedTypes)) {
+                    return anyType;
+                }
+                removeAllButLast(sortedTypes, undefinedType);
+                removeAllButLast(sortedTypes, nullType);
+            }
+            else {
+                removeSubtypes(sortedTypes);
+            }
+            if (sortedTypes.length === 1) {
+                return sortedTypes[0];
+            }
+            var id = getTypeListId(sortedTypes);
+            var type = unionTypes[id];
+            if (!type) {
+                type = unionTypes[id] = createObjectType(16384 | getWideningFlagsOfTypes(sortedTypes));
+                type.types = sortedTypes;
+                type.reducedType = noSubtypeReduction ? undefined : type;
+            }
+            return type;
+        }
+        function getReducedTypeOfUnionType(type) {
+            if (!type.reducedType) {
+                type.reducedType = getUnionType(type.types, false);
+            }
+            return type.reducedType;
+        }
+        function getTypeFromUnionTypeNode(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), true);
+            }
+            return links.resolvedType;
+        }
+        function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = createObjectType(32768, node.symbol);
+            }
+            return links.resolvedType;
+        }
+        function getStringLiteralType(node) {
+            if (ts.hasProperty(stringLiteralTypes, node.text)) {
+                return stringLiteralTypes[node.text];
+            }
+            var type = stringLiteralTypes[node.text] = createType(256);
+            type.text = ts.getTextOfNode(node);
+            return type;
+        }
+        function getTypeFromStringLiteral(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = getStringLiteralType(node);
+            }
+            return links.resolvedType;
+        }
+        function getTypeFromTypeNode(node) {
+            switch (node.kind) {
+                case 112:
+                    return anyType;
+                case 121:
+                    return stringType;
+                case 119:
+                    return numberType;
+                case 113:
+                    return booleanType;
+                case 122:
+                    return esSymbolType;
+                case 99:
+                    return voidType;
+                case 8:
+                    return getTypeFromStringLiteral(node);
+                case 141:
+                    return getTypeFromTypeReference(node);
+                case 177:
+                    return getTypeFromHeritageClauseElement(node);
+                case 144:
+                    return getTypeFromTypeQueryNode(node);
+                case 146:
+                    return getTypeFromArrayTypeNode(node);
+                case 147:
+                    return getTypeFromTupleTypeNode(node);
+                case 148:
+                    return getTypeFromUnionTypeNode(node);
+                case 149:
+                    return getTypeFromTypeNode(node.type);
+                case 142:
+                case 143:
+                case 145:
+                    return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
+                case 65:
+                case 126:
+                    var symbol = getSymbolInfo(node);
+                    return symbol && getDeclaredTypeOfSymbol(symbol);
+                default:
+                    return unknownType;
+            }
+        }
+        function instantiateList(items, mapper, instantiator) {
+            if (items && items.length) {
+                var result = [];
+                for (var _i = 0; _i < items.length; _i++) {
+                    var v = items[_i];
+                    result.push(instantiator(v, mapper));
+                }
+                return result;
+            }
+            return items;
+        }
+        function createUnaryTypeMapper(source, target) {
+            return function (t) { return t === source ? target : t; };
+        }
+        function createBinaryTypeMapper(source1, target1, source2, target2) {
+            return function (t) { return t === source1 ? target1 : t === source2 ? target2 : t; };
+        }
+        function createTypeMapper(sources, targets) {
+            switch (sources.length) {
+                case 1: return createUnaryTypeMapper(sources[0], targets[0]);
+                case 2: return createBinaryTypeMapper(sources[0], targets[0], sources[1], targets[1]);
+            }
+            return function (t) {
+                for (var i = 0; i < sources.length; i++) {
+                    if (t === sources[i]) {
+                        return targets[i];
+                    }
+                }
+                return t;
+            };
+        }
+        function createUnaryTypeEraser(source) {
+            return function (t) { return t === source ? anyType : t; };
+        }
+        function createBinaryTypeEraser(source1, source2) {
+            return function (t) { return t === source1 || t === source2 ? anyType : t; };
+        }
+        function createTypeEraser(sources) {
+            switch (sources.length) {
+                case 1: return createUnaryTypeEraser(sources[0]);
+                case 2: return createBinaryTypeEraser(sources[0], sources[1]);
+            }
+            return function (t) {
+                for (var _i = 0; _i < sources.length; _i++) {
+                    var source = sources[_i];
+                    if (t === source) {
+                        return anyType;
+                    }
+                }
+                return t;
+            };
+        }
+        function createInferenceMapper(context) {
+            return function (t) {
+                for (var i = 0; i < context.typeParameters.length; i++) {
+                    if (t === context.typeParameters[i]) {
+                        context.inferences[i].isFixed = true;
+                        return getInferredType(context, i);
+                    }
+                }
+                return t;
+            };
+        }
+        function identityMapper(type) {
+            return type;
+        }
+        function combineTypeMappers(mapper1, mapper2) {
+            return function (t) { return instantiateType(mapper1(t), mapper2); };
+        }
+        function instantiateTypeParameter(typeParameter, mapper) {
+            var result = createType(512);
+            result.symbol = typeParameter.symbol;
+            if (typeParameter.constraint) {
+                result.constraint = instantiateType(typeParameter.constraint, mapper);
+            }
+            else {
+                result.target = typeParameter;
+                result.mapper = mapper;
+            }
+            return result;
+        }
+        function instantiateSignature(signature, mapper, eraseTypeParameters) {
+            var freshTypeParameters;
+            if (signature.typeParameters && !eraseTypeParameters) {
+                freshTypeParameters = instantiateList(signature.typeParameters, mapper, instantiateTypeParameter);
+                mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper);
+            }
+            var result = createSignature(signature.declaration, freshTypeParameters, instantiateList(signature.parameters, mapper, instantiateSymbol), signature.resolvedReturnType ? instantiateType(signature.resolvedReturnType, mapper) : undefined, signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
+            result.target = signature;
+            result.mapper = mapper;
+            return result;
+        }
+        function instantiateSymbol(symbol, mapper) {
+            if (symbol.flags & 16777216) {
+                var links = getSymbolLinks(symbol);
+                symbol = links.target;
+                mapper = combineTypeMappers(links.mapper, mapper);
+            }
+            var result = createSymbol(16777216 | 67108864 | symbol.flags, symbol.name);
+            result.declarations = symbol.declarations;
+            result.parent = symbol.parent;
+            result.target = symbol;
+            result.mapper = mapper;
+            if (symbol.valueDeclaration) {
+                result.valueDeclaration = symbol.valueDeclaration;
+            }
+            return result;
+        }
+        function instantiateAnonymousType(type, mapper) {
+            var result = createObjectType(32768, type.symbol);
+            result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
+            result.members = createSymbolTable(result.properties);
+            result.callSignatures = instantiateList(getSignaturesOfType(type, 0), mapper, instantiateSignature);
+            result.constructSignatures = instantiateList(getSignaturesOfType(type, 1), mapper, instantiateSignature);
+            var stringIndexType = getIndexTypeOfType(type, 0);
+            var numberIndexType = getIndexTypeOfType(type, 1);
+            if (stringIndexType)
+                result.stringIndexType = instantiateType(stringIndexType, mapper);
+            if (numberIndexType)
+                result.numberIndexType = instantiateType(numberIndexType, mapper);
+            return result;
+        }
+        function instantiateType(type, mapper) {
+            if (mapper !== identityMapper) {
+                if (type.flags & 512) {
+                    return mapper(type);
+                }
+                if (type.flags & 32768) {
+                    return type.symbol && type.symbol.flags & (16 | 8192 | 2048 | 4096) ?
+                        instantiateAnonymousType(type, mapper) : type;
+                }
+                if (type.flags & 4096) {
+                    return createTypeReference(type.target, instantiateList(type.typeArguments, mapper, instantiateType));
+                }
+                if (type.flags & 8192) {
+                    return createTupleType(instantiateList(type.elementTypes, mapper, instantiateType));
+                }
+                if (type.flags & 16384) {
+                    return getUnionType(instantiateList(type.types, mapper, instantiateType), true);
+                }
+            }
+            return type;
+        }
+        function isContextSensitive(node) {
+            ts.Debug.assert(node.kind !== 134 || ts.isObjectLiteralMethod(node));
+            switch (node.kind) {
+                case 162:
+                case 163:
+                    return isContextSensitiveFunctionLikeDeclaration(node);
+                case 154:
+                    return ts.forEach(node.properties, isContextSensitive);
+                case 153:
+                    return ts.forEach(node.elements, isContextSensitive);
+                case 170:
+                    return isContextSensitive(node.whenTrue) ||
+                        isContextSensitive(node.whenFalse);
+                case 169:
+                    return node.operatorToken.kind === 49 &&
+                        (isContextSensitive(node.left) || isContextSensitive(node.right));
+                case 224:
+                    return isContextSensitive(node.initializer);
+                case 134:
+                case 133:
+                    return isContextSensitiveFunctionLikeDeclaration(node);
+                case 161:
+                    return isContextSensitive(node.expression);
+            }
+            return false;
+        }
+        function isContextSensitiveFunctionLikeDeclaration(node) {
+            return !node.typeParameters && node.parameters.length && !ts.forEach(node.parameters, function (p) { return p.type; });
+        }
+        function getTypeWithoutConstructors(type) {
+            if (type.flags & 48128) {
+                var resolved = resolveObjectOrUnionTypeMembers(type);
+                if (resolved.constructSignatures.length) {
+                    var result = createObjectType(32768, type.symbol);
+                    result.members = resolved.members;
+                    result.properties = resolved.properties;
+                    result.callSignatures = resolved.callSignatures;
+                    result.constructSignatures = emptyArray;
+                    type = result;
+                }
+            }
+            return type;
+        }
+        var subtypeRelation = {};
+        var assignableRelation = {};
+        var identityRelation = {};
+        function isTypeIdenticalTo(source, target) {
+            return checkTypeRelatedTo(source, target, identityRelation, undefined);
+        }
+        function compareTypes(source, target) {
+            return checkTypeRelatedTo(source, target, identityRelation, undefined) ? -1 : 0;
+        }
+        function isTypeSubtypeOf(source, target) {
+            return checkTypeSubtypeOf(source, target, undefined);
+        }
+        function isTypeAssignableTo(source, target) {
+            return checkTypeAssignableTo(source, target, undefined);
+        }
+        function checkTypeSubtypeOf(source, target, errorNode, headMessage, containingMessageChain) {
+            return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain);
+        }
+        function checkTypeAssignableTo(source, target, errorNode, headMessage) {
+            return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage);
+        }
+        function isSignatureAssignableTo(source, target) {
+            var sourceType = getOrCreateTypeFromSignature(source);
+            var targetType = getOrCreateTypeFromSignature(target);
+            return checkTypeRelatedTo(sourceType, targetType, assignableRelation, undefined);
+        }
+        function checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain) {
+            var errorInfo;
+            var sourceStack;
+            var targetStack;
+            var maybeStack;
+            var expandingFlags;
+            var depth = 0;
+            var overflow = false;
+            var elaborateErrors = false;
+            ts.Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
+            var result = isRelatedTo(source, target, errorNode !== undefined, headMessage);
+            if (overflow) {
+                error(errorNode, ts.Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
+            }
+            else if (errorInfo) {
+                if (errorInfo.next === undefined) {
+                    errorInfo = undefined;
+                    elaborateErrors = true;
+                    isRelatedTo(source, target, errorNode !== undefined, headMessage);
+                }
+                if (containingMessageChain) {
+                    errorInfo = ts.concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
+                }
+                diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, errorInfo));
+            }
+            return result !== 0;
+            function reportError(message, arg0, arg1, arg2) {
+                errorInfo = ts.chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
+            }
+            function isRelatedTo(source, target, reportErrors, headMessage) {
+                var result;
+                if (source === target)
+                    return -1;
+                if (relation !== identityRelation) {
+                    if (target.flags & 1)
+                        return -1;
+                    if (source === undefinedType)
+                        return -1;
+                    if (source === nullType && target !== undefinedType)
+                        return -1;
+                    if (source.flags & 128 && target === numberType)
+                        return -1;
+                    if (source.flags & 256 && target === stringType)
+                        return -1;
+                    if (relation === assignableRelation) {
+                        if (source.flags & 1)
+                            return -1;
+                        if (source === numberType && target.flags & 128)
+                            return -1;
+                    }
+                }
+                var saveErrorInfo = errorInfo;
+                if (source.flags & 16384 || target.flags & 16384) {
+                    if (relation === identityRelation) {
+                        if (source.flags & 16384 && target.flags & 16384) {
+                            if (result = unionTypeRelatedToUnionType(source, target)) {
+                                if (result &= unionTypeRelatedToUnionType(target, source)) {
+                                    return result;
+                                }
+                            }
+                        }
+                        else if (source.flags & 16384) {
+                            if (result = unionTypeRelatedToType(source, target, reportErrors)) {
+                                return result;
+                            }
+                        }
+                        else {
+                            if (result = unionTypeRelatedToType(target, source, reportErrors)) {
+                                return result;
+                            }
+                        }
+                    }
+                    else {
+                        if (source.flags & 16384) {
+                            if (result = unionTypeRelatedToType(source, target, reportErrors)) {
+                                return result;
+                            }
+                        }
+                        else {
+                            if (result = typeRelatedToUnionType(source, target, reportErrors)) {
+                                return result;
+                            }
+                        }
+                    }
+                }
+                else if (source.flags & 512 && target.flags & 512) {
+                    if (result = typeParameterRelatedTo(source, target, reportErrors)) {
+                        return result;
+                    }
+                }
+                else if (source.flags & 4096 && target.flags & 4096 && source.target === target.target) {
+                    if (result = typesRelatedTo(source.typeArguments, target.typeArguments, reportErrors)) {
+                        return result;
+                    }
+                }
+                var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
+                var sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
+                if (sourceOrApparentType.flags & 48128 && target.flags & 48128) {
+                    if (result = objectTypeRelatedTo(sourceOrApparentType, target, reportStructuralErrors)) {
+                        errorInfo = saveErrorInfo;
+                        return result;
+                    }
+                }
+                else if (source.flags & 512 && sourceOrApparentType.flags & 16384) {
+                    errorInfo = saveErrorInfo;
+                    if (result = isRelatedTo(sourceOrApparentType, target, reportErrors)) {
+                        return result;
+                    }
+                }
+                if (reportErrors) {
+                    headMessage = headMessage || ts.Diagnostics.Type_0_is_not_assignable_to_type_1;
+                    var sourceType = typeToString(source);
+                    var targetType = typeToString(target);
+                    if (sourceType === targetType) {
+                        sourceType = typeToString(source, undefined, 128);
+                        targetType = typeToString(target, undefined, 128);
+                    }
+                    reportError(headMessage, sourceType, targetType);
+                }
+                return 0;
+            }
+            function unionTypeRelatedToUnionType(source, target) {
+                var result = -1;
+                var sourceTypes = source.types;
+                for (var _i = 0; _i < sourceTypes.length; _i++) {
+                    var sourceType = sourceTypes[_i];
+                    var related = typeRelatedToUnionType(sourceType, target, false);
+                    if (!related) {
+                        return 0;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+            function typeRelatedToUnionType(source, target, reportErrors) {
+                var targetTypes = target.types;
+                for (var i = 0, len = targetTypes.length; i < len; i++) {
+                    var related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
+                    if (related) {
+                        return related;
+                    }
+                }
+                return 0;
+            }
+            function unionTypeRelatedToType(source, target, reportErrors) {
+                var result = -1;
+                var sourceTypes = source.types;
+                for (var _i = 0; _i < sourceTypes.length; _i++) {
+                    var sourceType = sourceTypes[_i];
+                    var related = isRelatedTo(sourceType, target, reportErrors);
+                    if (!related) {
+                        return 0;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+            function typesRelatedTo(sources, targets, reportErrors) {
+                var result = -1;
+                for (var i = 0, len = sources.length; i < len; i++) {
+                    var related = isRelatedTo(sources[i], targets[i], reportErrors);
+                    if (!related) {
+                        return 0;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+            function typeParameterRelatedTo(source, target, reportErrors) {
+                if (relation === identityRelation) {
+                    if (source.symbol.name !== target.symbol.name) {
+                        return 0;
+                    }
+                    if (source.constraint === target.constraint) {
+                        return -1;
+                    }
+                    if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
+                        return 0;
+                    }
+                    return isRelatedTo(source.constraint, target.constraint, reportErrors);
+                }
+                else {
+                    while (true) {
+                        var constraint = getConstraintOfTypeParameter(source);
+                        if (constraint === target)
+                            return -1;
+                        if (!(constraint && constraint.flags & 512))
+                            break;
+                        source = constraint;
+                    }
+                    return 0;
+                }
+            }
+            function objectTypeRelatedTo(source, target, reportErrors) {
+                if (overflow) {
+                    return 0;
+                }
+                var id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
+                var related = relation[id];
+                if (related !== undefined) {
+                    if (!elaborateErrors || (related === 3)) {
+                        return related === 1 ? -1 : 0;
+                    }
+                }
+                if (depth > 0) {
+                    for (var i = 0; i < depth; i++) {
+                        if (maybeStack[i][id]) {
+                            return 1;
+                        }
+                    }
+                    if (depth === 100) {
+                        overflow = true;
+                        return 0;
+                    }
+                }
+                else {
+                    sourceStack = [];
+                    targetStack = [];
+                    maybeStack = [];
+                    expandingFlags = 0;
+                }
+                sourceStack[depth] = source;
+                targetStack[depth] = target;
+                maybeStack[depth] = {};
+                maybeStack[depth][id] = 1;
+                depth++;
+                var saveExpandingFlags = expandingFlags;
+                if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack))
+                    expandingFlags |= 1;
+                if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack))
+                    expandingFlags |= 2;
+                var result;
+                if (expandingFlags === 3) {
+                    result = 1;
+                }
+                else {
+                    result = propertiesRelatedTo(source, target, reportErrors);
+                    if (result) {
+                        result &= signaturesRelatedTo(source, target, 0, reportErrors);
+                        if (result) {
+                            result &= signaturesRelatedTo(source, target, 1, reportErrors);
+                            if (result) {
+                                result &= stringIndexTypesRelatedTo(source, target, reportErrors);
+                                if (result) {
+                                    result &= numberIndexTypesRelatedTo(source, target, reportErrors);
+                                }
+                            }
+                        }
+                    }
+                }
+                expandingFlags = saveExpandingFlags;
+                depth--;
+                if (result) {
+                    var maybeCache = maybeStack[depth];
+                    var destinationCache = (result === -1 || depth === 0) ? relation : maybeStack[depth - 1];
+                    ts.copyMap(maybeCache, destinationCache);
+                }
+                else {
+                    relation[id] = reportErrors ? 3 : 2;
+                }
+                return result;
+            }
+            function isDeeplyNestedGeneric(type, stack) {
+                if (type.flags & 4096 && depth >= 10) {
+                    var target_1 = type.target;
+                    var count = 0;
+                    for (var i = 0; i < depth; i++) {
+                        var t = stack[i];
+                        if (t.flags & 4096 && t.target === target_1) {
+                            count++;
+                            if (count >= 10)
+                                return true;
+                        }
+                    }
+                }
+                return false;
+            }
+            function propertiesRelatedTo(source, target, reportErrors) {
+                if (relation === identityRelation) {
+                    return propertiesIdenticalTo(source, target);
+                }
+                var result = -1;
+                var properties = getPropertiesOfObjectType(target);
+                var requireOptionalProperties = relation === subtypeRelation && !(source.flags & 131072);
+                for (var _i = 0; _i < properties.length; _i++) {
+                    var targetProp = properties[_i];
+                    var sourceProp = getPropertyOfType(source, targetProp.name);
+                    if (sourceProp !== targetProp) {
+                        if (!sourceProp) {
+                            if (!(targetProp.flags & 536870912) || requireOptionalProperties) {
+                                if (reportErrors) {
+                                    reportError(ts.Diagnostics.Property_0_is_missing_in_type_1, symbolToString(targetProp), typeToString(source));
+                                }
+                                return 0;
+                            }
+                        }
+                        else if (!(targetProp.flags & 134217728)) {
+                            var sourceFlags = getDeclarationFlagsFromSymbol(sourceProp);
+                            var targetFlags = getDeclarationFlagsFromSymbol(targetProp);
+                            if (sourceFlags & 32 || targetFlags & 32) {
+                                if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
+                                    if (reportErrors) {
+                                        if (sourceFlags & 32 && targetFlags & 32) {
+                                            reportError(ts.Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
+                                        }
+                                        else {
+                                            reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourceFlags & 32 ? source : target), typeToString(sourceFlags & 32 ? target : source));
+                                        }
+                                    }
+                                    return 0;
+                                }
+                            }
+                            else if (targetFlags & 64) {
+                                var sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & 32;
+                                var sourceClass = sourceDeclaredInClass ? getDeclaredTypeOfSymbol(sourceProp.parent) : undefined;
+                                var targetClass = getDeclaredTypeOfSymbol(targetProp.parent);
+                                if (!sourceClass || !hasBaseType(sourceClass, targetClass)) {
+                                    if (reportErrors) {
+                                        reportError(ts.Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), typeToString(sourceClass || source), typeToString(targetClass));
+                                    }
+                                    return 0;
+                                }
+                            }
+                            else if (sourceFlags & 64) {
+                                if (reportErrors) {
+                                    reportError(ts.Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target));
+                                }
+                                return 0;
+                            }
+                            var related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors);
+                            if (!related) {
+                                if (reportErrors) {
+                                    reportError(ts.Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
+                                }
+                                return 0;
+                            }
+                            result &= related;
+                            if (sourceProp.flags & 536870912 && !(targetProp.flags & 536870912)) {
+                                if (reportErrors) {
+                                    reportError(ts.Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target));
+                                }
+                                return 0;
+                            }
+                        }
+                    }
+                }
+                return result;
+            }
+            function propertiesIdenticalTo(source, target) {
+                var sourceProperties = getPropertiesOfObjectType(source);
+                var targetProperties = getPropertiesOfObjectType(target);
+                if (sourceProperties.length !== targetProperties.length) {
+                    return 0;
+                }
+                var result = -1;
+                for (var _i = 0; _i < sourceProperties.length; _i++) {
+                    var sourceProp = sourceProperties[_i];
+                    var targetProp = getPropertyOfObjectType(target, sourceProp.name);
+                    if (!targetProp) {
+                        return 0;
+                    }
+                    var related = compareProperties(sourceProp, targetProp, isRelatedTo);
+                    if (!related) {
+                        return 0;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+            function signaturesRelatedTo(source, target, kind, reportErrors) {
+                if (relation === identityRelation) {
+                    return signaturesIdenticalTo(source, target, kind);
+                }
+                if (target === anyFunctionType || source === anyFunctionType) {
+                    return -1;
+                }
+                var sourceSignatures = getSignaturesOfType(source, kind);
+                var targetSignatures = getSignaturesOfType(target, kind);
+                var result = -1;
+                var saveErrorInfo = errorInfo;
+                outer: for (var _i = 0; _i < targetSignatures.length; _i++) {
+                    var t = targetSignatures[_i];
+                    if (!t.hasStringLiterals || target.flags & 65536) {
+                        var localErrors = reportErrors;
+                        for (var _a = 0; _a < sourceSignatures.length; _a++) {
+                            var s = sourceSignatures[_a];
+                            if (!s.hasStringLiterals || source.flags & 65536) {
+                                var related = signatureRelatedTo(s, t, localErrors);
+                                if (related) {
+                                    result &= related;
+                                    errorInfo = saveErrorInfo;
+                                    continue outer;
+                                }
+                                localErrors = false;
+                            }
+                        }
+                        return 0;
+                    }
+                }
+                return result;
+            }
+            function signatureRelatedTo(source, target, reportErrors) {
+                if (source === target) {
+                    return -1;
+                }
+                if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) {
+                    return 0;
+                }
+                var sourceMax = source.parameters.length;
+                var targetMax = target.parameters.length;
+                var checkCount;
+                if (source.hasRestParameter && target.hasRestParameter) {
+                    checkCount = sourceMax > targetMax ? sourceMax : targetMax;
+                    sourceMax--;
+                    targetMax--;
+                }
+                else if (source.hasRestParameter) {
+                    sourceMax--;
+                    checkCount = targetMax;
+                }
+                else if (target.hasRestParameter) {
+                    targetMax--;
+                    checkCount = sourceMax;
+                }
+                else {
+                    checkCount = sourceMax < targetMax ? sourceMax : targetMax;
+                }
+                source = getErasedSignature(source);
+                target = getErasedSignature(target);
+                var result = -1;
+                for (var i = 0; i < checkCount; i++) {
+                    var s_1 = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
+                    var t_1 = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
+                    var saveErrorInfo = errorInfo;
+                    var related = isRelatedTo(s_1, t_1, reportErrors);
+                    if (!related) {
+                        related = isRelatedTo(t_1, s_1, false);
+                        if (!related) {
+                            if (reportErrors) {
+                                reportError(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, source.parameters[i < sourceMax ? i : sourceMax].name, target.parameters[i < targetMax ? i : targetMax].name);
+                            }
+                            return 0;
+                        }
+                        errorInfo = saveErrorInfo;
+                    }
+                    result &= related;
+                }
+                var t = getReturnTypeOfSignature(target);
+                if (t === voidType)
+                    return result;
+                var s = getReturnTypeOfSignature(source);
+                return result & isRelatedTo(s, t, reportErrors);
+            }
+            function signaturesIdenticalTo(source, target, kind) {
+                var sourceSignatures = getSignaturesOfType(source, kind);
+                var targetSignatures = getSignaturesOfType(target, kind);
+                if (sourceSignatures.length !== targetSignatures.length) {
+                    return 0;
+                }
+                var result = -1;
+                for (var i = 0, len = sourceSignatures.length; i < len; ++i) {
+                    var related = compareSignatures(sourceSignatures[i], targetSignatures[i], true, isRelatedTo);
+                    if (!related) {
+                        return 0;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+            function stringIndexTypesRelatedTo(source, target, reportErrors) {
+                if (relation === identityRelation) {
+                    return indexTypesIdenticalTo(0, source, target);
+                }
+                var targetType = getIndexTypeOfType(target, 0);
+                if (targetType) {
+                    var sourceType = getIndexTypeOfType(source, 0);
+                    if (!sourceType) {
+                        if (reportErrors) {
+                            reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
+                        }
+                        return 0;
+                    }
+                    var related = isRelatedTo(sourceType, targetType, reportErrors);
+                    if (!related) {
+                        if (reportErrors) {
+                            reportError(ts.Diagnostics.Index_signatures_are_incompatible);
+                        }
+                        return 0;
+                    }
+                    return related;
+                }
+                return -1;
+            }
+            function numberIndexTypesRelatedTo(source, target, reportErrors) {
+                if (relation === identityRelation) {
+                    return indexTypesIdenticalTo(1, source, target);
+                }
+                var targetType = getIndexTypeOfType(target, 1);
+                if (targetType) {
+                    var sourceStringType = getIndexTypeOfType(source, 0);
+                    var sourceNumberType = getIndexTypeOfType(source, 1);
+                    if (!(sourceStringType || sourceNumberType)) {
+                        if (reportErrors) {
+                            reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
+                        }
+                        return 0;
+                    }
+                    var related;
+                    if (sourceStringType && sourceNumberType) {
+                        related = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
+                    }
+                    else {
+                        related = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
+                    }
+                    if (!related) {
+                        if (reportErrors) {
+                            reportError(ts.Diagnostics.Index_signatures_are_incompatible);
+                        }
+                        return 0;
+                    }
+                    return related;
+                }
+                return -1;
+            }
+            function indexTypesIdenticalTo(indexKind, source, target) {
+                var targetType = getIndexTypeOfType(target, indexKind);
+                var sourceType = getIndexTypeOfType(source, indexKind);
+                if (!sourceType && !targetType) {
+                    return -1;
+                }
+                if (sourceType && targetType) {
+                    return isRelatedTo(sourceType, targetType);
+                }
+                return 0;
+            }
+        }
+        function isPropertyIdenticalTo(sourceProp, targetProp) {
+            return compareProperties(sourceProp, targetProp, compareTypes) !== 0;
+        }
+        function compareProperties(sourceProp, targetProp, compareTypes) {
+            if (sourceProp === targetProp) {
+                return -1;
+            }
+            var sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (32 | 64);
+            var targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (32 | 64);
+            if (sourcePropAccessibility !== targetPropAccessibility) {
+                return 0;
+            }
+            if (sourcePropAccessibility) {
+                if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) {
+                    return 0;
+                }
+            }
+            else {
+                if ((sourceProp.flags & 536870912) !== (targetProp.flags & 536870912)) {
+                    return 0;
+                }
+            }
+            return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
+        }
+        function compareSignatures(source, target, compareReturnTypes, compareTypes) {
+            if (source === target) {
+                return -1;
+            }
+            if (source.parameters.length !== target.parameters.length ||
+                source.minArgumentCount !== target.minArgumentCount ||
+                source.hasRestParameter !== target.hasRestParameter) {
+                return 0;
+            }
+            var result = -1;
+            if (source.typeParameters && target.typeParameters) {
+                if (source.typeParameters.length !== target.typeParameters.length) {
+                    return 0;
+                }
+                for (var i = 0, len = source.typeParameters.length; i < len; ++i) {
+                    var related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
+                    if (!related) {
+                        return 0;
+                    }
+                    result &= related;
+                }
+            }
+            else if (source.typeParameters || target.typeParameters) {
+                return 0;
+            }
+            source = getErasedSignature(source);
+            target = getErasedSignature(target);
+            for (var i = 0, len = source.parameters.length; i < len; i++) {
+                var s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
+                var t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
+                var related = compareTypes(s, t);
+                if (!related) {
+                    return 0;
+                }
+                result &= related;
+            }
+            if (compareReturnTypes) {
+                result &= compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
+            }
+            return result;
+        }
+        function isSupertypeOfEach(candidate, types) {
+            for (var _i = 0; _i < types.length; _i++) {
+                var type = types[_i];
+                if (candidate !== type && !isTypeSubtypeOf(type, candidate))
+                    return false;
+            }
+            return true;
+        }
+        function getCommonSupertype(types) {
+            return ts.forEach(types, function (t) { return isSupertypeOfEach(t, types) ? t : undefined; });
+        }
+        function reportNoCommonSupertypeError(types, errorLocation, errorMessageChainHead) {
+            var bestSupertype;
+            var bestSupertypeDownfallType;
+            var bestSupertypeScore = 0;
+            for (var i = 0; i < types.length; i++) {
+                var score = 0;
+                var downfallType = undefined;
+                for (var j = 0; j < types.length; j++) {
+                    if (isTypeSubtypeOf(types[j], types[i])) {
+                        score++;
+                    }
+                    else if (!downfallType) {
+                        downfallType = types[j];
+                    }
+                }
+                ts.Debug.assert(!!downfallType, "If there is no common supertype, each type should have a downfallType");
+                if (score > bestSupertypeScore) {
+                    bestSupertype = types[i];
+                    bestSupertypeDownfallType = downfallType;
+                    bestSupertypeScore = score;
+                }
+                if (bestSupertypeScore === types.length - 1) {
+                    break;
+                }
+            }
+            checkTypeSubtypeOf(bestSupertypeDownfallType, bestSupertype, errorLocation, ts.Diagnostics.Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0, errorMessageChainHead);
+        }
+        function isArrayType(type) {
+            return type.flags & 4096 && type.target === globalArrayType;
+        }
+        function isArrayLikeType(type) {
+            return !(type.flags & (32 | 64)) && isTypeAssignableTo(type, anyArrayType);
+        }
+        function isTupleLikeType(type) {
+            return !!getPropertyOfType(type, "0");
+        }
+        function isTupleType(type) {
+            return (type.flags & 8192) && !!type.elementTypes;
+        }
+        function getWidenedTypeOfObjectLiteral(type) {
+            var properties = getPropertiesOfObjectType(type);
+            var members = {};
+            ts.forEach(properties, function (p) {
+                var propType = getTypeOfSymbol(p);
+                var widenedType = getWidenedType(propType);
+                if (propType !== widenedType) {
+                    var symbol = createSymbol(p.flags | 67108864, p.name);
+                    symbol.declarations = p.declarations;
+                    symbol.parent = p.parent;
+                    symbol.type = widenedType;
+                    symbol.target = p;
+                    if (p.valueDeclaration)
+                        symbol.valueDeclaration = p.valueDeclaration;
+                    p = symbol;
+                }
+                members[p.name] = p;
+            });
+            var stringIndexType = getIndexTypeOfType(type, 0);
+            var numberIndexType = getIndexTypeOfType(type, 1);
+            if (stringIndexType)
+                stringIndexType = getWidenedType(stringIndexType);
+            if (numberIndexType)
+                numberIndexType = getWidenedType(numberIndexType);
+            return createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
+        }
+        function getWidenedType(type) {
+            if (type.flags & 786432) {
+                if (type.flags & (32 | 64)) {
+                    return anyType;
+                }
+                if (type.flags & 131072) {
+                    return getWidenedTypeOfObjectLiteral(type);
+                }
+                if (type.flags & 16384) {
+                    return getUnionType(ts.map(type.types, getWidenedType));
+                }
+                if (isArrayType(type)) {
+                    return createArrayType(getWidenedType(type.typeArguments[0]));
+                }
+            }
+            return type;
+        }
+        function reportWideningErrorsInType(type) {
+            if (type.flags & 16384) {
+                var errorReported = false;
+                ts.forEach(type.types, function (t) {
+                    if (reportWideningErrorsInType(t)) {
+                        errorReported = true;
+                    }
+                });
+                return errorReported;
+            }
+            if (isArrayType(type)) {
+                return reportWideningErrorsInType(type.typeArguments[0]);
+            }
+            if (type.flags & 131072) {
+                var errorReported = false;
+                ts.forEach(getPropertiesOfObjectType(type), function (p) {
+                    var t = getTypeOfSymbol(p);
+                    if (t.flags & 262144) {
+                        if (!reportWideningErrorsInType(t)) {
+                            error(p.valueDeclaration, ts.Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
+                        }
+                        errorReported = true;
+                    }
+                });
+                return errorReported;
+            }
+            return false;
+        }
+        function reportImplicitAnyError(declaration, type) {
+            var typeAsString = typeToString(getWidenedType(type));
+            var diagnostic;
+            switch (declaration.kind) {
+                case 132:
+                case 131:
+                    diagnostic = ts.Diagnostics.Member_0_implicitly_has_an_1_type;
+                    break;
+                case 129:
+                    diagnostic = declaration.dotDotDotToken ?
+                        ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type :
+                        ts.Diagnostics.Parameter_0_implicitly_has_an_1_type;
+                    break;
+                case 200:
+                case 134:
+                case 133:
+                case 136:
+                case 137:
+                case 162:
+                case 163:
+                    if (!declaration.name) {
+                        error(declaration, ts.Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
+                        return;
+                    }
+                    diagnostic = ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type;
+                    break;
+                default:
+                    diagnostic = ts.Diagnostics.Variable_0_implicitly_has_an_1_type;
+            }
+            error(declaration, diagnostic, ts.declarationNameToString(declaration.name), typeAsString);
+        }
+        function reportErrorsFromWidening(declaration, type) {
+            if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & 262144) {
+                if (!reportWideningErrorsInType(type)) {
+                    reportImplicitAnyError(declaration, type);
+                }
+            }
+        }
+        function forEachMatchingParameterType(source, target, callback) {
+            var sourceMax = source.parameters.length;
+            var targetMax = target.parameters.length;
+            var count;
+            if (source.hasRestParameter && target.hasRestParameter) {
+                count = sourceMax > targetMax ? sourceMax : targetMax;
+                sourceMax--;
+                targetMax--;
+            }
+            else if (source.hasRestParameter) {
+                sourceMax--;
+                count = targetMax;
+            }
+            else if (target.hasRestParameter) {
+                targetMax--;
+                count = sourceMax;
+            }
+            else {
+                count = sourceMax < targetMax ? sourceMax : targetMax;
+            }
+            for (var i = 0; i < count; i++) {
+                var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
+                var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
+                callback(s, t);
+            }
+        }
+        function createInferenceContext(typeParameters, inferUnionTypes) {
+            var inferences = [];
+            for (var _i = 0; _i < typeParameters.length; _i++) {
+                var unused = typeParameters[_i];
+                inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
+            }
+            return {
+                typeParameters: typeParameters,
+                inferUnionTypes: inferUnionTypes,
+                inferences: inferences,
+                inferredTypes: new Array(typeParameters.length),
+            };
+        }
+        function inferTypes(context, source, target) {
+            var sourceStack;
+            var targetStack;
+            var depth = 0;
+            var inferiority = 0;
+            inferFromTypes(source, target);
+            function isInProcess(source, target) {
+                for (var i = 0; i < depth; i++) {
+                    if (source === sourceStack[i] && target === targetStack[i]) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+            function isWithinDepthLimit(type, stack) {
+                if (depth >= 5) {
+                    var target_2 = type.target;
+                    var count = 0;
+                    for (var i = 0; i < depth; i++) {
+                        var t = stack[i];
+                        if (t.flags & 4096 && t.target === target_2) {
+                            count++;
+                        }
+                    }
+                    return count < 5;
+                }
+                return true;
+            }
+            function inferFromTypes(source, target) {
+                if (source === anyFunctionType) {
+                    return;
+                }
+                if (target.flags & 512) {
+                    var typeParameters = context.typeParameters;
+                    for (var i = 0; i < typeParameters.length; i++) {
+                        if (target === typeParameters[i]) {
+                            var inferences = context.inferences[i];
+                            if (!inferences.isFixed) {
+                                var candidates = inferiority ?
+                                    inferences.secondary || (inferences.secondary = []) :
+                                    inferences.primary || (inferences.primary = []);
+                                if (!ts.contains(candidates, source)) {
+                                    candidates.push(source);
+                                }
+                            }
+                            return;
+                        }
+                    }
+                }
+                else if (source.flags & 4096 && target.flags & 4096 && source.target === target.target) {
+                    var sourceTypes = source.typeArguments;
+                    var targetTypes = target.typeArguments;
+                    for (var i = 0; i < sourceTypes.length; i++) {
+                        inferFromTypes(sourceTypes[i], targetTypes[i]);
+                    }
+                }
+                else if (target.flags & 16384) {
+                    var targetTypes = target.types;
+                    var typeParameterCount = 0;
+                    var typeParameter;
+                    for (var _i = 0; _i < targetTypes.length; _i++) {
+                        var t = targetTypes[_i];
+                        if (t.flags & 512 && ts.contains(context.typeParameters, t)) {
+                            typeParameter = t;
+                            typeParameterCount++;
+                        }
+                        else {
+                            inferFromTypes(source, t);
+                        }
+                    }
+                    if (typeParameterCount === 1) {
+                        inferiority++;
+                        inferFromTypes(source, typeParameter);
+                        inferiority--;
+                    }
+                }
+                else if (source.flags & 16384) {
+                    var sourceTypes = source.types;
+                    for (var _a = 0; _a < sourceTypes.length; _a++) {
+                        var sourceType = sourceTypes[_a];
+                        inferFromTypes(sourceType, target);
+                    }
+                }
+                else if (source.flags & 48128 && (target.flags & (4096 | 8192) ||
+                    (target.flags & 32768) && target.symbol && target.symbol.flags & (8192 | 2048))) {
+                    if (!isInProcess(source, target) && isWithinDepthLimit(source, sourceStack) && isWithinDepthLimit(target, targetStack)) {
+                        if (depth === 0) {
+                            sourceStack = [];
+                            targetStack = [];
+                        }
+                        sourceStack[depth] = source;
+                        targetStack[depth] = target;
+                        depth++;
+                        inferFromProperties(source, target);
+                        inferFromSignatures(source, target, 0);
+                        inferFromSignatures(source, target, 1);
+                        inferFromIndexTypes(source, target, 0, 0);
+                        inferFromIndexTypes(source, target, 1, 1);
+                        inferFromIndexTypes(source, target, 0, 1);
+                        depth--;
+                    }
+                }
+            }
+            function inferFromProperties(source, target) {
+                var properties = getPropertiesOfObjectType(target);
+                for (var _i = 0; _i < properties.length; _i++) {
+                    var targetProp = properties[_i];
+                    var sourceProp = getPropertyOfObjectType(source, targetProp.name);
+                    if (sourceProp) {
+                        inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
+                    }
+                }
+            }
+            function inferFromSignatures(source, target, kind) {
+                var sourceSignatures = getSignaturesOfType(source, kind);
+                var targetSignatures = getSignaturesOfType(target, kind);
+                var sourceLen = sourceSignatures.length;
+                var targetLen = targetSignatures.length;
+                var len = sourceLen < targetLen ? sourceLen : targetLen;
+                for (var i = 0; i < len; i++) {
+                    inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]));
+                }
+            }
+            function inferFromSignature(source, target) {
+                forEachMatchingParameterType(source, target, inferFromTypes);
+                inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
+            }
+            function inferFromIndexTypes(source, target, sourceKind, targetKind) {
+                var targetIndexType = getIndexTypeOfType(target, targetKind);
+                if (targetIndexType) {
+                    var sourceIndexType = getIndexTypeOfType(source, sourceKind);
+                    if (sourceIndexType) {
+                        inferFromTypes(sourceIndexType, targetIndexType);
+                    }
+                }
+            }
+        }
+        function getInferenceCandidates(context, index) {
+            var inferences = context.inferences[index];
+            return inferences.primary || inferences.secondary || emptyArray;
+        }
+        function getInferredType(context, index) {
+            var inferredType = context.inferredTypes[index];
+            var inferenceSucceeded;
+            if (!inferredType) {
+                var inferences = getInferenceCandidates(context, index);
+                if (inferences.length) {
+                    var unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences);
+                    inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
+                    inferenceSucceeded = !!unionOrSuperType;
+                }
+                else {
+                    inferredType = emptyObjectType;
+                    inferenceSucceeded = true;
+                }
+                if (inferenceSucceeded) {
+                    var constraint = getConstraintOfTypeParameter(context.typeParameters[index]);
+                    inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType;
+                }
+                else if (context.failedTypeParameterIndex === undefined || context.failedTypeParameterIndex > index) {
+                    context.failedTypeParameterIndex = index;
+                }
+                context.inferredTypes[index] = inferredType;
+            }
+            return inferredType;
+        }
+        function getInferredTypes(context) {
+            for (var i = 0; i < context.inferredTypes.length; i++) {
+                getInferredType(context, i);
+            }
+            return context.inferredTypes;
+        }
+        function hasAncestor(node, kind) {
+            return ts.getAncestor(node, kind) !== undefined;
+        }
+        function getResolvedSymbol(node) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedSymbol) {
+                links.resolvedSymbol = (!ts.nodeIsMissing(node) && resolveName(node, node.text, 107455 | 1048576, ts.Diagnostics.Cannot_find_name_0, node)) || unknownSymbol;
+            }
+            return links.resolvedSymbol;
+        }
+        function isInTypeQuery(node) {
+            while (node) {
+                switch (node.kind) {
+                    case 144:
+                        return true;
+                    case 65:
+                    case 126:
+                        node = node.parent;
+                        continue;
+                    default:
+                        return false;
+                }
+            }
+            ts.Debug.fail("should not get here");
+        }
+        function removeTypesFromUnionType(type, typeKind, isOfTypeKind, allowEmptyUnionResult) {
+            if (type.flags & 16384) {
+                var types = type.types;
+                if (ts.forEach(types, function (t) { return !!(t.flags & typeKind) === isOfTypeKind; })) {
+                    var narrowedType = getUnionType(ts.filter(types, function (t) { return !(t.flags & typeKind) === isOfTypeKind; }));
+                    if (allowEmptyUnionResult || narrowedType !== emptyObjectType) {
+                        return narrowedType;
+                    }
+                }
+            }
+            else if (allowEmptyUnionResult && !!(type.flags & typeKind) === isOfTypeKind) {
+                return getUnionType(emptyArray);
+            }
+            return type;
+        }
+        function hasInitializer(node) {
+            return !!(node.initializer || ts.isBindingPattern(node.parent) && hasInitializer(node.parent.parent));
+        }
+        function isVariableAssignedWithin(symbol, node) {
+            var links = getNodeLinks(node);
+            if (links.assignmentChecks) {
+                var cachedResult = links.assignmentChecks[symbol.id];
+                if (cachedResult !== undefined) {
+                    return cachedResult;
+                }
+            }
+            else {
+                links.assignmentChecks = {};
+            }
+            return links.assignmentChecks[symbol.id] = isAssignedIn(node);
+            function isAssignedInBinaryExpression(node) {
+                if (node.operatorToken.kind >= 53 && node.operatorToken.kind <= 64) {
+                    var n = node.left;
+                    while (n.kind === 161) {
+                        n = n.expression;
+                    }
+                    if (n.kind === 65 && getResolvedSymbol(n) === symbol) {
+                        return true;
+                    }
+                }
+                return ts.forEachChild(node, isAssignedIn);
+            }
+            function isAssignedInVariableDeclaration(node) {
+                if (!ts.isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) {
+                    return true;
+                }
+                return ts.forEachChild(node, isAssignedIn);
+            }
+            function isAssignedIn(node) {
+                switch (node.kind) {
+                    case 169:
+                        return isAssignedInBinaryExpression(node);
+                    case 198:
+                    case 152:
+                        return isAssignedInVariableDeclaration(node);
+                    case 150:
+                    case 151:
+                    case 153:
+                    case 154:
+                    case 155:
+                    case 156:
+                    case 157:
+                    case 158:
+                    case 160:
+                    case 161:
+                    case 167:
+                    case 164:
+                    case 165:
+                    case 166:
+                    case 168:
+                    case 170:
+                    case 173:
+                    case 179:
+                    case 180:
+                    case 182:
+                    case 183:
+                    case 184:
+                    case 185:
+                    case 186:
+                    case 187:
+                    case 188:
+                    case 191:
+                    case 192:
+                    case 193:
+                    case 220:
+                    case 221:
+                    case 194:
+                    case 195:
+                    case 196:
+                    case 223:
+                        return ts.forEachChild(node, isAssignedIn);
+                }
+                return false;
+            }
+        }
+        function resolveLocation(node) {
+            var containerNodes = [];
+            for (var parent_2 = node.parent; parent_2; parent_2 = parent_2.parent) {
+                if ((ts.isExpression(parent_2) || ts.isObjectLiteralMethod(node)) &&
+                    isContextSensitive(parent_2)) {
+                    containerNodes.unshift(parent_2);
+                }
+            }
+            ts.forEach(containerNodes, function (node) { getTypeOfNode(node); });
+        }
+        function getSymbolAtLocation(node) {
+            resolveLocation(node);
+            return getSymbolInfo(node);
+        }
+        function getTypeAtLocation(node) {
+            resolveLocation(node);
+            return getTypeOfNode(node);
+        }
+        function getTypeOfSymbolAtLocation(symbol, node) {
+            resolveLocation(node);
+            return getNarrowedTypeOfSymbol(symbol, node);
+        }
+        function getNarrowedTypeOfSymbol(symbol, node) {
+            var type = getTypeOfSymbol(symbol);
+            if (node && symbol.flags & 3 && type.flags & (1 | 48128 | 16384 | 512)) {
+                loop: while (node.parent) {
+                    var child = node;
+                    node = node.parent;
+                    var narrowedType = type;
+                    switch (node.kind) {
+                        case 183:
+                            if (child !== node.expression) {
+                                narrowedType = narrowType(type, node.expression, child === node.thenStatement);
+                            }
+                            break;
+                        case 170:
+                            if (child !== node.condition) {
+                                narrowedType = narrowType(type, node.condition, child === node.whenTrue);
+                            }
+                            break;
+                        case 169:
+                            if (child === node.right) {
+                                if (node.operatorToken.kind === 48) {
+                                    narrowedType = narrowType(type, node.left, true);
+                                }
+                                else if (node.operatorToken.kind === 49) {
+                                    narrowedType = narrowType(type, node.left, false);
+                                }
+                            }
+                            break;
+                        case 227:
+                        case 205:
+                        case 200:
+                        case 134:
+                        case 133:
+                        case 136:
+                        case 137:
+                        case 135:
+                            break loop;
+                    }
+                    if (narrowedType !== type) {
+                        if (isVariableAssignedWithin(symbol, node)) {
+                            break;
+                        }
+                        type = narrowedType;
+                    }
+                }
+            }
+            return type;
+            function narrowTypeByEquality(type, expr, assumeTrue) {
+                if (expr.left.kind !== 165 || expr.right.kind !== 8) {
+                    return type;
+                }
+                var left = expr.left;
+                var right = expr.right;
+                if (left.expression.kind !== 65 || getResolvedSymbol(left.expression) !== symbol) {
+                    return type;
+                }
+                var typeInfo = primitiveTypeInfo[right.text];
+                if (expr.operatorToken.kind === 31) {
+                    assumeTrue = !assumeTrue;
+                }
+                if (assumeTrue) {
+                    if (!typeInfo) {
+                        return removeTypesFromUnionType(type, 258 | 132 | 8 | 1048576, true, false);
+                    }
+                    if (isTypeSubtypeOf(typeInfo.type, type)) {
+                        return typeInfo.type;
+                    }
+                    return removeTypesFromUnionType(type, typeInfo.flags, false, false);
+                }
+                else {
+                    if (typeInfo) {
+                        return removeTypesFromUnionType(type, typeInfo.flags, true, false);
+                    }
+                    return type;
+                }
+            }
+            function narrowTypeByAnd(type, expr, assumeTrue) {
+                if (assumeTrue) {
+                    return narrowType(narrowType(type, expr.left, true), expr.right, true);
+                }
+                else {
+                    return getUnionType([
+                        narrowType(type, expr.left, false),
+                        narrowType(narrowType(type, expr.left, true), expr.right, false)
+                    ]);
+                }
+            }
+            function narrowTypeByOr(type, expr, assumeTrue) {
+                if (assumeTrue) {
+                    return getUnionType([
+                        narrowType(type, expr.left, true),
+                        narrowType(narrowType(type, expr.left, false), expr.right, true)
+                    ]);
+                }
+                else {
+                    return narrowType(narrowType(type, expr.left, false), expr.right, false);
+                }
+            }
+            function narrowTypeByInstanceof(type, expr, assumeTrue) {
+                if (type.flags & 1 || !assumeTrue || expr.left.kind !== 65 || getResolvedSymbol(expr.left) !== symbol) {
+                    return type;
+                }
+                var rightType = checkExpression(expr.right);
+                if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
+                    return type;
+                }
+                var prototypeProperty = getPropertyOfType(rightType, "prototype");
+                if (!prototypeProperty) {
+                    return type;
+                }
+                var targetType = getTypeOfSymbol(prototypeProperty);
+                if (isTypeSubtypeOf(targetType, type)) {
+                    return targetType;
+                }
+                if (type.flags & 16384) {
+                    return getUnionType(ts.filter(type.types, function (t) { return isTypeSubtypeOf(t, targetType); }));
+                }
+                return type;
+            }
+            function narrowType(type, expr, assumeTrue) {
+                switch (expr.kind) {
+                    case 161:
+                        return narrowType(type, expr.expression, assumeTrue);
+                    case 169:
+                        var operator = expr.operatorToken.kind;
+                        if (operator === 30 || operator === 31) {
+                            return narrowTypeByEquality(type, expr, assumeTrue);
+                        }
+                        else if (operator === 48) {
+                            return narrowTypeByAnd(type, expr, assumeTrue);
+                        }
+                        else if (operator === 49) {
+                            return narrowTypeByOr(type, expr, assumeTrue);
+                        }
+                        else if (operator === 87) {
+                            return narrowTypeByInstanceof(type, expr, assumeTrue);
+                        }
+                        break;
+                    case 167:
+                        if (expr.operator === 46) {
+                            return narrowType(type, expr.operand, !assumeTrue);
+                        }
+                        break;
+                }
+                return type;
+            }
+        }
+        function checkIdentifier(node) {
+            var symbol = getResolvedSymbol(node);
+            if (symbol === argumentsSymbol && ts.getContainingFunction(node).kind === 163 && languageVersion < 2) {
+                error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
+            }
+            if (symbol.flags & 8388608 && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
+                markAliasSymbolAsReferenced(symbol);
+            }
+            checkCollisionWithCapturedSuperVariable(node, node);
+            checkCollisionWithCapturedThisVariable(node, node);
+            checkBlockScopedBindingCapturedInLoop(node, symbol);
+            return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
+        }
+        function isInsideFunction(node, threshold) {
+            var current = node;
+            while (current && current !== threshold) {
+                if (ts.isFunctionLike(current)) {
+                    return true;
+                }
+                current = current.parent;
+            }
+            return false;
+        }
+        function checkBlockScopedBindingCapturedInLoop(node, symbol) {
+            if (languageVersion >= 2 ||
+                (symbol.flags & 2) === 0 ||
+                symbol.valueDeclaration.parent.kind === 223) {
+                return;
+            }
+            var container = symbol.valueDeclaration;
+            while (container.kind !== 199) {
+                container = container.parent;
+            }
+            container = container.parent;
+            if (container.kind === 180) {
+                container = container.parent;
+            }
+            var inFunction = isInsideFunction(node.parent, container);
+            var current = container;
+            while (current && !ts.nodeStartsNewLexicalEnvironment(current)) {
+                if (isIterationStatement(current, false)) {
+                    if (inFunction) {
+                        grammarErrorOnFirstToken(current, ts.Diagnostics.Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher, ts.declarationNameToString(node));
+                    }
+                    getNodeLinks(symbol.valueDeclaration).flags |= 256;
+                    break;
+                }
+                current = current.parent;
+            }
+        }
+        function captureLexicalThis(node, container) {
+            var classNode = container.parent && container.parent.kind === 201 ? container.parent : undefined;
+            getNodeLinks(node).flags |= 2;
+            if (container.kind === 132 || container.kind === 135) {
+                getNodeLinks(classNode).flags |= 4;
+            }
+            else {
+                getNodeLinks(container).flags |= 4;
+            }
+        }
+        function checkThisExpression(node) {
+            var container = ts.getThisContainer(node, true);
+            var needToCaptureLexicalThis = false;
+            if (container.kind === 163) {
+                container = ts.getThisContainer(container, false);
+                needToCaptureLexicalThis = (languageVersion < 2);
+            }
+            switch (container.kind) {
+                case 205:
+                    error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_module_body);
+                    break;
+                case 204:
+                    error(node, ts.Diagnostics.this_cannot_be_referenced_in_current_location);
+                    break;
+                case 135:
+                    if (isInConstructorArgumentInitializer(node, container)) {
+                        error(node, ts.Diagnostics.this_cannot_be_referenced_in_constructor_arguments);
+                    }
+                    break;
+                case 132:
+                case 131:
+                    if (container.flags & 128) {
+                        error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer);
+                    }
+                    break;
+                case 127:
+                    error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_computed_property_name);
+                    break;
+            }
+            if (needToCaptureLexicalThis) {
+                captureLexicalThis(node, container);
+            }
+            var classNode = container.parent && container.parent.kind === 201 ? container.parent : undefined;
+            if (classNode) {
+                var symbol = getSymbolOfNode(classNode);
+                return container.flags & 128 ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol);
+            }
+            return anyType;
+        }
+        function isInConstructorArgumentInitializer(node, constructorDecl) {
+            for (var n = node; n && n !== constructorDecl; n = n.parent) {
+                if (n.kind === 129) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        function checkSuperExpression(node) {
+            var isCallExpression = node.parent.kind === 157 && node.parent.expression === node;
+            var enclosingClass = ts.getAncestor(node, 201);
+            var baseClass;
+            if (enclosingClass && ts.getClassExtendsHeritageClauseElement(enclosingClass)) {
+                var classType = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClass));
+                var baseTypes = getBaseTypes(classType);
+                baseClass = baseTypes.length && baseTypes[0];
+            }
+            if (!baseClass) {
+                error(node, ts.Diagnostics.super_can_only_be_referenced_in_a_derived_class);
+                return unknownType;
+            }
+            var container = ts.getSuperContainer(node, true);
+            if (container) {
+                var canUseSuperExpression = false;
+                var needToCaptureLexicalThis;
+                if (isCallExpression) {
+                    canUseSuperExpression = container.kind === 135;
+                }
+                else {
+                    needToCaptureLexicalThis = false;
+                    while (container && container.kind === 163) {
+                        container = ts.getSuperContainer(container, true);
+                        needToCaptureLexicalThis = languageVersion < 2;
+                    }
+                    if (container && container.parent && container.parent.kind === 201) {
+                        if (container.flags & 128) {
+                            canUseSuperExpression =
+                                container.kind === 134 ||
+                                    container.kind === 133 ||
+                                    container.kind === 136 ||
+                                    container.kind === 137;
+                        }
+                        else {
+                            canUseSuperExpression =
+                                container.kind === 134 ||
+                                    container.kind === 133 ||
+                                    container.kind === 136 ||
+                                    container.kind === 137 ||
+                                    container.kind === 132 ||
+                                    container.kind === 131 ||
+                                    container.kind === 135;
+                        }
+                    }
+                }
+                if (canUseSuperExpression) {
+                    var returnType;
+                    if ((container.flags & 128) || isCallExpression) {
+                        getNodeLinks(node).flags |= 32;
+                        returnType = getTypeOfSymbol(baseClass.symbol);
+                    }
+                    else {
+                        getNodeLinks(node).flags |= 16;
+                        returnType = baseClass;
+                    }
+                    if (container.kind === 135 && isInConstructorArgumentInitializer(node, container)) {
+                        error(node, ts.Diagnostics.super_cannot_be_referenced_in_constructor_arguments);
+                        returnType = unknownType;
+                    }
+                    if (!isCallExpression && needToCaptureLexicalThis) {
+                        captureLexicalThis(node.parent, container);
+                    }
+                    return returnType;
+                }
+            }
+            if (container && container.kind === 127) {
+                error(node, ts.Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
+            }
+            else if (isCallExpression) {
+                error(node, ts.Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors);
+            }
+            else {
+                error(node, ts.Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class);
+            }
+            return unknownType;
+        }
+        function getContextuallyTypedParameterType(parameter) {
+            if (isFunctionExpressionOrArrowFunction(parameter.parent)) {
+                var func = parameter.parent;
+                if (isContextSensitive(func)) {
+                    var contextualSignature = getContextualSignature(func);
+                    if (contextualSignature) {
+                        var funcHasRestParameters = ts.hasRestParameters(func);
+                        var len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
+                        var indexOfParameter = ts.indexOf(func.parameters, parameter);
+                        if (indexOfParameter < len) {
+                            return getTypeAtPosition(contextualSignature, indexOfParameter);
+                        }
+                        if (indexOfParameter === (func.parameters.length - 1) &&
+                            funcHasRestParameters && contextualSignature.hasRestParameter && func.parameters.length >= contextualSignature.parameters.length) {
+                            return getTypeOfSymbol(contextualSignature.parameters[contextualSignature.parameters.length - 1]);
+                        }
+                    }
+                }
+            }
+            return undefined;
+        }
+        function getContextualTypeForInitializerExpression(node) {
+            var declaration = node.parent;
+            if (node === declaration.initializer) {
+                if (declaration.type) {
+                    return getTypeFromTypeNode(declaration.type);
+                }
+                if (declaration.kind === 129) {
+                    var type = getContextuallyTypedParameterType(declaration);
+                    if (type) {
+                        return type;
+                    }
+                }
+                if (ts.isBindingPattern(declaration.name)) {
+                    return getTypeFromBindingPattern(declaration.name);
+                }
+            }
+            return undefined;
+        }
+        function getContextualTypeForReturnExpression(node) {
+            var func = ts.getContainingFunction(node);
+            if (func) {
+                if (func.type || func.kind === 135 || func.kind === 136 && getSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(func.symbol, 137))) {
+                    return getReturnTypeOfSignature(getSignatureFromDeclaration(func));
+                }
+                var signature = getContextualSignatureForFunctionLikeDeclaration(func);
+                if (signature) {
+                    return getReturnTypeOfSignature(signature);
+                }
+            }
+            return undefined;
+        }
+        function getContextualTypeForArgument(callTarget, arg) {
+            var args = getEffectiveCallArguments(callTarget);
+            var argIndex = ts.indexOf(args, arg);
+            if (argIndex >= 0) {
+                var signature = getResolvedSignature(callTarget);
+                return getTypeAtPosition(signature, argIndex);
+            }
+            return undefined;
+        }
+        function getContextualTypeForSubstitutionExpression(template, substitutionExpression) {
+            if (template.parent.kind === 159) {
+                return getContextualTypeForArgument(template.parent, substitutionExpression);
+            }
+            return undefined;
+        }
+        function getContextualTypeForBinaryOperand(node) {
+            var binaryExpression = node.parent;
+            var operator = binaryExpression.operatorToken.kind;
+            if (operator >= 53 && operator <= 64) {
+                if (node === binaryExpression.right) {
+                    return checkExpression(binaryExpression.left);
+                }
+            }
+            else if (operator === 49) {
+                var type = getContextualType(binaryExpression);
+                if (!type && node === binaryExpression.right) {
+                    type = checkExpression(binaryExpression.left);
+                }
+                return type;
+            }
+            return undefined;
+        }
+        function applyToContextualType(type, mapper) {
+            if (!(type.flags & 16384)) {
+                return mapper(type);
+            }
+            var types = type.types;
+            var mappedType;
+            var mappedTypes;
+            for (var _i = 0; _i < types.length; _i++) {
+                var current = types[_i];
+                var t = mapper(current);
+                if (t) {
+                    if (!mappedType) {
+                        mappedType = t;
+                    }
+                    else if (!mappedTypes) {
+                        mappedTypes = [mappedType, t];
+                    }
+                    else {
+                        mappedTypes.push(t);
+                    }
+                }
+            }
+            return mappedTypes ? getUnionType(mappedTypes) : mappedType;
+        }
+        function getTypeOfPropertyOfContextualType(type, name) {
+            return applyToContextualType(type, function (t) {
+                var prop = getPropertyOfObjectType(t, name);
+                return prop ? getTypeOfSymbol(prop) : undefined;
+            });
+        }
+        function getIndexTypeOfContextualType(type, kind) {
+            return applyToContextualType(type, function (t) { return getIndexTypeOfObjectOrUnionType(t, kind); });
+        }
+        function contextualTypeIsTupleLikeType(type) {
+            return !!(type.flags & 16384 ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type));
+        }
+        function contextualTypeHasIndexSignature(type, kind) {
+            return !!(type.flags & 16384 ? ts.forEach(type.types, function (t) { return getIndexTypeOfObjectOrUnionType(t, kind); }) : getIndexTypeOfObjectOrUnionType(type, kind));
+        }
+        function getContextualTypeForObjectLiteralMethod(node) {
+            ts.Debug.assert(ts.isObjectLiteralMethod(node));
+            if (isInsideWithStatementBody(node)) {
+                return undefined;
+            }
+            return getContextualTypeForObjectLiteralElement(node);
+        }
+        function getContextualTypeForObjectLiteralElement(element) {
+            var objectLiteral = element.parent;
+            var type = getContextualType(objectLiteral);
+            if (type) {
+                if (!ts.hasDynamicName(element)) {
+                    var symbolName = getSymbolOfNode(element).name;
+                    var propertyType = getTypeOfPropertyOfContextualType(type, symbolName);
+                    if (propertyType) {
+                        return propertyType;
+                    }
+                }
+                return isNumericName(element.name) && getIndexTypeOfContextualType(type, 1) ||
+                    getIndexTypeOfContextualType(type, 0);
+            }
+            return undefined;
+        }
+        function getContextualTypeForElementExpression(node) {
+            var arrayLiteral = node.parent;
+            var type = getContextualType(arrayLiteral);
+            if (type) {
+                var index = ts.indexOf(arrayLiteral.elements, node);
+                return getTypeOfPropertyOfContextualType(type, "" + index)
+                    || getIndexTypeOfContextualType(type, 1)
+                    || (languageVersion >= 2 ? checkIteratedType(type, undefined) : undefined);
+            }
+            return undefined;
+        }
+        function getContextualTypeForConditionalOperand(node) {
+            var conditional = node.parent;
+            return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
+        }
+        function getContextualType(node) {
+            if (isInsideWithStatementBody(node)) {
+                return undefined;
+            }
+            if (node.contextualType) {
+                return node.contextualType;
+            }
+            var parent = node.parent;
+            switch (parent.kind) {
+                case 198:
+                case 129:
+                case 132:
+                case 131:
+                case 152:
+                    return getContextualTypeForInitializerExpression(node);
+                case 163:
+                case 191:
+                    return getContextualTypeForReturnExpression(node);
+                case 157:
+                case 158:
+                    return getContextualTypeForArgument(parent, node);
+                case 160:
+                    return getTypeFromTypeNode(parent.type);
+                case 169:
+                    return getContextualTypeForBinaryOperand(node);
+                case 224:
+                    return getContextualTypeForObjectLiteralElement(parent);
+                case 153:
+                    return getContextualTypeForElementExpression(node);
+                case 170:
+                    return getContextualTypeForConditionalOperand(node);
+                case 176:
+                    ts.Debug.assert(parent.parent.kind === 171);
+                    return getContextualTypeForSubstitutionExpression(parent.parent, node);
+                case 161:
+                    return getContextualType(parent);
+            }
+            return undefined;
+        }
+        function getNonGenericSignature(type) {
+            var signatures = getSignaturesOfObjectOrUnionType(type, 0);
+            if (signatures.length === 1) {
+                var signature = signatures[0];
+                if (!signature.typeParameters) {
+                    return signature;
+                }
+            }
+        }
+        function isFunctionExpressionOrArrowFunction(node) {
+            return node.kind === 162 || node.kind === 163;
+        }
+        function getContextualSignatureForFunctionLikeDeclaration(node) {
+            return isFunctionExpressionOrArrowFunction(node) ? getContextualSignature(node) : undefined;
+        }
+        function getContextualSignature(node) {
+            ts.Debug.assert(node.kind !== 134 || ts.isObjectLiteralMethod(node));
+            var type = ts.isObjectLiteralMethod(node)
+                ? getContextualTypeForObjectLiteralMethod(node)
+                : getContextualType(node);
+            if (!type) {
+                return undefined;
+            }
+            if (!(type.flags & 16384)) {
+                return getNonGenericSignature(type);
+            }
+            var signatureList;
+            var types = type.types;
+            for (var _i = 0; _i < types.length; _i++) {
+                var current = types[_i];
+                if (signatureList &&
+                    getSignaturesOfObjectOrUnionType(current, 0).length > 1) {
+                    return undefined;
+                }
+                var signature = getNonGenericSignature(current);
+                if (signature) {
+                    if (!signatureList) {
+                        signatureList = [signature];
+                    }
+                    else if (!compareSignatures(signatureList[0], signature, false, compareTypes)) {
+                        return undefined;
+                    }
+                    else {
+                        signatureList.push(signature);
+                    }
+                }
+            }
+            var result;
+            if (signatureList) {
+                result = cloneSignature(signatureList[0]);
+                result.resolvedReturnType = undefined;
+                result.unionSignatures = signatureList;
+            }
+            return result;
+        }
+        function isInferentialContext(mapper) {
+            return mapper && mapper !== identityMapper;
+        }
+        function isAssignmentTarget(node) {
+            var parent = node.parent;
+            if (parent.kind === 169 && parent.operatorToken.kind === 53 && parent.left === node) {
+                return true;
+            }
+            if (parent.kind === 224) {
+                return isAssignmentTarget(parent.parent);
+            }
+            if (parent.kind === 153) {
+                return isAssignmentTarget(parent);
+            }
+            return false;
+        }
+        function checkSpreadElementExpression(node, contextualMapper) {
+            var arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
+            return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, false);
+        }
+        function checkArrayLiteral(node, contextualMapper) {
+            var elements = node.elements;
+            if (!elements.length) {
+                return createArrayType(undefinedType);
+            }
+            var hasSpreadElement = false;
+            var elementTypes = [];
+            var inDestructuringPattern = isAssignmentTarget(node);
+            for (var _i = 0; _i < elements.length; _i++) {
+                var e = elements[_i];
+                if (inDestructuringPattern && e.kind === 173) {
+                    var restArrayType = checkExpression(e.expression, contextualMapper);
+                    var restElementType = getIndexTypeOfType(restArrayType, 1) ||
+                        (languageVersion >= 2 ? checkIteratedType(restArrayType, undefined) : undefined);
+                    if (restElementType) {
+                        elementTypes.push(restElementType);
+                    }
+                }
+                else {
+                    var type = checkExpression(e, contextualMapper);
+                    elementTypes.push(type);
+                }
+                hasSpreadElement = hasSpreadElement || e.kind === 173;
+            }
+            if (!hasSpreadElement) {
+                var contextualType = getContextualType(node);
+                if (contextualType && contextualTypeIsTupleLikeType(contextualType) || inDestructuringPattern) {
+                    return createTupleType(elementTypes);
+                }
+            }
+            return createArrayType(getUnionType(elementTypes));
+        }
+        function isNumericName(name) {
+            return name.kind === 127 ? isNumericComputedName(name) : isNumericLiteralName(name.text);
+        }
+        function isNumericComputedName(name) {
+            return allConstituentTypesHaveKind(checkComputedPropertyName(name), 1 | 132);
+        }
+        function isNumericLiteralName(name) {
+            return (+name).toString() === name;
+        }
+        function checkComputedPropertyName(node) {
+            var links = getNodeLinks(node.expression);
+            if (!links.resolvedType) {
+                links.resolvedType = checkExpression(node.expression);
+                if (!allConstituentTypesHaveKind(links.resolvedType, 1 | 132 | 258 | 1048576)) {
+                    error(node, ts.Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
+                }
+                else {
+                    checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, true);
+                }
+            }
+            return links.resolvedType;
+        }
+        function checkObjectLiteral(node, contextualMapper) {
+            checkGrammarObjectLiteralExpression(node);
+            var propertiesTable = {};
+            var propertiesArray = [];
+            var contextualType = getContextualType(node);
+            var typeFlags;
+            for (var _i = 0, _a = node.properties; _i < _a.length; _i++) {
+                var memberDecl = _a[_i];
+                var member = memberDecl.symbol;
+                if (memberDecl.kind === 224 ||
+                    memberDecl.kind === 225 ||
+                    ts.isObjectLiteralMethod(memberDecl)) {
+                    var type = void 0;
+                    if (memberDecl.kind === 224) {
+                        type = checkPropertyAssignment(memberDecl, contextualMapper);
+                    }
+                    else if (memberDecl.kind === 134) {
+                        type = checkObjectLiteralMethod(memberDecl, contextualMapper);
+                    }
+                    else {
+                        ts.Debug.assert(memberDecl.kind === 225);
+                        type = checkExpression(memberDecl.name, contextualMapper);
+                    }
+                    typeFlags |= type.flags;
+                    var prop = createSymbol(4 | 67108864 | member.flags, member.name);
+                    prop.declarations = member.declarations;
+                    prop.parent = member.parent;
+                    if (member.valueDeclaration) {
+                        prop.valueDeclaration = member.valueDeclaration;
+                    }
+                    prop.type = type;
+                    prop.target = member;
+                    member = prop;
+                }
+                else {
+                    ts.Debug.assert(memberDecl.kind === 136 || memberDecl.kind === 137);
+                    checkAccessorDeclaration(memberDecl);
+                }
+                if (!ts.hasDynamicName(memberDecl)) {
+                    propertiesTable[member.name] = member;
+                }
+                propertiesArray.push(member);
+            }
+            var stringIndexType = getIndexType(0);
+            var numberIndexType = getIndexType(1);
+            var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
+            result.flags |= 131072 | 524288 | (typeFlags & 262144);
+            return result;
+            function getIndexType(kind) {
+                if (contextualType && contextualTypeHasIndexSignature(contextualType, kind)) {
+                    var propTypes = [];
+                    for (var i = 0; i < propertiesArray.length; i++) {
+                        var propertyDecl = node.properties[i];
+                        if (kind === 0 || isNumericName(propertyDecl.name)) {
+                            var type = getTypeOfSymbol(propertiesArray[i]);
+                            if (!ts.contains(propTypes, type)) {
+                                propTypes.push(type);
+                            }
+                        }
+                    }
+                    var result_1 = propTypes.length ? getUnionType(propTypes) : undefinedType;
+                    typeFlags |= result_1.flags;
+                    return result_1;
+                }
+                return undefined;
+            }
+        }
+        function getDeclarationKindFromSymbol(s) {
+            return s.valueDeclaration ? s.valueDeclaration.kind : 132;
+        }
+        function getDeclarationFlagsFromSymbol(s) {
+            return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : s.flags & 134217728 ? 16 | 128 : 0;
+        }
+        function checkClassPropertyAccess(node, left, type, prop) {
+            var flags = getDeclarationFlagsFromSymbol(prop);
+            if (!(flags & (32 | 64))) {
+                return;
+            }
+            var enclosingClassDeclaration = ts.getAncestor(node, 201);
+            var enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined;
+            var declaringClass = getDeclaredTypeOfSymbol(prop.parent);
+            if (flags & 32) {
+                if (declaringClass !== enclosingClass) {
+                    error(node, ts.Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass));
+                }
+                return;
+            }
+            if (left.kind === 91) {
+                return;
+            }
+            if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) {
+                error(node, ts.Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass));
+                return;
+            }
+            if (flags & 128) {
+                return;
+            }
+            if (!(getTargetType(type).flags & (1024 | 2048) && hasBaseType(type, enclosingClass))) {
+                error(node, ts.Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
+            }
+        }
+        function checkPropertyAccessExpression(node) {
+            return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name);
+        }
+        function checkQualifiedName(node) {
+            return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
+        }
+        function checkPropertyAccessExpressionOrQualifiedName(node, left, right) {
+            var type = checkExpressionOrQualifiedName(left);
+            if (type === unknownType)
+                return type;
+            if (type !== anyType) {
+                var apparentType = getApparentType(getWidenedType(type));
+                if (apparentType === unknownType) {
+                    return unknownType;
+                }
+                var prop = getPropertyOfType(apparentType, right.text);
+                if (!prop) {
+                    if (right.text) {
+                        error(right, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(right), typeToString(type));
+                    }
+                    return unknownType;
+                }
+                getNodeLinks(node).resolvedSymbol = prop;
+                if (prop.parent && prop.parent.flags & 32) {
+                    if (left.kind === 91 && getDeclarationKindFromSymbol(prop) !== 134) {
+                        error(right, ts.Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
+                    }
+                    else {
+                        checkClassPropertyAccess(node, left, type, prop);
+                    }
+                }
+                return getTypeOfSymbol(prop);
+            }
+            return anyType;
+        }
+        function isValidPropertyAccess(node, propertyName) {
+            var left = node.kind === 155
+                ? node.expression
+                : node.left;
+            var type = checkExpressionOrQualifiedName(left);
+            if (type !== unknownType && type !== anyType) {
+                var prop = getPropertyOfType(getWidenedType(type), propertyName);
+                if (prop && prop.parent && prop.parent.flags & 32) {
+                    if (left.kind === 91 && getDeclarationKindFromSymbol(prop) !== 134) {
+                        return false;
+                    }
+                    else {
+                        var modificationCount = diagnostics.getModificationCount();
+                        checkClassPropertyAccess(node, left, type, prop);
+                        return diagnostics.getModificationCount() === modificationCount;
+                    }
+                }
+            }
+            return true;
+        }
+        function checkIndexedAccess(node) {
+            if (!node.argumentExpression) {
+                var sourceFile = getSourceFile(node);
+                if (node.parent.kind === 158 && node.parent.expression === node) {
+                    var start = ts.skipTrivia(sourceFile.text, node.expression.end);
+                    var end = node.end;
+                    grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
+                }
+                else {
+                    var start = node.end - "]".length;
+                    var end = node.end;
+                    grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Expression_expected);
+                }
+            }
+            var objectType = getApparentType(checkExpression(node.expression));
+            var indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType;
+            if (objectType === unknownType) {
+                return unknownType;
+            }
+            var isConstEnum = isConstEnumObjectType(objectType);
+            if (isConstEnum &&
+                (!node.argumentExpression || node.argumentExpression.kind !== 8)) {
+                error(node.argumentExpression, ts.Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
+                return unknownType;
+            }
+            if (node.argumentExpression) {
+                var name_3 = getPropertyNameForIndexedAccess(node.argumentExpression, indexType);
+                if (name_3 !== undefined) {
+                    var prop = getPropertyOfType(objectType, name_3);
+                    if (prop) {
+                        getNodeLinks(node).resolvedSymbol = prop;
+                        return getTypeOfSymbol(prop);
+                    }
+                    else if (isConstEnum) {
+                        error(node.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_const_enum_1, name_3, symbolToString(objectType.symbol));
+                        return unknownType;
+                    }
+                }
+            }
+            if (allConstituentTypesHaveKind(indexType, 1 | 258 | 132 | 1048576)) {
+                if (allConstituentTypesHaveKind(indexType, 1 | 132)) {
+                    var numberIndexType = getIndexTypeOfType(objectType, 1);
+                    if (numberIndexType) {
+                        return numberIndexType;
+                    }
+                }
+                var stringIndexType = getIndexTypeOfType(objectType, 0);
+                if (stringIndexType) {
+                    return stringIndexType;
+                }
+                if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && objectType !== anyType) {
+                    error(node, ts.Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type);
+                }
+                return anyType;
+            }
+            error(node, ts.Diagnostics.An_index_expression_argument_must_be_of_type_string_number_symbol_or_any);
+            return unknownType;
+        }
+        function getPropertyNameForIndexedAccess(indexArgumentExpression, indexArgumentType) {
+            if (indexArgumentExpression.kind === 8 || indexArgumentExpression.kind === 7) {
+                return indexArgumentExpression.text;
+            }
+            if (checkThatExpressionIsProperSymbolReference(indexArgumentExpression, indexArgumentType, false)) {
+                var rightHandSideName = indexArgumentExpression.name.text;
+                return ts.getPropertyNameForKnownSymbolName(rightHandSideName);
+            }
+            return undefined;
+        }
+        function checkThatExpressionIsProperSymbolReference(expression, expressionType, reportError) {
+            if (expressionType === unknownType) {
+                return false;
+            }
+            if (!ts.isWellKnownSymbolSyntactically(expression)) {
+                return false;
+            }
+            if ((expressionType.flags & 1048576) === 0) {
+                if (reportError) {
+                    error(expression, ts.Diagnostics.A_computed_property_name_of_the_form_0_must_be_of_type_symbol, ts.getTextOfNode(expression));
+                }
+                return false;
+            }
+            var leftHandSide = expression.expression;
+            var leftHandSideSymbol = getResolvedSymbol(leftHandSide);
+            if (!leftHandSideSymbol) {
+                return false;
+            }
+            var globalESSymbol = getGlobalESSymbolConstructorSymbol();
+            if (!globalESSymbol) {
+                return false;
+            }
+            if (leftHandSideSymbol !== globalESSymbol) {
+                if (reportError) {
+                    error(leftHandSide, ts.Diagnostics.Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object);
+                }
+                return false;
+            }
+            return true;
+        }
+        function resolveUntypedCall(node) {
+            if (node.kind === 159) {
+                checkExpression(node.template);
+            }
+            else {
+                ts.forEach(node.arguments, function (argument) {
+                    checkExpression(argument);
+                });
+            }
+            return anySignature;
+        }
+        function resolveErrorCall(node) {
+            resolveUntypedCall(node);
+            return unknownSignature;
+        }
+        function reorderCandidates(signatures, result) {
+            var lastParent;
+            var lastSymbol;
+            var cutoffIndex = 0;
+            var index;
+            var specializedIndex = -1;
+            var spliceIndex;
+            ts.Debug.assert(!result.length);
+            for (var _i = 0; _i < signatures.length; _i++) {
+                var signature = signatures[_i];
+                var symbol = signature.declaration && getSymbolOfNode(signature.declaration);
+                var parent_3 = signature.declaration && signature.declaration.parent;
+                if (!lastSymbol || symbol === lastSymbol) {
+                    if (lastParent && parent_3 === lastParent) {
+                        index++;
+                    }
+                    else {
+                        lastParent = parent_3;
+                        index = cutoffIndex;
+                    }
+                }
+                else {
+                    index = cutoffIndex = result.length;
+                    lastParent = parent_3;
+                }
+                lastSymbol = symbol;
+                if (signature.hasStringLiterals) {
+                    specializedIndex++;
+                    spliceIndex = specializedIndex;
+                    cutoffIndex++;
+                }
+                else {
+                    spliceIndex = index;
+                }
+                result.splice(spliceIndex, 0, signature);
+            }
+        }
+        function getSpreadArgumentIndex(args) {
+            for (var i = 0; i < args.length; i++) {
+                if (args[i].kind === 173) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+        function hasCorrectArity(node, args, signature) {
+            var adjustedArgCount;
+            var typeArguments;
+            var callIsIncomplete;
+            if (node.kind === 159) {
+                var tagExpression = node;
+                adjustedArgCount = args.length;
+                typeArguments = undefined;
+                if (tagExpression.template.kind === 171) {
+                    var templateExpression = tagExpression.template;
+                    var lastSpan = ts.lastOrUndefined(templateExpression.templateSpans);
+                    ts.Debug.assert(lastSpan !== undefined);
+                    callIsIncomplete = ts.nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated;
+                }
+                else {
+                    var templateLiteral = tagExpression.template;
+                    ts.Debug.assert(templateLiteral.kind === 10);
+                    callIsIncomplete = !!templateLiteral.isUnterminated;
+                }
+            }
+            else {
+                var callExpression = node;
+                if (!callExpression.arguments) {
+                    ts.Debug.assert(callExpression.kind === 158);
+                    return signature.minArgumentCount === 0;
+                }
+                adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
+                callIsIncomplete = callExpression.arguments.end === callExpression.end;
+                typeArguments = callExpression.typeArguments;
+            }
+            var hasRightNumberOfTypeArgs = !typeArguments ||
+                (signature.typeParameters && typeArguments.length === signature.typeParameters.length);
+            if (!hasRightNumberOfTypeArgs) {
+                return false;
+            }
+            var spreadArgIndex = getSpreadArgumentIndex(args);
+            if (spreadArgIndex >= 0) {
+                return signature.hasRestParameter && spreadArgIndex >= signature.parameters.length - 1;
+            }
+            if (!signature.hasRestParameter && adjustedArgCount > signature.parameters.length) {
+                return false;
+            }
+            var hasEnoughArguments = adjustedArgCount >= signature.minArgumentCount;
+            return callIsIncomplete || hasEnoughArguments;
+        }
+        function getSingleCallSignature(type) {
+            if (type.flags & 48128) {
+                var resolved = resolveObjectOrUnionTypeMembers(type);
+                if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 &&
+                    resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
+                    return resolved.callSignatures[0];
+                }
+            }
+            return undefined;
+        }
+        function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper) {
+            var context = createInferenceContext(signature.typeParameters, true);
+            forEachMatchingParameterType(contextualSignature, signature, function (source, target) {
+                inferTypes(context, instantiateType(source, contextualMapper), target);
+            });
+            return getSignatureInstantiation(signature, getInferredTypes(context));
+        }
+        function inferTypeArguments(signature, args, excludeArgument, context) {
+            var typeParameters = signature.typeParameters;
+            var inferenceMapper = createInferenceMapper(context);
+            for (var i = 0; i < typeParameters.length; i++) {
+                if (!context.inferences[i].isFixed) {
+                    context.inferredTypes[i] = undefined;
+                }
+            }
+            if (context.failedTypeParameterIndex !== undefined && !context.inferences[context.failedTypeParameterIndex].isFixed) {
+                context.failedTypeParameterIndex = undefined;
+            }
+            for (var i = 0; i < args.length; i++) {
+                var arg = args[i];
+                if (arg.kind !== 175) {
+                    var paramType = getTypeAtPosition(signature, i);
+                    var argType = void 0;
+                    if (i === 0 && args[i].parent.kind === 159) {
+                        argType = globalTemplateStringsArrayType;
+                    }
+                    else {
+                        var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : inferenceMapper;
+                        argType = checkExpressionWithContextualType(arg, paramType, mapper);
+                    }
+                    inferTypes(context, argType, paramType);
+                }
+            }
+            if (excludeArgument) {
+                for (var i = 0; i < args.length; i++) {
+                    if (excludeArgument[i] === false) {
+                        var arg = args[i];
+                        var paramType = getTypeAtPosition(signature, i);
+                        inferTypes(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
+                    }
+                }
+            }
+            getInferredTypes(context);
+        }
+        function checkTypeArguments(signature, typeArguments, typeArgumentResultTypes, reportErrors) {
+            var typeParameters = signature.typeParameters;
+            var typeArgumentsAreAssignable = true;
+            for (var i = 0; i < typeParameters.length; i++) {
+                var typeArgNode = typeArguments[i];
+                var typeArgument = getTypeFromTypeNode(typeArgNode);
+                typeArgumentResultTypes[i] = typeArgument;
+                if (typeArgumentsAreAssignable) {
+                    var constraint = getConstraintOfTypeParameter(typeParameters[i]);
+                    if (constraint) {
+                        typeArgumentsAreAssignable = checkTypeAssignableTo(typeArgument, constraint, reportErrors ? typeArgNode : undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
+                    }
+                }
+            }
+            return typeArgumentsAreAssignable;
+        }
+        function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) {
+            for (var i = 0; i < args.length; i++) {
+                var arg = args[i];
+                if (arg.kind !== 175) {
+                    var paramType = getTypeAtPosition(signature, i);
+                    var argType = i === 0 && node.kind === 159
+                        ? globalTemplateStringsArrayType
+                        : arg.kind === 8 && !reportErrors
+                            ? getStringLiteralType(arg)
+                            : checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
+                    if (!checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined, ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        function getEffectiveCallArguments(node) {
+            var args;
+            if (node.kind === 159) {
+                var template = node.template;
+                args = [template];
+                if (template.kind === 171) {
+                    ts.forEach(template.templateSpans, function (span) {
+                        args.push(span.expression);
+                    });
+                }
+            }
+            else {
+                args = node.arguments || emptyArray;
+            }
+            return args;
+        }
+        function getEffectiveTypeArguments(callExpression) {
+            if (callExpression.expression.kind === 91) {
+                var containingClass = ts.getAncestor(callExpression, 201);
+                var baseClassTypeNode = containingClass && ts.getClassExtendsHeritageClauseElement(containingClass);
+                return baseClassTypeNode && baseClassTypeNode.typeArguments;
+            }
+            else {
+                return callExpression.typeArguments;
+            }
+        }
+        function resolveCall(node, signatures, candidatesOutArray) {
+            var isTaggedTemplate = node.kind === 159;
+            var typeArguments;
+            if (!isTaggedTemplate) {
+                typeArguments = getEffectiveTypeArguments(node);
+                if (node.expression.kind !== 91) {
+                    ts.forEach(typeArguments, checkSourceElement);
+                }
+            }
+            var candidates = candidatesOutArray || [];
+            reorderCandidates(signatures, candidates);
+            if (!candidates.length) {
+                error(node, ts.Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
+                return resolveErrorCall(node);
+            }
+            var args = getEffectiveCallArguments(node);
+            var excludeArgument;
+            for (var i = isTaggedTemplate ? 1 : 0; i < args.length; i++) {
+                if (isContextSensitive(args[i])) {
+                    if (!excludeArgument) {
+                        excludeArgument = new Array(args.length);
+                    }
+                    excludeArgument[i] = true;
+                }
+            }
+            var candidateForArgumentError;
+            var candidateForTypeArgumentError;
+            var resultOfFailedInference;
+            var result;
+            if (candidates.length > 1) {
+                result = chooseOverload(candidates, subtypeRelation);
+            }
+            if (!result) {
+                candidateForArgumentError = undefined;
+                candidateForTypeArgumentError = undefined;
+                resultOfFailedInference = undefined;
+                result = chooseOverload(candidates, assignableRelation);
+            }
+            if (result) {
+                return result;
+            }
+            if (candidateForArgumentError) {
+                checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, undefined, true);
+            }
+            else if (candidateForTypeArgumentError) {
+                if (!isTaggedTemplate && node.typeArguments) {
+                    checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, [], true);
+                }
+                else {
+                    ts.Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
+                    var failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex];
+                    var inferenceCandidates = getInferenceCandidates(resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex);
+                    var diagnosticChainHead = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly, typeToString(failedTypeParameter));
+                    reportNoCommonSupertypeError(inferenceCandidates, node.expression || node.tag, diagnosticChainHead);
+                }
+            }
+            else {
+                error(node, ts.Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
+            }
+            if (!produceDiagnostics) {
+                for (var _i = 0; _i < candidates.length; _i++) {
+                    var candidate = candidates[_i];
+                    if (hasCorrectArity(node, args, candidate)) {
+                        return candidate;
+                    }
+                }
+            }
+            return resolveErrorCall(node);
+            function chooseOverload(candidates, relation) {
+                for (var _i = 0; _i < candidates.length; _i++) {
+                    var originalCandidate = candidates[_i];
+                    if (!hasCorrectArity(node, args, originalCandidate)) {
+                        continue;
+                    }
+                    var candidate = void 0;
+                    var typeArgumentsAreValid = void 0;
+                    var inferenceContext = originalCandidate.typeParameters
+                        ? createInferenceContext(originalCandidate.typeParameters, false)
+                        : undefined;
+                    while (true) {
+                        candidate = originalCandidate;
+                        if (candidate.typeParameters) {
+                            var typeArgumentTypes = void 0;
+                            if (typeArguments) {
+                                typeArgumentTypes = new Array(candidate.typeParameters.length);
+                                typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, false);
+                            }
+                            else {
+                                inferTypeArguments(candidate, args, excludeArgument, inferenceContext);
+                                typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
+                                typeArgumentTypes = inferenceContext.inferredTypes;
+                            }
+                            if (!typeArgumentsAreValid) {
+                                break;
+                            }
+                            candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
+                        }
+                        if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) {
+                            break;
+                        }
+                        var index = excludeArgument ? ts.indexOf(excludeArgument, true) : -1;
+                        if (index < 0) {
+                            return candidate;
+                        }
+                        excludeArgument[index] = false;
+                    }
+                    if (originalCandidate.typeParameters) {
+                        var instantiatedCandidate = candidate;
+                        if (typeArgumentsAreValid) {
+                            candidateForArgumentError = instantiatedCandidate;
+                        }
+                        else {
+                            candidateForTypeArgumentError = originalCandidate;
+                            if (!typeArguments) {
+                                resultOfFailedInference = inferenceContext;
+                            }
+                        }
+                    }
+                    else {
+                        ts.Debug.assert(originalCandidate === candidate);
+                        candidateForArgumentError = originalCandidate;
+                    }
+                }
+                return undefined;
+            }
+        }
+        function resolveCallExpression(node, candidatesOutArray) {
+            if (node.expression.kind === 91) {
+                var superType = checkSuperExpression(node.expression);
+                if (superType !== unknownType) {
+                    return resolveCall(node, getSignaturesOfType(superType, 1), candidatesOutArray);
+                }
+                return resolveUntypedCall(node);
+            }
+            var funcType = checkExpression(node.expression);
+            var apparentType = getApparentType(funcType);
+            if (apparentType === unknownType) {
+                return resolveErrorCall(node);
+            }
+            var callSignatures = getSignaturesOfType(apparentType, 0);
+            var constructSignatures = getSignaturesOfType(apparentType, 1);
+            if (funcType === anyType || (!callSignatures.length && !constructSignatures.length && !(funcType.flags & 16384) && isTypeAssignableTo(funcType, globalFunctionType))) {
+                if (node.typeArguments) {
+                    error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
+                }
+                return resolveUntypedCall(node);
+            }
+            if (!callSignatures.length) {
+                if (constructSignatures.length) {
+                    error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
+                }
+                else {
+                    error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
+                }
+                return resolveErrorCall(node);
+            }
+            return resolveCall(node, callSignatures, candidatesOutArray);
+        }
+        function resolveNewExpression(node, candidatesOutArray) {
+            if (node.arguments && languageVersion < 2) {
+                var spreadIndex = getSpreadArgumentIndex(node.arguments);
+                if (spreadIndex >= 0) {
+                    error(node.arguments[spreadIndex], ts.Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher);
+                }
+            }
+            var expressionType = checkExpression(node.expression);
+            if (expressionType === anyType) {
+                if (node.typeArguments) {
+                    error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
+                }
+                return resolveUntypedCall(node);
+            }
+            expressionType = getApparentType(expressionType);
+            if (expressionType === unknownType) {
+                return resolveErrorCall(node);
+            }
+            var constructSignatures = getSignaturesOfType(expressionType, 1);
+            if (constructSignatures.length) {
+                return resolveCall(node, constructSignatures, candidatesOutArray);
+            }
+            var callSignatures = getSignaturesOfType(expressionType, 0);
+            if (callSignatures.length) {
+                var signature = resolveCall(node, callSignatures, candidatesOutArray);
+                if (getReturnTypeOfSignature(signature) !== voidType) {
+                    error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
+                }
+                return signature;
+            }
+            error(node, ts.Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature);
+            return resolveErrorCall(node);
+        }
+        function resolveTaggedTemplateExpression(node, candidatesOutArray) {
+            var tagType = checkExpression(node.tag);
+            var apparentType = getApparentType(tagType);
+            if (apparentType === unknownType) {
+                return resolveErrorCall(node);
+            }
+            var callSignatures = getSignaturesOfType(apparentType, 0);
+            if (tagType === anyType || (!callSignatures.length && !(tagType.flags & 16384) && isTypeAssignableTo(tagType, globalFunctionType))) {
+                return resolveUntypedCall(node);
+            }
+            if (!callSignatures.length) {
+                error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
+                return resolveErrorCall(node);
+            }
+            return resolveCall(node, callSignatures, candidatesOutArray);
+        }
+        function getResolvedSignature(node, candidatesOutArray) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedSignature || candidatesOutArray) {
+                links.resolvedSignature = anySignature;
+                if (node.kind === 157) {
+                    links.resolvedSignature = resolveCallExpression(node, candidatesOutArray);
+                }
+                else if (node.kind === 158) {
+                    links.resolvedSignature = resolveNewExpression(node, candidatesOutArray);
+                }
+                else if (node.kind === 159) {
+                    links.resolvedSignature = resolveTaggedTemplateExpression(node, candidatesOutArray);
+                }
+                else {
+                    ts.Debug.fail("Branch in 'getResolvedSignature' should be unreachable.");
+                }
+            }
+            return links.resolvedSignature;
+        }
+        function checkCallExpression(node) {
+            checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
+            var signature = getResolvedSignature(node);
+            if (node.expression.kind === 91) {
+                return voidType;
+            }
+            if (node.kind === 158) {
+                var declaration = signature.declaration;
+                if (declaration &&
+                    declaration.kind !== 135 &&
+                    declaration.kind !== 139 &&
+                    declaration.kind !== 143) {
+                    if (compilerOptions.noImplicitAny) {
+                        error(node, ts.Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
+                    }
+                    return anyType;
+                }
+            }
+            return getReturnTypeOfSignature(signature);
+        }
+        function checkTaggedTemplateExpression(node) {
+            return getReturnTypeOfSignature(getResolvedSignature(node));
+        }
+        function checkTypeAssertion(node) {
+            var exprType = checkExpression(node.expression);
+            var targetType = getTypeFromTypeNode(node.type);
+            if (produceDiagnostics && targetType !== unknownType) {
+                var widenedType = getWidenedType(exprType);
+                if (!(isTypeAssignableTo(targetType, widenedType))) {
+                    checkTypeAssignableTo(exprType, targetType, node, ts.Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
+                }
+            }
+            return targetType;
+        }
+        function getTypeAtPosition(signature, pos) {
+            return signature.hasRestParameter ?
+                pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
+                pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType;
+        }
+        function assignContextualParameterTypes(signature, context, mapper) {
+            var len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
+            for (var i = 0; i < len; i++) {
+                var parameter = signature.parameters[i];
+                var links = getSymbolLinks(parameter);
+                links.type = instantiateType(getTypeAtPosition(context, i), mapper);
+            }
+            if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
+                var parameter = signature.parameters[signature.parameters.length - 1];
+                var links = getSymbolLinks(parameter);
+                links.type = instantiateType(getTypeOfSymbol(context.parameters[context.parameters.length - 1]), mapper);
+            }
+        }
+        function getReturnTypeFromBody(func, contextualMapper) {
+            var contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
+            if (!func.body) {
+                return unknownType;
+            }
+            var type;
+            if (func.body.kind !== 179) {
+                type = checkExpressionCached(func.body, contextualMapper);
+            }
+            else {
+                var types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper);
+                if (types.length === 0) {
+                    return voidType;
+                }
+                type = contextualSignature ? getUnionType(types) : getCommonSupertype(types);
+                if (!type) {
+                    error(func, ts.Diagnostics.No_best_common_type_exists_among_return_expressions);
+                    return unknownType;
+                }
+            }
+            if (!contextualSignature) {
+                reportErrorsFromWidening(func, type);
+            }
+            return getWidenedType(type);
+        }
+        function checkAndAggregateReturnExpressionTypes(body, contextualMapper) {
+            var aggregatedTypes = [];
+            ts.forEachReturnStatement(body, function (returnStatement) {
+                var expr = returnStatement.expression;
+                if (expr) {
+                    var type = checkExpressionCached(expr, contextualMapper);
+                    if (!ts.contains(aggregatedTypes, type)) {
+                        aggregatedTypes.push(type);
+                    }
+                }
+            });
+            return aggregatedTypes;
+        }
+        function bodyContainsAReturnStatement(funcBody) {
+            return ts.forEachReturnStatement(funcBody, function (returnStatement) {
+                return true;
+            });
+        }
+        function bodyContainsSingleThrowStatement(body) {
+            return (body.statements.length === 1) && (body.statements[0].kind === 195);
+        }
+        function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func, returnType) {
+            if (!produceDiagnostics) {
+                return;
+            }
+            if (returnType === voidType || returnType === anyType) {
+                return;
+            }
+            if (ts.nodeIsMissing(func.body) || func.body.kind !== 179) {
+                return;
+            }
+            var bodyBlock = func.body;
+            if (bodyContainsAReturnStatement(bodyBlock)) {
+                return;
+            }
+            if (bodyContainsSingleThrowStatement(bodyBlock)) {
+                return;
+            }
+            error(func.type, ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement);
+        }
+        function checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper) {
+            ts.Debug.assert(node.kind !== 134 || ts.isObjectLiteralMethod(node));
+            var hasGrammarError = checkGrammarDeclarationNameInStrictMode(node) || checkGrammarFunctionLikeDeclaration(node);
+            if (!hasGrammarError && node.kind === 162) {
+                checkGrammarFunctionName(node.name) || checkGrammarForGenerator(node);
+            }
+            if (contextualMapper === identityMapper && isContextSensitive(node)) {
+                return anyFunctionType;
+            }
+            var links = getNodeLinks(node);
+            var type = getTypeOfSymbol(node.symbol);
+            if (!(links.flags & 64)) {
+                var contextualSignature = getContextualSignature(node);
+                if (!(links.flags & 64)) {
+                    links.flags |= 64;
+                    if (contextualSignature) {
+                        var signature = getSignaturesOfType(type, 0)[0];
+                        if (isContextSensitive(node)) {
+                            assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper);
+                        }
+                        if (!node.type) {
+                            signature.resolvedReturnType = resolvingType;
+                            var returnType = getReturnTypeFromBody(node, contextualMapper);
+                            if (signature.resolvedReturnType === resolvingType) {
+                                signature.resolvedReturnType = returnType;
+                            }
+                        }
+                    }
+                    checkSignatureDeclaration(node);
+                }
+            }
+            if (produceDiagnostics && node.kind !== 134 && node.kind !== 133) {
+                checkCollisionWithCapturedSuperVariable(node, node.name);
+                checkCollisionWithCapturedThisVariable(node, node.name);
+            }
+            return type;
+        }
+        function checkFunctionExpressionOrObjectLiteralMethodBody(node) {
+            ts.Debug.assert(node.kind !== 134 || ts.isObjectLiteralMethod(node));
+            if (node.type && !node.asteriskToken) {
+                checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
+            }
+            if (node.body) {
+                if (node.body.kind === 179) {
+                    checkSourceElement(node.body);
+                }
+                else {
+                    var exprType = checkExpression(node.body);
+                    if (node.type) {
+                        checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, undefined);
+                    }
+                    checkFunctionExpressionBodies(node.body);
+                }
+            }
+        }
+        function checkArithmeticOperandType(operand, type, diagnostic) {
+            if (!allConstituentTypesHaveKind(type, 1 | 132)) {
+                error(operand, diagnostic);
+                return false;
+            }
+            return true;
+        }
+        function checkReferenceExpression(n, invalidReferenceMessage, constantVariableMessage) {
+            function findSymbol(n) {
+                var symbol = getNodeLinks(n).resolvedSymbol;
+                return symbol && getExportSymbolOfValueSymbolIfExported(symbol);
+            }
+            function isReferenceOrErrorExpression(n) {
+                switch (n.kind) {
+                    case 65: {
+                        var symbol = findSymbol(n);
+                        return !symbol || symbol === unknownSymbol || symbol === argumentsSymbol || (symbol.flags & 3) !== 0;
+                    }
+                    case 155: {
+                        var symbol = findSymbol(n);
+                        return !symbol || symbol === unknownSymbol || (symbol.flags & ~8) !== 0;
+                    }
+                    case 156:
+                        return true;
+                    case 161:
+                        return isReferenceOrErrorExpression(n.expression);
+                    default:
+                        return false;
+                }
+            }
+            function isConstVariableReference(n) {
+                switch (n.kind) {
+                    case 65:
+                    case 155: {
+                        var symbol = findSymbol(n);
+                        return symbol && (symbol.flags & 3) !== 0 && (getDeclarationFlagsFromSymbol(symbol) & 8192) !== 0;
+                    }
+                    case 156: {
+                        var index = n.argumentExpression;
+                        var symbol = findSymbol(n.expression);
+                        if (symbol && index && index.kind === 8) {
+                            var name_4 = index.text;
+                            var prop = getPropertyOfType(getTypeOfSymbol(symbol), name_4);
+                            return prop && (prop.flags & 3) !== 0 && (getDeclarationFlagsFromSymbol(prop) & 8192) !== 0;
+                        }
+                        return false;
+                    }
+                    case 161:
+                        return isConstVariableReference(n.expression);
+                    default:
+                        return false;
+                }
+            }
+            if (!isReferenceOrErrorExpression(n)) {
+                error(n, invalidReferenceMessage);
+                return false;
+            }
+            if (isConstVariableReference(n)) {
+                error(n, constantVariableMessage);
+                return false;
+            }
+            return true;
+        }
+        function checkDeleteExpression(node) {
+            if (node.parserContextFlags & 1 && node.expression.kind === 65) {
+                grammarErrorOnNode(node.expression, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
+            }
+            var operandType = checkExpression(node.expression);
+            return booleanType;
+        }
+        function checkTypeOfExpression(node) {
+            var operandType = checkExpression(node.expression);
+            return stringType;
+        }
+        function checkVoidExpression(node) {
+            var operandType = checkExpression(node.expression);
+            return undefinedType;
+        }
+        function checkPrefixUnaryExpression(node) {
+            if ((node.operator === 38 || node.operator === 39)) {
+                checkGrammarEvalOrArgumentsInStrictMode(node, node.operand);
+            }
+            var operandType = checkExpression(node.operand);
+            switch (node.operator) {
+                case 33:
+                case 34:
+                case 47:
+                    if (someConstituentTypeHasKind(operandType, 1048576)) {
+                        error(node.operand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(node.operator));
+                    }
+                    return numberType;
+                case 46:
+                    return booleanType;
+                case 38:
+                case 39:
+                    var ok = checkArithmeticOperandType(node.operand, operandType, ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
+                    if (ok) {
+                        checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
+                    }
+                    return numberType;
+            }
+            return unknownType;
+        }
+        function checkPostfixUnaryExpression(node) {
+            checkGrammarEvalOrArgumentsInStrictMode(node, node.operand);
+            var operandType = checkExpression(node.operand);
+            var ok = checkArithmeticOperandType(node.operand, operandType, ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
+            if (ok) {
+                checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
+            }
+            return numberType;
+        }
+        function someConstituentTypeHasKind(type, kind) {
+            if (type.flags & kind) {
+                return true;
+            }
+            if (type.flags & 16384) {
+                var types = type.types;
+                for (var _i = 0; _i < types.length; _i++) {
+                    var current = types[_i];
+                    if (current.flags & kind) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+            return false;
+        }
+        function allConstituentTypesHaveKind(type, kind) {
+            if (type.flags & kind) {
+                return true;
+            }
+            if (type.flags & 16384) {
+                var types = type.types;
+                for (var _i = 0; _i < types.length; _i++) {
+                    var current = types[_i];
+                    if (!(current.flags & kind)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+        function isConstEnumObjectType(type) {
+            return type.flags & (48128 | 32768) && type.symbol && isConstEnumSymbol(type.symbol);
+        }
+        function isConstEnumSymbol(symbol) {
+            return (symbol.flags & 128) !== 0;
+        }
+        function checkInstanceOfExpression(node, leftType, rightType) {
+            if (allConstituentTypesHaveKind(leftType, 1049086)) {
+                error(node.left, ts.Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
+            }
+            if (!(rightType.flags & 1 || isTypeSubtypeOf(rightType, globalFunctionType))) {
+                error(node.right, ts.Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
+            }
+            return booleanType;
+        }
+        function checkInExpression(node, leftType, rightType) {
+            if (!allConstituentTypesHaveKind(leftType, 1 | 258 | 132 | 1048576)) {
+                error(node.left, ts.Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
+            }
+            if (!allConstituentTypesHaveKind(rightType, 1 | 48128 | 512)) {
+                error(node.right, ts.Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
+            }
+            return booleanType;
+        }
+        function checkObjectLiteralAssignment(node, sourceType, contextualMapper) {
+            var properties = node.properties;
+            for (var _i = 0; _i < properties.length; _i++) {
+                var p = properties[_i];
+                if (p.kind === 224 || p.kind === 225) {
+                    var name_5 = p.name;
+                    var type = sourceType.flags & 1 ? sourceType :
+                        getTypeOfPropertyOfType(sourceType, name_5.text) ||
+                            isNumericLiteralName(name_5.text) && getIndexTypeOfType(sourceType, 1) ||
+                            getIndexTypeOfType(sourceType, 0);
+                    if (type) {
+                        checkDestructuringAssignment(p.initializer || name_5, type);
+                    }
+                    else {
+                        error(name_5, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(sourceType), ts.declarationNameToString(name_5));
+                    }
+                }
+                else {
+                    error(p, ts.Diagnostics.Property_assignment_expected);
+                }
+            }
+            return sourceType;
+        }
+        function checkArrayLiteralAssignment(node, sourceType, contextualMapper) {
+            var elementType = checkIteratedTypeOrElementType(sourceType, node, false) || unknownType;
+            var elements = node.elements;
+            for (var i = 0; i < elements.length; i++) {
+                var e = elements[i];
+                if (e.kind !== 175) {
+                    if (e.kind !== 173) {
+                        var propName = "" + i;
+                        var type = sourceType.flags & 1 ? sourceType :
+                            isTupleLikeType(sourceType)
+                                ? getTypeOfPropertyOfType(sourceType, propName)
+                                : elementType;
+                        if (type) {
+                            checkDestructuringAssignment(e, type, contextualMapper);
+                        }
+                        else {
+                            if (isTupleType(sourceType)) {
+                                error(e, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), sourceType.elementTypes.length, elements.length);
+                            }
+                            else {
+                                error(e, ts.Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
+                            }
+                        }
+                    }
+                    else {
+                        if (i < elements.length - 1) {
+                            error(e, ts.Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
+                        }
+                        else {
+                            var restExpression = e.expression;
+                            if (restExpression.kind === 169 && restExpression.operatorToken.kind === 53) {
+                                error(restExpression.operatorToken, ts.Diagnostics.A_rest_element_cannot_have_an_initializer);
+                            }
+                            else {
+                                checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
+                            }
+                        }
+                    }
+                }
+            }
+            return sourceType;
+        }
+        function checkDestructuringAssignment(target, sourceType, contextualMapper) {
+            if (target.kind === 169 && target.operatorToken.kind === 53) {
+                checkBinaryExpression(target, contextualMapper);
+                target = target.left;
+            }
+            if (target.kind === 154) {
+                return checkObjectLiteralAssignment(target, sourceType, contextualMapper);
+            }
+            if (target.kind === 153) {
+                return checkArrayLiteralAssignment(target, sourceType, contextualMapper);
+            }
+            return checkReferenceAssignment(target, sourceType, contextualMapper);
+        }
+        function checkReferenceAssignment(target, sourceType, contextualMapper) {
+            var targetType = checkExpression(target, contextualMapper);
+            if (checkReferenceExpression(target, ts.Diagnostics.Invalid_left_hand_side_of_assignment_expression, ts.Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant)) {
+                checkTypeAssignableTo(sourceType, targetType, target, undefined);
+            }
+            return sourceType;
+        }
+        function checkBinaryExpression(node, contextualMapper) {
+            if (ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) {
+                checkGrammarEvalOrArgumentsInStrictMode(node, node.left);
+            }
+            var operator = node.operatorToken.kind;
+            if (operator === 53 && (node.left.kind === 154 || node.left.kind === 153)) {
+                return checkDestructuringAssignment(node.left, checkExpression(node.right, contextualMapper), contextualMapper);
+            }
+            var leftType = checkExpression(node.left, contextualMapper);
+            var rightType = checkExpression(node.right, contextualMapper);
+            switch (operator) {
+                case 35:
+                case 56:
+                case 36:
+                case 57:
+                case 37:
+                case 58:
+                case 34:
+                case 55:
+                case 40:
+                case 59:
+                case 41:
+                case 60:
+                case 42:
+                case 61:
+                case 44:
+                case 63:
+                case 45:
+                case 64:
+                case 43:
+                case 62:
+                    if (leftType.flags & (32 | 64))
+                        leftType = rightType;
+                    if (rightType.flags & (32 | 64))
+                        rightType = leftType;
+                    var suggestedOperator;
+                    if ((leftType.flags & 8) &&
+                        (rightType.flags & 8) &&
+                        (suggestedOperator = getSuggestedBooleanOperator(node.operatorToken.kind)) !== undefined) {
+                        error(node, ts.Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, ts.tokenToString(node.operatorToken.kind), ts.tokenToString(suggestedOperator));
+                    }
+                    else {
+                        var leftOk = checkArithmeticOperandType(node.left, leftType, ts.Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
+                        var rightOk = checkArithmeticOperandType(node.right, rightType, ts.Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
+                        if (leftOk && rightOk) {
+                            checkAssignmentOperator(numberType);
+                        }
+                    }
+                    return numberType;
+                case 33:
+                case 54:
+                    if (leftType.flags & (32 | 64))
+                        leftType = rightType;
+                    if (rightType.flags & (32 | 64))
+                        rightType = leftType;
+                    var resultType;
+                    if (allConstituentTypesHaveKind(leftType, 132) && allConstituentTypesHaveKind(rightType, 132)) {
+                        resultType = numberType;
+                    }
+                    else {
+                        if (allConstituentTypesHaveKind(leftType, 258) || allConstituentTypesHaveKind(rightType, 258)) {
+                            resultType = stringType;
+                        }
+                        else if (leftType.flags & 1 || rightType.flags & 1) {
+                            resultType = anyType;
+                        }
+                        if (resultType && !checkForDisallowedESSymbolOperand(operator)) {
+                            return resultType;
+                        }
+                    }
+                    if (!resultType) {
+                        reportOperatorError();
+                        return anyType;
+                    }
+                    if (operator === 54) {
+                        checkAssignmentOperator(resultType);
+                    }
+                    return resultType;
+                case 24:
+                case 25:
+                case 26:
+                case 27:
+                    if (!checkForDisallowedESSymbolOperand(operator)) {
+                        return booleanType;
+                    }
+                case 28:
+                case 29:
+                case 30:
+                case 31:
+                    if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) {
+                        reportOperatorError();
+                    }
+                    return booleanType;
+                case 87:
+                    return checkInstanceOfExpression(node, leftType, rightType);
+                case 86:
+                    return checkInExpression(node, leftType, rightType);
+                case 48:
+                    return rightType;
+                case 49:
+                    return getUnionType([leftType, rightType]);
+                case 53:
+                    checkAssignmentOperator(rightType);
+                    return rightType;
+                case 23:
+                    return rightType;
+            }
+            function checkForDisallowedESSymbolOperand(operator) {
+                var offendingSymbolOperand = someConstituentTypeHasKind(leftType, 1048576) ? node.left :
+                    someConstituentTypeHasKind(rightType, 1048576) ? node.right :
+                        undefined;
+                if (offendingSymbolOperand) {
+                    error(offendingSymbolOperand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(operator));
+                    return false;
+                }
+                return true;
+            }
+            function getSuggestedBooleanOperator(operator) {
+                switch (operator) {
+                    case 44:
+                    case 63:
+                        return 49;
+                    case 45:
+                    case 64:
+                        return 31;
+                    case 43:
+                    case 62:
+                        return 48;
+                    default:
+                        return undefined;
+                }
+            }
+            function checkAssignmentOperator(valueType) {
+                if (produceDiagnostics && operator >= 53 && operator <= 64) {
+                    var ok = checkReferenceExpression(node.left, ts.Diagnostics.Invalid_left_hand_side_of_assignment_expression, ts.Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant);
+                    if (ok) {
+                        checkTypeAssignableTo(valueType, leftType, node.left, undefined);
+                    }
+                }
+            }
+            function reportOperatorError() {
+                error(node, ts.Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, ts.tokenToString(node.operatorToken.kind), typeToString(leftType), typeToString(rightType));
+            }
+        }
+        function checkYieldExpression(node) {
+            if (!(node.parserContextFlags & 4)) {
+                grammarErrorOnFirstToken(node, ts.Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
+            }
+            else {
+                grammarErrorOnFirstToken(node, ts.Diagnostics.yield_expressions_are_not_currently_supported);
+            }
+        }
+        function checkConditionalExpression(node, contextualMapper) {
+            checkExpression(node.condition);
+            var type1 = checkExpression(node.whenTrue, contextualMapper);
+            var type2 = checkExpression(node.whenFalse, contextualMapper);
+            return getUnionType([type1, type2]);
+        }
+        function checkTemplateExpression(node) {
+            ts.forEach(node.templateSpans, function (templateSpan) {
+                checkExpression(templateSpan.expression);
+            });
+            return stringType;
+        }
+        function checkExpressionWithContextualType(node, contextualType, contextualMapper) {
+            var saveContextualType = node.contextualType;
+            node.contextualType = contextualType;
+            var result = checkExpression(node, contextualMapper);
+            node.contextualType = saveContextualType;
+            return result;
+        }
+        function checkExpressionCached(node, contextualMapper) {
+            var links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = checkExpression(node, contextualMapper);
+            }
+            return links.resolvedType;
+        }
+        function checkPropertyAssignment(node, contextualMapper) {
+            if (node.name.kind === 127) {
+                checkComputedPropertyName(node.name);
+            }
+            return checkExpression(node.initializer, contextualMapper);
+        }
+        function checkObjectLiteralMethod(node, contextualMapper) {
+            checkGrammarMethod(node);
+            if (node.name.kind === 127) {
+                checkComputedPropertyName(node.name);
+            }
+            var uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
+            return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
+        }
+        function instantiateTypeWithSingleGenericCallSignature(node, type, contextualMapper) {
+            if (contextualMapper && contextualMapper !== identityMapper) {
+                var signature = getSingleCallSignature(type);
+                if (signature && signature.typeParameters) {
+                    var contextualType = getContextualType(node);
+                    if (contextualType) {
+                        var contextualSignature = getSingleCallSignature(contextualType);
+                        if (contextualSignature && !contextualSignature.typeParameters) {
+                            return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
+                        }
+                    }
+                }
+            }
+            return type;
+        }
+        function checkExpression(node, contextualMapper) {
+            checkGrammarIdentifierInStrictMode(node);
+            return checkExpressionOrQualifiedName(node, contextualMapper);
+        }
+        function checkExpressionOrQualifiedName(node, contextualMapper) {
+            var type;
+            if (node.kind == 126) {
+                type = checkQualifiedName(node);
+            }
+            else {
+                var uninstantiatedType = checkExpressionWorker(node, contextualMapper);
+                type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
+            }
+            if (isConstEnumObjectType(type)) {
+                var ok = (node.parent.kind === 155 && node.parent.expression === node) ||
+                    (node.parent.kind === 156 && node.parent.expression === node) ||
+                    ((node.kind === 65 || node.kind === 126) && isInRightSideOfImportOrExportAssignment(node));
+                if (!ok) {
+                    error(node, ts.Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment);
+                }
+            }
+            return type;
+        }
+        function checkNumericLiteral(node) {
+            checkGrammarNumericLiteral(node);
+            return numberType;
+        }
+        function checkExpressionWorker(node, contextualMapper) {
+            switch (node.kind) {
+                case 65:
+                    return checkIdentifier(node);
+                case 93:
+                    return checkThisExpression(node);
+                case 91:
+                    return checkSuperExpression(node);
+                case 89:
+                    return nullType;
+                case 95:
+                case 80:
+                    return booleanType;
+                case 7:
+                    return checkNumericLiteral(node);
+                case 171:
+                    return checkTemplateExpression(node);
+                case 8:
+                case 10:
+                    return stringType;
+                case 9:
+                    return globalRegExpType;
+                case 153:
+                    return checkArrayLiteral(node, contextualMapper);
+                case 154:
+                    return checkObjectLiteral(node, contextualMapper);
+                case 155:
+                    return checkPropertyAccessExpression(node);
+                case 156:
+                    return checkIndexedAccess(node);
+                case 157:
+                case 158:
+                    return checkCallExpression(node);
+                case 159:
+                    return checkTaggedTemplateExpression(node);
+                case 160:
+                    return checkTypeAssertion(node);
+                case 161:
+                    return checkExpression(node.expression, contextualMapper);
+                case 174:
+                    return checkClassExpression(node);
+                case 162:
+                case 163:
+                    return checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
+                case 165:
+                    return checkTypeOfExpression(node);
+                case 164:
+                    return checkDeleteExpression(node);
+                case 166:
+                    return checkVoidExpression(node);
+                case 167:
+                    return checkPrefixUnaryExpression(node);
+                case 168:
+                    return checkPostfixUnaryExpression(node);
+                case 169:
+                    return checkBinaryExpression(node, contextualMapper);
+                case 170:
+                    return checkConditionalExpression(node, contextualMapper);
+                case 173:
+                    return checkSpreadElementExpression(node, contextualMapper);
+                case 175:
+                    return undefinedType;
+                case 172:
+                    checkYieldExpression(node);
+                    return unknownType;
+            }
+            return unknownType;
+        }
+        function checkTypeParameter(node) {
+            checkGrammarDeclarationNameInStrictMode(node);
+            if (node.expression) {
+                grammarErrorOnFirstToken(node.expression, ts.Diagnostics.Type_expected);
+            }
+            checkSourceElement(node.constraint);
+            if (produceDiagnostics) {
+                checkTypeParameterHasIllegalReferencesInConstraint(node);
+                checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_parameter_name_cannot_be_0);
+            }
+        }
+        function checkParameter(node) {
+            // Grammar checking
+            // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
+            // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code
+            // or if its FunctionBody is strict code(11.1.5).
+            // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
+            // strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
+            checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
+            checkVariableLikeDeclaration(node);
+            var func = ts.getContainingFunction(node);
+            if (node.flags & 112) {
+                func = ts.getContainingFunction(node);
+                if (!(func.kind === 135 && ts.nodeIsPresent(func.body))) {
+                    error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
+                }
+            }
+            if (node.questionToken && ts.isBindingPattern(node.name) && func.body) {
+                error(node, ts.Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
+            }
+            if (node.dotDotDotToken && !ts.isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) {
+                error(node, ts.Diagnostics.A_rest_parameter_must_be_of_an_array_type);
+            }
+        }
+        function checkSignatureDeclaration(node) {
+            if (node.kind === 140) {
+                checkGrammarIndexSignature(node);
+            }
+            else if (node.kind === 142 || node.kind === 200 || node.kind === 143 ||
+                node.kind === 138 || node.kind === 135 ||
+                node.kind === 139) {
+                checkGrammarFunctionLikeDeclaration(node);
+            }
+            checkTypeParameters(node.typeParameters);
+            ts.forEach(node.parameters, checkParameter);
+            if (node.type) {
+                checkSourceElement(node.type);
+            }
+            if (produceDiagnostics) {
+                checkCollisionWithArgumentsInGeneratedCode(node);
+                if (compilerOptions.noImplicitAny && !node.type) {
+                    switch (node.kind) {
+                        case 139:
+                            error(node, ts.Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
+                            break;
+                        case 138:
+                            error(node, ts.Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
+                            break;
+                    }
+                }
+            }
+            checkSpecializedSignatureDeclaration(node);
+        }
+        function checkTypeForDuplicateIndexSignatures(node) {
+            if (node.kind === 202) {
+                var nodeSymbol = getSymbolOfNode(node);
+                if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) {
+                    return;
+                }
+            }
+            var indexSymbol = getIndexSymbol(getSymbolOfNode(node));
+            if (indexSymbol) {
+                var seenNumericIndexer = false;
+                var seenStringIndexer = false;
+                for (var _i = 0, _a = indexSymbol.declarations; _i < _a.length; _i++) {
+                    var decl = _a[_i];
+                    var declaration = decl;
+                    if (declaration.parameters.length === 1 && declaration.parameters[0].type) {
+                        switch (declaration.parameters[0].type.kind) {
+                            case 121:
+                                if (!seenStringIndexer) {
+                                    seenStringIndexer = true;
+                                }
+                                else {
+                                    error(declaration, ts.Diagnostics.Duplicate_string_index_signature);
+                                }
+                                break;
+                            case 119:
+                                if (!seenNumericIndexer) {
+                                    seenNumericIndexer = true;
+                                }
+                                else {
+                                    error(declaration, ts.Diagnostics.Duplicate_number_index_signature);
+                                }
+                                break;
+                        }
+                    }
+                }
+            }
+        }
+        function checkPropertyDeclaration(node) {
+            checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name);
+            checkVariableLikeDeclaration(node);
+        }
+        function checkMethodDeclaration(node) {
+            checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name);
+            checkFunctionLikeDeclaration(node);
+        }
+        function checkConstructorDeclaration(node) {
+            checkSignatureDeclaration(node);
+            checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node);
+            checkSourceElement(node.body);
+            var symbol = getSymbolOfNode(node);
+            var firstDeclaration = ts.getDeclarationOfKind(symbol, node.kind);
+            if (node === firstDeclaration) {
+                checkFunctionOrConstructorSymbol(symbol);
+            }
+            if (ts.nodeIsMissing(node.body)) {
+                return;
+            }
+            if (!produceDiagnostics) {
+                return;
+            }
+            function isSuperCallExpression(n) {
+                return n.kind === 157 && n.expression.kind === 91;
+            }
+            function containsSuperCall(n) {
+                if (isSuperCallExpression(n)) {
+                    return true;
+                }
+                switch (n.kind) {
+                    case 162:
+                    case 200:
+                    case 163:
+                    case 154: return false;
+                    default: return ts.forEachChild(n, containsSuperCall);
+                }
+            }
+            function markThisReferencesAsErrors(n) {
+                if (n.kind === 93) {
+                    error(n, ts.Diagnostics.this_cannot_be_referenced_in_current_location);
+                }
+                else if (n.kind !== 162 && n.kind !== 200) {
+                    ts.forEachChild(n, markThisReferencesAsErrors);
+                }
+            }
+            function isInstancePropertyWithInitializer(n) {
+                return n.kind === 132 &&
+                    !(n.flags & 128) &&
+                    !!n.initializer;
+            }
+            if (ts.getClassExtendsHeritageClauseElement(node.parent)) {
+                if (containsSuperCall(node.body)) {
+                    var superCallShouldBeFirst = ts.forEach(node.parent.members, isInstancePropertyWithInitializer) ||
+                        ts.forEach(node.parameters, function (p) { return p.flags & (16 | 32 | 64); });
+                    if (superCallShouldBeFirst) {
+                        var statements = node.body.statements;
+                        if (!statements.length || statements[0].kind !== 182 || !isSuperCallExpression(statements[0].expression)) {
+                            error(node, ts.Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties);
+                        }
+                        else {
+                            markThisReferencesAsErrors(statements[0].expression);
+                        }
+                    }
+                }
+                else {
+                    error(node, ts.Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call);
+                }
+            }
+        }
+        function checkAccessorDeclaration(node) {
+            if (produceDiagnostics) {
+                checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
+                if (node.kind === 136) {
+                    if (!ts.isInAmbientContext(node) && ts.nodeIsPresent(node.body) && !(bodyContainsAReturnStatement(node.body) || bodyContainsSingleThrowStatement(node.body))) {
+                        error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
+                    }
+                }
+                if (!ts.hasDynamicName(node)) {
+                    var otherKind = node.kind === 136 ? 137 : 136;
+                    var otherAccessor = ts.getDeclarationOfKind(node.symbol, otherKind);
+                    if (otherAccessor) {
+                        if (((node.flags & 112) !== (otherAccessor.flags & 112))) {
+                            error(node.name, ts.Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility);
+                        }
+                        var currentAccessorType = getAnnotatedAccessorType(node);
+                        var otherAccessorType = getAnnotatedAccessorType(otherAccessor);
+                        if (currentAccessorType && otherAccessorType) {
+                            if (!isTypeIdenticalTo(currentAccessorType, otherAccessorType)) {
+                                error(node, ts.Diagnostics.get_and_set_accessor_must_have_the_same_type);
+                            }
+                        }
+                    }
+                }
+                checkAndStoreTypeOfAccessors(getSymbolOfNode(node));
+            }
+            checkFunctionLikeDeclaration(node);
+        }
+        function checkMissingDeclaration(node) {
+            checkDecorators(node);
+        }
+        function checkTypeReferenceNode(node) {
+            checkGrammarTypeReferenceInStrictMode(node.typeName);
+            return checkTypeReferenceOrHeritageClauseElement(node);
+        }
+        function checkHeritageClauseElement(node) {
+            checkGrammarHeritageClauseElementInStrictMode(node.expression);
+            return checkTypeReferenceOrHeritageClauseElement(node);
+        }
+        function checkTypeReferenceOrHeritageClauseElement(node) {
+            checkGrammarTypeArguments(node, node.typeArguments);
+            var type = getTypeFromTypeReferenceOrHeritageClauseElement(node);
+            if (type !== unknownType && node.typeArguments) {
+                var len = node.typeArguments.length;
+                for (var i = 0; i < len; i++) {
+                    checkSourceElement(node.typeArguments[i]);
+                    var constraint = getConstraintOfTypeParameter(type.target.typeParameters[i]);
+                    if (produceDiagnostics && constraint) {
+                        var typeArgument = type.typeArguments[i];
+                        checkTypeAssignableTo(typeArgument, constraint, node, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
+                    }
+                }
+            }
+        }
+        function checkTypeQuery(node) {
+            getTypeFromTypeQueryNode(node);
+        }
+        function checkTypeLiteral(node) {
+            ts.forEach(node.members, checkSourceElement);
+            if (produceDiagnostics) {
+                var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
+                checkIndexConstraints(type);
+                checkTypeForDuplicateIndexSignatures(node);
+            }
+        }
+        function checkArrayType(node) {
+            checkSourceElement(node.elementType);
+        }
+        function checkTupleType(node) {
+            var hasErrorFromDisallowedTrailingComma = checkGrammarForDisallowedTrailingComma(node.elementTypes);
+            if (!hasErrorFromDisallowedTrailingComma && node.elementTypes.length === 0) {
+                grammarErrorOnNode(node, ts.Diagnostics.A_tuple_type_element_list_cannot_be_empty);
+            }
+            ts.forEach(node.elementTypes, checkSourceElement);
+        }
+        function checkUnionType(node) {
+            ts.forEach(node.types, checkSourceElement);
+        }
+        function isPrivateWithinAmbient(node) {
+            return (node.flags & 32) && ts.isInAmbientContext(node);
+        }
+        function checkSpecializedSignatureDeclaration(signatureDeclarationNode) {
+            if (!produceDiagnostics) {
+                return;
+            }
+            var signature = getSignatureFromDeclaration(signatureDeclarationNode);
+            if (!signature.hasStringLiterals) {
+                return;
+            }
+            if (ts.nodeIsPresent(signatureDeclarationNode.body)) {
+                error(signatureDeclarationNode, ts.Diagnostics.A_signature_with_an_implementation_cannot_use_a_string_literal_type);
+                return;
+            }
+            var signaturesToCheck;
+            if (!signatureDeclarationNode.name && signatureDeclarationNode.parent && signatureDeclarationNode.parent.kind === 202) {
+                ts.Debug.assert(signatureDeclarationNode.kind === 138 || signatureDeclarationNode.kind === 139);
+                var signatureKind = signatureDeclarationNode.kind === 138 ? 0 : 1;
+                var containingSymbol = getSymbolOfNode(signatureDeclarationNode.parent);
+                var containingType = getDeclaredTypeOfSymbol(containingSymbol);
+                signaturesToCheck = getSignaturesOfType(containingType, signatureKind);
+            }
+            else {
+                signaturesToCheck = getSignaturesOfSymbol(getSymbolOfNode(signatureDeclarationNode));
+            }
+            for (var _i = 0; _i < signaturesToCheck.length; _i++) {
+                var otherSignature = signaturesToCheck[_i];
+                if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) {
+                    return;
+                }
+            }
+            error(signatureDeclarationNode, ts.Diagnostics.Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature);
+        }
+        function getEffectiveDeclarationFlags(n, flagsToCheck) {
+            var flags = ts.getCombinedNodeFlags(n);
+            if (n.parent.kind !== 202 && ts.isInAmbientContext(n)) {
+                if (!(flags & 2)) {
+                    flags |= 1;
+                }
+                flags |= 2;
+            }
+            return flags & flagsToCheck;
+        }
+        function checkFunctionOrConstructorSymbol(symbol) {
+            if (!produceDiagnostics) {
+                return;
+            }
+            function getCanonicalOverload(overloads, implementation) {
+                var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
+                return implementationSharesContainerWithFirstOverload ? implementation : overloads[0];
+            }
+            function checkFlagAgreementBetweenOverloads(overloads, implementation, flagsToCheck, someOverloadFlags, allOverloadFlags) {
+                var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
+                if (someButNotAllOverloadFlags !== 0) {
+                    var canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck);
+                    ts.forEach(overloads, function (o) {
+                        var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
+                        if (deviation & 1) {
+                            error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_exported_or_not_exported);
+                        }
+                        else if (deviation & 2) {
+                            error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
+                        }
+                        else if (deviation & (32 | 64)) {
+                            error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
+                        }
+                    });
+                }
+            }
+            function checkQuestionTokenAgreementBetweenOverloads(overloads, implementation, someHaveQuestionToken, allHaveQuestionToken) {
+                if (someHaveQuestionToken !== allHaveQuestionToken) {
+                    var canonicalHasQuestionToken = ts.hasQuestionToken(getCanonicalOverload(overloads, implementation));
+                    ts.forEach(overloads, function (o) {
+                        var deviation = ts.hasQuestionToken(o) !== canonicalHasQuestionToken;
+                        if (deviation) {
+                            error(o.name, ts.Diagnostics.Overload_signatures_must_all_be_optional_or_required);
+                        }
+                    });
+                }
+            }
+            var flagsToCheck = 1 | 2 | 32 | 64;
+            var someNodeFlags = 0;
+            var allNodeFlags = flagsToCheck;
+            var someHaveQuestionToken = false;
+            var allHaveQuestionToken = true;
+            var hasOverloads = false;
+            var bodyDeclaration;
+            var lastSeenNonAmbientDeclaration;
+            var previousDeclaration;
+            var declarations = symbol.declarations;
+            var isConstructor = (symbol.flags & 16384) !== 0;
+            function reportImplementationExpectedError(node) {
+                if (node.name && ts.nodeIsMissing(node.name)) {
+                    return;
+                }
+                var seen = false;
+                var subsequentNode = ts.forEachChild(node.parent, function (c) {
+                    if (seen) {
+                        return c;
+                    }
+                    else {
+                        seen = c === node;
+                    }
+                });
+                if (subsequentNode) {
+                    if (subsequentNode.kind === node.kind) {
+                        var errorNode_1 = subsequentNode.name || subsequentNode;
+                        if (node.name && subsequentNode.name && node.name.text === subsequentNode.name.text) {
+                            ts.Debug.assert(node.kind === 134 || node.kind === 133);
+                            ts.Debug.assert((node.flags & 128) !== (subsequentNode.flags & 128));
+                            var diagnostic = node.flags & 128 ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static;
+                            error(errorNode_1, diagnostic);
+                            return;
+                        }
+                        else if (ts.nodeIsPresent(subsequentNode.body)) {
+                            error(errorNode_1, ts.Diagnostics.Function_implementation_name_must_be_0, ts.declarationNameToString(node.name));
+                            return;
+                        }
+                    }
+                }
+                var errorNode = node.name || node;
+                if (isConstructor) {
+                    error(errorNode, ts.Diagnostics.Constructor_implementation_is_missing);
+                }
+                else {
+                    error(errorNode, ts.Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration);
+                }
+            }
+            var isExportSymbolInsideModule = symbol.parent && symbol.parent.flags & 1536;
+            var duplicateFunctionDeclaration = false;
+            var multipleConstructorImplementation = false;
+            for (var _i = 0; _i < declarations.length; _i++) {
+                var current = declarations[_i];
+                var node = current;
+                var inAmbientContext = ts.isInAmbientContext(node);
+                var inAmbientContextOrInterface = node.parent.kind === 202 || node.parent.kind === 145 || inAmbientContext;
+                if (inAmbientContextOrInterface) {
+                    previousDeclaration = undefined;
+                }
+                if (node.kind === 200 || node.kind === 134 || node.kind === 133 || node.kind === 135) {
+                    var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
+                    someNodeFlags |= currentNodeFlags;
+                    allNodeFlags &= currentNodeFlags;
+                    someHaveQuestionToken = someHaveQuestionToken || ts.hasQuestionToken(node);
+                    allHaveQuestionToken = allHaveQuestionToken && ts.hasQuestionToken(node);
+                    if (ts.nodeIsPresent(node.body) && bodyDeclaration) {
+                        if (isConstructor) {
+                            multipleConstructorImplementation = true;
+                        }
+                        else {
+                            duplicateFunctionDeclaration = true;
+                        }
+                    }
+                    else if (!isExportSymbolInsideModule && previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) {
+                        reportImplementationExpectedError(previousDeclaration);
+                    }
+                    if (ts.nodeIsPresent(node.body)) {
+                        if (!bodyDeclaration) {
+                            bodyDeclaration = node;
+                        }
+                    }
+                    else {
+                        hasOverloads = true;
+                    }
+                    previousDeclaration = node;
+                    if (!inAmbientContextOrInterface) {
+                        lastSeenNonAmbientDeclaration = node;
+                    }
+                }
+            }
+            if (multipleConstructorImplementation) {
+                ts.forEach(declarations, function (declaration) {
+                    error(declaration, ts.Diagnostics.Multiple_constructor_implementations_are_not_allowed);
+                });
+            }
+            if (duplicateFunctionDeclaration) {
+                ts.forEach(declarations, function (declaration) {
+                    error(declaration.name, ts.Diagnostics.Duplicate_function_implementation);
+                });
+            }
+            if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body) {
+                reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
+            }
+            if (hasOverloads) {
+                checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags);
+                checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken);
+                if (bodyDeclaration) {
+                    var signatures = getSignaturesOfSymbol(symbol);
+                    var bodySignature = getSignatureFromDeclaration(bodyDeclaration);
+                    if (!bodySignature.hasStringLiterals) {
+                        for (var _a = 0; _a < signatures.length; _a++) {
+                            var signature = signatures[_a];
+                            if (!signature.hasStringLiterals && !isSignatureAssignableTo(bodySignature, signature)) {
+                                error(signature.declaration, ts.Diagnostics.Overload_signature_is_not_compatible_with_function_implementation);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        function checkExportsOnMergedDeclarations(node) {
+            if (!produceDiagnostics) {
+                return;
+            }
+            var symbol = node.localSymbol;
+            if (!symbol) {
+                symbol = getSymbolOfNode(node);
+                if (!(symbol.flags & 7340032)) {
+                    return;
+                }
+            }
+            if (ts.getDeclarationOfKind(symbol, node.kind) !== node) {
+                return;
+            }
+            var exportedDeclarationSpaces = 0;
+            var nonExportedDeclarationSpaces = 0;
+            ts.forEach(symbol.declarations, function (d) {
+                var declarationSpaces = getDeclarationSpaces(d);
+                if (getEffectiveDeclarationFlags(d, 1)) {
+                    exportedDeclarationSpaces |= declarationSpaces;
+                }
+                else {
+                    nonExportedDeclarationSpaces |= declarationSpaces;
+                }
+            });
+            var commonDeclarationSpace = exportedDeclarationSpaces & nonExportedDeclarationSpaces;
+            if (commonDeclarationSpace) {
+                ts.forEach(symbol.declarations, function (d) {
+                    if (getDeclarationSpaces(d) & commonDeclarationSpace) {
+                        error(d.name, ts.Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, ts.declarationNameToString(d.name));
+                    }
+                });
+            }
+            function getDeclarationSpaces(d) {
+                switch (d.kind) {
+                    case 202:
+                        return 2097152;
+                    case 205:
+                        return d.name.kind === 8 || ts.getModuleInstanceState(d) !== 0
+                            ? 4194304 | 1048576
+                            : 4194304;
+                    case 201:
+                    case 204:
+                        return 2097152 | 1048576;
+                    case 208:
+                        var result = 0;
+                        var target = resolveAlias(getSymbolOfNode(d));
+                        ts.forEach(target.declarations, function (d) { result |= getDeclarationSpaces(d); });
+                        return result;
+                    default:
+                        return 1048576;
+                }
+            }
+        }
+        function checkDecorator(node) {
+            var expression = node.expression;
+            var exprType = checkExpression(expression);
+            switch (node.parent.kind) {
+                case 201:
+                    var classSymbol = getSymbolOfNode(node.parent);
+                    var classConstructorType = getTypeOfSymbol(classSymbol);
+                    var classDecoratorType = instantiateSingleCallFunctionType(getGlobalClassDecoratorType(), [classConstructorType]);
+                    checkTypeAssignableTo(exprType, classDecoratorType, node);
+                    break;
+                case 132:
+                    checkTypeAssignableTo(exprType, getGlobalPropertyDecoratorType(), node);
+                    break;
+                case 134:
+                case 136:
+                case 137:
+                    var methodType = getTypeOfNode(node.parent);
+                    var methodDecoratorType = instantiateSingleCallFunctionType(getGlobalMethodDecoratorType(), [methodType]);
+                    checkTypeAssignableTo(exprType, methodDecoratorType, node);
+                    break;
+                case 129:
+                    checkTypeAssignableTo(exprType, getGlobalParameterDecoratorType(), node);
+                    break;
+            }
+        }
+        function checkTypeNodeAsExpression(node) {
+            if (node && node.kind === 141) {
+                var type = getTypeFromTypeNode(node);
+                var shouldCheckIfUnknownType = type === unknownType && compilerOptions.separateCompilation;
+                if (!type || (!shouldCheckIfUnknownType && type.flags & (1048703 | 132 | 258))) {
+                    return;
+                }
+                if (shouldCheckIfUnknownType || type.symbol.valueDeclaration) {
+                    checkExpressionOrQualifiedName(node.typeName);
+                }
+            }
+        }
+        function checkTypeAnnotationAsExpression(node) {
+            switch (node.kind) {
+                case 132:
+                    checkTypeNodeAsExpression(node.type);
+                    break;
+                case 129:
+                    checkTypeNodeAsExpression(node.type);
+                    break;
+                case 134:
+                    checkTypeNodeAsExpression(node.type);
+                    break;
+                case 136:
+                    checkTypeNodeAsExpression(node.type);
+                    break;
+                case 137:
+                    checkTypeNodeAsExpression(getSetAccessorTypeAnnotationNode(node));
+                    break;
+            }
+        }
+        function checkParameterTypeAnnotationsAsExpressions(node) {
+            for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) {
+                var parameter = _a[_i];
+                checkTypeAnnotationAsExpression(parameter);
+            }
+        }
+        function checkDecorators(node) {
+            if (!node.decorators) {
+                return;
+            }
+            if (!ts.nodeCanBeDecorated(node)) {
+                return;
+            }
+            if (compilerOptions.emitDecoratorMetadata) {
+                switch (node.kind) {
+                    case 201:
+                        var constructor = ts.getFirstConstructorWithBody(node);
+                        if (constructor) {
+                            checkParameterTypeAnnotationsAsExpressions(constructor);
+                        }
+                        break;
+                    case 134:
+                        checkParameterTypeAnnotationsAsExpressions(node);
+                    case 137:
+                    case 136:
+                    case 132:
+                    case 129:
+                        checkTypeAnnotationAsExpression(node);
+                        break;
+                }
+            }
+            emitDecorate = true;
+            if (node.kind === 129) {
+                emitParam = true;
+            }
+            ts.forEach(node.decorators, checkDecorator);
+        }
+        function checkFunctionDeclaration(node) {
+            if (produceDiagnostics) {
+                checkFunctionLikeDeclaration(node) ||
+                    checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) ||
+                    checkGrammarFunctionName(node.name) ||
+                    checkGrammarForGenerator(node);
+                checkCollisionWithCapturedSuperVariable(node, node.name);
+                checkCollisionWithCapturedThisVariable(node, node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            }
+        }
+        function checkFunctionLikeDeclaration(node) {
+            checkGrammarDeclarationNameInStrictMode(node);
+            checkDecorators(node);
+            checkSignatureDeclaration(node);
+            if (node.name && node.name.kind === 127) {
+                checkComputedPropertyName(node.name);
+            }
+            if (!ts.hasDynamicName(node)) {
+                var symbol = getSymbolOfNode(node);
+                var localSymbol = node.localSymbol || symbol;
+                var firstDeclaration = ts.getDeclarationOfKind(localSymbol, node.kind);
+                if (node === firstDeclaration) {
+                    checkFunctionOrConstructorSymbol(localSymbol);
+                }
+                if (symbol.parent) {
+                    if (ts.getDeclarationOfKind(symbol, node.kind) === node) {
+                        checkFunctionOrConstructorSymbol(symbol);
+                    }
+                }
+            }
+            checkSourceElement(node.body);
+            if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
+                checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
+            }
+            if (compilerOptions.noImplicitAny && ts.nodeIsMissing(node.body) && !node.type && !isPrivateWithinAmbient(node)) {
+                reportImplicitAnyError(node, anyType);
+            }
+        }
+        function checkBlock(node) {
+            if (node.kind === 179) {
+                checkGrammarStatementInAmbientContext(node);
+            }
+            ts.forEach(node.statements, checkSourceElement);
+            if (ts.isFunctionBlock(node) || node.kind === 206) {
+                checkFunctionExpressionBodies(node);
+            }
+        }
+        function checkCollisionWithArgumentsInGeneratedCode(node) {
+            if (!ts.hasRestParameters(node) || ts.isInAmbientContext(node) || ts.nodeIsMissing(node.body)) {
+                return;
+            }
+            ts.forEach(node.parameters, function (p) {
+                if (p.name && !ts.isBindingPattern(p.name) && p.name.text === argumentsSymbol.name) {
+                    error(p, ts.Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters);
+                }
+            });
+        }
+        function needCollisionCheckForIdentifier(node, identifier, name) {
+            if (!(identifier && identifier.text === name)) {
+                return false;
+            }
+            if (node.kind === 132 ||
+                node.kind === 131 ||
+                node.kind === 134 ||
+                node.kind === 133 ||
+                node.kind === 136 ||
+                node.kind === 137) {
+                return false;
+            }
+            if (ts.isInAmbientContext(node)) {
+                return false;
+            }
+            var root = getRootDeclaration(node);
+            if (root.kind === 129 && ts.nodeIsMissing(root.parent.body)) {
+                return false;
+            }
+            return true;
+        }
+        function checkCollisionWithCapturedThisVariable(node, name) {
+            if (needCollisionCheckForIdentifier(node, name, "_this")) {
+                potentialThisCollisions.push(node);
+            }
+        }
+        function checkIfThisIsCapturedInEnclosingScope(node) {
+            var current = node;
+            while (current) {
+                if (getNodeCheckFlags(current) & 4) {
+                    var isDeclaration_1 = node.kind !== 65;
+                    if (isDeclaration_1) {
+                        error(node.name, ts.Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference);
+                    }
+                    else {
+                        error(node, ts.Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference);
+                    }
+                    return;
+                }
+                current = current.parent;
+            }
+        }
+        function checkCollisionWithCapturedSuperVariable(node, name) {
+            if (!needCollisionCheckForIdentifier(node, name, "_super")) {
+                return;
+            }
+            var enclosingClass = ts.getAncestor(node, 201);
+            if (!enclosingClass || ts.isInAmbientContext(enclosingClass)) {
+                return;
+            }
+            if (ts.getClassExtendsHeritageClauseElement(enclosingClass)) {
+                var isDeclaration_2 = node.kind !== 65;
+                if (isDeclaration_2) {
+                    error(node, ts.Diagnostics.Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference);
+                }
+                else {
+                    error(node, ts.Diagnostics.Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference);
+                }
+            }
+        }
+        function checkCollisionWithRequireExportsInGeneratedCode(node, name) {
+            if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
+                return;
+            }
+            if (node.kind === 205 && ts.getModuleInstanceState(node) !== 1) {
+                return;
+            }
+            var parent = getDeclarationContainer(node);
+            if (parent.kind === 227 && ts.isExternalModule(parent)) {
+                error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, ts.declarationNameToString(name), ts.declarationNameToString(name));
+            }
+        }
+        function checkVarDeclaredNamesNotShadowed(node) {
+            // - ScriptBody : StatementList
+            // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
+            // also occurs in the VarDeclaredNames of StatementList.
+            if ((ts.getCombinedNodeFlags(node) & 12288) !== 0 || isParameterDeclaration(node)) {
+                return;
+            }
+            if (node.kind === 198 && !node.initializer) {
+                return;
+            }
+            var symbol = getSymbolOfNode(node);
+            if (symbol.flags & 1) {
+                var localDeclarationSymbol = resolveName(node, node.name.text, 3, undefined, undefined);
+                if (localDeclarationSymbol &&
+                    localDeclarationSymbol !== symbol &&
+                    localDeclarationSymbol.flags & 2) {
+                    if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & 12288) {
+                        var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 199);
+                        var container = varDeclList.parent.kind === 180 && varDeclList.parent.parent
+                            ? varDeclList.parent.parent
+                            : undefined;
+                        var namesShareScope = container &&
+                            (container.kind === 179 && ts.isFunctionLike(container.parent) ||
+                                container.kind === 206 ||
+                                container.kind === 205 ||
+                                container.kind === 227);
+                        if (!namesShareScope) {
+                            var name_6 = symbolToString(localDeclarationSymbol);
+                            error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name_6, name_6);
+                        }
+                    }
+                }
+            }
+        }
+        function isParameterDeclaration(node) {
+            while (node.kind === 152) {
+                node = node.parent.parent;
+            }
+            return node.kind === 129;
+        }
+        function checkParameterInitializer(node) {
+            if (getRootDeclaration(node).kind !== 129) {
+                return;
+            }
+            var func = ts.getContainingFunction(node);
+            visit(node.initializer);
+            function visit(n) {
+                if (n.kind === 65) {
+                    var referencedSymbol = getNodeLinks(n).resolvedSymbol;
+                    if (referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol(func.locals, referencedSymbol.name, 107455) === referencedSymbol) {
+                        if (referencedSymbol.valueDeclaration.kind === 129) {
+                            if (referencedSymbol.valueDeclaration === node) {
+                                error(n, ts.Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, ts.declarationNameToString(node.name));
+                                return;
+                            }
+                            if (referencedSymbol.valueDeclaration.pos < node.pos) {
+                                return;
+                            }
+                        }
+                        error(n, ts.Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, ts.declarationNameToString(node.name), ts.declarationNameToString(n));
+                    }
+                }
+                else {
+                    ts.forEachChild(n, visit);
+                }
+            }
+        }
+        function checkVariableLikeDeclaration(node) {
+            checkGrammarDeclarationNameInStrictMode(node);
+            checkDecorators(node);
+            checkSourceElement(node.type);
+            if (node.name.kind === 127) {
+                checkComputedPropertyName(node.name);
+                if (node.initializer) {
+                    checkExpressionCached(node.initializer);
+                }
+            }
+            if (ts.isBindingPattern(node.name)) {
+                ts.forEach(node.name.elements, checkSourceElement);
+            }
+            if (node.initializer && getRootDeclaration(node).kind === 129 && ts.nodeIsMissing(ts.getContainingFunction(node).body)) {
+                error(node, ts.Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
+                return;
+            }
+            if (ts.isBindingPattern(node.name)) {
+                if (node.initializer) {
+                    checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), node, undefined);
+                    checkParameterInitializer(node);
+                }
+                return;
+            }
+            var symbol = getSymbolOfNode(node);
+            var type = getTypeOfVariableOrParameterOrProperty(symbol);
+            if (node === symbol.valueDeclaration) {
+                if (node.initializer) {
+                    checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, undefined);
+                    checkParameterInitializer(node);
+                }
+            }
+            else {
+                var declarationType = getWidenedTypeForVariableLikeDeclaration(node);
+                if (type !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(type, declarationType)) {
+                    error(node.name, ts.Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, ts.declarationNameToString(node.name), typeToString(type), typeToString(declarationType));
+                }
+                if (node.initializer) {
+                    checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, undefined);
+                }
+            }
+            if (node.kind !== 132 && node.kind !== 131) {
+                checkExportsOnMergedDeclarations(node);
+                if (node.kind === 198 || node.kind === 152) {
+                    checkVarDeclaredNamesNotShadowed(node);
+                }
+                checkCollisionWithCapturedSuperVariable(node, node.name);
+                checkCollisionWithCapturedThisVariable(node, node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            }
+        }
+        function checkVariableDeclaration(node) {
+            checkGrammarVariableDeclaration(node);
+            return checkVariableLikeDeclaration(node);
+        }
+        function checkBindingElement(node) {
+            checkGrammarBindingElement(node);
+            return checkVariableLikeDeclaration(node);
+        }
+        function checkVariableStatement(node) {
+            checkGrammarDecorators(node) || checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node);
+            ts.forEach(node.declarationList.declarations, checkSourceElement);
+        }
+        function checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) {
+            if (node.modifiers) {
+                if (inBlockOrObjectLiteralExpression(node)) {
+                    return grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_cannot_appear_here);
+                }
+            }
+        }
+        function inBlockOrObjectLiteralExpression(node) {
+            while (node) {
+                if (node.kind === 179 || node.kind === 154) {
+                    return true;
+                }
+                node = node.parent;
+            }
+        }
+        function checkExpressionStatement(node) {
+            checkGrammarStatementInAmbientContext(node);
+            checkExpression(node.expression);
+        }
+        function checkIfStatement(node) {
+            checkGrammarStatementInAmbientContext(node);
+            checkExpression(node.expression);
+            checkSourceElement(node.thenStatement);
+            checkSourceElement(node.elseStatement);
+        }
+        function checkDoStatement(node) {
+            checkGrammarStatementInAmbientContext(node);
+            checkSourceElement(node.statement);
+            checkExpression(node.expression);
+        }
+        function checkWhileStatement(node) {
+            checkGrammarStatementInAmbientContext(node);
+            checkExpression(node.expression);
+            checkSourceElement(node.statement);
+        }
+        function checkForStatement(node) {
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                if (node.initializer && node.initializer.kind == 199) {
+                    checkGrammarVariableDeclarationList(node.initializer);
+                }
+            }
+            if (node.initializer) {
+                if (node.initializer.kind === 199) {
+                    ts.forEach(node.initializer.declarations, checkVariableDeclaration);
+                }
+                else {
+                    checkExpression(node.initializer);
+                }
+            }
+            if (node.condition)
+                checkExpression(node.condition);
+            if (node.incrementor)
+                checkExpression(node.incrementor);
+            checkSourceElement(node.statement);
+        }
+        function checkForOfStatement(node) {
+            checkGrammarForInOrForOfStatement(node);
+            if (node.initializer.kind === 199) {
+                checkForInOrForOfVariableDeclaration(node);
+            }
+            else {
+                var varExpr = node.initializer;
+                var iteratedType = checkRightHandSideOfForOf(node.expression);
+                if (varExpr.kind === 153 || varExpr.kind === 154) {
+                    checkDestructuringAssignment(varExpr, iteratedType || unknownType);
+                }
+                else {
+                    var leftType = checkExpression(varExpr);
+                    checkReferenceExpression(varExpr, ts.Diagnostics.Invalid_left_hand_side_in_for_of_statement, ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant);
+                    if (iteratedType) {
+                        checkTypeAssignableTo(iteratedType, leftType, varExpr, undefined);
+                    }
+                }
+            }
+            checkSourceElement(node.statement);
+        }
+        function checkForInStatement(node) {
+            checkGrammarForInOrForOfStatement(node);
+            if (node.initializer.kind === 199) {
+                var variable = node.initializer.declarations[0];
+                if (variable && ts.isBindingPattern(variable.name)) {
+                    error(variable.name, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
+                }
+                checkForInOrForOfVariableDeclaration(node);
+            }
+            else {
+                var varExpr = node.initializer;
+                var leftType = checkExpression(varExpr);
+                if (varExpr.kind === 153 || varExpr.kind === 154) {
+                    error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
+                }
+                else if (!allConstituentTypesHaveKind(leftType, 1 | 258)) {
+                    error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
+                }
+                else {
+                    checkReferenceExpression(varExpr, ts.Diagnostics.Invalid_left_hand_side_in_for_in_statement, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant);
+                }
+            }
+            var rightType = checkExpression(node.expression);
+            if (!allConstituentTypesHaveKind(rightType, 1 | 48128 | 512)) {
+                error(node.expression, ts.Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter);
+            }
+            checkSourceElement(node.statement);
+        }
+        function checkForInOrForOfVariableDeclaration(iterationStatement) {
+            var variableDeclarationList = iterationStatement.initializer;
+            if (variableDeclarationList.declarations.length >= 1) {
+                var decl = variableDeclarationList.declarations[0];
+                checkVariableDeclaration(decl);
+            }
+        }
+        function checkRightHandSideOfForOf(rhsExpression) {
+            var expressionType = getTypeOfExpression(rhsExpression);
+            return checkIteratedTypeOrElementType(expressionType, rhsExpression, true);
+        }
+        function checkIteratedTypeOrElementType(inputType, errorNode, allowStringInput) {
+            if (inputType.flags & 1) {
+                return inputType;
+            }
+            if (languageVersion >= 2) {
+                return checkIteratedType(inputType, errorNode) || anyType;
+            }
+            if (allowStringInput) {
+                return checkElementTypeOfArrayOrString(inputType, errorNode);
+            }
+            if (isArrayLikeType(inputType)) {
+                var indexType = getIndexTypeOfType(inputType, 1);
+                if (indexType) {
+                    return indexType;
+                }
+            }
+            error(errorNode, ts.Diagnostics.Type_0_is_not_an_array_type, typeToString(inputType));
+            return unknownType;
+        }
+        function checkIteratedType(iterable, errorNode) {
+            ts.Debug.assert(languageVersion >= 2);
+            var iteratedType = getIteratedType(iterable, errorNode);
+            if (errorNode && iteratedType) {
+                checkTypeAssignableTo(iterable, createIterableType(iteratedType), errorNode);
+            }
+            return iteratedType;
+            function getIteratedType(iterable, errorNode) {
+                // We want to treat type as an iterable, and get the type it is an iterable of. The iterable
+                // must have the following structure (annotated with the names of the variables below):
+                //
+                // { // iterable
+                //     [Symbol.iterator]: { // iteratorFunction
+                //         (): { // iterator
+                //             next: { // iteratorNextFunction
+                //                 (): { // iteratorNextResult
+                //                     value: T // iteratorNextValue
+                //                 }
+                //             }
+                //         }
+                //     }
+                // }
+                //
+                // T is the type we are after. At every level that involves analyzing return types
+                // of signatures, we union the return types of all the signatures.
+                //
+                // Another thing to note is that at any step of this process, we could run into a dead end,
+                // meaning either the property is missing, or we run into the anyType. If either of these things
+                // happens, we return undefined to signal that we could not find the iterated type. If a property
+                // is missing, and the previous step did not result in 'any', then we also give an error if the
+                // caller requested it. Then the caller can decide what to do in the case where there is no iterated
+                // type. This is different from returning anyType, because that would signify that we have matched the
+                // whole pattern and that T (above) is 'any'.
+                if (allConstituentTypesHaveKind(iterable, 1)) {
+                    return undefined;
+                }
+                if ((iterable.flags & 4096) && iterable.target === globalIterableType) {
+                    return iterable.typeArguments[0];
+                }
+                var iteratorFunction = getTypeOfPropertyOfType(iterable, ts.getPropertyNameForKnownSymbolName("iterator"));
+                if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, 1)) {
+                    return undefined;
+                }
+                var iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, 0) : emptyArray;
+                if (iteratorFunctionSignatures.length === 0) {
+                    if (errorNode) {
+                        error(errorNode, ts.Diagnostics.Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
+                    }
+                    return undefined;
+                }
+                var iterator = getUnionType(ts.map(iteratorFunctionSignatures, getReturnTypeOfSignature));
+                if (allConstituentTypesHaveKind(iterator, 1)) {
+                    return undefined;
+                }
+                var iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next");
+                if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, 1)) {
+                    return undefined;
+                }
+                var iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, 0) : emptyArray;
+                if (iteratorNextFunctionSignatures.length === 0) {
+                    if (errorNode) {
+                        error(errorNode, ts.Diagnostics.An_iterator_must_have_a_next_method);
+                    }
+                    return undefined;
+                }
+                var iteratorNextResult = getUnionType(ts.map(iteratorNextFunctionSignatures, getReturnTypeOfSignature));
+                if (allConstituentTypesHaveKind(iteratorNextResult, 1)) {
+                    return undefined;
+                }
+                var iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value");
+                if (!iteratorNextValue) {
+                    if (errorNode) {
+                        error(errorNode, ts.Diagnostics.The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property);
+                    }
+                    return undefined;
+                }
+                return iteratorNextValue;
+            }
+        }
+        function checkElementTypeOfArrayOrString(arrayOrStringType, errorNode) {
+            ts.Debug.assert(languageVersion < 2);
+            var arrayType = removeTypesFromUnionType(arrayOrStringType, 258, true, true);
+            var hasStringConstituent = arrayOrStringType !== arrayType;
+            var reportedError = false;
+            if (hasStringConstituent) {
+                if (languageVersion < 1) {
+                    error(errorNode, ts.Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher);
+                    reportedError = true;
+                }
+                if (arrayType === emptyObjectType) {
+                    return stringType;
+                }
+            }
+            if (!isArrayLikeType(arrayType)) {
+                if (!reportedError) {
+                    var diagnostic = hasStringConstituent
+                        ? ts.Diagnostics.Type_0_is_not_an_array_type
+                        : ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type;
+                    error(errorNode, diagnostic, typeToString(arrayType));
+                }
+                return hasStringConstituent ? stringType : unknownType;
+            }
+            var arrayElementType = getIndexTypeOfType(arrayType, 1) || unknownType;
+            if (hasStringConstituent) {
+                if (arrayElementType.flags & 258) {
+                    return stringType;
+                }
+                return getUnionType([arrayElementType, stringType]);
+            }
+            return arrayElementType;
+        }
+        function checkBreakOrContinueStatement(node) {
+            checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node);
+        }
+        function isGetAccessorWithAnnotatatedSetAccessor(node) {
+            return !!(node.kind === 136 && getSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(node.symbol, 137)));
+        }
+        function checkReturnStatement(node) {
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                var functionBlock = ts.getContainingFunction(node);
+                if (!functionBlock) {
+                    grammarErrorOnFirstToken(node, ts.Diagnostics.A_return_statement_can_only_be_used_within_a_function_body);
+                }
+            }
+            if (node.expression) {
+                var func = ts.getContainingFunction(node);
+                if (func) {
+                    var returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func));
+                    var exprType = checkExpressionCached(node.expression);
+                    if (func.kind === 137) {
+                        error(node.expression, ts.Diagnostics.Setters_cannot_return_a_value);
+                    }
+                    else {
+                        if (func.kind === 135) {
+                            if (!isTypeAssignableTo(exprType, returnType)) {
+                                error(node.expression, ts.Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
+                            }
+                        }
+                        else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func)) {
+                            checkTypeAssignableTo(exprType, returnType, node.expression, undefined);
+                        }
+                    }
+                }
+            }
+        }
+        function checkWithStatement(node) {
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                if (node.parserContextFlags & 1) {
+                    grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode);
+                }
+            }
+            checkExpression(node.expression);
+            error(node.expression, ts.Diagnostics.All_symbols_within_a_with_block_will_be_resolved_to_any);
+        }
+        function checkSwitchStatement(node) {
+            checkGrammarStatementInAmbientContext(node);
+            var firstDefaultClause;
+            var hasDuplicateDefaultClause = false;
+            var expressionType = checkExpression(node.expression);
+            ts.forEach(node.caseBlock.clauses, function (clause) {
+                if (clause.kind === 221 && !hasDuplicateDefaultClause) {
+                    if (firstDefaultClause === undefined) {
+                        firstDefaultClause = clause;
+                    }
+                    else {
+                        var sourceFile = ts.getSourceFileOfNode(node);
+                        var start = ts.skipTrivia(sourceFile.text, clause.pos);
+                        var end = clause.statements.length > 0 ? clause.statements[0].pos : clause.end;
+                        grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement);
+                        hasDuplicateDefaultClause = true;
+                    }
+                }
+                if (produceDiagnostics && clause.kind === 220) {
+                    var caseClause = clause;
+                    var caseType = checkExpression(caseClause.expression);
+                    if (!isTypeAssignableTo(expressionType, caseType)) {
+                        checkTypeAssignableTo(caseType, expressionType, caseClause.expression, undefined);
+                    }
+                }
+                ts.forEach(clause.statements, checkSourceElement);
+            });
+        }
+        function checkLabeledStatement(node) {
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                var current = node.parent;
+                while (current) {
+                    if (ts.isFunctionLike(current)) {
+                        break;
+                    }
+                    if (current.kind === 194 && current.label.text === node.label.text) {
+                        var sourceFile = ts.getSourceFileOfNode(node);
+                        grammarErrorOnNode(node.label, ts.Diagnostics.Duplicate_label_0, ts.getTextOfNodeFromSourceText(sourceFile.text, node.label));
+                        break;
+                    }
+                    current = current.parent;
+                }
+            }
+            checkSourceElement(node.statement);
+        }
+        function checkThrowStatement(node) {
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                if (node.expression === undefined) {
+                    grammarErrorAfterFirstToken(node, ts.Diagnostics.Line_break_not_permitted_here);
+                }
+            }
+            if (node.expression) {
+                checkExpression(node.expression);
+            }
+        }
+        function checkTryStatement(node) {
+            checkGrammarStatementInAmbientContext(node);
+            checkBlock(node.tryBlock);
+            var catchClause = node.catchClause;
+            if (catchClause) {
+                if (catchClause.variableDeclaration) {
+                    if (catchClause.variableDeclaration.name.kind !== 65) {
+                        grammarErrorOnFirstToken(catchClause.variableDeclaration.name, ts.Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
+                    }
+                    else if (catchClause.variableDeclaration.type) {
+                        grammarErrorOnFirstToken(catchClause.variableDeclaration.type, ts.Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
+                    }
+                    else if (catchClause.variableDeclaration.initializer) {
+                        grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, ts.Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
+                    }
+                    else {
+                        var identifierName = catchClause.variableDeclaration.name.text;
+                        var locals = catchClause.block.locals;
+                        if (locals && ts.hasProperty(locals, identifierName)) {
+                            var localSymbol = locals[identifierName];
+                            if (localSymbol && (localSymbol.flags & 2) !== 0) {
+                                grammarErrorOnNode(localSymbol.valueDeclaration, ts.Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, identifierName);
+                            }
+                        }
+                        checkGrammarEvalOrArgumentsInStrictMode(node, catchClause.variableDeclaration.name);
+                    }
+                }
+                checkBlock(catchClause.block);
+            }
+            if (node.finallyBlock) {
+                checkBlock(node.finallyBlock);
+            }
+        }
+        function checkIndexConstraints(type) {
+            var declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, 1);
+            var declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, 0);
+            var stringIndexType = getIndexTypeOfType(type, 0);
+            var numberIndexType = getIndexTypeOfType(type, 1);
+            if (stringIndexType || numberIndexType) {
+                ts.forEach(getPropertiesOfObjectType(type), function (prop) {
+                    var propType = getTypeOfSymbol(prop);
+                    checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, 0);
+                    checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, 1);
+                });
+                if (type.flags & 1024 && type.symbol.valueDeclaration.kind === 201) {
+                    var classDeclaration = type.symbol.valueDeclaration;
+                    for (var _i = 0, _a = classDeclaration.members; _i < _a.length; _i++) {
+                        var member = _a[_i];
+                        if (!(member.flags & 128) && ts.hasDynamicName(member)) {
+                            var propType = getTypeOfSymbol(member.symbol);
+                            checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, 0);
+                            checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, 1);
+                        }
+                    }
+                }
+            }
+            var errorNode;
+            if (stringIndexType && numberIndexType) {
+                errorNode = declaredNumberIndexer || declaredStringIndexer;
+                if (!errorNode && (type.flags & 2048)) {
+                    var someBaseTypeHasBothIndexers = ts.forEach(getBaseTypes(type), function (base) { return getIndexTypeOfType(base, 0) && getIndexTypeOfType(base, 1); });
+                    errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0];
+                }
+            }
+            if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) {
+                error(errorNode, ts.Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1, typeToString(numberIndexType), typeToString(stringIndexType));
+            }
+            function checkIndexConstraintForProperty(prop, propertyType, containingType, indexDeclaration, indexType, indexKind) {
+                if (!indexType) {
+                    return;
+                }
+                if (indexKind === 1 && !isNumericName(prop.valueDeclaration.name)) {
+                    return;
+                }
+                var errorNode;
+                if (prop.valueDeclaration.name.kind === 127 || prop.parent === containingType.symbol) {
+                    errorNode = prop.valueDeclaration;
+                }
+                else if (indexDeclaration) {
+                    errorNode = indexDeclaration;
+                }
+                else if (containingType.flags & 2048) {
+                    var someBaseClassHasBothPropertyAndIndexer = ts.forEach(getBaseTypes(containingType), function (base) { return getPropertyOfObjectType(base, prop.name) && getIndexTypeOfType(base, indexKind); });
+                    errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0];
+                }
+                if (errorNode && !isTypeAssignableTo(propertyType, indexType)) {
+                    var errorMessage = indexKind === 0
+                        ? ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2
+                        : ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2;
+                    error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType));
+                }
+            }
+        }
+        function checkTypeNameIsReserved(name, message) {
+            switch (name.text) {
+                case "any":
+                case "number":
+                case "boolean":
+                case "string":
+                case "symbol":
+                case "void":
+                    error(name, message, name.text);
+            }
+        }
+        function checkTypeParameters(typeParameterDeclarations) {
+            if (typeParameterDeclarations) {
+                for (var i = 0, n = typeParameterDeclarations.length; i < n; i++) {
+                    var node = typeParameterDeclarations[i];
+                    checkTypeParameter(node);
+                    if (produceDiagnostics) {
+                        for (var j = 0; j < i; j++) {
+                            if (typeParameterDeclarations[j].symbol === node.symbol) {
+                                error(node.name, ts.Diagnostics.Duplicate_identifier_0, ts.declarationNameToString(node.name));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        function checkClassExpression(node) {
+            grammarErrorOnNode(node, ts.Diagnostics.class_expressions_are_not_currently_supported);
+            ts.forEach(node.members, checkSourceElement);
+            return unknownType;
+        }
+        function checkClassDeclaration(node) {
+            checkGrammarDeclarationNameInStrictMode(node);
+            if (node.parent.kind !== 206 && node.parent.kind !== 227) {
+                grammarErrorOnNode(node, ts.Diagnostics.class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration);
+            }
+            if (!node.name && !(node.flags & 256)) {
+                grammarErrorOnFirstToken(node, ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
+            }
+            checkGrammarClassDeclarationHeritageClauses(node);
+            checkDecorators(node);
+            if (node.name) {
+                checkTypeNameIsReserved(node.name, ts.Diagnostics.Class_name_cannot_be_0);
+                checkCollisionWithCapturedThisVariable(node, node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            }
+            checkTypeParameters(node.typeParameters);
+            checkExportsOnMergedDeclarations(node);
+            var symbol = getSymbolOfNode(node);
+            var type = getDeclaredTypeOfSymbol(symbol);
+            var staticType = getTypeOfSymbol(symbol);
+            var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
+            if (baseTypeNode) {
+                if (!ts.isSupportedHeritageClauseElement(baseTypeNode)) {
+                    error(baseTypeNode.expression, ts.Diagnostics.Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses);
+                }
+                emitExtends = emitExtends || !ts.isInAmbientContext(node);
+                checkHeritageClauseElement(baseTypeNode);
+            }
+            var baseTypes = getBaseTypes(type);
+            if (baseTypes.length) {
+                if (produceDiagnostics) {
+                    var baseType = baseTypes[0];
+                    checkTypeAssignableTo(type, baseType, node.name || node, ts.Diagnostics.Class_0_incorrectly_extends_base_class_1);
+                    var staticBaseType = getTypeOfSymbol(baseType.symbol);
+                    checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name || node, ts.Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
+                    if (baseType.symbol !== resolveEntityName(baseTypeNode.expression, 107455)) {
+                        error(baseTypeNode, ts.Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
+                    }
+                    checkKindsOfPropertyMemberOverrides(type, baseType);
+                }
+            }
+            if (baseTypes.length || (baseTypeNode && compilerOptions.separateCompilation)) {
+                checkExpressionOrQualifiedName(baseTypeNode.expression);
+            }
+            var implementedTypeNodes = ts.getClassImplementsHeritageClauseElements(node);
+            if (implementedTypeNodes) {
+                ts.forEach(implementedTypeNodes, function (typeRefNode) {
+                    if (!ts.isSupportedHeritageClauseElement(typeRefNode)) {
+                        error(typeRefNode.expression, ts.Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments);
+                    }
+                    checkHeritageClauseElement(typeRefNode);
+                    if (produceDiagnostics) {
+                        var t = getTypeFromHeritageClauseElement(typeRefNode);
+                        if (t !== unknownType) {
+                            var declaredType = (t.flags & 4096) ? t.target : t;
+                            if (declaredType.flags & (1024 | 2048)) {
+                                checkTypeAssignableTo(type, t, node.name || node, ts.Diagnostics.Class_0_incorrectly_implements_interface_1);
+                            }
+                            else {
+                                error(typeRefNode, ts.Diagnostics.A_class_may_only_implement_another_class_or_interface);
+                            }
+                        }
+                    }
+                });
+            }
+            ts.forEach(node.members, checkSourceElement);
+            if (produceDiagnostics) {
+                checkIndexConstraints(type);
+                checkTypeForDuplicateIndexSignatures(node);
+            }
+        }
+        function getTargetSymbol(s) {
+            return s.flags & 16777216 ? getSymbolLinks(s).target : s;
+        }
+        function checkKindsOfPropertyMemberOverrides(type, baseType) {
+            // TypeScript 1.0 spec (April 2014): 8.2.3
+            // A derived class inherits all members from its base class it doesn't override.
+            // Inheritance means that a derived class implicitly contains all non - overridden members of the base class.
+            // Both public and private property members are inherited, but only public property members can be overridden.
+            // A property member in a derived class is said to override a property member in a base class
+            // when the derived class property member has the same name and kind(instance or static)
+            // as the base class property member.
+            // The type of an overriding property member must be assignable(section 3.8.4)
+            // to the type of the overridden property member, or otherwise a compile - time error occurs.
+            // Base class instance member functions can be overridden by derived class instance member functions,
+            // but not by other kinds of members.
+            // Base class instance member variables and accessors can be overridden by
+            // derived class instance member variables and accessors, but not by other kinds of members.
+            var baseProperties = getPropertiesOfObjectType(baseType);
+            for (var _i = 0; _i < baseProperties.length; _i++) {
+                var baseProperty = baseProperties[_i];
+                var base = getTargetSymbol(baseProperty);
+                if (base.flags & 134217728) {
+                    continue;
+                }
+                var derived = getTargetSymbol(getPropertyOfObjectType(type, base.name));
+                if (derived) {
+                    var baseDeclarationFlags = getDeclarationFlagsFromSymbol(base);
+                    var derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
+                    if ((baseDeclarationFlags & 32) || (derivedDeclarationFlags & 32)) {
+                        continue;
+                    }
+                    if ((baseDeclarationFlags & 128) !== (derivedDeclarationFlags & 128)) {
+                        continue;
+                    }
+                    if ((base.flags & derived.flags & 8192) || ((base.flags & 98308) && (derived.flags & 98308))) {
+                        continue;
+                    }
+                    var errorMessage = void 0;
+                    if (base.flags & 8192) {
+                        if (derived.flags & 98304) {
+                            errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
+                        }
+                        else {
+                            ts.Debug.assert((derived.flags & 4) !== 0);
+                            errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
+                        }
+                    }
+                    else if (base.flags & 4) {
+                        ts.Debug.assert((derived.flags & 8192) !== 0);
+                        errorMessage = ts.Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
+                    }
+                    else {
+                        ts.Debug.assert((base.flags & 98304) !== 0);
+                        ts.Debug.assert((derived.flags & 8192) !== 0);
+                        errorMessage = ts.Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
+                    }
+                    error(derived.valueDeclaration.name, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
+                }
+            }
+        }
+        function isAccessor(kind) {
+            return kind === 136 || kind === 137;
+        }
+        function areTypeParametersIdentical(list1, list2) {
+            if (!list1 && !list2) {
+                return true;
+            }
+            if (!list1 || !list2 || list1.length !== list2.length) {
+                return false;
+            }
+            for (var i = 0, len = list1.length; i < len; i++) {
+                var tp1 = list1[i];
+                var tp2 = list2[i];
+                if (tp1.name.text !== tp2.name.text) {
+                    return false;
+                }
+                if (!tp1.constraint && !tp2.constraint) {
+                    continue;
+                }
+                if (!tp1.constraint || !tp2.constraint) {
+                    return false;
+                }
+                if (!isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        function checkInheritedPropertiesAreIdentical(type, typeNode) {
+            var baseTypes = getBaseTypes(type);
+            if (baseTypes.length < 2) {
+                return true;
+            }
+            var seen = {};
+            ts.forEach(resolveDeclaredMembers(type).declaredProperties, function (p) { seen[p.name] = { prop: p, containingType: type }; });
+            var ok = true;
+            for (var _i = 0; _i < baseTypes.length; _i++) {
+                var base = baseTypes[_i];
+                var properties = getPropertiesOfObjectType(base);
+                for (var _a = 0; _a < properties.length; _a++) {
+                    var prop = properties[_a];
+                    if (!ts.hasProperty(seen, prop.name)) {
+                        seen[prop.name] = { prop: prop, containingType: base };
+                    }
+                    else {
+                        var existing = seen[prop.name];
+                        var isInheritedProperty = existing.containingType !== type;
+                        if (isInheritedProperty && !isPropertyIdenticalTo(existing.prop, prop)) {
+                            ok = false;
+                            var typeName1 = typeToString(existing.containingType);
+                            var typeName2 = typeToString(base);
+                            var errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2);
+                            errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
+                            diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(typeNode, errorInfo));
+                        }
+                    }
+                }
+            }
+            return ok;
+        }
+        function checkInterfaceDeclaration(node) {
+            checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
+            checkTypeParameters(node.typeParameters);
+            if (produceDiagnostics) {
+                checkTypeNameIsReserved(node.name, ts.Diagnostics.Interface_name_cannot_be_0);
+                checkExportsOnMergedDeclarations(node);
+                var symbol = getSymbolOfNode(node);
+                var firstInterfaceDecl = ts.getDeclarationOfKind(symbol, 202);
+                if (symbol.declarations.length > 1) {
+                    if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) {
+                        error(node.name, ts.Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters);
+                    }
+                }
+                if (node === firstInterfaceDecl) {
+                    var type = getDeclaredTypeOfSymbol(symbol);
+                    if (checkInheritedPropertiesAreIdentical(type, node.name)) {
+                        ts.forEach(getBaseTypes(type), function (baseType) {
+                            checkTypeAssignableTo(type, baseType, node.name, ts.Diagnostics.Interface_0_incorrectly_extends_interface_1);
+                        });
+                        checkIndexConstraints(type);
+                    }
+                }
+            }
+            ts.forEach(ts.getInterfaceBaseTypeNodes(node), function (heritageElement) {
+                if (!ts.isSupportedHeritageClauseElement(heritageElement)) {
+                    error(heritageElement.expression, ts.Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments);
+                }
+                checkHeritageClauseElement(heritageElement);
+            });
+            ts.forEach(node.members, checkSourceElement);
+            if (produceDiagnostics) {
+                checkTypeForDuplicateIndexSignatures(node);
+            }
+        }
+        function checkTypeAliasDeclaration(node) {
+            checkGrammarDecorators(node) || checkGrammarModifiers(node);
+            checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_alias_name_cannot_be_0);
+            checkSourceElement(node.type);
+        }
+        function computeEnumMemberValues(node) {
+            var nodeLinks = getNodeLinks(node);
+            if (!(nodeLinks.flags & 128)) {
+                var enumSymbol = getSymbolOfNode(node);
+                var enumType = getDeclaredTypeOfSymbol(enumSymbol);
+                var autoValue = 0;
+                var ambient = ts.isInAmbientContext(node);
+                var enumIsConst = ts.isConst(node);
+                ts.forEach(node.members, function (member) {
+                    if (member.name.kind !== 127 && isNumericLiteralName(member.name.text)) {
+                        error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name);
+                    }
+                    var initializer = member.initializer;
+                    if (initializer) {
+                        autoValue = getConstantValueForEnumMemberInitializer(initializer);
+                        if (autoValue === undefined) {
+                            if (enumIsConst) {
+                                error(initializer, ts.Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression);
+                            }
+                            else if (!ambient) {
+                                checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, undefined);
+                            }
+                        }
+                        else if (enumIsConst) {
+                            if (isNaN(autoValue)) {
+                                error(initializer, ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN);
+                            }
+                            else if (!isFinite(autoValue)) {
+                                error(initializer, ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value);
+                            }
+                        }
+                    }
+                    else if (ambient && !enumIsConst) {
+                        autoValue = undefined;
+                    }
+                    if (autoValue !== undefined) {
+                        getNodeLinks(member).enumMemberValue = autoValue++;
+                    }
+                });
+                nodeLinks.flags |= 128;
+            }
+            function getConstantValueForEnumMemberInitializer(initializer) {
+                return evalConstant(initializer);
+                function evalConstant(e) {
+                    switch (e.kind) {
+                        case 167:
+                            var value = evalConstant(e.operand);
+                            if (value === undefined) {
+                                return undefined;
+                            }
+                            switch (e.operator) {
+                                case 33: return value;
+                                case 34: return -value;
+                                case 47: return ~value;
+                            }
+                            return undefined;
+                        case 169:
+                            var left = evalConstant(e.left);
+                            if (left === undefined) {
+                                return undefined;
+                            }
+                            var right = evalConstant(e.right);
+                            if (right === undefined) {
+                                return undefined;
+                            }
+                            switch (e.operatorToken.kind) {
+                                case 44: return left | right;
+                                case 43: return left & right;
+                                case 41: return left >> right;
+                                case 42: return left >>> right;
+                                case 40: return left << right;
+                                case 45: return left ^ right;
+                                case 35: return left * right;
+                                case 36: return left / right;
+                                case 33: return left + right;
+                                case 34: return left - right;
+                                case 37: return left % right;
+                            }
+                            return undefined;
+                        case 7:
+                            return +e.text;
+                        case 161:
+                            return evalConstant(e.expression);
+                        case 65:
+                        case 156:
+                        case 155:
+                            var member = initializer.parent;
+                            var currentType = getTypeOfSymbol(getSymbolOfNode(member.parent));
+                            var enumType;
+                            var propertyName;
+                            if (e.kind === 65) {
+                                enumType = currentType;
+                                propertyName = e.text;
+                            }
+                            else {
+                                var expression;
+                                if (e.kind === 156) {
+                                    if (e.argumentExpression === undefined ||
+                                        e.argumentExpression.kind !== 8) {
+                                        return undefined;
+                                    }
+                                    expression = e.expression;
+                                    propertyName = e.argumentExpression.text;
+                                }
+                                else {
+                                    expression = e.expression;
+                                    propertyName = e.name.text;
+                                }
+                                var current = expression;
+                                while (current) {
+                                    if (current.kind === 65) {
+                                        break;
+                                    }
+                                    else if (current.kind === 155) {
+                                        current = current.expression;
+                                    }
+                                    else {
+                                        return undefined;
+                                    }
+                                }
+                                enumType = checkExpression(expression);
+                                if (!(enumType.symbol && (enumType.symbol.flags & 384))) {
+                                    return undefined;
+                                }
+                            }
+                            if (propertyName === undefined) {
+                                return undefined;
+                            }
+                            var property = getPropertyOfObjectType(enumType, propertyName);
+                            if (!property || !(property.flags & 8)) {
+                                return undefined;
+                            }
+                            var propertyDecl = property.valueDeclaration;
+                            if (member === propertyDecl) {
+                                return undefined;
+                            }
+                            if (!isDefinedBefore(propertyDecl, member)) {
+                                return undefined;
+                            }
+                            return getNodeLinks(propertyDecl).enumMemberValue;
+                    }
+                }
+            }
+        }
+        function checkEnumDeclaration(node) {
+            if (!produceDiagnostics) {
+                return;
+            }
+            checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
+            checkTypeNameIsReserved(node.name, ts.Diagnostics.Enum_name_cannot_be_0);
+            checkCollisionWithCapturedThisVariable(node, node.name);
+            checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            checkExportsOnMergedDeclarations(node);
+            computeEnumMemberValues(node);
+            var enumIsConst = ts.isConst(node);
+            if (compilerOptions.separateCompilation && enumIsConst && ts.isInAmbientContext(node)) {
+                error(node.name, ts.Diagnostics.Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided);
+            }
+            var enumSymbol = getSymbolOfNode(node);
+            var firstDeclaration = ts.getDeclarationOfKind(enumSymbol, node.kind);
+            if (node === firstDeclaration) {
+                if (enumSymbol.declarations.length > 1) {
+                    ts.forEach(enumSymbol.declarations, function (decl) {
+                        if (ts.isConstEnumDeclaration(decl) !== enumIsConst) {
+                            error(decl.name, ts.Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
+                        }
+                    });
+                }
+                var seenEnumMissingInitialInitializer = false;
+                ts.forEach(enumSymbol.declarations, function (declaration) {
+                    if (declaration.kind !== 204) {
+                        return false;
+                    }
+                    var enumDeclaration = declaration;
+                    if (!enumDeclaration.members.length) {
+                        return false;
+                    }
+                    var firstEnumMember = enumDeclaration.members[0];
+                    if (!firstEnumMember.initializer) {
+                        if (seenEnumMissingInitialInitializer) {
+                            error(firstEnumMember.name, ts.Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element);
+                        }
+                        else {
+                            seenEnumMissingInitialInitializer = true;
+                        }
+                    }
+                });
+            }
+        }
+        function getFirstNonAmbientClassOrFunctionDeclaration(symbol) {
+            var declarations = symbol.declarations;
+            for (var _i = 0; _i < declarations.length; _i++) {
+                var declaration = declarations[_i];
+                if ((declaration.kind === 201 ||
+                    (declaration.kind === 200 && ts.nodeIsPresent(declaration.body))) &&
+                    !ts.isInAmbientContext(declaration)) {
+                    return declaration;
+                }
+            }
+            return undefined;
+        }
+        function inSameLexicalScope(node1, node2) {
+            var container1 = ts.getEnclosingBlockScopeContainer(node1);
+            var container2 = ts.getEnclosingBlockScopeContainer(node2);
+            if (isGlobalSourceFile(container1)) {
+                return isGlobalSourceFile(container2);
+            }
+            else if (isGlobalSourceFile(container2)) {
+                return false;
+            }
+            else {
+                return container1 === container2;
+            }
+        }
+        function checkModuleDeclaration(node) {
+            if (produceDiagnostics) {
+                if (!checkGrammarDeclarationNameInStrictMode(node) && !checkGrammarDecorators(node) && !checkGrammarModifiers(node)) {
+                    if (!ts.isInAmbientContext(node) && node.name.kind === 8) {
+                        grammarErrorOnNode(node.name, ts.Diagnostics.Only_ambient_modules_can_use_quoted_names);
+                    }
+                }
+                checkCollisionWithCapturedThisVariable(node, node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+                checkExportsOnMergedDeclarations(node);
+                var symbol = getSymbolOfNode(node);
+                if (symbol.flags & 512
+                    && symbol.declarations.length > 1
+                    && !ts.isInAmbientContext(node)
+                    && ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.separateCompilation)) {
+                    var firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
+                    if (firstNonAmbientClassOrFunc) {
+                        if (ts.getSourceFileOfNode(node) !== ts.getSourceFileOfNode(firstNonAmbientClassOrFunc)) {
+                            error(node.name, ts.Diagnostics.A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged);
+                        }
+                        else if (node.pos < firstNonAmbientClassOrFunc.pos) {
+                            error(node.name, ts.Diagnostics.A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged);
+                        }
+                    }
+                    var mergedClass = ts.getDeclarationOfKind(symbol, 201);
+                    if (mergedClass &&
+                        inSameLexicalScope(node, mergedClass)) {
+                        getNodeLinks(node).flags |= 2048;
+                    }
+                }
+                if (node.name.kind === 8) {
+                    if (!isGlobalSourceFile(node.parent)) {
+                        error(node.name, ts.Diagnostics.Ambient_external_modules_cannot_be_nested_in_other_modules);
+                    }
+                    if (isExternalModuleNameRelative(node.name.text)) {
+                        error(node.name, ts.Diagnostics.Ambient_external_module_declaration_cannot_specify_relative_module_name);
+                    }
+                }
+            }
+            checkSourceElement(node.body);
+        }
+        function getFirstIdentifier(node) {
+            while (true) {
+                if (node.kind === 126) {
+                    node = node.left;
+                }
+                else if (node.kind === 155) {
+                    node = node.expression;
+                }
+                else {
+                    break;
+                }
+            }
+            ts.Debug.assert(node.kind === 65);
+            return node;
+        }
+        function checkExternalImportOrExportDeclaration(node) {
+            var moduleName = ts.getExternalModuleName(node);
+            if (!ts.nodeIsMissing(moduleName) && moduleName.kind !== 8) {
+                error(moduleName, ts.Diagnostics.String_literal_expected);
+                return false;
+            }
+            var inAmbientExternalModule = node.parent.kind === 206 && node.parent.parent.name.kind === 8;
+            if (node.parent.kind !== 227 && !inAmbientExternalModule) {
+                error(moduleName, node.kind === 215 ?
+                    ts.Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module :
+                    ts.Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
+                return false;
+            }
+            if (inAmbientExternalModule && isExternalModuleNameRelative(moduleName.text)) {
+                error(node, ts.Diagnostics.Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name);
+                return false;
+            }
+            return true;
+        }
+        function checkAliasSymbol(node) {
+            var symbol = getSymbolOfNode(node);
+            var target = resolveAlias(symbol);
+            if (target !== unknownSymbol) {
+                var excludedMeanings = (symbol.flags & 107455 ? 107455 : 0) |
+                    (symbol.flags & 793056 ? 793056 : 0) |
+                    (symbol.flags & 1536 ? 1536 : 0);
+                if (target.flags & excludedMeanings) {
+                    var message = node.kind === 217 ?
+                        ts.Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 :
+                        ts.Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0;
+                    error(node, message, symbolToString(symbol));
+                }
+            }
+        }
+        function checkImportBinding(node) {
+            checkCollisionWithCapturedThisVariable(node, node.name);
+            checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            checkAliasSymbol(node);
+        }
+        function checkImportDeclaration(node) {
+            if (!checkGrammarImportDeclarationNameInStrictMode(node) && !checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 499)) {
+                grammarErrorOnFirstToken(node, ts.Diagnostics.An_import_declaration_cannot_have_modifiers);
+            }
+            if (checkExternalImportOrExportDeclaration(node)) {
+                var importClause = node.importClause;
+                if (importClause) {
+                    if (importClause.name) {
+                        checkImportBinding(importClause);
+                    }
+                    if (importClause.namedBindings) {
+                        if (importClause.namedBindings.kind === 211) {
+                            checkImportBinding(importClause.namedBindings);
+                        }
+                        else {
+                            ts.forEach(importClause.namedBindings.elements, checkImportBinding);
+                        }
+                    }
+                }
+            }
+        }
+        function checkImportEqualsDeclaration(node) {
+            checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node);
+            if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
+                checkImportBinding(node);
+                if (node.flags & 1) {
+                    markExportAsReferenced(node);
+                }
+                if (ts.isInternalModuleImportEqualsDeclaration(node)) {
+                    var target = resolveAlias(getSymbolOfNode(node));
+                    if (target !== unknownSymbol) {
+                        if (target.flags & 107455) {
+                            var moduleName = getFirstIdentifier(node.moduleReference);
+                            if (!(resolveEntityName(moduleName, 107455 | 1536).flags & 1536)) {
+                                error(moduleName, ts.Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, ts.declarationNameToString(moduleName));
+                            }
+                        }
+                        if (target.flags & 793056) {
+                            checkTypeNameIsReserved(node.name, ts.Diagnostics.Import_name_cannot_be_0);
+                        }
+                    }
+                }
+                else {
+                    if (languageVersion >= 2) {
+                        grammarErrorOnNode(node, ts.Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead);
+                    }
+                }
+            }
+        }
+        function checkExportDeclaration(node) {
+            if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 499)) {
+                grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_declaration_cannot_have_modifiers);
+            }
+            if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
+                if (node.exportClause) {
+                    ts.forEach(node.exportClause.elements, checkExportSpecifier);
+                    var inAmbientExternalModule = node.parent.kind === 206 && node.parent.parent.name.kind === 8;
+                    if (node.parent.kind !== 227 && !inAmbientExternalModule) {
+                        error(node, ts.Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module);
+                    }
+                }
+                else {
+                    var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
+                    if (moduleSymbol && moduleSymbol.exports["export="]) {
+                        error(node.moduleSpecifier, ts.Diagnostics.External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
+                    }
+                }
+            }
+        }
+        function checkExportSpecifier(node) {
+            checkAliasSymbol(node);
+            if (!node.parent.parent.moduleSpecifier) {
+                markExportAsReferenced(node);
+            }
+        }
+        function checkExportAssignment(node) {
+            var container = node.parent.kind === 227 ? node.parent : node.parent.parent;
+            if (container.kind === 205 && container.name.kind === 65) {
+                error(node, ts.Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
+                return;
+            }
+            if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 499)) {
+                grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers);
+            }
+            if (node.expression.kind === 65) {
+                markExportAsReferenced(node);
+            }
+            else {
+                checkExpressionCached(node.expression);
+            }
+            checkExternalModuleExports(container);
+            if (node.isExportEquals && languageVersion >= 2) {
+                grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead);
+            }
+        }
+        function getModuleStatements(node) {
+            if (node.kind === 227) {
+                return node.statements;
+            }
+            if (node.kind === 205 && node.body.kind === 206) {
+                return node.body.statements;
+            }
+            return emptyArray;
+        }
+        function hasExportedMembers(moduleSymbol) {
+            for (var id in moduleSymbol.exports) {
+                if (id !== "export=") {
+                    return true;
+                }
+            }
+            return false;
+        }
+        function checkExternalModuleExports(node) {
+            var moduleSymbol = getSymbolOfNode(node);
+            var links = getSymbolLinks(moduleSymbol);
+            if (!links.exportsChecked) {
+                var exportEqualsSymbol = moduleSymbol.exports["export="];
+                if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) {
+                    var declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
+                    error(declaration, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
+                }
+                links.exportsChecked = true;
+            }
+        }
+        function checkSourceElement(node) {
+            if (!node)
+                return;
+            switch (node.kind) {
+                case 128:
+                    return checkTypeParameter(node);
+                case 129:
+                    return checkParameter(node);
+                case 132:
+                case 131:
+                    return checkPropertyDeclaration(node);
+                case 142:
+                case 143:
+                case 138:
+                case 139:
+                    return checkSignatureDeclaration(node);
+                case 140:
+                    return checkSignatureDeclaration(node);
+                case 134:
+                case 133:
+                    return checkMethodDeclaration(node);
+                case 135:
+                    return checkConstructorDeclaration(node);
+                case 136:
+                case 137:
+                    return checkAccessorDeclaration(node);
+                case 141:
+                    return checkTypeReferenceNode(node);
+                case 144:
+                    return checkTypeQuery(node);
+                case 145:
+                    return checkTypeLiteral(node);
+                case 146:
+                    return checkArrayType(node);
+                case 147:
+                    return checkTupleType(node);
+                case 148:
+                    return checkUnionType(node);
+                case 149:
+                    return checkSourceElement(node.type);
+                case 200:
+                    return checkFunctionDeclaration(node);
+                case 179:
+                case 206:
+                    return checkBlock(node);
+                case 180:
+                    return checkVariableStatement(node);
+                case 182:
+                    return checkExpressionStatement(node);
+                case 183:
+                    return checkIfStatement(node);
+                case 184:
+                    return checkDoStatement(node);
+                case 185:
+                    return checkWhileStatement(node);
+                case 186:
+                    return checkForStatement(node);
+                case 187:
+                    return checkForInStatement(node);
+                case 188:
+                    return checkForOfStatement(node);
+                case 189:
+                case 190:
+                    return checkBreakOrContinueStatement(node);
+                case 191:
+                    return checkReturnStatement(node);
+                case 192:
+                    return checkWithStatement(node);
+                case 193:
+                    return checkSwitchStatement(node);
+                case 194:
+                    return checkLabeledStatement(node);
+                case 195:
+                    return checkThrowStatement(node);
+                case 196:
+                    return checkTryStatement(node);
+                case 198:
+                    return checkVariableDeclaration(node);
+                case 152:
+                    return checkBindingElement(node);
+                case 201:
+                    return checkClassDeclaration(node);
+                case 202:
+                    return checkInterfaceDeclaration(node);
+                case 203:
+                    return checkTypeAliasDeclaration(node);
+                case 204:
+                    return checkEnumDeclaration(node);
+                case 205:
+                    return checkModuleDeclaration(node);
+                case 209:
+                    return checkImportDeclaration(node);
+                case 208:
+                    return checkImportEqualsDeclaration(node);
+                case 215:
+                    return checkExportDeclaration(node);
+                case 214:
+                    return checkExportAssignment(node);
+                case 181:
+                    checkGrammarStatementInAmbientContext(node);
+                    return;
+                case 197:
+                    checkGrammarStatementInAmbientContext(node);
+                    return;
+                case 218:
+                    return checkMissingDeclaration(node);
+            }
+        }
+        function checkFunctionExpressionBodies(node) {
+            switch (node.kind) {
+                case 162:
+                case 163:
+                    ts.forEach(node.parameters, checkFunctionExpressionBodies);
+                    checkFunctionExpressionOrObjectLiteralMethodBody(node);
+                    break;
+                case 134:
+                case 133:
+                    ts.forEach(node.parameters, checkFunctionExpressionBodies);
+                    if (ts.isObjectLiteralMethod(node)) {
+                        checkFunctionExpressionOrObjectLiteralMethodBody(node);
+                    }
+                    break;
+                case 135:
+                case 136:
+                case 137:
+                case 200:
+                    ts.forEach(node.parameters, checkFunctionExpressionBodies);
+                    break;
+                case 192:
+                    checkFunctionExpressionBodies(node.expression);
+                    break;
+                case 129:
+                case 132:
+                case 131:
+                case 150:
+                case 151:
+                case 152:
+                case 153:
+                case 154:
+                case 224:
+                case 155:
+                case 156:
+                case 157:
+                case 158:
+                case 159:
+                case 171:
+                case 176:
+                case 160:
+                case 161:
+                case 165:
+                case 166:
+                case 164:
+                case 167:
+                case 168:
+                case 169:
+                case 170:
+                case 173:
+                case 179:
+                case 206:
+                case 180:
+                case 182:
+                case 183:
+                case 184:
+                case 185:
+                case 186:
+                case 187:
+                case 188:
+                case 189:
+                case 190:
+                case 191:
+                case 193:
+                case 207:
+                case 220:
+                case 221:
+                case 194:
+                case 195:
+                case 196:
+                case 223:
+                case 198:
+                case 199:
+                case 201:
+                case 204:
+                case 226:
+                case 214:
+                case 227:
+                    ts.forEachChild(node, checkFunctionExpressionBodies);
+                    break;
+            }
+        }
+        function checkSourceFile(node) {
+            var start = new Date().getTime();
+            checkSourceFileWorker(node);
+            ts.checkTime += new Date().getTime() - start;
+        }
+        function checkSourceFileWorker(node) {
+            var links = getNodeLinks(node);
+            if (!(links.flags & 1)) {
+                checkGrammarSourceFile(node);
+                emitExtends = false;
+                emitDecorate = false;
+                emitParam = false;
+                potentialThisCollisions.length = 0;
+                ts.forEach(node.statements, checkSourceElement);
+                checkFunctionExpressionBodies(node);
+                if (ts.isExternalModule(node)) {
+                    checkExternalModuleExports(node);
+                }
+                if (potentialThisCollisions.length) {
+                    ts.forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
+                    potentialThisCollisions.length = 0;
+                }
+                if (emitExtends) {
+                    links.flags |= 8;
+                }
+                if (emitDecorate) {
+                    links.flags |= 512;
+                }
+                if (emitParam) {
+                    links.flags |= 1024;
+                }
+                links.flags |= 1;
+            }
+        }
+        function getDiagnostics(sourceFile) {
+            throwIfNonDiagnosticsProducing();
+            if (sourceFile) {
+                checkSourceFile(sourceFile);
+                return diagnostics.getDiagnostics(sourceFile.fileName);
+            }
+            ts.forEach(host.getSourceFiles(), checkSourceFile);
+            return diagnostics.getDiagnostics();
+        }
+        function getGlobalDiagnostics() {
+            throwIfNonDiagnosticsProducing();
+            return diagnostics.getGlobalDiagnostics();
+        }
+        function throwIfNonDiagnosticsProducing() {
+            if (!produceDiagnostics) {
+                throw new Error("Trying to get diagnostics from a type checker that does not produce them.");
+            }
+        }
+        function isInsideWithStatementBody(node) {
+            if (node) {
+                while (node.parent) {
+                    if (node.parent.kind === 192 && node.parent.statement === node) {
+                        return true;
+                    }
+                    node = node.parent;
+                }
+            }
+            return false;
+        }
+        function getSymbolsInScope(location, meaning) {
+            var symbols = {};
+            var memberFlags = 0;
+            if (isInsideWithStatementBody(location)) {
+                return [];
+            }
+            populateSymbols();
+            return symbolsToArray(symbols);
+            function populateSymbols() {
+                while (location) {
+                    if (location.locals && !isGlobalSourceFile(location)) {
+                        copySymbols(location.locals, meaning);
+                    }
+                    switch (location.kind) {
+                        case 227:
+                            if (!ts.isExternalModule(location)) {
+                                break;
+                            }
+                        case 205:
+                            copySymbols(getSymbolOfNode(location).exports, meaning & 8914931);
+                            break;
+                        case 204:
+                            copySymbols(getSymbolOfNode(location).exports, meaning & 8);
+                            break;
+                        case 201:
+                        case 202:
+                            if (!(memberFlags & 128)) {
+                                copySymbols(getSymbolOfNode(location).members, meaning & 793056);
+                            }
+                            break;
+                        case 162:
+                            if (location.name) {
+                                copySymbol(location.symbol, meaning);
+                            }
+                            break;
+                    }
+                    memberFlags = location.flags;
+                    location = location.parent;
+                }
+                copySymbols(globals, meaning);
+            }
+            function copySymbol(symbol, meaning) {
+                if (symbol.flags & meaning) {
+                    var id = symbol.name;
+                    if (!isReservedMemberName(id) && !ts.hasProperty(symbols, id)) {
+                        symbols[id] = symbol;
+                    }
+                }
+            }
+            function copySymbols(source, meaning) {
+                if (meaning) {
+                    for (var id in source) {
+                        if (ts.hasProperty(source, id)) {
+                            copySymbol(source[id], meaning);
+                        }
+                    }
+                }
+            }
+            if (isInsideWithStatementBody(location)) {
+                return [];
+            }
+            while (location) {
+                if (location.locals && !isGlobalSourceFile(location)) {
+                    copySymbols(location.locals, meaning);
+                }
+                switch (location.kind) {
+                    case 227:
+                        if (!ts.isExternalModule(location))
+                            break;
+                    case 205:
+                        copySymbols(getSymbolOfNode(location).exports, meaning & 8914931);
+                        break;
+                    case 204:
+                        copySymbols(getSymbolOfNode(location).exports, meaning & 8);
+                        break;
+                    case 201:
+                    case 202:
+                        if (!(memberFlags & 128)) {
+                            copySymbols(getSymbolOfNode(location).members, meaning & 793056);
+                        }
+                        break;
+                    case 162:
+                        if (location.name) {
+                            copySymbol(location.symbol, meaning);
+                        }
+                        break;
+                }
+                memberFlags = location.flags;
+                location = location.parent;
+            }
+            copySymbols(globals, meaning);
+            return symbolsToArray(symbols);
+        }
+        function isTypeDeclarationName(name) {
+            return name.kind == 65 &&
+                isTypeDeclaration(name.parent) &&
+                name.parent.name === name;
+        }
+        function isTypeDeclaration(node) {
+            switch (node.kind) {
+                case 128:
+                case 201:
+                case 202:
+                case 203:
+                case 204:
+                    return true;
+            }
+        }
+        function isTypeReferenceIdentifier(entityName) {
+            var node = entityName;
+            while (node.parent && node.parent.kind === 126) {
+                node = node.parent;
+            }
+            return node.parent && node.parent.kind === 141;
+        }
+        function isHeritageClauseElementIdentifier(entityName) {
+            var node = entityName;
+            while (node.parent && node.parent.kind === 155) {
+                node = node.parent;
+            }
+            return node.parent && node.parent.kind === 177;
+        }
+        function isTypeNode(node) {
+            if (141 <= node.kind && node.kind <= 149) {
+                return true;
+            }
+            switch (node.kind) {
+                case 112:
+                case 119:
+                case 121:
+                case 113:
+                case 122:
+                    return true;
+                case 99:
+                    return node.parent.kind !== 166;
+                case 8:
+                    return node.parent.kind === 129;
+                case 177:
+                    return true;
+                case 65:
+                    if (node.parent.kind === 126 && node.parent.right === node) {
+                        node = node.parent;
+                    }
+                    else if (node.parent.kind === 155 && node.parent.name === node) {
+                        node = node.parent;
+                    }
+                case 126:
+                case 155:
+                    ts.Debug.assert(node.kind === 65 || node.kind === 126 || node.kind === 155, "'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'.");
+                    var parent_4 = node.parent;
+                    if (parent_4.kind === 144) {
+                        return false;
+                    }
+                    if (141 <= parent_4.kind && parent_4.kind <= 149) {
+                        return true;
+                    }
+                    switch (parent_4.kind) {
+                        case 177:
+                            return true;
+                        case 128:
+                            return node === parent_4.constraint;
+                        case 132:
+                        case 131:
+                        case 129:
+                        case 198:
+                            return node === parent_4.type;
+                        case 200:
+                        case 162:
+                        case 163:
+                        case 135:
+                        case 134:
+                        case 133:
+                        case 136:
+                        case 137:
+                            return node === parent_4.type;
+                        case 138:
+                        case 139:
+                        case 140:
+                            return node === parent_4.type;
+                        case 160:
+                            return node === parent_4.type;
+                        case 157:
+                        case 158:
+                            return parent_4.typeArguments && ts.indexOf(parent_4.typeArguments, node) >= 0;
+                        case 159:
+                            return false;
+                    }
+            }
+            return false;
+        }
+        function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide) {
+            while (nodeOnRightSide.parent.kind === 126) {
+                nodeOnRightSide = nodeOnRightSide.parent;
+            }
+            if (nodeOnRightSide.parent.kind === 208) {
+                return nodeOnRightSide.parent.moduleReference === nodeOnRightSide && nodeOnRightSide.parent;
+            }
+            if (nodeOnRightSide.parent.kind === 214) {
+                return nodeOnRightSide.parent.expression === nodeOnRightSide && nodeOnRightSide.parent;
+            }
+            return undefined;
+        }
+        function isInRightSideOfImportOrExportAssignment(node) {
+            return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
+        }
+        function getSymbolOfEntityNameOrPropertyAccessExpression(entityName) {
+            if (ts.isDeclarationName(entityName)) {
+                return getSymbolOfNode(entityName.parent);
+            }
+            if (entityName.parent.kind === 214) {
+                return resolveEntityName(entityName, 107455 | 793056 | 1536 | 8388608);
+            }
+            if (entityName.kind !== 155) {
+                if (isInRightSideOfImportOrExportAssignment(entityName)) {
+                    return getSymbolOfPartOfRightHandSideOfImportEquals(entityName);
+                }
+            }
+            if (ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
+                entityName = entityName.parent;
+            }
+            if (isHeritageClauseElementIdentifier(entityName)) {
+                var meaning = entityName.parent.kind === 177 ? 793056 : 1536;
+                meaning |= 8388608;
+                return resolveEntityName(entityName, meaning);
+            }
+            else if (ts.isExpression(entityName)) {
+                if (ts.nodeIsMissing(entityName)) {
+                    return undefined;
+                }
+                if (entityName.kind === 65) {
+                    var meaning = 107455 | 8388608;
+                    return resolveEntityName(entityName, meaning);
+                }
+                else if (entityName.kind === 155) {
+                    var symbol = getNodeLinks(entityName).resolvedSymbol;
+                    if (!symbol) {
+                        checkPropertyAccessExpression(entityName);
+                    }
+                    return getNodeLinks(entityName).resolvedSymbol;
+                }
+                else if (entityName.kind === 126) {
+                    var symbol = getNodeLinks(entityName).resolvedSymbol;
+                    if (!symbol) {
+                        checkQualifiedName(entityName);
+                    }
+                    return getNodeLinks(entityName).resolvedSymbol;
+                }
+            }
+            else if (isTypeReferenceIdentifier(entityName)) {
+                var meaning = entityName.parent.kind === 141 ? 793056 : 1536;
+                meaning |= 8388608;
+                return resolveEntityName(entityName, meaning);
+            }
+            return undefined;
+        }
+        function getSymbolInfo(node) {
+            if (isInsideWithStatementBody(node)) {
+                return undefined;
+            }
+            if (ts.isDeclarationName(node)) {
+                return getSymbolOfNode(node.parent);
+            }
+            if (node.kind === 65 && isInRightSideOfImportOrExportAssignment(node)) {
+                return node.parent.kind === 214
+                    ? getSymbolOfEntityNameOrPropertyAccessExpression(node)
+                    : getSymbolOfPartOfRightHandSideOfImportEquals(node);
+            }
+            switch (node.kind) {
+                case 65:
+                case 155:
+                case 126:
+                    return getSymbolOfEntityNameOrPropertyAccessExpression(node);
+                case 93:
+                case 91:
+                    var type = checkExpression(node);
+                    return type.symbol;
+                case 114:
+                    var constructorDeclaration = node.parent;
+                    if (constructorDeclaration && constructorDeclaration.kind === 135) {
+                        return constructorDeclaration.parent.symbol;
+                    }
+                    return undefined;
+                case 8:
+                    var moduleName;
+                    if ((ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) &&
+                        ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) ||
+                        ((node.parent.kind === 209 || node.parent.kind === 215) &&
+                            node.parent.moduleSpecifier === node)) {
+                        return resolveExternalModuleName(node, node);
+                    }
+                case 7:
+                    if (node.parent.kind == 156 && node.parent.argumentExpression === node) {
+                        var objectType = checkExpression(node.parent.expression);
+                        if (objectType === unknownType)
+                            return undefined;
+                        var apparentType = getApparentType(objectType);
+                        if (apparentType === unknownType)
+                            return undefined;
+                        return getPropertyOfType(apparentType, node.text);
+                    }
+                    break;
+            }
+            return undefined;
+        }
+        function getShorthandAssignmentValueSymbol(location) {
+            if (location && location.kind === 225) {
+                return resolveEntityName(location.name, 107455);
+            }
+            return undefined;
+        }
+        function getTypeOfNode(node) {
+            if (isInsideWithStatementBody(node)) {
+                return unknownType;
+            }
+            if (isTypeNode(node)) {
+                return getTypeFromTypeNode(node);
+            }
+            if (ts.isExpression(node)) {
+                return getTypeOfExpression(node);
+            }
+            if (isTypeDeclaration(node)) {
+                var symbol = getSymbolOfNode(node);
+                return getDeclaredTypeOfSymbol(symbol);
+            }
+            if (isTypeDeclarationName(node)) {
+                var symbol = getSymbolInfo(node);
+                return symbol && getDeclaredTypeOfSymbol(symbol);
+            }
+            if (ts.isDeclaration(node)) {
+                var symbol = getSymbolOfNode(node);
+                return getTypeOfSymbol(symbol);
+            }
+            if (ts.isDeclarationName(node)) {
+                var symbol = getSymbolInfo(node);
+                return symbol && getTypeOfSymbol(symbol);
+            }
+            if (isInRightSideOfImportOrExportAssignment(node)) {
+                var symbol = getSymbolInfo(node);
+                var declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
+                return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
+            }
+            return unknownType;
+        }
+        function getTypeOfExpression(expr) {
+            if (ts.isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
+                expr = expr.parent;
+            }
+            return checkExpression(expr);
+        }
+        function getAugmentedPropertiesOfType(type) {
+            type = getApparentType(type);
+            var propsByName = createSymbolTable(getPropertiesOfType(type));
+            if (getSignaturesOfType(type, 0).length || getSignaturesOfType(type, 1).length) {
+                ts.forEach(getPropertiesOfType(globalFunctionType), function (p) {
+                    if (!ts.hasProperty(propsByName, p.name)) {
+                        propsByName[p.name] = p;
+                    }
+                });
+            }
+            return getNamedMembers(propsByName);
+        }
+        function getRootSymbols(symbol) {
+            if (symbol.flags & 268435456) {
+                var symbols = [];
+                var name_7 = symbol.name;
+                ts.forEach(getSymbolLinks(symbol).unionType.types, function (t) {
+                    symbols.push(getPropertyOfType(t, name_7));
+                });
+                return symbols;
+            }
+            else if (symbol.flags & 67108864) {
+                var target = getSymbolLinks(symbol).target;
+                if (target) {
+                    return [target];
+                }
+            }
+            return [symbol];
+        }
+        function isExternalModuleSymbol(symbol) {
+            return symbol.flags & 512 && symbol.declarations.length === 1 && symbol.declarations[0].kind === 227;
+        }
+        function getAliasNameSubstitution(symbol, getGeneratedNameForNode) {
+            if (languageVersion >= 2) {
+                return undefined;
+            }
+            var node = getDeclarationOfAliasSymbol(symbol);
+            if (node) {
+                if (node.kind === 210) {
+                    var defaultKeyword;
+                    if (languageVersion === 0) {
+                        defaultKeyword = "[\"default\"]";
+                    }
+                    else {
+                        defaultKeyword = ".default";
+                    }
+                    return getGeneratedNameForNode(node.parent) + defaultKeyword;
+                }
+                if (node.kind === 213) {
+                    var moduleName = getGeneratedNameForNode(node.parent.parent.parent);
+                    var propertyName = node.propertyName || node.name;
+                    return moduleName + "." + ts.unescapeIdentifier(propertyName.text);
+                }
+            }
+        }
+        function getExportNameSubstitution(symbol, location, getGeneratedNameForNode) {
+            if (isExternalModuleSymbol(symbol.parent)) {
+                if (languageVersion >= 2) {
+                    return undefined;
+                }
+                return "exports." + ts.unescapeIdentifier(symbol.name);
+            }
+            var node = location;
+            var containerSymbol = getParentOfSymbol(symbol);
+            while (node) {
+                if ((node.kind === 205 || node.kind === 204) && getSymbolOfNode(node) === containerSymbol) {
+                    return getGeneratedNameForNode(node) + "." + ts.unescapeIdentifier(symbol.name);
+                }
+                node = node.parent;
+            }
+        }
+        function getExpressionNameSubstitution(node, getGeneratedNameForNode) {
+            var symbol = getNodeLinks(node).resolvedSymbol || (ts.isDeclarationName(node) ? getSymbolOfNode(node.parent) : undefined);
+            if (symbol) {
+                if (symbol.parent) {
+                    return getExportNameSubstitution(symbol, node.parent, getGeneratedNameForNode);
+                }
+                var exportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
+                if (symbol !== exportSymbol && !(exportSymbol.flags & 944)) {
+                    return getExportNameSubstitution(exportSymbol, node.parent, getGeneratedNameForNode);
+                }
+                if (symbol.flags & 8388608) {
+                    return getAliasNameSubstitution(symbol, getGeneratedNameForNode);
+                }
+            }
+        }
+        function isValueAliasDeclaration(node) {
+            switch (node.kind) {
+                case 208:
+                case 210:
+                case 211:
+                case 213:
+                case 217:
+                    return isAliasResolvedToValue(getSymbolOfNode(node));
+                case 215:
+                    var exportClause = node.exportClause;
+                    return exportClause && ts.forEach(exportClause.elements, isValueAliasDeclaration);
+                case 214:
+                    return node.expression && node.expression.kind === 65 ? isAliasResolvedToValue(getSymbolOfNode(node)) : true;
+            }
+            return false;
+        }
+        function isTopLevelValueImportEqualsWithEntityName(node) {
+            if (node.parent.kind !== 227 || !ts.isInternalModuleImportEqualsDeclaration(node)) {
+                return false;
+            }
+            var isValue = isAliasResolvedToValue(getSymbolOfNode(node));
+            return isValue && node.moduleReference && !ts.nodeIsMissing(node.moduleReference);
+        }
+        function isAliasResolvedToValue(symbol) {
+            var target = resolveAlias(symbol);
+            if (target === unknownSymbol && compilerOptions.separateCompilation) {
+                return true;
+            }
+            return target !== unknownSymbol && target && target.flags & 107455 && !isConstEnumOrConstEnumOnlyModule(target);
+        }
+        function isConstEnumOrConstEnumOnlyModule(s) {
+            return isConstEnumSymbol(s) || s.constEnumOnlyModule;
+        }
+        function isReferencedAliasDeclaration(node, checkChildren) {
+            if (ts.isAliasSymbolDeclaration(node)) {
+                var symbol = getSymbolOfNode(node);
+                if (getSymbolLinks(symbol).referenced) {
+                    return true;
+                }
+            }
+            if (checkChildren) {
+                return ts.forEachChild(node, function (node) { return isReferencedAliasDeclaration(node, checkChildren); });
+            }
+            return false;
+        }
+        function isImplementationOfOverload(node) {
+            if (ts.nodeIsPresent(node.body)) {
+                var symbol = getSymbolOfNode(node);
+                var signaturesOfSymbol = getSignaturesOfSymbol(symbol);
+                return signaturesOfSymbol.length > 1 ||
+                    (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node);
+            }
+            return false;
+        }
+        function getNodeCheckFlags(node) {
+            return getNodeLinks(node).flags;
+        }
+        function getEnumMemberValue(node) {
+            computeEnumMemberValues(node.parent);
+            return getNodeLinks(node).enumMemberValue;
+        }
+        function getConstantValue(node) {
+            if (node.kind === 226) {
+                return getEnumMemberValue(node);
+            }
+            var symbol = getNodeLinks(node).resolvedSymbol;
+            if (symbol && (symbol.flags & 8)) {
+                if (ts.isConstEnumDeclaration(symbol.valueDeclaration.parent)) {
+                    return getEnumMemberValue(symbol.valueDeclaration);
+                }
+            }
+            return undefined;
+        }
+        function serializeEntityName(node, getGeneratedNameForNode, fallbackPath) {
+            if (node.kind === 65) {
+                var substitution = getExpressionNameSubstitution(node, getGeneratedNameForNode);
+                var text = substitution || node.text;
+                if (fallbackPath) {
+                    fallbackPath.push(text);
+                }
+                else {
+                    return text;
+                }
+            }
+            else {
+                var left = serializeEntityName(node.left, getGeneratedNameForNode, fallbackPath);
+                var right = serializeEntityName(node.right, getGeneratedNameForNode, fallbackPath);
+                if (!fallbackPath) {
+                    return left + "." + right;
+                }
+            }
+        }
+        function serializeTypeReferenceNode(node, getGeneratedNameForNode) {
+            var type = getTypeFromTypeReference(node);
+            if (type.flags & 16) {
+                return "void 0";
+            }
+            else if (type.flags & 8) {
+                return "Boolean";
+            }
+            else if (type.flags & 132) {
+                return "Number";
+            }
+            else if (type.flags & 258) {
+                return "String";
+            }
+            else if (type.flags & 8192) {
+                return "Array";
+            }
+            else if (type.flags & 1048576) {
+                return "Symbol";
+            }
+            else if (type === unknownType) {
+                var fallbackPath = [];
+                serializeEntityName(node.typeName, getGeneratedNameForNode, fallbackPath);
+                return fallbackPath;
+            }
+            else if (type.symbol && type.symbol.valueDeclaration) {
+                return serializeEntityName(node.typeName, getGeneratedNameForNode);
+            }
+            else if (typeHasCallOrConstructSignatures(type)) {
+                return "Function";
+            }
+            return "Object";
+        }
+        function serializeTypeNode(node, getGeneratedNameForNode) {
+            if (node) {
+                switch (node.kind) {
+                    case 99:
+                        return "void 0";
+                    case 149:
+                        return serializeTypeNode(node.type, getGeneratedNameForNode);
+                    case 142:
+                    case 143:
+                        return "Function";
+                    case 146:
+                    case 147:
+                        return "Array";
+                    case 113:
+                        return "Boolean";
+                    case 121:
+                    case 8:
+                        return "String";
+                    case 119:
+                        return "Number";
+                    case 141:
+                        return serializeTypeReferenceNode(node, getGeneratedNameForNode);
+                    case 144:
+                    case 145:
+                    case 148:
+                    case 112:
+                        break;
+                    default:
+                        ts.Debug.fail("Cannot serialize unexpected type node.");
+                        break;
+                }
+            }
+            return "Object";
+        }
+        function serializeTypeOfNode(node, getGeneratedNameForNode) {
+            switch (node.kind) {
+                case 201: return "Function";
+                case 132: return serializeTypeNode(node.type, getGeneratedNameForNode);
+                case 129: return serializeTypeNode(node.type, getGeneratedNameForNode);
+                case 136: return serializeTypeNode(node.type, getGeneratedNameForNode);
+                case 137: return serializeTypeNode(getSetAccessorTypeAnnotationNode(node), getGeneratedNameForNode);
+            }
+            if (ts.isFunctionLike(node)) {
+                return "Function";
+            }
+            return "void 0";
+        }
+        function serializeParameterTypesOfNode(node, getGeneratedNameForNode) {
+            if (node) {
+                var valueDeclaration;
+                if (node.kind === 201) {
+                    valueDeclaration = ts.getFirstConstructorWithBody(node);
+                }
+                else if (ts.isFunctionLike(node) && ts.nodeIsPresent(node.body)) {
+                    valueDeclaration = node;
+                }
+                if (valueDeclaration) {
+                    var result;
+                    var parameters = valueDeclaration.parameters;
+                    var parameterCount = parameters.length;
+                    if (parameterCount > 0) {
+                        result = new Array(parameterCount);
+                        for (var i = 0; i < parameterCount; i++) {
+                            if (parameters[i].dotDotDotToken) {
+                                var parameterType = parameters[i].type;
+                                if (parameterType.kind === 146) {
+                                    parameterType = parameterType.elementType;
+                                }
+                                else if (parameterType.kind === 141 && parameterType.typeArguments && parameterType.typeArguments.length === 1) {
+                                    parameterType = parameterType.typeArguments[0];
+                                }
+                                else {
+                                    parameterType = undefined;
+                                }
+                                result[i] = serializeTypeNode(parameterType, getGeneratedNameForNode);
+                            }
+                            else {
+                                result[i] = serializeTypeOfNode(parameters[i], getGeneratedNameForNode);
+                            }
+                        }
+                        return result;
+                    }
+                }
+            }
+            return emptyArray;
+        }
+        function serializeReturnTypeOfNode(node, getGeneratedNameForNode) {
+            if (node && ts.isFunctionLike(node)) {
+                return serializeTypeNode(node.type, getGeneratedNameForNode);
+            }
+            return "void 0";
+        }
+        function writeTypeOfDeclaration(declaration, enclosingDeclaration, flags, writer) {
+            var symbol = getSymbolOfNode(declaration);
+            var type = symbol && !(symbol.flags & (2048 | 131072))
+                ? getTypeOfSymbol(symbol)
+                : unknownType;
+            getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+        }
+        function writeReturnTypeOfSignatureDeclaration(signatureDeclaration, enclosingDeclaration, flags, writer) {
+            var signature = getSignatureFromDeclaration(signatureDeclaration);
+            getSymbolDisplayBuilder().buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags);
+        }
+        function writeTypeOfExpression(expr, enclosingDeclaration, flags, writer) {
+            var type = getTypeOfExpression(expr);
+            getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+        }
+        function hasGlobalName(name) {
+            return ts.hasProperty(globals, name);
+        }
+        function resolvesToSomeValue(location, name) {
+            ts.Debug.assert(!ts.nodeIsSynthesized(location), "resolvesToSomeValue called with a synthesized location");
+            return !!resolveName(location, name, 107455, undefined, undefined);
+        }
+        function getBlockScopedVariableId(n) {
+            ts.Debug.assert(!ts.nodeIsSynthesized(n));
+            var isVariableDeclarationOrBindingElement = n.parent.kind === 152 || (n.parent.kind === 198 && n.parent.name === n);
+            var symbol = (isVariableDeclarationOrBindingElement ? getSymbolOfNode(n.parent) : undefined) ||
+                getNodeLinks(n).resolvedSymbol ||
+                resolveName(n, n.text, 107455 | 8388608, undefined, undefined);
+            var isLetOrConst = symbol &&
+                (symbol.flags & 2) &&
+                symbol.valueDeclaration.parent.kind !== 223;
+            if (isLetOrConst) {
+                getSymbolLinks(symbol);
+                return symbol.id;
+            }
+            return undefined;
+        }
+        function instantiateSingleCallFunctionType(functionType, typeArguments) {
+            if (functionType === unknownType) {
+                return unknownType;
+            }
+            var signature = getSingleCallSignature(functionType);
+            if (!signature) {
+                return unknownType;
+            }
+            var instantiatedSignature = getSignatureInstantiation(signature, typeArguments);
+            return getOrCreateTypeFromSignature(instantiatedSignature);
+        }
+        function createResolver() {
+            return {
+                getExpressionNameSubstitution: getExpressionNameSubstitution,
+                isValueAliasDeclaration: isValueAliasDeclaration,
+                hasGlobalName: hasGlobalName,
+                isReferencedAliasDeclaration: isReferencedAliasDeclaration,
+                getNodeCheckFlags: getNodeCheckFlags,
+                isTopLevelValueImportEqualsWithEntityName: isTopLevelValueImportEqualsWithEntityName,
+                isDeclarationVisible: isDeclarationVisible,
+                isImplementationOfOverload: isImplementationOfOverload,
+                writeTypeOfDeclaration: writeTypeOfDeclaration,
+                writeReturnTypeOfSignatureDeclaration: writeReturnTypeOfSignatureDeclaration,
+                writeTypeOfExpression: writeTypeOfExpression,
+                isSymbolAccessible: isSymbolAccessible,
+                isEntityNameVisible: isEntityNameVisible,
+                getConstantValue: getConstantValue,
+                resolvesToSomeValue: resolvesToSomeValue,
+                collectLinkedAliases: collectLinkedAliases,
+                getBlockScopedVariableId: getBlockScopedVariableId,
+                serializeTypeOfNode: serializeTypeOfNode,
+                serializeParameterTypesOfNode: serializeParameterTypesOfNode,
+                serializeReturnTypeOfNode: serializeReturnTypeOfNode,
+            };
+        }
+        function initializeTypeChecker() {
+            ts.forEach(host.getSourceFiles(), function (file) {
+                ts.bindSourceFile(file);
+            });
+            ts.forEach(host.getSourceFiles(), function (file) {
+                if (!ts.isExternalModule(file)) {
+                    mergeSymbolTable(globals, file.locals);
+                }
+            });
+            getSymbolLinks(undefinedSymbol).type = undefinedType;
+            getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
+            getSymbolLinks(unknownSymbol).type = unknownType;
+            globals[undefinedSymbol.name] = undefinedSymbol;
+            globalArraySymbol = getGlobalTypeSymbol("Array");
+            globalArrayType = getTypeOfGlobalSymbol(globalArraySymbol, 1);
+            globalObjectType = getGlobalType("Object");
+            globalFunctionType = getGlobalType("Function");
+            globalStringType = getGlobalType("String");
+            globalNumberType = getGlobalType("Number");
+            globalBooleanType = getGlobalType("Boolean");
+            globalRegExpType = getGlobalType("RegExp");
+            getGlobalClassDecoratorType = ts.memoize(function () { return getGlobalType("ClassDecorator"); });
+            getGlobalPropertyDecoratorType = ts.memoize(function () { return getGlobalType("PropertyDecorator"); });
+            getGlobalMethodDecoratorType = ts.memoize(function () { return getGlobalType("MethodDecorator"); });
+            getGlobalParameterDecoratorType = ts.memoize(function () { return getGlobalType("ParameterDecorator"); });
+            if (languageVersion >= 2) {
+                globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray");
+                globalESSymbolType = getGlobalType("Symbol");
+                globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol");
+                globalIterableType = getGlobalType("Iterable", 1);
+            }
+            else {
+                globalTemplateStringsArrayType = unknownType;
+                globalESSymbolType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+                globalESSymbolConstructorSymbol = undefined;
+            }
+            anyArrayType = createArrayType(anyType);
+        }
+        function isReservedWordInStrictMode(node) {
+            return (node.parserContextFlags & 1) &&
+                (102 <= node.originalKeywordKind && node.originalKeywordKind <= 110);
+        }
+        function reportStrictModeGrammarErrorInClassDeclaration(identifier, message, arg0, arg1, arg2) {
+            if (ts.getAncestor(identifier, 201) || ts.getAncestor(identifier, 174)) {
+                return grammarErrorOnNode(identifier, message, arg0);
+            }
+            return false;
+        }
+        function checkGrammarImportDeclarationNameInStrictMode(node) {
+            if (node.importClause) {
+                var impotClause = node.importClause;
+                if (impotClause.namedBindings) {
+                    var nameBindings = impotClause.namedBindings;
+                    if (nameBindings.kind === 211) {
+                        var name_8 = nameBindings.name;
+                        if (isReservedWordInStrictMode(name_8)) {
+                            var nameText = ts.declarationNameToString(name_8);
+                            return grammarErrorOnNode(name_8, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                        }
+                    }
+                    else if (nameBindings.kind === 212) {
+                        var reportError = false;
+                        for (var _i = 0, _a = nameBindings.elements; _i < _a.length; _i++) {
+                            var element = _a[_i];
+                            var name_9 = element.name;
+                            if (isReservedWordInStrictMode(name_9)) {
+                                var nameText = ts.declarationNameToString(name_9);
+                                reportError = reportError || grammarErrorOnNode(name_9, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                            }
+                        }
+                        return reportError;
+                    }
+                }
+            }
+            return false;
+        }
+        function checkGrammarDeclarationNameInStrictMode(node) {
+            var name = node.name;
+            if (name && name.kind === 65 && isReservedWordInStrictMode(name)) {
+                var nameText = ts.declarationNameToString(name);
+                switch (node.kind) {
+                    case 129:
+                    case 198:
+                    case 200:
+                    case 128:
+                    case 152:
+                    case 202:
+                    case 203:
+                    case 204:
+                        return checkGrammarIdentifierInStrictMode(name);
+                    case 201:
+                        return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText);
+                    case 205:
+                        return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                    case 208:
+                        return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                }
+            }
+            return false;
+        }
+        function checkGrammarTypeReferenceInStrictMode(typeName) {
+            if (typeName.kind === 65) {
+                checkGrammarTypeNameInStrictMode(typeName);
+            }
+            else if (typeName.kind === 126) {
+                checkGrammarTypeNameInStrictMode(typeName.right);
+                checkGrammarTypeReferenceInStrictMode(typeName.left);
+            }
+        }
+        function checkGrammarHeritageClauseElementInStrictMode(expression) {
+            if (expression && expression.kind === 65) {
+                return checkGrammarIdentifierInStrictMode(expression);
+            }
+            else if (expression && expression.kind === 155) {
+                checkGrammarHeritageClauseElementInStrictMode(expression.expression);
+            }
+        }
+        function checkGrammarIdentifierInStrictMode(node, nameText) {
+            if (node && node.kind === 65 && isReservedWordInStrictMode(node)) {
+                if (!nameText) {
+                    nameText = ts.declarationNameToString(node);
+                }
+                var errorReport = reportStrictModeGrammarErrorInClassDeclaration(node, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText) ||
+                    grammarErrorOnNode(node, ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                return errorReport;
+            }
+            return false;
+        }
+        function checkGrammarTypeNameInStrictMode(node) {
+            if (node && node.kind === 65 && isReservedWordInStrictMode(node)) {
+                var nameText = ts.declarationNameToString(node);
+                var errorReport = reportStrictModeGrammarErrorInClassDeclaration(node, ts.Diagnostics.Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText) ||
+                    grammarErrorOnNode(node, ts.Diagnostics.Type_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                return errorReport;
+            }
+            return false;
+        }
+        function checkGrammarDecorators(node) {
+            if (!node.decorators) {
+                return false;
+            }
+            if (!ts.nodeCanBeDecorated(node)) {
+                return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_not_valid_here);
+            }
+            else if (languageVersion < 1) {
+                return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
+            }
+            else if (node.kind === 136 || node.kind === 137) {
+                var accessors = ts.getAllAccessorDeclarations(node.parent.members, node);
+                if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) {
+                    return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name);
+                }
+            }
+            return false;
+        }
+        function checkGrammarModifiers(node) {
+            switch (node.kind) {
+                case 136:
+                case 137:
+                case 135:
+                case 132:
+                case 131:
+                case 134:
+                case 133:
+                case 140:
+                case 201:
+                case 202:
+                case 205:
+                case 204:
+                case 180:
+                case 200:
+                case 203:
+                case 209:
+                case 208:
+                case 215:
+                case 214:
+                case 129:
+                    break;
+                default:
+                    return false;
+            }
+            if (!node.modifiers) {
+                return;
+            }
+            var lastStatic, lastPrivate, lastProtected, lastDeclare;
+            var flags = 0;
+            for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) {
+                var modifier = _a[_i];
+                switch (modifier.kind) {
+                    case 108:
+                    case 107:
+                    case 106:
+                        var text = void 0;
+                        if (modifier.kind === 108) {
+                            text = "public";
+                        }
+                        else if (modifier.kind === 107) {
+                            text = "protected";
+                            lastProtected = modifier;
+                        }
+                        else {
+                            text = "private";
+                            lastPrivate = modifier;
+                        }
+                        if (flags & 112) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics.Accessibility_modifier_already_seen);
+                        }
+                        else if (flags & 128) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
+                        }
+                        else if (node.parent.kind === 206 || node.parent.kind === 227) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_element, text);
+                        }
+                        flags |= ts.modifierToFlag(modifier.kind);
+                        break;
+                    case 109:
+                        if (flags & 128) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "static");
+                        }
+                        else if (node.parent.kind === 206 || node.parent.kind === 227) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_element, "static");
+                        }
+                        else if (node.kind === 129) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static");
+                        }
+                        flags |= 128;
+                        lastStatic = modifier;
+                        break;
+                    case 78:
+                        if (flags & 1) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "export");
+                        }
+                        else if (flags & 2) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
+                        }
+                        else if (node.parent.kind === 201) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export");
+                        }
+                        else if (node.kind === 129) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export");
+                        }
+                        flags |= 1;
+                        break;
+                    case 115:
+                        if (flags & 2) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "declare");
+                        }
+                        else if (node.parent.kind === 201) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare");
+                        }
+                        else if (node.kind === 129) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare");
+                        }
+                        else if (ts.isInAmbientContext(node.parent) && node.parent.kind === 206) {
+                            return grammarErrorOnNode(modifier, ts.Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
+                        }
+                        flags |= 2;
+                        lastDeclare = modifier;
+                        break;
+                }
+            }
+            if (node.kind === 135) {
+                if (flags & 128) {
+                    return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static");
+                }
+                else if (flags & 64) {
+                    return grammarErrorOnNode(lastProtected, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
+                }
+                else if (flags & 32) {
+                    return grammarErrorOnNode(lastPrivate, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
+                }
+            }
+            else if ((node.kind === 209 || node.kind === 208) && flags & 2) {
+                return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_declare_modifier_cannot_be_used_with_an_import_declaration, "declare");
+            }
+            else if (node.kind === 202 && flags & 2) {
+                return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_declare_modifier_cannot_be_used_with_an_interface_declaration, "declare");
+            }
+            else if (node.kind === 129 && (flags & 112) && ts.isBindingPattern(node.name)) {
+                return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_may_not_be_a_binding_pattern);
+            }
+        }
+        function checkGrammarForDisallowedTrailingComma(list) {
+            if (list && list.hasTrailingComma) {
+                var start = list.end - ",".length;
+                var end = list.end;
+                var sourceFile = ts.getSourceFileOfNode(list[0]);
+                return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Trailing_comma_not_allowed);
+            }
+        }
+        function checkGrammarTypeParameterList(node, typeParameters, file) {
+            if (checkGrammarForDisallowedTrailingComma(typeParameters)) {
+                return true;
+            }
+            if (typeParameters && typeParameters.length === 0) {
+                var start = typeParameters.pos - "<".length;
+                var end = ts.skipTrivia(file.text, typeParameters.end) + ">".length;
+                return grammarErrorAtPos(file, start, end - start, ts.Diagnostics.Type_parameter_list_cannot_be_empty);
+            }
+        }
+        function checkGrammarParameterList(parameters) {
+            if (checkGrammarForDisallowedTrailingComma(parameters)) {
+                return true;
+            }
+            var seenOptionalParameter = false;
+            var parameterCount = parameters.length;
+            for (var i = 0; i < parameterCount; i++) {
+                var parameter = parameters[i];
+                if (parameter.dotDotDotToken) {
+                    if (i !== (parameterCount - 1)) {
+                        return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
+                    }
+                    if (ts.isBindingPattern(parameter.name)) {
+                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
+                    }
+                    if (parameter.questionToken) {
+                        return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_rest_parameter_cannot_be_optional);
+                    }
+                    if (parameter.initializer) {
+                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_rest_parameter_cannot_have_an_initializer);
+                    }
+                }
+                else if (parameter.questionToken || parameter.initializer) {
+                    seenOptionalParameter = true;
+                    if (parameter.questionToken && parameter.initializer) {
+                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.Parameter_cannot_have_question_mark_and_initializer);
+                    }
+                }
+                else {
+                    if (seenOptionalParameter) {
+                        return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter);
+                    }
+                }
+            }
+        }
+        function checkGrammarFunctionLikeDeclaration(node) {
+            var file = ts.getSourceFileOfNode(node);
+            return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters, file) ||
+                checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
+        }
+        function checkGrammarArrowFunction(node, file) {
+            if (node.kind === 163) {
+                var arrowFunction = node;
+                var startLine = ts.getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.pos).line;
+                var endLine = ts.getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.end).line;
+                if (startLine !== endLine) {
+                    return grammarErrorOnNode(arrowFunction.equalsGreaterThanToken, ts.Diagnostics.Line_terminator_not_permitted_before_arrow);
+                }
+            }
+            return false;
+        }
+        function checkGrammarIndexSignatureParameters(node) {
+            var parameter = node.parameters[0];
+            if (node.parameters.length !== 1) {
+                if (parameter) {
+                    return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter);
+                }
+                else {
+                    return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter);
+                }
+            }
+            if (parameter.dotDotDotToken) {
+                return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.An_index_signature_cannot_have_a_rest_parameter);
+            }
+            if (parameter.flags & 499) {
+                return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier);
+            }
+            if (parameter.questionToken) {
+                return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark);
+            }
+            if (parameter.initializer) {
+                return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_initializer);
+            }
+            if (!parameter.type) {
+                return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_must_have_a_type_annotation);
+            }
+            if (parameter.type.kind !== 121 && parameter.type.kind !== 119) {
+                return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_must_be_string_or_number);
+            }
+            if (!node.type) {
+                return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_a_type_annotation);
+            }
+        }
+        function checkGrammarForIndexSignatureModifier(node) {
+            if (node.flags & 499) {
+                grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_not_permitted_on_index_signature_members);
+            }
+        }
+        function checkGrammarIndexSignature(node) {
+            return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node) || checkGrammarForIndexSignatureModifier(node);
+        }
+        function checkGrammarForAtLeastOneTypeArgument(node, typeArguments) {
+            if (typeArguments && typeArguments.length === 0) {
+                var sourceFile = ts.getSourceFileOfNode(node);
+                var start = typeArguments.pos - "<".length;
+                var end = ts.skipTrivia(sourceFile.text, typeArguments.end) + ">".length;
+                return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Type_argument_list_cannot_be_empty);
+            }
+        }
+        function checkGrammarTypeArguments(node, typeArguments) {
+            return checkGrammarForDisallowedTrailingComma(typeArguments) ||
+                checkGrammarForAtLeastOneTypeArgument(node, typeArguments);
+        }
+        function checkGrammarForOmittedArgument(node, arguments) {
+            if (arguments) {
+                var sourceFile = ts.getSourceFileOfNode(node);
+                for (var _i = 0; _i < arguments.length; _i++) {
+                    var arg = arguments[_i];
+                    if (arg.kind === 175) {
+                        return grammarErrorAtPos(sourceFile, arg.pos, 0, ts.Diagnostics.Argument_expression_expected);
+                    }
+                }
+            }
+        }
+        function checkGrammarArguments(node, arguments) {
+            return checkGrammarForDisallowedTrailingComma(arguments) ||
+                checkGrammarForOmittedArgument(node, arguments);
+        }
+        function checkGrammarHeritageClause(node) {
+            var types = node.types;
+            if (checkGrammarForDisallowedTrailingComma(types)) {
+                return true;
+            }
+            if (types && types.length === 0) {
+                var listType = ts.tokenToString(node.token);
+                var sourceFile = ts.getSourceFileOfNode(node);
+                return grammarErrorAtPos(sourceFile, types.pos, 0, ts.Diagnostics._0_list_cannot_be_empty, listType);
+            }
+        }
+        function checkGrammarClassDeclarationHeritageClauses(node) {
+            var seenExtendsClause = false;
+            var seenImplementsClause = false;
+            if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && node.heritageClauses) {
+                for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) {
+                    var heritageClause = _a[_i];
+                    if (heritageClause.token === 79) {
+                        if (seenExtendsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen);
+                        }
+                        if (seenImplementsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_must_precede_implements_clause);
+                        }
+                        if (heritageClause.types.length > 1) {
+                            return grammarErrorOnFirstToken(heritageClause.types[1], ts.Diagnostics.Classes_can_only_extend_a_single_class);
+                        }
+                        seenExtendsClause = true;
+                    }
+                    else {
+                        ts.Debug.assert(heritageClause.token === 102);
+                        if (seenImplementsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.implements_clause_already_seen);
+                        }
+                        seenImplementsClause = true;
+                    }
+                    checkGrammarHeritageClause(heritageClause);
+                }
+            }
+        }
+        function checkGrammarInterfaceDeclaration(node) {
+            var seenExtendsClause = false;
+            if (node.heritageClauses) {
+                for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) {
+                    var heritageClause = _a[_i];
+                    if (heritageClause.token === 79) {
+                        if (seenExtendsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen);
+                        }
+                        seenExtendsClause = true;
+                    }
+                    else {
+                        ts.Debug.assert(heritageClause.token === 102);
+                        return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.Interface_declaration_cannot_have_implements_clause);
+                    }
+                    checkGrammarHeritageClause(heritageClause);
+                }
+            }
+            return false;
+        }
+        function checkGrammarComputedPropertyName(node) {
+            if (node.kind !== 127) {
+                return false;
+            }
+            var computedPropertyName = node;
+            if (computedPropertyName.expression.kind === 169 && computedPropertyName.expression.operatorToken.kind === 23) {
+                return grammarErrorOnNode(computedPropertyName.expression, ts.Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name);
+            }
+        }
+        function checkGrammarForGenerator(node) {
+            if (node.asteriskToken) {
+                return grammarErrorOnNode(node.asteriskToken, ts.Diagnostics.Generators_are_not_currently_supported);
+            }
+        }
+        function checkGrammarFunctionName(name) {
+            return checkGrammarEvalOrArgumentsInStrictMode(name, name);
+        }
+        function checkGrammarForInvalidQuestionMark(node, questionToken, message) {
+            if (questionToken) {
+                return grammarErrorOnNode(questionToken, message);
+            }
+        }
+        function checkGrammarObjectLiteralExpression(node) {
+            var seen = {};
+            var Property = 1;
+            var GetAccessor = 2;
+            var SetAccesor = 4;
+            var GetOrSetAccessor = GetAccessor | SetAccesor;
+            var inStrictMode = (node.parserContextFlags & 1) !== 0;
+            for (var _i = 0, _a = node.properties; _i < _a.length; _i++) {
+                var prop = _a[_i];
+                var name_10 = prop.name;
+                if (prop.kind === 175 ||
+                    name_10.kind === 127) {
+                    checkGrammarComputedPropertyName(name_10);
+                    continue;
+                }
+                var currentKind = void 0;
+                if (prop.kind === 224 || prop.kind === 225) {
+                    checkGrammarForInvalidQuestionMark(prop, prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional);
+                    if (name_10.kind === 7) {
+                        checkGrammarNumericLiteral(name_10);
+                    }
+                    currentKind = Property;
+                }
+                else if (prop.kind === 134) {
+                    currentKind = Property;
+                }
+                else if (prop.kind === 136) {
+                    currentKind = GetAccessor;
+                }
+                else if (prop.kind === 137) {
+                    currentKind = SetAccesor;
+                }
+                else {
+                    ts.Debug.fail("Unexpected syntax kind:" + prop.kind);
+                }
+                if (!ts.hasProperty(seen, name_10.text)) {
+                    seen[name_10.text] = currentKind;
+                }
+                else {
+                    var existingKind = seen[name_10.text];
+                    if (currentKind === Property && existingKind === Property) {
+                        if (inStrictMode) {
+                            grammarErrorOnNode(name_10, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode);
+                        }
+                    }
+                    else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) {
+                        if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) {
+                            seen[name_10.text] = currentKind | existingKind;
+                        }
+                        else {
+                            return grammarErrorOnNode(name_10, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
+                        }
+                    }
+                    else {
+                        return grammarErrorOnNode(name_10, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
+                    }
+                }
+            }
+        }
+        function checkGrammarForInOrForOfStatement(forInOrOfStatement) {
+            if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) {
+                return true;
+            }
+            if (forInOrOfStatement.initializer.kind === 199) {
+                var variableList = forInOrOfStatement.initializer;
+                if (!checkGrammarVariableDeclarationList(variableList)) {
+                    if (variableList.declarations.length > 1) {
+                        var diagnostic = forInOrOfStatement.kind === 187
+                            ? ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
+                            : ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
+                        return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
+                    }
+                    var firstDeclaration = variableList.declarations[0];
+                    if (firstDeclaration.initializer) {
+                        var diagnostic = forInOrOfStatement.kind === 187
+                            ? ts.Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
+                            : ts.Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer;
+                        return grammarErrorOnNode(firstDeclaration.name, diagnostic);
+                    }
+                    if (firstDeclaration.type) {
+                        var diagnostic = forInOrOfStatement.kind === 187
+                            ? ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation
+                            : ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation;
+                        return grammarErrorOnNode(firstDeclaration, diagnostic);
+                    }
+                }
+            }
+            return false;
+        }
+        function checkGrammarAccessor(accessor) {
+            var kind = accessor.kind;
+            if (languageVersion < 1) {
+                return grammarErrorOnNode(accessor.name, ts.Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
+            }
+            else if (ts.isInAmbientContext(accessor)) {
+                return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context);
+            }
+            else if (accessor.body === undefined) {
+                return grammarErrorAtPos(ts.getSourceFileOfNode(accessor), accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{");
+            }
+            else if (accessor.typeParameters) {
+                return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_have_type_parameters);
+            }
+            else if (kind === 136 && accessor.parameters.length) {
+                return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_get_accessor_cannot_have_parameters);
+            }
+            else if (kind === 137) {
+                if (accessor.type) {
+                    return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation);
+                }
+                else if (accessor.parameters.length !== 1) {
+                    return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_must_have_exactly_one_parameter);
+                }
+                else {
+                    var parameter = accessor.parameters[0];
+                    if (parameter.dotDotDotToken) {
+                        return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_set_accessor_cannot_have_rest_parameter);
+                    }
+                    else if (parameter.flags & 499) {
+                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
+                    }
+                    else if (parameter.questionToken) {
+                        return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_set_accessor_cannot_have_an_optional_parameter);
+                    }
+                    else if (parameter.initializer) {
+                        return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer);
+                    }
+                }
+            }
+        }
+        function checkGrammarForNonSymbolComputedProperty(node, message) {
+            if (node.kind === 127 && !ts.isWellKnownSymbolSyntactically(node.expression)) {
+                return grammarErrorOnNode(node, message);
+            }
+        }
+        function checkGrammarMethod(node) {
+            if (checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) ||
+                checkGrammarFunctionLikeDeclaration(node) ||
+                checkGrammarForGenerator(node)) {
+                return true;
+            }
+            if (node.parent.kind === 154) {
+                if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional)) {
+                    return true;
+                }
+                else if (node.body === undefined) {
+                    return grammarErrorAtPos(getSourceFile(node), node.end - 1, ";".length, ts.Diagnostics._0_expected, "{");
+                }
+            }
+            if (node.parent.kind === 201) {
+                if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional)) {
+                    return true;
+                }
+                if (ts.isInAmbientContext(node)) {
+                    return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol);
+                }
+                else if (!node.body) {
+                    return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol);
+                }
+            }
+            else if (node.parent.kind === 202) {
+                return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol);
+            }
+            else if (node.parent.kind === 145) {
+                return checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol);
+            }
+        }
+        function isIterationStatement(node, lookInLabeledStatements) {
+            switch (node.kind) {
+                case 186:
+                case 187:
+                case 188:
+                case 184:
+                case 185:
+                    return true;
+                case 194:
+                    return lookInLabeledStatements && isIterationStatement(node.statement, lookInLabeledStatements);
+            }
+            return false;
+        }
+        function checkGrammarBreakOrContinueStatement(node) {
+            var current = node;
+            while (current) {
+                if (ts.isFunctionLike(current)) {
+                    return grammarErrorOnNode(node, ts.Diagnostics.Jump_target_cannot_cross_function_boundary);
+                }
+                switch (current.kind) {
+                    case 194:
+                        if (node.label && current.label.text === node.label.text) {
+                            var isMisplacedContinueLabel = node.kind === 189
+                                && !isIterationStatement(current.statement, true);
+                            if (isMisplacedContinueLabel) {
+                                return grammarErrorOnNode(node, ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement);
+                            }
+                            return false;
+                        }
+                        break;
+                    case 193:
+                        if (node.kind === 190 && !node.label) {
+                            return false;
+                        }
+                        break;
+                    default:
+                        if (isIterationStatement(current, false) && !node.label) {
+                            return false;
+                        }
+                        break;
+                }
+                current = current.parent;
+            }
+            if (node.label) {
+                var message = node.kind === 190
+                    ? ts.Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement
+                    : ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement;
+                return grammarErrorOnNode(node, message);
+            }
+            else {
+                var message = node.kind === 190
+                    ? ts.Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement
+                    : ts.Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement;
+                return grammarErrorOnNode(node, message);
+            }
+        }
+        function checkGrammarBindingElement(node) {
+            if (node.dotDotDotToken) {
+                var elements = node.parent.elements;
+                if (node !== elements[elements.length - 1]) {
+                    return grammarErrorOnNode(node, ts.Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
+                }
+                if (node.name.kind === 151 || node.name.kind === 150) {
+                    return grammarErrorOnNode(node.name, ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
+                }
+                if (node.initializer) {
+                    return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - 1, 1, ts.Diagnostics.A_rest_element_cannot_have_an_initializer);
+                }
+            }
+            return checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
+        }
+        function checkGrammarVariableDeclaration(node) {
+            if (node.parent.parent.kind !== 187 && node.parent.parent.kind !== 188) {
+                if (ts.isInAmbientContext(node)) {
+                    if (node.initializer) {
+                        var equalsTokenLength = "=".length;
+                        return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
+                    }
+                }
+                else if (!node.initializer) {
+                    if (ts.isBindingPattern(node.name) && !ts.isBindingPattern(node.parent)) {
+                        return grammarErrorOnNode(node, ts.Diagnostics.A_destructuring_declaration_must_have_an_initializer);
+                    }
+                    if (ts.isConst(node)) {
+                        return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_must_be_initialized);
+                    }
+                }
+            }
+            var checkLetConstNames = languageVersion >= 2 && (ts.isLet(node) || ts.isConst(node));
+            return (checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name)) ||
+                checkGrammarEvalOrArgumentsInStrictMode(node, node.name);
+        }
+        function checkGrammarNameInLetOrConstDeclarations(name) {
+            if (name.kind === 65) {
+                if (name.text === "let") {
+                    return grammarErrorOnNode(name, ts.Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
+                }
+            }
+            else {
+                var elements = name.elements;
+                for (var _i = 0; _i < elements.length; _i++) {
+                    var element = elements[_i];
+                    if (element.kind !== 175) {
+                        checkGrammarNameInLetOrConstDeclarations(element.name);
+                    }
+                }
+            }
+        }
+        function checkGrammarVariableDeclarationList(declarationList) {
+            var declarations = declarationList.declarations;
+            if (checkGrammarForDisallowedTrailingComma(declarationList.declarations)) {
+                return true;
+            }
+            if (!declarationList.declarations.length) {
+                return grammarErrorAtPos(ts.getSourceFileOfNode(declarationList), declarations.pos, declarations.end - declarations.pos, ts.Diagnostics.Variable_declaration_list_cannot_be_empty);
+            }
+        }
+        function allowLetAndConstDeclarations(parent) {
+            switch (parent.kind) {
+                case 183:
+                case 184:
+                case 185:
+                case 192:
+                case 186:
+                case 187:
+                case 188:
+                    return false;
+                case 194:
+                    return allowLetAndConstDeclarations(parent.parent);
+            }
+            return true;
+        }
+        function checkGrammarForDisallowedLetOrConstStatement(node) {
+            if (!allowLetAndConstDeclarations(node.parent)) {
+                if (ts.isLet(node.declarationList)) {
+                    return grammarErrorOnNode(node, ts.Diagnostics.let_declarations_can_only_be_declared_inside_a_block);
+                }
+                else if (ts.isConst(node.declarationList)) {
+                    return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_can_only_be_declared_inside_a_block);
+                }
+            }
+        }
+        function isIntegerLiteral(expression) {
+            if (expression.kind === 167) {
+                var unaryExpression = expression;
+                if (unaryExpression.operator === 33 || unaryExpression.operator === 34) {
+                    expression = unaryExpression.operand;
+                }
+            }
+            if (expression.kind === 7) {
+                return /^[0-9]+([eE]\+?[0-9]+)?$/.test(expression.text);
+            }
+            return false;
+        }
+        function checkGrammarEnumDeclaration(enumDecl) {
+            var enumIsConst = (enumDecl.flags & 8192) !== 0;
+            var hasError = false;
+            if (!enumIsConst) {
+                var inConstantEnumMemberSection = true;
+                var inAmbientContext = ts.isInAmbientContext(enumDecl);
+                for (var _i = 0, _a = enumDecl.members; _i < _a.length; _i++) {
+                    var node = _a[_i];
+                    if (node.name.kind === 127) {
+                        hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums);
+                    }
+                    else if (inAmbientContext) {
+                        if (node.initializer && !isIntegerLiteral(node.initializer)) {
+                            hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers) || hasError;
+                        }
+                    }
+                    else if (node.initializer) {
+                        inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
+                    }
+                    else if (!inConstantEnumMemberSection) {
+                        hasError = grammarErrorOnNode(node.name, ts.Diagnostics.Enum_member_must_have_initializer) || hasError;
+                    }
+                }
+            }
+            return hasError;
+        }
+        function hasParseDiagnostics(sourceFile) {
+            return sourceFile.parseDiagnostics.length > 0;
+        }
+        function grammarErrorOnFirstToken(node, message, arg0, arg1, arg2) {
+            var sourceFile = ts.getSourceFileOfNode(node);
+            if (!hasParseDiagnostics(sourceFile)) {
+                var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos);
+                diagnostics.add(ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+        function grammarErrorAtPos(sourceFile, start, length, message, arg0, arg1, arg2) {
+            if (!hasParseDiagnostics(sourceFile)) {
+                diagnostics.add(ts.createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+        function grammarErrorOnNode(node, message, arg0, arg1, arg2) {
+            var sourceFile = ts.getSourceFileOfNode(node);
+            if (!hasParseDiagnostics(sourceFile)) {
+                diagnostics.add(ts.createDiagnosticForNode(node, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+        function checkGrammarEvalOrArgumentsInStrictMode(contextNode, name) {
+            if (name && name.kind === 65) {
+                var identifier = name;
+                if (contextNode && (contextNode.parserContextFlags & 1) && isEvalOrArgumentsIdentifier(identifier)) {
+                    var nameText = ts.declarationNameToString(identifier);
+                    var reportErrorInClassDeclaration = reportStrictModeGrammarErrorInClassDeclaration(identifier, ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode, nameText);
+                    if (!reportErrorInClassDeclaration) {
+                        return grammarErrorOnNode(identifier, ts.Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
+                    }
+                    return reportErrorInClassDeclaration;
+                }
+            }
+        }
+        function isEvalOrArgumentsIdentifier(node) {
+            return node.kind === 65 &&
+                (node.text === "eval" || node.text === "arguments");
+        }
+        function checkGrammarConstructorTypeParameters(node) {
+            if (node.typeParameters) {
+                return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.typeParameters.pos, node.typeParameters.end - node.typeParameters.pos, ts.Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration);
+            }
+        }
+        function checkGrammarConstructorTypeAnnotation(node) {
+            if (node.type) {
+                return grammarErrorOnNode(node.type, ts.Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration);
+            }
+        }
+        function checkGrammarProperty(node) {
+            if (node.parent.kind === 201) {
+                if (checkGrammarForInvalidQuestionMark(node, node.questionToken, ts.Diagnostics.A_class_member_cannot_be_declared_optional) ||
+                    checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) {
+                    return true;
+                }
+            }
+            else if (node.parent.kind === 202) {
+                if (checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol)) {
+                    return true;
+                }
+            }
+            else if (node.parent.kind === 145) {
+                if (checkGrammarForNonSymbolComputedProperty(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol)) {
+                    return true;
+                }
+            }
+            if (ts.isInAmbientContext(node) && node.initializer) {
+                return grammarErrorOnFirstToken(node.initializer, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
+            }
+        }
+        function checkGrammarTopLevelElementForRequiredDeclareModifier(node) {
+            if (node.kind === 202 ||
+                node.kind === 209 ||
+                node.kind === 208 ||
+                node.kind === 215 ||
+                node.kind === 214 ||
+                (node.flags & 2) ||
+                (node.flags & (1 | 256))) {
+                return false;
+            }
+            return grammarErrorOnFirstToken(node, ts.Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file);
+        }
+        function checkGrammarTopLevelElementsForRequiredDeclareModifier(file) {
+            for (var _i = 0, _a = file.statements; _i < _a.length; _i++) {
+                var decl = _a[_i];
+                if (ts.isDeclaration(decl) || decl.kind === 180) {
+                    if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        function checkGrammarSourceFile(node) {
+            return ts.isInAmbientContext(node) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node);
+        }
+        function checkGrammarStatementInAmbientContext(node) {
+            if (ts.isInAmbientContext(node)) {
+                if (isAccessor(node.parent.kind)) {
+                    return getNodeLinks(node).hasReportedStatementInAmbientContext = true;
+                }
+                var links = getNodeLinks(node);
+                if (!links.hasReportedStatementInAmbientContext && ts.isFunctionLike(node.parent)) {
+                    return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
+                }
+                if (node.parent.kind === 179 || node.parent.kind === 206 || node.parent.kind === 227) {
+                    var links_1 = getNodeLinks(node.parent);
+                    if (!links_1.hasReportedStatementInAmbientContext) {
+                        return links_1.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
+                    }
+                }
+                else {
+                }
+            }
+        }
+        function checkGrammarNumericLiteral(node) {
+            if (node.flags & 16384) {
+                if (node.parserContextFlags & 1) {
+                    return grammarErrorOnNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode);
+                }
+                else if (languageVersion >= 1) {
+                    return grammarErrorOnNode(node, ts.Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);
+                }
+            }
+        }
+        function grammarErrorAfterFirstToken(node, message, arg0, arg1, arg2) {
+            var sourceFile = ts.getSourceFileOfNode(node);
+            if (!hasParseDiagnostics(sourceFile)) {
+                var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos);
+                diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), 0, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+        initializeTypeChecker();
+        return checker;
+    }
+    ts.createTypeChecker = createTypeChecker;
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/commandLineParser.js b/dist/typescript/compiler/commandLineParser.js
new file mode 100644
index 000000000..831e1f3bc
--- /dev/null
+++ b/dist/typescript/compiler/commandLineParser.js
@@ -0,0 +1,361 @@
+/// <reference path="sys.ts"/>
+/// <reference path="types.ts"/>
+/// <reference path="core.ts"/>
+/// <reference path="scanner.ts"/>
+var ts;
+(function (ts) {
+    ts.optionDeclarations = [
+        {
+            name: "charset",
+            type: "string",
+        },
+        {
+            name: "declaration",
+            shortName: "d",
+            type: "boolean",
+            description: ts.Diagnostics.Generates_corresponding_d_ts_file,
+        },
+        {
+            name: "diagnostics",
+            type: "boolean",
+        },
+        {
+            name: "emitBOM",
+            type: "boolean"
+        },
+        {
+            name: "help",
+            shortName: "h",
+            type: "boolean",
+            description: ts.Diagnostics.Print_this_message,
+        },
+        {
+            name: "listFiles",
+            type: "boolean",
+        },
+        {
+            name: "locale",
+            type: "string",
+        },
+        {
+            name: "mapRoot",
+            type: "string",
+            isFilePath: true,
+            description: ts.Diagnostics.Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
+            paramType: ts.Diagnostics.LOCATION,
+        },
+        {
+            name: "module",
+            shortName: "m",
+            type: {
+                "commonjs": 1,
+                "amd": 2,
+                "umd": 3
+            },
+            description: ts.Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_or_umd,
+            paramType: ts.Diagnostics.KIND,
+            error: ts.Diagnostics.Argument_for_module_option_must_be_commonjs_amd_or_umd
+        },
+        {
+            name: "noEmit",
+            type: "boolean",
+            description: ts.Diagnostics.Do_not_emit_outputs,
+        },
+        {
+            name: "noEmitOnError",
+            type: "boolean",
+            description: ts.Diagnostics.Do_not_emit_outputs_if_any_type_checking_errors_were_reported,
+        },
+        {
+            name: "noImplicitAny",
+            type: "boolean",
+            description: ts.Diagnostics.Raise_error_on_expressions_and_declarations_with_an_implied_any_type,
+        },
+        {
+            name: "noLib",
+            type: "boolean",
+        },
+        {
+            name: "noResolve",
+            type: "boolean",
+        },
+        {
+            name: "out",
+            type: "string",
+            description: ts.Diagnostics.Concatenate_and_emit_output_to_single_file,
+            paramType: ts.Diagnostics.FILE,
+        },
+        {
+            name: "outDir",
+            type: "string",
+            isFilePath: true,
+            description: ts.Diagnostics.Redirect_output_structure_to_the_directory,
+            paramType: ts.Diagnostics.DIRECTORY,
+        },
+        {
+            name: "preserveConstEnums",
+            type: "boolean",
+            description: ts.Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
+        },
+        {
+            name: "project",
+            shortName: "p",
+            type: "string",
+            isFilePath: true,
+            description: ts.Diagnostics.Compile_the_project_in_the_given_directory,
+            paramType: ts.Diagnostics.DIRECTORY
+        },
+        {
+            name: "removeComments",
+            type: "boolean",
+            description: ts.Diagnostics.Do_not_emit_comments_to_output,
+        },
+        {
+            name: "rootDir",
+            type: "string",
+            isFilePath: true,
+            description: ts.Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir,
+            paramType: ts.Diagnostics.LOCATION,
+        },
+        {
+            name: "separateCompilation",
+            type: "boolean",
+        },
+        {
+            name: "sourceMap",
+            type: "boolean",
+            description: ts.Diagnostics.Generates_corresponding_map_file,
+        },
+        {
+            name: "sourceRoot",
+            type: "string",
+            isFilePath: true,
+            description: ts.Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
+            paramType: ts.Diagnostics.LOCATION,
+        },
+        {
+            name: "suppressImplicitAnyIndexErrors",
+            type: "boolean",
+            description: ts.Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures,
+        },
+        {
+            name: "stripInternal",
+            type: "boolean",
+            description: ts.Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation,
+            experimental: true
+        },
+        {
+            name: "target",
+            shortName: "t",
+            type: { "es3": 0, "es5": 1, "es6": 2 },
+            description: ts.Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
+            paramType: ts.Diagnostics.VERSION,
+            error: ts.Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES6
+        },
+        {
+            name: "version",
+            shortName: "v",
+            type: "boolean",
+            description: ts.Diagnostics.Print_the_compiler_s_version,
+        },
+        {
+            name: "watch",
+            shortName: "w",
+            type: "boolean",
+            description: ts.Diagnostics.Watch_input_files,
+        },
+        {
+            name: "emitDecoratorMetadata",
+            type: "boolean",
+            experimental: true
+        }
+    ];
+    function parseCommandLine(commandLine) {
+        var options = {};
+        var fileNames = [];
+        var errors = [];
+        var shortOptionNames = {};
+        var optionNameMap = {};
+        ts.forEach(ts.optionDeclarations, function (option) {
+            optionNameMap[option.name.toLowerCase()] = option;
+            if (option.shortName) {
+                shortOptionNames[option.shortName] = option.name;
+            }
+        });
+        parseStrings(commandLine);
+        return {
+            options: options,
+            fileNames: fileNames,
+            errors: errors
+        };
+        function parseStrings(args) {
+            var i = 0;
+            while (i < args.length) {
+                var s = args[i++];
+                if (s.charCodeAt(0) === 64) {
+                    parseResponseFile(s.slice(1));
+                }
+                else if (s.charCodeAt(0) === 45) {
+                    s = s.slice(s.charCodeAt(1) === 45 ? 2 : 1).toLowerCase();
+                    if (ts.hasProperty(shortOptionNames, s)) {
+                        s = shortOptionNames[s];
+                    }
+                    if (ts.hasProperty(optionNameMap, s)) {
+                        var opt = optionNameMap[s];
+                        if (!args[i] && opt.type !== "boolean") {
+                            errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
+                        }
+                        switch (opt.type) {
+                            case "number":
+                                options[opt.name] = parseInt(args[i++]);
+                                break;
+                            case "boolean":
+                                options[opt.name] = true;
+                                break;
+                            case "string":
+                                options[opt.name] = args[i++] || "";
+                                break;
+                            default:
+                                var map = opt.type;
+                                var key = (args[i++] || "").toLowerCase();
+                                if (ts.hasProperty(map, key)) {
+                                    options[opt.name] = map[key];
+                                }
+                                else {
+                                    errors.push(ts.createCompilerDiagnostic(opt.error));
+                                }
+                        }
+                    }
+                    else {
+                        errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_compiler_option_0, s));
+                    }
+                }
+                else {
+                    fileNames.push(s);
+                }
+            }
+        }
+        function parseResponseFile(fileName) {
+            var text = ts.sys.readFile(fileName);
+            if (!text) {
+                errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, fileName));
+                return;
+            }
+            var args = [];
+            var pos = 0;
+            while (true) {
+                while (pos < text.length && text.charCodeAt(pos) <= 32)
+                    pos++;
+                if (pos >= text.length)
+                    break;
+                var start = pos;
+                if (text.charCodeAt(start) === 34) {
+                    pos++;
+                    while (pos < text.length && text.charCodeAt(pos) !== 34)
+                        pos++;
+                    if (pos < text.length) {
+                        args.push(text.substring(start + 1, pos));
+                        pos++;
+                    }
+                    else {
+                        errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName));
+                    }
+                }
+                else {
+                    while (text.charCodeAt(pos) > 32)
+                        pos++;
+                    args.push(text.substring(start, pos));
+                }
+            }
+            parseStrings(args);
+        }
+    }
+    ts.parseCommandLine = parseCommandLine;
+    function readConfigFile(fileName) {
+        try {
+            var text = ts.sys.readFile(fileName);
+        }
+        catch (e) {
+            return { error: ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
+        }
+        return parseConfigFileText(fileName, text);
+    }
+    ts.readConfigFile = readConfigFile;
+    function parseConfigFileText(fileName, jsonText) {
+        try {
+            return { config: /\S/.test(jsonText) ? JSON.parse(jsonText) : {} };
+        }
+        catch (e) {
+            return { error: ts.createCompilerDiagnostic(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) };
+        }
+    }
+    ts.parseConfigFileText = parseConfigFileText;
+    function parseConfigFile(json, host, basePath) {
+        var errors = [];
+        return {
+            options: getCompilerOptions(),
+            fileNames: getFiles(),
+            errors: errors
+        };
+        function getCompilerOptions() {
+            var options = {};
+            var optionNameMap = {};
+            ts.forEach(ts.optionDeclarations, function (option) {
+                optionNameMap[option.name] = option;
+            });
+            var jsonOptions = json["compilerOptions"];
+            if (jsonOptions) {
+                for (var id in jsonOptions) {
+                    if (ts.hasProperty(optionNameMap, id)) {
+                        var opt = optionNameMap[id];
+                        var optType = opt.type;
+                        var value = jsonOptions[id];
+                        var expectedType = typeof optType === "string" ? optType : "string";
+                        if (typeof value === expectedType) {
+                            if (typeof optType !== "string") {
+                                var key = value.toLowerCase();
+                                if (ts.hasProperty(optType, key)) {
+                                    value = optType[key];
+                                }
+                                else {
+                                    errors.push(ts.createCompilerDiagnostic(opt.error));
+                                    value = 0;
+                                }
+                            }
+                            if (opt.isFilePath) {
+                                value = ts.normalizePath(ts.combinePaths(basePath, value));
+                            }
+                            options[opt.name] = value;
+                        }
+                        else {
+                            errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
+                        }
+                    }
+                    else {
+                        errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_compiler_option_0, id));
+                    }
+                }
+            }
+            return options;
+        }
+        function getFiles() {
+            var files = [];
+            if (ts.hasProperty(json, "files")) {
+                if (json["files"] instanceof Array) {
+                    var files = ts.map(json["files"], function (s) { return ts.combinePaths(basePath, s); });
+                }
+            }
+            else {
+                var sysFiles = host.readDirectory(basePath, ".ts");
+                for (var i = 0; i < sysFiles.length; i++) {
+                    var name = sysFiles[i];
+                    if (!ts.fileExtensionIs(name, ".d.ts") || !ts.contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
+                        files.push(name);
+                    }
+                }
+            }
+            return files;
+        }
+    }
+    ts.parseConfigFile = parseConfigFile;
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/core.js b/dist/typescript/compiler/core.js
new file mode 100644
index 000000000..a7758e3d9
--- /dev/null
+++ b/dist/typescript/compiler/core.js
@@ -0,0 +1,652 @@
+/// <reference path="types.ts"/>
+var ts;
+(function (ts) {
+    (function (Ternary) {
+        Ternary[Ternary["False"] = 0] = "False";
+        Ternary[Ternary["Maybe"] = 1] = "Maybe";
+        Ternary[Ternary["True"] = -1] = "True";
+    })(ts.Ternary || (ts.Ternary = {}));
+    var Ternary = ts.Ternary;
+    (function (Comparison) {
+        Comparison[Comparison["LessThan"] = -1] = "LessThan";
+        Comparison[Comparison["EqualTo"] = 0] = "EqualTo";
+        Comparison[Comparison["GreaterThan"] = 1] = "GreaterThan";
+    })(ts.Comparison || (ts.Comparison = {}));
+    var Comparison = ts.Comparison;
+    function forEach(array, callback) {
+        if (array) {
+            for (var i = 0, len = array.length; i < len; i++) {
+                var result = callback(array[i], i);
+                if (result) {
+                    return result;
+                }
+            }
+        }
+        return undefined;
+    }
+    ts.forEach = forEach;
+    function contains(array, value) {
+        if (array) {
+            for (var _i = 0; _i < array.length; _i++) {
+                var v = array[_i];
+                if (v === value) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    ts.contains = contains;
+    function indexOf(array, value) {
+        if (array) {
+            for (var i = 0, len = array.length; i < len; i++) {
+                if (array[i] === value) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+    ts.indexOf = indexOf;
+    function countWhere(array, predicate) {
+        var count = 0;
+        if (array) {
+            for (var _i = 0; _i < array.length; _i++) {
+                var v = array[_i];
+                if (predicate(v)) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+    ts.countWhere = countWhere;
+    function filter(array, f) {
+        var result;
+        if (array) {
+            result = [];
+            for (var _i = 0; _i < array.length; _i++) {
+                var item_1 = array[_i];
+                if (f(item_1)) {
+                    result.push(item_1);
+                }
+            }
+        }
+        return result;
+    }
+    ts.filter = filter;
+    function map(array, f) {
+        var result;
+        if (array) {
+            result = [];
+            for (var _i = 0; _i < array.length; _i++) {
+                var v = array[_i];
+                result.push(f(v));
+            }
+        }
+        return result;
+    }
+    ts.map = map;
+    function concatenate(array1, array2) {
+        if (!array2 || !array2.length)
+            return array1;
+        if (!array1 || !array1.length)
+            return array2;
+        return array1.concat(array2);
+    }
+    ts.concatenate = concatenate;
+    function deduplicate(array) {
+        var result;
+        if (array) {
+            result = [];
+            for (var _i = 0; _i < array.length; _i++) {
+                var item_2 = array[_i];
+                if (!contains(result, item_2)) {
+                    result.push(item_2);
+                }
+            }
+        }
+        return result;
+    }
+    ts.deduplicate = deduplicate;
+    function sum(array, prop) {
+        var result = 0;
+        for (var _i = 0; _i < array.length; _i++) {
+            var v = array[_i];
+            result += v[prop];
+        }
+        return result;
+    }
+    ts.sum = sum;
+    function addRange(to, from) {
+        if (to && from) {
+            for (var _i = 0; _i < from.length; _i++) {
+                var v = from[_i];
+                to.push(v);
+            }
+        }
+    }
+    ts.addRange = addRange;
+    function lastOrUndefined(array) {
+        if (array.length === 0) {
+            return undefined;
+        }
+        return array[array.length - 1];
+    }
+    ts.lastOrUndefined = lastOrUndefined;
+    function binarySearch(array, value) {
+        var low = 0;
+        var high = array.length - 1;
+        while (low <= high) {
+            var middle = low + ((high - low) >> 1);
+            var midValue = array[middle];
+            if (midValue === value) {
+                return middle;
+            }
+            else if (midValue > value) {
+                high = middle - 1;
+            }
+            else {
+                low = middle + 1;
+            }
+        }
+        return ~low;
+    }
+    ts.binarySearch = binarySearch;
+    function reduceLeft(array, f, initial) {
+        if (array) {
+            var count = array.length;
+            if (count > 0) {
+                var pos = 0;
+                var result = arguments.length <= 2 ? array[pos++] : initial;
+                while (pos < count) {
+                    result = f(result, array[pos++]);
+                }
+                return result;
+            }
+        }
+        return initial;
+    }
+    ts.reduceLeft = reduceLeft;
+    function reduceRight(array, f, initial) {
+        if (array) {
+            var pos = array.length - 1;
+            if (pos >= 0) {
+                var result = arguments.length <= 2 ? array[pos--] : initial;
+                while (pos >= 0) {
+                    result = f(result, array[pos--]);
+                }
+                return result;
+            }
+        }
+        return initial;
+    }
+    ts.reduceRight = reduceRight;
+    var hasOwnProperty = Object.prototype.hasOwnProperty;
+    function hasProperty(map, key) {
+        return hasOwnProperty.call(map, key);
+    }
+    ts.hasProperty = hasProperty;
+    function getProperty(map, key) {
+        return hasOwnProperty.call(map, key) ? map[key] : undefined;
+    }
+    ts.getProperty = getProperty;
+    function isEmpty(map) {
+        for (var id in map) {
+            if (hasProperty(map, id)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    ts.isEmpty = isEmpty;
+    function clone(object) {
+        var result = {};
+        for (var id in object) {
+            result[id] = object[id];
+        }
+        return result;
+    }
+    ts.clone = clone;
+    function extend(first, second) {
+        var result = {};
+        for (var id in first) {
+            result[id] = first[id];
+        }
+        for (var id in second) {
+            if (!hasProperty(result, id)) {
+                result[id] = second[id];
+            }
+        }
+        return result;
+    }
+    ts.extend = extend;
+    function forEachValue(map, callback) {
+        var result;
+        for (var id in map) {
+            if (result = callback(map[id]))
+                break;
+        }
+        return result;
+    }
+    ts.forEachValue = forEachValue;
+    function forEachKey(map, callback) {
+        var result;
+        for (var id in map) {
+            if (result = callback(id))
+                break;
+        }
+        return result;
+    }
+    ts.forEachKey = forEachKey;
+    function lookUp(map, key) {
+        return hasProperty(map, key) ? map[key] : undefined;
+    }
+    ts.lookUp = lookUp;
+    function copyMap(source, target) {
+        for (var p in source) {
+            target[p] = source[p];
+        }
+    }
+    ts.copyMap = copyMap;
+    function arrayToMap(array, makeKey) {
+        var result = {};
+        forEach(array, function (value) {
+            result[makeKey(value)] = value;
+        });
+        return result;
+    }
+    ts.arrayToMap = arrayToMap;
+    function memoize(callback) {
+        var value;
+        return function () {
+            if (callback) {
+                value = callback();
+                callback = undefined;
+            }
+            return value;
+        };
+    }
+    ts.memoize = memoize;
+    function formatStringFromArgs(text, args, baseIndex) {
+        baseIndex = baseIndex || 0;
+        return text.replace(/{(\d+)}/g, function (match, index) { return args[+index + baseIndex]; });
+    }
+    ts.localizedDiagnosticMessages = undefined;
+    function getLocaleSpecificMessage(message) {
+        return ts.localizedDiagnosticMessages && ts.localizedDiagnosticMessages[message]
+            ? ts.localizedDiagnosticMessages[message]
+            : message;
+    }
+    ts.getLocaleSpecificMessage = getLocaleSpecificMessage;
+    function createFileDiagnostic(file, start, length, message) {
+        var end = start + length;
+        Debug.assert(start >= 0, "start must be non-negative, is " + start);
+        Debug.assert(length >= 0, "length must be non-negative, is " + length);
+        Debug.assert(start <= file.text.length, "start must be within the bounds of the file. " + start + " > " + file.text.length);
+        Debug.assert(end <= file.text.length, "end must be the bounds of the file. " + end + " > " + file.text.length);
+        var text = getLocaleSpecificMessage(message.key);
+        if (arguments.length > 4) {
+            text = formatStringFromArgs(text, arguments, 4);
+        }
+        return {
+            file: file,
+            start: start,
+            length: length,
+            messageText: text,
+            category: message.category,
+            code: message.code,
+        };
+    }
+    ts.createFileDiagnostic = createFileDiagnostic;
+    function createCompilerDiagnostic(message) {
+        var text = getLocaleSpecificMessage(message.key);
+        if (arguments.length > 1) {
+            text = formatStringFromArgs(text, arguments, 1);
+        }
+        return {
+            file: undefined,
+            start: undefined,
+            length: undefined,
+            messageText: text,
+            category: message.category,
+            code: message.code
+        };
+    }
+    ts.createCompilerDiagnostic = createCompilerDiagnostic;
+    function chainDiagnosticMessages(details, message) {
+        var text = getLocaleSpecificMessage(message.key);
+        if (arguments.length > 2) {
+            text = formatStringFromArgs(text, arguments, 2);
+        }
+        return {
+            messageText: text,
+            category: message.category,
+            code: message.code,
+            next: details
+        };
+    }
+    ts.chainDiagnosticMessages = chainDiagnosticMessages;
+    function concatenateDiagnosticMessageChains(headChain, tailChain) {
+        Debug.assert(!headChain.next);
+        headChain.next = tailChain;
+        return headChain;
+    }
+    ts.concatenateDiagnosticMessageChains = concatenateDiagnosticMessageChains;
+    function compareValues(a, b) {
+        if (a === b)
+            return 0;
+        if (a === undefined)
+            return -1;
+        if (b === undefined)
+            return 1;
+        return a < b ? -1 : 1;
+    }
+    ts.compareValues = compareValues;
+    function getDiagnosticFileName(diagnostic) {
+        return diagnostic.file ? diagnostic.file.fileName : undefined;
+    }
+    function compareDiagnostics(d1, d2) {
+        return compareValues(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) ||
+            compareValues(d1.start, d2.start) ||
+            compareValues(d1.length, d2.length) ||
+            compareValues(d1.code, d2.code) ||
+            compareMessageText(d1.messageText, d2.messageText) ||
+            0;
+    }
+    ts.compareDiagnostics = compareDiagnostics;
+    function compareMessageText(text1, text2) {
+        while (text1 && text2) {
+            var string1 = typeof text1 === "string" ? text1 : text1.messageText;
+            var string2 = typeof text2 === "string" ? text2 : text2.messageText;
+            var res = compareValues(string1, string2);
+            if (res) {
+                return res;
+            }
+            text1 = typeof text1 === "string" ? undefined : text1.next;
+            text2 = typeof text2 === "string" ? undefined : text2.next;
+        }
+        if (!text1 && !text2) {
+            return 0;
+        }
+        return text1 ? 1 : -1;
+    }
+    function sortAndDeduplicateDiagnostics(diagnostics) {
+        return deduplicateSortedDiagnostics(diagnostics.sort(compareDiagnostics));
+    }
+    ts.sortAndDeduplicateDiagnostics = sortAndDeduplicateDiagnostics;
+    function deduplicateSortedDiagnostics(diagnostics) {
+        if (diagnostics.length < 2) {
+            return diagnostics;
+        }
+        var newDiagnostics = [diagnostics[0]];
+        var previousDiagnostic = diagnostics[0];
+        for (var i = 1; i < diagnostics.length; i++) {
+            var currentDiagnostic = diagnostics[i];
+            var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === 0;
+            if (!isDupe) {
+                newDiagnostics.push(currentDiagnostic);
+                previousDiagnostic = currentDiagnostic;
+            }
+        }
+        return newDiagnostics;
+    }
+    ts.deduplicateSortedDiagnostics = deduplicateSortedDiagnostics;
+    function normalizeSlashes(path) {
+        return path.replace(/\\/g, "/");
+    }
+    ts.normalizeSlashes = normalizeSlashes;
+    function getRootLength(path) {
+        if (path.charCodeAt(0) === 47) {
+            if (path.charCodeAt(1) !== 47)
+                return 1;
+            var p1 = path.indexOf("/", 2);
+            if (p1 < 0)
+                return 2;
+            var p2 = path.indexOf("/", p1 + 1);
+            if (p2 < 0)
+                return p1 + 1;
+            return p2 + 1;
+        }
+        if (path.charCodeAt(1) === 58) {
+            if (path.charCodeAt(2) === 47)
+                return 3;
+            return 2;
+        }
+        var idx = path.indexOf('://');
+        if (idx !== -1)
+            return idx + 3;
+        return 0;
+    }
+    ts.getRootLength = getRootLength;
+    ts.directorySeparator = "/";
+    function getNormalizedParts(normalizedSlashedPath, rootLength) {
+        var parts = normalizedSlashedPath.substr(rootLength).split(ts.directorySeparator);
+        var normalized = [];
+        for (var _i = 0; _i < parts.length; _i++) {
+            var part = parts[_i];
+            if (part !== ".") {
+                if (part === ".." && normalized.length > 0 && normalized[normalized.length - 1] !== "..") {
+                    normalized.pop();
+                }
+                else {
+                    if (part) {
+                        normalized.push(part);
+                    }
+                }
+            }
+        }
+        return normalized;
+    }
+    function normalizePath(path) {
+        path = normalizeSlashes(path);
+        var rootLength = getRootLength(path);
+        var normalized = getNormalizedParts(path, rootLength);
+        return path.substr(0, rootLength) + normalized.join(ts.directorySeparator);
+    }
+    ts.normalizePath = normalizePath;
+    function getDirectoryPath(path) {
+        return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(ts.directorySeparator)));
+    }
+    ts.getDirectoryPath = getDirectoryPath;
+    function isUrl(path) {
+        return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1;
+    }
+    ts.isUrl = isUrl;
+    function isRootedDiskPath(path) {
+        return getRootLength(path) !== 0;
+    }
+    ts.isRootedDiskPath = isRootedDiskPath;
+    function normalizedPathComponents(path, rootLength) {
+        var normalizedParts = getNormalizedParts(path, rootLength);
+        return [path.substr(0, rootLength)].concat(normalizedParts);
+    }
+    function getNormalizedPathComponents(path, currentDirectory) {
+        path = normalizeSlashes(path);
+        var rootLength = getRootLength(path);
+        if (rootLength == 0) {
+            path = combinePaths(normalizeSlashes(currentDirectory), path);
+            rootLength = getRootLength(path);
+        }
+        return normalizedPathComponents(path, rootLength);
+    }
+    ts.getNormalizedPathComponents = getNormalizedPathComponents;
+    function getNormalizedAbsolutePath(fileName, currentDirectory) {
+        return getNormalizedPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory));
+    }
+    ts.getNormalizedAbsolutePath = getNormalizedAbsolutePath;
+    function getNormalizedPathFromPathComponents(pathComponents) {
+        if (pathComponents && pathComponents.length) {
+            return pathComponents[0] + pathComponents.slice(1).join(ts.directorySeparator);
+        }
+    }
+    ts.getNormalizedPathFromPathComponents = getNormalizedPathFromPathComponents;
+    function getNormalizedPathComponentsOfUrl(url) {
+        // Get root length of http://www.website.com/folder1/foler2/
+        // In this example the root is:  http://www.website.com/ 
+        // normalized path components should be ["http://www.website.com/", "folder1", "folder2"]
+        var urlLength = url.length;
+        var rootLength = url.indexOf("://") + "://".length;
+        while (rootLength < urlLength) {
+            if (url.charCodeAt(rootLength) === 47) {
+                rootLength++;
+            }
+            else {
+                break;
+            }
+        }
+        if (rootLength === urlLength) {
+            return [url];
+        }
+        var indexOfNextSlash = url.indexOf(ts.directorySeparator, rootLength);
+        if (indexOfNextSlash !== -1) {
+            rootLength = indexOfNextSlash + 1;
+            return normalizedPathComponents(url, rootLength);
+        }
+        else {
+            return [url + ts.directorySeparator];
+        }
+    }
+    function getNormalizedPathOrUrlComponents(pathOrUrl, currentDirectory) {
+        if (isUrl(pathOrUrl)) {
+            return getNormalizedPathComponentsOfUrl(pathOrUrl);
+        }
+        else {
+            return getNormalizedPathComponents(pathOrUrl, currentDirectory);
+        }
+    }
+    function getRelativePathToDirectoryOrUrl(directoryPathOrUrl, relativeOrAbsolutePath, currentDirectory, getCanonicalFileName, isAbsolutePathAnUrl) {
+        var pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
+        var directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
+        if (directoryComponents.length > 1 && directoryComponents[directoryComponents.length - 1] === "") {
+            directoryComponents.length--;
+        }
+        for (var joinStartIndex = 0; joinStartIndex < pathComponents.length && joinStartIndex < directoryComponents.length; joinStartIndex++) {
+            if (getCanonicalFileName(directoryComponents[joinStartIndex]) !== getCanonicalFileName(pathComponents[joinStartIndex])) {
+                break;
+            }
+        }
+        if (joinStartIndex) {
+            var relativePath = "";
+            var relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
+            for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
+                if (directoryComponents[joinStartIndex] !== "") {
+                    relativePath = relativePath + ".." + ts.directorySeparator;
+                }
+            }
+            return relativePath + relativePathComponents.join(ts.directorySeparator);
+        }
+        var absolutePath = getNormalizedPathFromPathComponents(pathComponents);
+        if (isAbsolutePathAnUrl && isRootedDiskPath(absolutePath)) {
+            absolutePath = "file:///" + absolutePath;
+        }
+        return absolutePath;
+    }
+    ts.getRelativePathToDirectoryOrUrl = getRelativePathToDirectoryOrUrl;
+    function getBaseFileName(path) {
+        var i = path.lastIndexOf(ts.directorySeparator);
+        return i < 0 ? path : path.substring(i + 1);
+    }
+    ts.getBaseFileName = getBaseFileName;
+    function combinePaths(path1, path2) {
+        if (!(path1 && path1.length))
+            return path2;
+        if (!(path2 && path2.length))
+            return path1;
+        if (getRootLength(path2) !== 0)
+            return path2;
+        if (path1.charAt(path1.length - 1) === ts.directorySeparator)
+            return path1 + path2;
+        return path1 + ts.directorySeparator + path2;
+    }
+    ts.combinePaths = combinePaths;
+    function fileExtensionIs(path, extension) {
+        var pathLen = path.length;
+        var extLen = extension.length;
+        return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
+    }
+    ts.fileExtensionIs = fileExtensionIs;
+    var supportedExtensions = [".d.ts", ".ts", ".js"];
+    function removeFileExtension(path) {
+        for (var _i = 0; _i < supportedExtensions.length; _i++) {
+            var ext = supportedExtensions[_i];
+            if (fileExtensionIs(path, ext)) {
+                return path.substr(0, path.length - ext.length);
+            }
+        }
+        return path;
+    }
+    ts.removeFileExtension = removeFileExtension;
+    var backslashOrDoubleQuote = /[\"\\]/g;
+    var escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
+    var escapedCharsMap = {
+        "\0": "\\0",
+        "\t": "\\t",
+        "\v": "\\v",
+        "\f": "\\f",
+        "\b": "\\b",
+        "\r": "\\r",
+        "\n": "\\n",
+        "\\": "\\\\",
+        "\"": "\\\"",
+        "\u2028": "\\u2028",
+        "\u2029": "\\u2029",
+        "\u0085": "\\u0085"
+    };
+    function Symbol(flags, name) {
+        this.flags = flags;
+        this.name = name;
+        this.declarations = undefined;
+    }
+    function Type(checker, flags) {
+        this.flags = flags;
+    }
+    function Signature(checker) {
+    }
+    ts.objectAllocator = {
+        getNodeConstructor: function (kind) {
+            function Node() {
+            }
+            Node.prototype = {
+                kind: kind,
+                pos: 0,
+                end: 0,
+                flags: 0,
+                parent: undefined,
+            };
+            return Node;
+        },
+        getSymbolConstructor: function () { return Symbol; },
+        getTypeConstructor: function () { return Type; },
+        getSignatureConstructor: function () { return Signature; }
+    };
+    (function (AssertionLevel) {
+        AssertionLevel[AssertionLevel["None"] = 0] = "None";
+        AssertionLevel[AssertionLevel["Normal"] = 1] = "Normal";
+        AssertionLevel[AssertionLevel["Aggressive"] = 2] = "Aggressive";
+        AssertionLevel[AssertionLevel["VeryAggressive"] = 3] = "VeryAggressive";
+    })(ts.AssertionLevel || (ts.AssertionLevel = {}));
+    var AssertionLevel = ts.AssertionLevel;
+    var Debug;
+    (function (Debug) {
+        var currentAssertionLevel = 0;
+        function shouldAssert(level) {
+            return currentAssertionLevel >= level;
+        }
+        Debug.shouldAssert = shouldAssert;
+        function assert(expression, message, verboseDebugInfo) {
+            if (!expression) {
+                var verboseDebugString = "";
+                if (verboseDebugInfo) {
+                    verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
+                }
+                throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString);
+            }
+        }
+        Debug.assert = assert;
+        function fail(message) {
+            Debug.assert(false, message);
+        }
+        Debug.fail = fail;
+    })(Debug = ts.Debug || (ts.Debug = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/declarationEmitter.js b/dist/typescript/compiler/declarationEmitter.js
new file mode 100644
index 000000000..f7f993023
--- /dev/null
+++ b/dist/typescript/compiler/declarationEmitter.js
@@ -0,0 +1,1300 @@
+/// <reference path="checker.ts"/>
+var ts;
+(function (ts) {
+    function getDeclarationDiagnostics(host, resolver, targetSourceFile) {
+        var diagnostics = [];
+        var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
+        emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
+        return diagnostics;
+    }
+    ts.getDeclarationDiagnostics = getDeclarationDiagnostics;
+    function emitDeclarations(host, resolver, diagnostics, jsFilePath, root) {
+        var newLine = host.getNewLine();
+        var compilerOptions = host.getCompilerOptions();
+        var languageVersion = compilerOptions.target || 0;
+        var write;
+        var writeLine;
+        var increaseIndent;
+        var decreaseIndent;
+        var writeTextOfNode;
+        var writer = createAndSetNewTextWriterWithSymbolWriter();
+        var enclosingDeclaration;
+        var currentSourceFile;
+        var reportedDeclarationError = false;
+        var emitJsDocComments = compilerOptions.removeComments ? function (declaration) { } : writeJsDocComments;
+        var emit = compilerOptions.stripInternal ? stripInternal : emitNode;
+        var moduleElementDeclarationEmitInfo = [];
+        var asynchronousSubModuleDeclarationEmitInfo;
+        var referencePathsOutput = "";
+        if (root) {
+            if (!compilerOptions.noResolve) {
+                var addedGlobalFileReference = false;
+                ts.forEach(root.referencedFiles, function (fileReference) {
+                    var referencedFile = ts.tryResolveScriptReference(host, root, fileReference);
+                    if (referencedFile && ((referencedFile.flags & 2048) ||
+                        ts.shouldEmitToOwnFile(referencedFile, compilerOptions) ||
+                        !addedGlobalFileReference)) {
+                        writeReferencePath(referencedFile);
+                        if (!ts.isExternalModuleOrDeclarationFile(referencedFile)) {
+                            addedGlobalFileReference = true;
+                        }
+                    }
+                });
+            }
+            emitSourceFile(root);
+            if (moduleElementDeclarationEmitInfo.length) {
+                var oldWriter = writer;
+                ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) {
+                    if (aliasEmitInfo.isVisible) {
+                        ts.Debug.assert(aliasEmitInfo.node.kind === 209);
+                        createAndSetNewTextWriterWithSymbolWriter();
+                        ts.Debug.assert(aliasEmitInfo.indent === 0);
+                        writeImportDeclaration(aliasEmitInfo.node);
+                        aliasEmitInfo.asynchronousOutput = writer.getText();
+                    }
+                });
+                setWriter(oldWriter);
+            }
+        }
+        else {
+            var emittedReferencedFiles = [];
+            ts.forEach(host.getSourceFiles(), function (sourceFile) {
+                if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) {
+                    if (!compilerOptions.noResolve) {
+                        ts.forEach(sourceFile.referencedFiles, function (fileReference) {
+                            var referencedFile = ts.tryResolveScriptReference(host, sourceFile, fileReference);
+                            if (referencedFile && (ts.isExternalModuleOrDeclarationFile(referencedFile) &&
+                                !ts.contains(emittedReferencedFiles, referencedFile))) {
+                                writeReferencePath(referencedFile);
+                                emittedReferencedFiles.push(referencedFile);
+                            }
+                        });
+                    }
+                    emitSourceFile(sourceFile);
+                }
+            });
+        }
+        return {
+            reportedDeclarationError: reportedDeclarationError,
+            moduleElementDeclarationEmitInfo: moduleElementDeclarationEmitInfo,
+            synchronousDeclarationOutput: writer.getText(),
+            referencePathsOutput: referencePathsOutput,
+        };
+        function hasInternalAnnotation(range) {
+            var text = currentSourceFile.text;
+            var comment = text.substring(range.pos, range.end);
+            return comment.indexOf("@internal") >= 0;
+        }
+        function stripInternal(node) {
+            if (node) {
+                var leadingCommentRanges = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos);
+                if (ts.forEach(leadingCommentRanges, hasInternalAnnotation)) {
+                    return;
+                }
+                emitNode(node);
+            }
+        }
+        function createAndSetNewTextWriterWithSymbolWriter() {
+            var writer = ts.createTextWriter(newLine);
+            writer.trackSymbol = trackSymbol;
+            writer.writeKeyword = writer.write;
+            writer.writeOperator = writer.write;
+            writer.writePunctuation = writer.write;
+            writer.writeSpace = writer.write;
+            writer.writeStringLiteral = writer.writeLiteral;
+            writer.writeParameter = writer.write;
+            writer.writeSymbol = writer.write;
+            setWriter(writer);
+            return writer;
+        }
+        function setWriter(newWriter) {
+            writer = newWriter;
+            write = newWriter.write;
+            writeTextOfNode = newWriter.writeTextOfNode;
+            writeLine = newWriter.writeLine;
+            increaseIndent = newWriter.increaseIndent;
+            decreaseIndent = newWriter.decreaseIndent;
+        }
+        function writeAsynchronousModuleElements(nodes) {
+            var oldWriter = writer;
+            ts.forEach(nodes, function (declaration) {
+                var nodeToCheck;
+                if (declaration.kind === 198) {
+                    nodeToCheck = declaration.parent.parent;
+                }
+                else if (declaration.kind === 212 || declaration.kind === 213 || declaration.kind === 210) {
+                    ts.Debug.fail("We should be getting ImportDeclaration instead to write");
+                }
+                else {
+                    nodeToCheck = declaration;
+                }
+                var moduleElementEmitInfo = ts.forEach(moduleElementDeclarationEmitInfo, function (declEmitInfo) { return declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined; });
+                if (!moduleElementEmitInfo && asynchronousSubModuleDeclarationEmitInfo) {
+                    moduleElementEmitInfo = ts.forEach(asynchronousSubModuleDeclarationEmitInfo, function (declEmitInfo) { return declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined; });
+                }
+                if (moduleElementEmitInfo) {
+                    if (moduleElementEmitInfo.node.kind === 209) {
+                        moduleElementEmitInfo.isVisible = true;
+                    }
+                    else {
+                        createAndSetNewTextWriterWithSymbolWriter();
+                        for (var declarationIndent = moduleElementEmitInfo.indent; declarationIndent; declarationIndent--) {
+                            increaseIndent();
+                        }
+                        if (nodeToCheck.kind === 205) {
+                            ts.Debug.assert(asynchronousSubModuleDeclarationEmitInfo === undefined);
+                            asynchronousSubModuleDeclarationEmitInfo = [];
+                        }
+                        writeModuleElement(nodeToCheck);
+                        if (nodeToCheck.kind === 205) {
+                            moduleElementEmitInfo.subModuleElementDeclarationEmitInfo = asynchronousSubModuleDeclarationEmitInfo;
+                            asynchronousSubModuleDeclarationEmitInfo = undefined;
+                        }
+                        moduleElementEmitInfo.asynchronousOutput = writer.getText();
+                    }
+                }
+            });
+            setWriter(oldWriter);
+        }
+        function handleSymbolAccessibilityError(symbolAccesibilityResult) {
+            if (symbolAccesibilityResult.accessibility === 0) {
+                if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) {
+                    writeAsynchronousModuleElements(symbolAccesibilityResult.aliasesToMakeVisible);
+                }
+            }
+            else {
+                reportedDeclarationError = true;
+                var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult);
+                if (errorInfo) {
+                    if (errorInfo.typeName) {
+                        diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName));
+                    }
+                    else {
+                        diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName));
+                    }
+                }
+            }
+        }
+        function trackSymbol(symbol, enclosingDeclaration, meaning) {
+            handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning));
+        }
+        function writeTypeOfDeclaration(declaration, type, getSymbolAccessibilityDiagnostic) {
+            writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
+            write(": ");
+            if (type) {
+                emitType(type);
+            }
+            else {
+                resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, 2, writer);
+            }
+        }
+        function writeReturnTypeAtSignature(signature, getSymbolAccessibilityDiagnostic) {
+            writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
+            write(": ");
+            if (signature.type) {
+                emitType(signature.type);
+            }
+            else {
+                resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, 2, writer);
+            }
+        }
+        function emitLines(nodes) {
+            for (var _i = 0; _i < nodes.length; _i++) {
+                var node = nodes[_i];
+                emit(node);
+            }
+        }
+        function emitSeparatedList(nodes, separator, eachNodeEmitFn, canEmitFn) {
+            var currentWriterPos = writer.getTextPos();
+            for (var _i = 0; _i < nodes.length; _i++) {
+                var node = nodes[_i];
+                if (!canEmitFn || canEmitFn(node)) {
+                    if (currentWriterPos !== writer.getTextPos()) {
+                        write(separator);
+                    }
+                    currentWriterPos = writer.getTextPos();
+                    eachNodeEmitFn(node);
+                }
+            }
+        }
+        function emitCommaList(nodes, eachNodeEmitFn, canEmitFn) {
+            emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn);
+        }
+        function writeJsDocComments(declaration) {
+            if (declaration) {
+                var jsDocComments = ts.getJsDocComments(declaration, currentSourceFile);
+                ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments);
+                ts.emitComments(currentSourceFile, writer, jsDocComments, true, newLine, ts.writeCommentRange);
+            }
+        }
+        function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) {
+            writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
+            emitType(type);
+        }
+        function emitType(type) {
+            switch (type.kind) {
+                case 112:
+                case 121:
+                case 119:
+                case 113:
+                case 122:
+                case 99:
+                case 8:
+                    return writeTextOfNode(currentSourceFile, type);
+                case 177:
+                    return emitHeritageClauseElement(type);
+                case 141:
+                    return emitTypeReference(type);
+                case 144:
+                    return emitTypeQuery(type);
+                case 146:
+                    return emitArrayType(type);
+                case 147:
+                    return emitTupleType(type);
+                case 148:
+                    return emitUnionType(type);
+                case 149:
+                    return emitParenType(type);
+                case 142:
+                case 143:
+                    return emitSignatureDeclarationWithJsDocComments(type);
+                case 145:
+                    return emitTypeLiteral(type);
+                case 65:
+                    return emitEntityName(type);
+                case 126:
+                    return emitEntityName(type);
+            }
+            function emitEntityName(entityName) {
+                var visibilityResult = resolver.isEntityNameVisible(entityName, entityName.parent.kind === 208 ? entityName.parent : enclosingDeclaration);
+                handleSymbolAccessibilityError(visibilityResult);
+                writeEntityName(entityName);
+                function writeEntityName(entityName) {
+                    if (entityName.kind === 65) {
+                        writeTextOfNode(currentSourceFile, entityName);
+                    }
+                    else {
+                        var left = entityName.kind === 126 ? entityName.left : entityName.expression;
+                        var right = entityName.kind === 126 ? entityName.right : entityName.name;
+                        writeEntityName(left);
+                        write(".");
+                        writeTextOfNode(currentSourceFile, right);
+                    }
+                }
+            }
+            function emitHeritageClauseElement(node) {
+                if (ts.isSupportedHeritageClauseElement(node)) {
+                    ts.Debug.assert(node.expression.kind === 65 || node.expression.kind === 155);
+                    emitEntityName(node.expression);
+                    if (node.typeArguments) {
+                        write("<");
+                        emitCommaList(node.typeArguments, emitType);
+                        write(">");
+                    }
+                }
+            }
+            function emitTypeReference(type) {
+                emitEntityName(type.typeName);
+                if (type.typeArguments) {
+                    write("<");
+                    emitCommaList(type.typeArguments, emitType);
+                    write(">");
+                }
+            }
+            function emitTypeQuery(type) {
+                write("typeof ");
+                emitEntityName(type.exprName);
+            }
+            function emitArrayType(type) {
+                emitType(type.elementType);
+                write("[]");
+            }
+            function emitTupleType(type) {
+                write("[");
+                emitCommaList(type.elementTypes, emitType);
+                write("]");
+            }
+            function emitUnionType(type) {
+                emitSeparatedList(type.types, " | ", emitType);
+            }
+            function emitParenType(type) {
+                write("(");
+                emitType(type.type);
+                write(")");
+            }
+            function emitTypeLiteral(type) {
+                write("{");
+                if (type.members.length) {
+                    writeLine();
+                    increaseIndent();
+                    emitLines(type.members);
+                    decreaseIndent();
+                }
+                write("}");
+            }
+        }
+        function emitSourceFile(node) {
+            currentSourceFile = node;
+            enclosingDeclaration = node;
+            emitLines(node.statements);
+        }
+        function getExportDefaultTempVariableName() {
+            var baseName = "_default";
+            if (!ts.hasProperty(currentSourceFile.identifiers, baseName)) {
+                return baseName;
+            }
+            var count = 0;
+            while (true) {
+                var name_1 = baseName + "_" + (++count);
+                if (!ts.hasProperty(currentSourceFile.identifiers, name_1)) {
+                    return name_1;
+                }
+            }
+        }
+        function emitExportAssignment(node) {
+            if (node.expression.kind === 65) {
+                write(node.isExportEquals ? "export = " : "export default ");
+                writeTextOfNode(currentSourceFile, node.expression);
+            }
+            else {
+                var tempVarName = getExportDefaultTempVariableName();
+                write("declare var ");
+                write(tempVarName);
+                write(": ");
+                writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic;
+                resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, 2, writer);
+                write(";");
+                writeLine();
+                write(node.isExportEquals ? "export = " : "export default ");
+                write(tempVarName);
+            }
+            write(";");
+            writeLine();
+            if (node.expression.kind === 65) {
+                var nodes = resolver.collectLinkedAliases(node.expression);
+                writeAsynchronousModuleElements(nodes);
+            }
+            function getDefaultExportAccessibilityDiagnostic(diagnostic) {
+                return {
+                    diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
+                    errorNode: node
+                };
+            }
+        }
+        function isModuleElementVisible(node) {
+            return resolver.isDeclarationVisible(node);
+        }
+        function emitModuleElement(node, isModuleElementVisible) {
+            if (isModuleElementVisible) {
+                writeModuleElement(node);
+            }
+            else if (node.kind === 208 ||
+                (node.parent.kind === 227 && ts.isExternalModule(currentSourceFile))) {
+                var isVisible;
+                if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 227) {
+                    asynchronousSubModuleDeclarationEmitInfo.push({
+                        node: node,
+                        outputPos: writer.getTextPos(),
+                        indent: writer.getIndent(),
+                        isVisible: isVisible
+                    });
+                }
+                else {
+                    if (node.kind === 209) {
+                        var importDeclaration = node;
+                        if (importDeclaration.importClause) {
+                            isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) ||
+                                isVisibleNamedBinding(importDeclaration.importClause.namedBindings);
+                        }
+                    }
+                    moduleElementDeclarationEmitInfo.push({
+                        node: node,
+                        outputPos: writer.getTextPos(),
+                        indent: writer.getIndent(),
+                        isVisible: isVisible
+                    });
+                }
+            }
+        }
+        function writeModuleElement(node) {
+            switch (node.kind) {
+                case 200:
+                    return writeFunctionDeclaration(node);
+                case 180:
+                    return writeVariableStatement(node);
+                case 202:
+                    return writeInterfaceDeclaration(node);
+                case 201:
+                    return writeClassDeclaration(node);
+                case 203:
+                    return writeTypeAliasDeclaration(node);
+                case 204:
+                    return writeEnumDeclaration(node);
+                case 205:
+                    return writeModuleDeclaration(node);
+                case 208:
+                    return writeImportEqualsDeclaration(node);
+                case 209:
+                    return writeImportDeclaration(node);
+                default:
+                    ts.Debug.fail("Unknown symbol kind");
+            }
+        }
+        function emitModuleElementDeclarationFlags(node) {
+            if (node.parent === currentSourceFile) {
+                if (node.flags & 1) {
+                    write("export ");
+                }
+                if (node.flags & 256) {
+                    write("default ");
+                }
+                else if (node.kind !== 202) {
+                    write("declare ");
+                }
+            }
+        }
+        function emitClassMemberDeclarationFlags(node) {
+            if (node.flags & 32) {
+                write("private ");
+            }
+            else if (node.flags & 64) {
+                write("protected ");
+            }
+            if (node.flags & 128) {
+                write("static ");
+            }
+        }
+        function writeImportEqualsDeclaration(node) {
+            emitJsDocComments(node);
+            if (node.flags & 1) {
+                write("export ");
+            }
+            write("import ");
+            writeTextOfNode(currentSourceFile, node.name);
+            write(" = ");
+            if (ts.isInternalModuleImportEqualsDeclaration(node)) {
+                emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError);
+                write(";");
+            }
+            else {
+                write("require(");
+                writeTextOfNode(currentSourceFile, ts.getExternalModuleImportEqualsDeclarationExpression(node));
+                write(");");
+            }
+            writer.writeLine();
+            function getImportEntityNameVisibilityError(symbolAccesibilityResult) {
+                return {
+                    diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1,
+                    errorNode: node,
+                    typeName: node.name
+                };
+            }
+        }
+        function isVisibleNamedBinding(namedBindings) {
+            if (namedBindings) {
+                if (namedBindings.kind === 211) {
+                    return resolver.isDeclarationVisible(namedBindings);
+                }
+                else {
+                    return ts.forEach(namedBindings.elements, function (namedImport) { return resolver.isDeclarationVisible(namedImport); });
+                }
+            }
+        }
+        function writeImportDeclaration(node) {
+            if (!node.importClause && !(node.flags & 1)) {
+                return;
+            }
+            emitJsDocComments(node);
+            if (node.flags & 1) {
+                write("export ");
+            }
+            write("import ");
+            if (node.importClause) {
+                var currentWriterPos = writer.getTextPos();
+                if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) {
+                    writeTextOfNode(currentSourceFile, node.importClause.name);
+                }
+                if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) {
+                    if (currentWriterPos !== writer.getTextPos()) {
+                        write(", ");
+                    }
+                    if (node.importClause.namedBindings.kind === 211) {
+                        write("* as ");
+                        writeTextOfNode(currentSourceFile, node.importClause.namedBindings.name);
+                    }
+                    else {
+                        write("{ ");
+                        emitCommaList(node.importClause.namedBindings.elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible);
+                        write(" }");
+                    }
+                }
+                write(" from ");
+            }
+            writeTextOfNode(currentSourceFile, node.moduleSpecifier);
+            write(";");
+            writer.writeLine();
+        }
+        function emitImportOrExportSpecifier(node) {
+            if (node.propertyName) {
+                writeTextOfNode(currentSourceFile, node.propertyName);
+                write(" as ");
+            }
+            writeTextOfNode(currentSourceFile, node.name);
+        }
+        function emitExportSpecifier(node) {
+            emitImportOrExportSpecifier(node);
+            var nodes = resolver.collectLinkedAliases(node.propertyName || node.name);
+            writeAsynchronousModuleElements(nodes);
+        }
+        function emitExportDeclaration(node) {
+            emitJsDocComments(node);
+            write("export ");
+            if (node.exportClause) {
+                write("{ ");
+                emitCommaList(node.exportClause.elements, emitExportSpecifier);
+                write(" }");
+            }
+            else {
+                write("*");
+            }
+            if (node.moduleSpecifier) {
+                write(" from ");
+                writeTextOfNode(currentSourceFile, node.moduleSpecifier);
+            }
+            write(";");
+            writer.writeLine();
+        }
+        function writeModuleDeclaration(node) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("module ");
+            writeTextOfNode(currentSourceFile, node.name);
+            while (node.body.kind !== 206) {
+                node = node.body;
+                write(".");
+                writeTextOfNode(currentSourceFile, node.name);
+            }
+            var prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitLines(node.body.statements);
+            decreaseIndent();
+            write("}");
+            writeLine();
+            enclosingDeclaration = prevEnclosingDeclaration;
+        }
+        function writeTypeAliasDeclaration(node) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("type ");
+            writeTextOfNode(currentSourceFile, node.name);
+            write(" = ");
+            emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
+            write(";");
+            writeLine();
+            function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult) {
+                return {
+                    diagnosticMessage: ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
+                    errorNode: node.type,
+                    typeName: node.name
+                };
+            }
+        }
+        function writeEnumDeclaration(node) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            if (ts.isConst(node)) {
+                write("const ");
+            }
+            write("enum ");
+            writeTextOfNode(currentSourceFile, node.name);
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitLines(node.members);
+            decreaseIndent();
+            write("}");
+            writeLine();
+        }
+        function emitEnumMemberDeclaration(node) {
+            emitJsDocComments(node);
+            writeTextOfNode(currentSourceFile, node.name);
+            var enumMemberValue = resolver.getConstantValue(node);
+            if (enumMemberValue !== undefined) {
+                write(" = ");
+                write(enumMemberValue.toString());
+            }
+            write(",");
+            writeLine();
+        }
+        function isPrivateMethodTypeParameter(node) {
+            return node.parent.kind === 134 && (node.parent.flags & 32);
+        }
+        function emitTypeParameters(typeParameters) {
+            function emitTypeParameter(node) {
+                increaseIndent();
+                emitJsDocComments(node);
+                decreaseIndent();
+                writeTextOfNode(currentSourceFile, node.name);
+                if (node.constraint && !isPrivateMethodTypeParameter(node)) {
+                    write(" extends ");
+                    if (node.parent.kind === 142 ||
+                        node.parent.kind === 143 ||
+                        (node.parent.parent && node.parent.parent.kind === 145)) {
+                        ts.Debug.assert(node.parent.kind === 134 ||
+                            node.parent.kind === 133 ||
+                            node.parent.kind === 142 ||
+                            node.parent.kind === 143 ||
+                            node.parent.kind === 138 ||
+                            node.parent.kind === 139);
+                        emitType(node.constraint);
+                    }
+                    else {
+                        emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError);
+                    }
+                }
+                function getTypeParameterConstraintVisibilityError(symbolAccesibilityResult) {
+                    var diagnosticMessage;
+                    switch (node.parent.kind) {
+                        case 201:
+                            diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1;
+                            break;
+                        case 202:
+                            diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1;
+                            break;
+                        case 139:
+                            diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
+                            break;
+                        case 138:
+                            diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
+                            break;
+                        case 134:
+                        case 133:
+                            if (node.parent.flags & 128) {
+                                diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
+                            }
+                            else if (node.parent.parent.kind === 201) {
+                                diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
+                            }
+                            else {
+                                diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
+                            }
+                            break;
+                        case 200:
+                            diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1;
+                            break;
+                        default:
+                            ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind);
+                    }
+                    return {
+                        diagnosticMessage: diagnosticMessage,
+                        errorNode: node,
+                        typeName: node.name
+                    };
+                }
+            }
+            if (typeParameters) {
+                write("<");
+                emitCommaList(typeParameters, emitTypeParameter);
+                write(">");
+            }
+        }
+        function emitHeritageClause(typeReferences, isImplementsList) {
+            if (typeReferences) {
+                write(isImplementsList ? " implements " : " extends ");
+                emitCommaList(typeReferences, emitTypeOfTypeReference);
+            }
+            function emitTypeOfTypeReference(node) {
+                if (ts.isSupportedHeritageClauseElement(node)) {
+                    emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
+                }
+                function getHeritageClauseVisibilityError(symbolAccesibilityResult) {
+                    var diagnosticMessage;
+                    if (node.parent.parent.kind === 201) {
+                        diagnosticMessage = isImplementsList ?
+                            ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 :
+                            ts.Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
+                    }
+                    else {
+                        diagnosticMessage = ts.Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1;
+                    }
+                    return {
+                        diagnosticMessage: diagnosticMessage,
+                        errorNode: node,
+                        typeName: node.parent.parent.name
+                    };
+                }
+            }
+        }
+        function writeClassDeclaration(node) {
+            function emitParameterProperties(constructorDeclaration) {
+                if (constructorDeclaration) {
+                    ts.forEach(constructorDeclaration.parameters, function (param) {
+                        if (param.flags & 112) {
+                            emitPropertyDeclaration(param);
+                        }
+                    });
+                }
+            }
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("class ");
+            writeTextOfNode(currentSourceFile, node.name);
+            var prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+            emitTypeParameters(node.typeParameters);
+            var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
+            if (baseTypeNode) {
+                emitHeritageClause([baseTypeNode], false);
+            }
+            emitHeritageClause(ts.getClassImplementsHeritageClauseElements(node), true);
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitParameterProperties(ts.getFirstConstructorWithBody(node));
+            emitLines(node.members);
+            decreaseIndent();
+            write("}");
+            writeLine();
+            enclosingDeclaration = prevEnclosingDeclaration;
+        }
+        function writeInterfaceDeclaration(node) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("interface ");
+            writeTextOfNode(currentSourceFile, node.name);
+            var prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+            emitTypeParameters(node.typeParameters);
+            emitHeritageClause(ts.getInterfaceBaseTypeNodes(node), false);
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitLines(node.members);
+            decreaseIndent();
+            write("}");
+            writeLine();
+            enclosingDeclaration = prevEnclosingDeclaration;
+        }
+        function emitPropertyDeclaration(node) {
+            if (ts.hasDynamicName(node)) {
+                return;
+            }
+            emitJsDocComments(node);
+            emitClassMemberDeclarationFlags(node);
+            emitVariableDeclaration(node);
+            write(";");
+            writeLine();
+        }
+        function emitVariableDeclaration(node) {
+            if (node.kind !== 198 || resolver.isDeclarationVisible(node)) {
+                if (ts.isBindingPattern(node.name)) {
+                    emitBindingPattern(node.name);
+                }
+                else {
+                    writeTextOfNode(currentSourceFile, node.name);
+                    if ((node.kind === 132 || node.kind === 131) && ts.hasQuestionToken(node)) {
+                        write("?");
+                    }
+                    if ((node.kind === 132 || node.kind === 131) && node.parent.kind === 145) {
+                        emitTypeOfVariableDeclarationFromTypeLiteral(node);
+                    }
+                    else if (!(node.flags & 32)) {
+                        writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError);
+                    }
+                }
+            }
+            function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult) {
+                if (node.kind === 198) {
+                    return symbolAccesibilityResult.errorModuleName ?
+                        symbolAccesibilityResult.accessibility === 2 ?
+                            ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                            ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 :
+                        ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1;
+                }
+                else if (node.kind === 132 || node.kind === 131) {
+                    if (node.flags & 128) {
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === 2 ?
+                                ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1;
+                    }
+                    else if (node.parent.kind === 201) {
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === 2 ?
+                                ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1;
+                    }
+                    else {
+                        return symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1;
+                    }
+                }
+            }
+            function getVariableDeclarationTypeVisibilityError(symbolAccesibilityResult) {
+                var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                return diagnosticMessage !== undefined ? {
+                    diagnosticMessage: diagnosticMessage,
+                    errorNode: node,
+                    typeName: node.name
+                } : undefined;
+            }
+            function emitBindingPattern(bindingPattern) {
+                var elements = [];
+                for (var _i = 0, _a = bindingPattern.elements; _i < _a.length; _i++) {
+                    var element = _a[_i];
+                    if (element.kind !== 175) {
+                        elements.push(element);
+                    }
+                }
+                emitCommaList(elements, emitBindingElement);
+            }
+            function emitBindingElement(bindingElement) {
+                function getBindingElementTypeVisibilityError(symbolAccesibilityResult) {
+                    var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                    return diagnosticMessage !== undefined ? {
+                        diagnosticMessage: diagnosticMessage,
+                        errorNode: bindingElement,
+                        typeName: bindingElement.name
+                    } : undefined;
+                }
+                if (bindingElement.name) {
+                    if (ts.isBindingPattern(bindingElement.name)) {
+                        emitBindingPattern(bindingElement.name);
+                    }
+                    else {
+                        writeTextOfNode(currentSourceFile, bindingElement.name);
+                        writeTypeOfDeclaration(bindingElement, undefined, getBindingElementTypeVisibilityError);
+                    }
+                }
+            }
+        }
+        function emitTypeOfVariableDeclarationFromTypeLiteral(node) {
+            if (node.type) {
+                write(": ");
+                emitType(node.type);
+            }
+        }
+        function isVariableStatementVisible(node) {
+            return ts.forEach(node.declarationList.declarations, function (varDeclaration) { return resolver.isDeclarationVisible(varDeclaration); });
+        }
+        function writeVariableStatement(node) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            if (ts.isLet(node.declarationList)) {
+                write("let ");
+            }
+            else if (ts.isConst(node.declarationList)) {
+                write("const ");
+            }
+            else {
+                write("var ");
+            }
+            emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
+            write(";");
+            writeLine();
+        }
+        function emitAccessorDeclaration(node) {
+            if (ts.hasDynamicName(node)) {
+                return;
+            }
+            var accessors = ts.getAllAccessorDeclarations(node.parent.members, node);
+            var accessorWithTypeAnnotation;
+            if (node === accessors.firstAccessor) {
+                emitJsDocComments(accessors.getAccessor);
+                emitJsDocComments(accessors.setAccessor);
+                emitClassMemberDeclarationFlags(node);
+                writeTextOfNode(currentSourceFile, node.name);
+                if (!(node.flags & 32)) {
+                    accessorWithTypeAnnotation = node;
+                    var type = getTypeAnnotationFromAccessor(node);
+                    if (!type) {
+                        var anotherAccessor = node.kind === 136 ? accessors.setAccessor : accessors.getAccessor;
+                        type = getTypeAnnotationFromAccessor(anotherAccessor);
+                        if (type) {
+                            accessorWithTypeAnnotation = anotherAccessor;
+                        }
+                    }
+                    writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError);
+                }
+                write(";");
+                writeLine();
+            }
+            function getTypeAnnotationFromAccessor(accessor) {
+                if (accessor) {
+                    return accessor.kind === 136
+                        ? accessor.type
+                        : accessor.parameters.length > 0
+                            ? accessor.parameters[0].type
+                            : undefined;
+                }
+            }
+            function getAccessorDeclarationTypeVisibilityError(symbolAccesibilityResult) {
+                var diagnosticMessage;
+                if (accessorWithTypeAnnotation.kind === 137) {
+                    if (accessorWithTypeAnnotation.parent.flags & 128) {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1;
+                    }
+                    else {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1;
+                    }
+                    return {
+                        diagnosticMessage: diagnosticMessage,
+                        errorNode: accessorWithTypeAnnotation.parameters[0],
+                        typeName: accessorWithTypeAnnotation.name
+                    };
+                }
+                else {
+                    if (accessorWithTypeAnnotation.flags & 128) {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === 2 ?
+                                ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                            ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0;
+                    }
+                    else {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === 2 ?
+                                ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                            ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0;
+                    }
+                    return {
+                        diagnosticMessage: diagnosticMessage,
+                        errorNode: accessorWithTypeAnnotation.name,
+                        typeName: undefined
+                    };
+                }
+            }
+        }
+        function writeFunctionDeclaration(node) {
+            if (ts.hasDynamicName(node)) {
+                return;
+            }
+            if (!resolver.isImplementationOfOverload(node)) {
+                emitJsDocComments(node);
+                if (node.kind === 200) {
+                    emitModuleElementDeclarationFlags(node);
+                }
+                else if (node.kind === 134) {
+                    emitClassMemberDeclarationFlags(node);
+                }
+                if (node.kind === 200) {
+                    write("function ");
+                    writeTextOfNode(currentSourceFile, node.name);
+                }
+                else if (node.kind === 135) {
+                    write("constructor");
+                }
+                else {
+                    writeTextOfNode(currentSourceFile, node.name);
+                    if (ts.hasQuestionToken(node)) {
+                        write("?");
+                    }
+                }
+                emitSignatureDeclaration(node);
+            }
+        }
+        function emitSignatureDeclarationWithJsDocComments(node) {
+            emitJsDocComments(node);
+            emitSignatureDeclaration(node);
+        }
+        function emitSignatureDeclaration(node) {
+            if (node.kind === 139 || node.kind === 143) {
+                write("new ");
+            }
+            emitTypeParameters(node.typeParameters);
+            if (node.kind === 140) {
+                write("[");
+            }
+            else {
+                write("(");
+            }
+            var prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+            emitCommaList(node.parameters, emitParameterDeclaration);
+            if (node.kind === 140) {
+                write("]");
+            }
+            else {
+                write(")");
+            }
+            var isFunctionTypeOrConstructorType = node.kind === 142 || node.kind === 143;
+            if (isFunctionTypeOrConstructorType || node.parent.kind === 145) {
+                if (node.type) {
+                    write(isFunctionTypeOrConstructorType ? " => " : ": ");
+                    emitType(node.type);
+                }
+            }
+            else if (node.kind !== 135 && !(node.flags & 32)) {
+                writeReturnTypeAtSignature(node, getReturnTypeVisibilityError);
+            }
+            enclosingDeclaration = prevEnclosingDeclaration;
+            if (!isFunctionTypeOrConstructorType) {
+                write(";");
+                writeLine();
+            }
+            function getReturnTypeVisibilityError(symbolAccesibilityResult) {
+                var diagnosticMessage;
+                switch (node.kind) {
+                    case 139:
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                            ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0;
+                        break;
+                    case 138:
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                            ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0;
+                        break;
+                    case 140:
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                            ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0;
+                        break;
+                    case 134:
+                    case 133:
+                        if (node.flags & 128) {
+                            diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === 2 ?
+                                    ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                    ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                                ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0;
+                        }
+                        else if (node.parent.kind === 201) {
+                            diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === 2 ?
+                                    ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                    ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                                ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0;
+                        }
+                        else {
+                            diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                                ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                                ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0;
+                        }
+                        break;
+                    case 200:
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === 2 ?
+                                ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 :
+                            ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0;
+                        break;
+                    default:
+                        ts.Debug.fail("This is unknown kind for signature: " + node.kind);
+                }
+                return {
+                    diagnosticMessage: diagnosticMessage,
+                    errorNode: node.name || node,
+                };
+            }
+        }
+        function emitParameterDeclaration(node) {
+            increaseIndent();
+            emitJsDocComments(node);
+            if (node.dotDotDotToken) {
+                write("...");
+            }
+            if (ts.isBindingPattern(node.name)) {
+                emitBindingPattern(node.name);
+            }
+            else {
+                writeTextOfNode(currentSourceFile, node.name);
+            }
+            if (node.initializer || ts.hasQuestionToken(node)) {
+                write("?");
+            }
+            decreaseIndent();
+            if (node.parent.kind === 142 ||
+                node.parent.kind === 143 ||
+                node.parent.parent.kind === 145) {
+                emitTypeOfVariableDeclarationFromTypeLiteral(node);
+            }
+            else if (!(node.parent.flags & 32)) {
+                writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError);
+            }
+            function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult) {
+                var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                return diagnosticMessage !== undefined ? {
+                    diagnosticMessage: diagnosticMessage,
+                    errorNode: node,
+                    typeName: node.name
+                } : undefined;
+            }
+            function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult) {
+                switch (node.parent.kind) {
+                    case 135:
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === 2 ?
+                                ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1;
+                    case 139:
+                        return symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
+                    case 138:
+                        return symbolAccesibilityResult.errorModuleName ?
+                            ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
+                    case 134:
+                    case 133:
+                        if (node.parent.flags & 128) {
+                            return symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === 2 ?
+                                    ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                    ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                                ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
+                        }
+                        else if (node.parent.parent.kind === 201) {
+                            return symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === 2 ?
+                                    ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                    ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                                ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
+                        }
+                        else {
+                            return symbolAccesibilityResult.errorModuleName ?
+                                ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                                ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
+                        }
+                    case 200:
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === 2 ?
+                                ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 :
+                            ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1;
+                    default:
+                        ts.Debug.fail("This is unknown parent for parameter: " + node.parent.kind);
+                }
+            }
+            function emitBindingPattern(bindingPattern) {
+                if (bindingPattern.kind === 150) {
+                    write("{");
+                    emitCommaList(bindingPattern.elements, emitBindingElement);
+                    write("}");
+                }
+                else if (bindingPattern.kind === 151) {
+                    write("[");
+                    var elements = bindingPattern.elements;
+                    emitCommaList(elements, emitBindingElement);
+                    if (elements && elements.hasTrailingComma) {
+                        write(", ");
+                    }
+                    write("]");
+                }
+            }
+            function emitBindingElement(bindingElement) {
+                function getBindingElementTypeVisibilityError(symbolAccesibilityResult) {
+                    var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                    return diagnosticMessage !== undefined ? {
+                        diagnosticMessage: diagnosticMessage,
+                        errorNode: bindingElement,
+                        typeName: bindingElement.name
+                    } : undefined;
+                }
+                if (bindingElement.kind === 175) {
+                    write(" ");
+                }
+                else if (bindingElement.kind === 152) {
+                    if (bindingElement.propertyName) {
+                        writeTextOfNode(currentSourceFile, bindingElement.propertyName);
+                        write(": ");
+                        emitBindingPattern(bindingElement.name);
+                    }
+                    else if (bindingElement.name) {
+                        if (ts.isBindingPattern(bindingElement.name)) {
+                            emitBindingPattern(bindingElement.name);
+                        }
+                        else {
+                            ts.Debug.assert(bindingElement.name.kind === 65);
+                            if (bindingElement.dotDotDotToken) {
+                                write("...");
+                            }
+                            writeTextOfNode(currentSourceFile, bindingElement.name);
+                        }
+                    }
+                }
+            }
+        }
+        function emitNode(node) {
+            switch (node.kind) {
+                case 200:
+                case 205:
+                case 208:
+                case 202:
+                case 201:
+                case 203:
+                case 204:
+                    return emitModuleElement(node, isModuleElementVisible(node));
+                case 180:
+                    return emitModuleElement(node, isVariableStatementVisible(node));
+                case 209:
+                    return emitModuleElement(node, !node.importClause);
+                case 215:
+                    return emitExportDeclaration(node);
+                case 135:
+                case 134:
+                case 133:
+                    return writeFunctionDeclaration(node);
+                case 139:
+                case 138:
+                case 140:
+                    return emitSignatureDeclarationWithJsDocComments(node);
+                case 136:
+                case 137:
+                    return emitAccessorDeclaration(node);
+                case 132:
+                case 131:
+                    return emitPropertyDeclaration(node);
+                case 226:
+                    return emitEnumMemberDeclaration(node);
+                case 214:
+                    return emitExportAssignment(node);
+                case 227:
+                    return emitSourceFile(node);
+            }
+        }
+        function writeReferencePath(referencedFile) {
+            var declFileName = referencedFile.flags & 2048
+                ? referencedFile.fileName
+                : ts.shouldEmitToOwnFile(referencedFile, compilerOptions)
+                    ? ts.getOwnEmitOutputFilePath(referencedFile, host, ".d.ts")
+                    : ts.removeFileExtension(compilerOptions.out) + ".d.ts";
+            declFileName = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizeSlashes(jsFilePath)), declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, false);
+            referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
+        }
+    }
+    function writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics) {
+        var emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile);
+        if (!emitDeclarationResult.reportedDeclarationError) {
+            var declarationOutput = emitDeclarationResult.referencePathsOutput
+                + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
+            ts.writeFile(host, diagnostics, ts.removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM);
+        }
+        function getDeclarationOutput(synchronousDeclarationOutput, moduleElementDeclarationEmitInfo) {
+            var appliedSyncOutputPos = 0;
+            var declarationOutput = "";
+            ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) {
+                if (aliasEmitInfo.asynchronousOutput) {
+                    declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos);
+                    declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo);
+                    appliedSyncOutputPos = aliasEmitInfo.outputPos;
+                }
+            });
+            declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos);
+            return declarationOutput;
+        }
+    }
+    ts.writeDeclarationFile = writeDeclarationFile;
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/diagnosticInformationMap.generated.js b/dist/typescript/compiler/diagnosticInformationMap.generated.js
new file mode 100644
index 000000000..1d25c0864
--- /dev/null
+++ b/dist/typescript/compiler/diagnosticInformationMap.generated.js
@@ -0,0 +1,541 @@
+/// <reference path="types.ts" />
+var ts;
+(function (ts) {
+    ts.Diagnostics = {
+        Unterminated_string_literal: { code: 1002, category: ts.DiagnosticCategory.Error, key: "Unterminated string literal." },
+        Identifier_expected: { code: 1003, category: ts.DiagnosticCategory.Error, key: "Identifier expected." },
+        _0_expected: { code: 1005, category: ts.DiagnosticCategory.Error, key: "'{0}' expected." },
+        A_file_cannot_have_a_reference_to_itself: { code: 1006, category: ts.DiagnosticCategory.Error, key: "A file cannot have a reference to itself." },
+        Trailing_comma_not_allowed: { code: 1009, category: ts.DiagnosticCategory.Error, key: "Trailing comma not allowed." },
+        Asterisk_Slash_expected: { code: 1010, category: ts.DiagnosticCategory.Error, key: "'*/' expected." },
+        Unexpected_token: { code: 1012, category: ts.DiagnosticCategory.Error, key: "Unexpected token." },
+        A_rest_parameter_must_be_last_in_a_parameter_list: { code: 1014, category: ts.DiagnosticCategory.Error, key: "A rest parameter must be last in a parameter list." },
+        Parameter_cannot_have_question_mark_and_initializer: { code: 1015, category: ts.DiagnosticCategory.Error, key: "Parameter cannot have question mark and initializer." },
+        A_required_parameter_cannot_follow_an_optional_parameter: { code: 1016, category: ts.DiagnosticCategory.Error, key: "A required parameter cannot follow an optional parameter." },
+        An_index_signature_cannot_have_a_rest_parameter: { code: 1017, category: ts.DiagnosticCategory.Error, key: "An index signature cannot have a rest parameter." },
+        An_index_signature_parameter_cannot_have_an_accessibility_modifier: { code: 1018, category: ts.DiagnosticCategory.Error, key: "An index signature parameter cannot have an accessibility modifier." },
+        An_index_signature_parameter_cannot_have_a_question_mark: { code: 1019, category: ts.DiagnosticCategory.Error, key: "An index signature parameter cannot have a question mark." },
+        An_index_signature_parameter_cannot_have_an_initializer: { code: 1020, category: ts.DiagnosticCategory.Error, key: "An index signature parameter cannot have an initializer." },
+        An_index_signature_must_have_a_type_annotation: { code: 1021, category: ts.DiagnosticCategory.Error, key: "An index signature must have a type annotation." },
+        An_index_signature_parameter_must_have_a_type_annotation: { code: 1022, category: ts.DiagnosticCategory.Error, key: "An index signature parameter must have a type annotation." },
+        An_index_signature_parameter_type_must_be_string_or_number: { code: 1023, category: ts.DiagnosticCategory.Error, key: "An index signature parameter type must be 'string' or 'number'." },
+        A_class_or_interface_declaration_can_only_have_one_extends_clause: { code: 1024, category: ts.DiagnosticCategory.Error, key: "A class or interface declaration can only have one 'extends' clause." },
+        An_extends_clause_must_precede_an_implements_clause: { code: 1025, category: ts.DiagnosticCategory.Error, key: "An 'extends' clause must precede an 'implements' clause." },
+        A_class_can_only_extend_a_single_class: { code: 1026, category: ts.DiagnosticCategory.Error, key: "A class can only extend a single class." },
+        A_class_declaration_can_only_have_one_implements_clause: { code: 1027, category: ts.DiagnosticCategory.Error, key: "A class declaration can only have one 'implements' clause." },
+        Accessibility_modifier_already_seen: { code: 1028, category: ts.DiagnosticCategory.Error, key: "Accessibility modifier already seen." },
+        _0_modifier_must_precede_1_modifier: { code: 1029, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier must precede '{1}' modifier." },
+        _0_modifier_already_seen: { code: 1030, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier already seen." },
+        _0_modifier_cannot_appear_on_a_class_element: { code: 1031, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a class element." },
+        An_interface_declaration_cannot_have_an_implements_clause: { code: 1032, category: ts.DiagnosticCategory.Error, key: "An interface declaration cannot have an 'implements' clause." },
+        super_must_be_followed_by_an_argument_list_or_member_access: { code: 1034, category: ts.DiagnosticCategory.Error, key: "'super' must be followed by an argument list or member access." },
+        Only_ambient_modules_can_use_quoted_names: { code: 1035, category: ts.DiagnosticCategory.Error, key: "Only ambient modules can use quoted names." },
+        Statements_are_not_allowed_in_ambient_contexts: { code: 1036, category: ts.DiagnosticCategory.Error, key: "Statements are not allowed in ambient contexts." },
+        A_declare_modifier_cannot_be_used_in_an_already_ambient_context: { code: 1038, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used in an already ambient context." },
+        Initializers_are_not_allowed_in_ambient_contexts: { code: 1039, category: ts.DiagnosticCategory.Error, key: "Initializers are not allowed in ambient contexts." },
+        _0_modifier_cannot_appear_on_a_module_element: { code: 1044, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a module element." },
+        A_declare_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an interface declaration." },
+        A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: { code: 1046, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier is required for a top level declaration in a .d.ts file." },
+        A_rest_parameter_cannot_be_optional: { code: 1047, category: ts.DiagnosticCategory.Error, key: "A rest parameter cannot be optional." },
+        A_rest_parameter_cannot_have_an_initializer: { code: 1048, category: ts.DiagnosticCategory.Error, key: "A rest parameter cannot have an initializer." },
+        A_set_accessor_must_have_exactly_one_parameter: { code: 1049, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor must have exactly one parameter." },
+        A_set_accessor_cannot_have_an_optional_parameter: { code: 1051, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor cannot have an optional parameter." },
+        A_set_accessor_parameter_cannot_have_an_initializer: { code: 1052, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor parameter cannot have an initializer." },
+        A_set_accessor_cannot_have_rest_parameter: { code: 1053, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor cannot have rest parameter." },
+        A_get_accessor_cannot_have_parameters: { code: 1054, category: ts.DiagnosticCategory.Error, key: "A 'get' accessor cannot have parameters." },
+        Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1056, category: ts.DiagnosticCategory.Error, key: "Accessors are only available when targeting ECMAScript 5 and higher." },
+        Enum_member_must_have_initializer: { code: 1061, category: ts.DiagnosticCategory.Error, key: "Enum member must have initializer." },
+        An_export_assignment_cannot_be_used_in_an_internal_module: { code: 1063, category: ts.DiagnosticCategory.Error, key: "An export assignment cannot be used in an internal module." },
+        Ambient_enum_elements_can_only_have_integer_literal_initializers: { code: 1066, category: ts.DiagnosticCategory.Error, key: "Ambient enum elements can only have integer literal initializers." },
+        Unexpected_token_A_constructor_method_accessor_or_property_was_expected: { code: 1068, category: ts.DiagnosticCategory.Error, key: "Unexpected token. A constructor, method, accessor, or property was expected." },
+        A_declare_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: ts.DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an import declaration." },
+        Invalid_reference_directive_syntax: { code: 1084, category: ts.DiagnosticCategory.Error, key: "Invalid 'reference' directive syntax." },
+        Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: { code: 1085, category: ts.DiagnosticCategory.Error, key: "Octal literals are not available when targeting ECMAScript 5 and higher." },
+        An_accessor_cannot_be_declared_in_an_ambient_context: { code: 1086, category: ts.DiagnosticCategory.Error, key: "An accessor cannot be declared in an ambient context." },
+        _0_modifier_cannot_appear_on_a_constructor_declaration: { code: 1089, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a constructor declaration." },
+        _0_modifier_cannot_appear_on_a_parameter: { code: 1090, category: ts.DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a parameter." },
+        Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement: { code: 1091, category: ts.DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...in' statement." },
+        Type_parameters_cannot_appear_on_a_constructor_declaration: { code: 1092, category: ts.DiagnosticCategory.Error, key: "Type parameters cannot appear on a constructor declaration." },
+        Type_annotation_cannot_appear_on_a_constructor_declaration: { code: 1093, category: ts.DiagnosticCategory.Error, key: "Type annotation cannot appear on a constructor declaration." },
+        An_accessor_cannot_have_type_parameters: { code: 1094, category: ts.DiagnosticCategory.Error, key: "An accessor cannot have type parameters." },
+        A_set_accessor_cannot_have_a_return_type_annotation: { code: 1095, category: ts.DiagnosticCategory.Error, key: "A 'set' accessor cannot have a return type annotation." },
+        An_index_signature_must_have_exactly_one_parameter: { code: 1096, category: ts.DiagnosticCategory.Error, key: "An index signature must have exactly one parameter." },
+        _0_list_cannot_be_empty: { code: 1097, category: ts.DiagnosticCategory.Error, key: "'{0}' list cannot be empty." },
+        Type_parameter_list_cannot_be_empty: { code: 1098, category: ts.DiagnosticCategory.Error, key: "Type parameter list cannot be empty." },
+        Type_argument_list_cannot_be_empty: { code: 1099, category: ts.DiagnosticCategory.Error, key: "Type argument list cannot be empty." },
+        Invalid_use_of_0_in_strict_mode: { code: 1100, category: ts.DiagnosticCategory.Error, key: "Invalid use of '{0}' in strict mode." },
+        with_statements_are_not_allowed_in_strict_mode: { code: 1101, category: ts.DiagnosticCategory.Error, key: "'with' statements are not allowed in strict mode." },
+        delete_cannot_be_called_on_an_identifier_in_strict_mode: { code: 1102, category: ts.DiagnosticCategory.Error, key: "'delete' cannot be called on an identifier in strict mode." },
+        A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement: { code: 1104, category: ts.DiagnosticCategory.Error, key: "A 'continue' statement can only be used within an enclosing iteration statement." },
+        A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement: { code: 1105, category: ts.DiagnosticCategory.Error, key: "A 'break' statement can only be used within an enclosing iteration or switch statement." },
+        Jump_target_cannot_cross_function_boundary: { code: 1107, category: ts.DiagnosticCategory.Error, key: "Jump target cannot cross function boundary." },
+        A_return_statement_can_only_be_used_within_a_function_body: { code: 1108, category: ts.DiagnosticCategory.Error, key: "A 'return' statement can only be used within a function body." },
+        Expression_expected: { code: 1109, category: ts.DiagnosticCategory.Error, key: "Expression expected." },
+        Type_expected: { code: 1110, category: ts.DiagnosticCategory.Error, key: "Type expected." },
+        A_class_member_cannot_be_declared_optional: { code: 1112, category: ts.DiagnosticCategory.Error, key: "A class member cannot be declared optional." },
+        A_default_clause_cannot_appear_more_than_once_in_a_switch_statement: { code: 1113, category: ts.DiagnosticCategory.Error, key: "A 'default' clause cannot appear more than once in a 'switch' statement." },
+        Duplicate_label_0: { code: 1114, category: ts.DiagnosticCategory.Error, key: "Duplicate label '{0}'" },
+        A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement: { code: 1115, category: ts.DiagnosticCategory.Error, key: "A 'continue' statement can only jump to a label of an enclosing iteration statement." },
+        A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement: { code: 1116, category: ts.DiagnosticCategory.Error, key: "A 'break' statement can only jump to a label of an enclosing statement." },
+        An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode: { code: 1117, category: ts.DiagnosticCategory.Error, key: "An object literal cannot have multiple properties with the same name in strict mode." },
+        An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name: { code: 1118, category: ts.DiagnosticCategory.Error, key: "An object literal cannot have multiple get/set accessors with the same name." },
+        An_object_literal_cannot_have_property_and_accessor_with_the_same_name: { code: 1119, category: ts.DiagnosticCategory.Error, key: "An object literal cannot have property and accessor with the same name." },
+        An_export_assignment_cannot_have_modifiers: { code: 1120, category: ts.DiagnosticCategory.Error, key: "An export assignment cannot have modifiers." },
+        Octal_literals_are_not_allowed_in_strict_mode: { code: 1121, category: ts.DiagnosticCategory.Error, key: "Octal literals are not allowed in strict mode." },
+        A_tuple_type_element_list_cannot_be_empty: { code: 1122, category: ts.DiagnosticCategory.Error, key: "A tuple type element list cannot be empty." },
+        Variable_declaration_list_cannot_be_empty: { code: 1123, category: ts.DiagnosticCategory.Error, key: "Variable declaration list cannot be empty." },
+        Digit_expected: { code: 1124, category: ts.DiagnosticCategory.Error, key: "Digit expected." },
+        Hexadecimal_digit_expected: { code: 1125, category: ts.DiagnosticCategory.Error, key: "Hexadecimal digit expected." },
+        Unexpected_end_of_text: { code: 1126, category: ts.DiagnosticCategory.Error, key: "Unexpected end of text." },
+        Invalid_character: { code: 1127, category: ts.DiagnosticCategory.Error, key: "Invalid character." },
+        Declaration_or_statement_expected: { code: 1128, category: ts.DiagnosticCategory.Error, key: "Declaration or statement expected." },
+        Statement_expected: { code: 1129, category: ts.DiagnosticCategory.Error, key: "Statement expected." },
+        case_or_default_expected: { code: 1130, category: ts.DiagnosticCategory.Error, key: "'case' or 'default' expected." },
+        Property_or_signature_expected: { code: 1131, category: ts.DiagnosticCategory.Error, key: "Property or signature expected." },
+        Enum_member_expected: { code: 1132, category: ts.DiagnosticCategory.Error, key: "Enum member expected." },
+        Type_reference_expected: { code: 1133, category: ts.DiagnosticCategory.Error, key: "Type reference expected." },
+        Variable_declaration_expected: { code: 1134, category: ts.DiagnosticCategory.Error, key: "Variable declaration expected." },
+        Argument_expression_expected: { code: 1135, category: ts.DiagnosticCategory.Error, key: "Argument expression expected." },
+        Property_assignment_expected: { code: 1136, category: ts.DiagnosticCategory.Error, key: "Property assignment expected." },
+        Expression_or_comma_expected: { code: 1137, category: ts.DiagnosticCategory.Error, key: "Expression or comma expected." },
+        Parameter_declaration_expected: { code: 1138, category: ts.DiagnosticCategory.Error, key: "Parameter declaration expected." },
+        Type_parameter_declaration_expected: { code: 1139, category: ts.DiagnosticCategory.Error, key: "Type parameter declaration expected." },
+        Type_argument_expected: { code: 1140, category: ts.DiagnosticCategory.Error, key: "Type argument expected." },
+        String_literal_expected: { code: 1141, category: ts.DiagnosticCategory.Error, key: "String literal expected." },
+        Line_break_not_permitted_here: { code: 1142, category: ts.DiagnosticCategory.Error, key: "Line break not permitted here." },
+        or_expected: { code: 1144, category: ts.DiagnosticCategory.Error, key: "'{' or ';' expected." },
+        Modifiers_not_permitted_on_index_signature_members: { code: 1145, category: ts.DiagnosticCategory.Error, key: "Modifiers not permitted on index signature members." },
+        Declaration_expected: { code: 1146, category: ts.DiagnosticCategory.Error, key: "Declaration expected." },
+        Import_declarations_in_an_internal_module_cannot_reference_an_external_module: { code: 1147, category: ts.DiagnosticCategory.Error, key: "Import declarations in an internal module cannot reference an external module." },
+        Cannot_compile_external_modules_unless_the_module_flag_is_provided: { code: 1148, category: ts.DiagnosticCategory.Error, key: "Cannot compile external modules unless the '--module' flag is provided." },
+        File_name_0_differs_from_already_included_file_name_1_only_in_casing: { code: 1149, category: ts.DiagnosticCategory.Error, key: "File name '{0}' differs from already included file name '{1}' only in casing" },
+        new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 1150, category: ts.DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
+        var_let_or_const_expected: { code: 1152, category: ts.DiagnosticCategory.Error, key: "'var', 'let' or 'const' expected." },
+        let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1153, category: ts.DiagnosticCategory.Error, key: "'let' declarations are only available when targeting ECMAScript 6 and higher." },
+        const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1154, category: ts.DiagnosticCategory.Error, key: "'const' declarations are only available when targeting ECMAScript 6 and higher." },
+        const_declarations_must_be_initialized: { code: 1155, category: ts.DiagnosticCategory.Error, key: "'const' declarations must be initialized" },
+        const_declarations_can_only_be_declared_inside_a_block: { code: 1156, category: ts.DiagnosticCategory.Error, key: "'const' declarations can only be declared inside a block." },
+        let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: ts.DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
+        Unterminated_template_literal: { code: 1160, category: ts.DiagnosticCategory.Error, key: "Unterminated template literal." },
+        Unterminated_regular_expression_literal: { code: 1161, category: ts.DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
+        An_object_member_cannot_be_declared_optional: { code: 1162, category: ts.DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
+        yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: ts.DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
+        Computed_property_names_are_not_allowed_in_enums: { code: 1164, category: ts.DiagnosticCategory.Error, key: "Computed property names are not allowed in enums." },
+        A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol: { code: 1165, category: ts.DiagnosticCategory.Error, key: "A computed property name in an ambient context must directly refer to a built-in symbol." },
+        A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol: { code: 1166, category: ts.DiagnosticCategory.Error, key: "A computed property name in a class property declaration must directly refer to a built-in symbol." },
+        Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1167, category: ts.DiagnosticCategory.Error, key: "Computed property names are only available when targeting ECMAScript 6 and higher." },
+        A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol: { code: 1168, category: ts.DiagnosticCategory.Error, key: "A computed property name in a method overload must directly refer to a built-in symbol." },
+        A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol: { code: 1169, category: ts.DiagnosticCategory.Error, key: "A computed property name in an interface must directly refer to a built-in symbol." },
+        A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol: { code: 1170, category: ts.DiagnosticCategory.Error, key: "A computed property name in a type literal must directly refer to a built-in symbol." },
+        A_comma_expression_is_not_allowed_in_a_computed_property_name: { code: 1171, category: ts.DiagnosticCategory.Error, key: "A comma expression is not allowed in a computed property name." },
+        extends_clause_already_seen: { code: 1172, category: ts.DiagnosticCategory.Error, key: "'extends' clause already seen." },
+        extends_clause_must_precede_implements_clause: { code: 1173, category: ts.DiagnosticCategory.Error, key: "'extends' clause must precede 'implements' clause." },
+        Classes_can_only_extend_a_single_class: { code: 1174, category: ts.DiagnosticCategory.Error, key: "Classes can only extend a single class." },
+        implements_clause_already_seen: { code: 1175, category: ts.DiagnosticCategory.Error, key: "'implements' clause already seen." },
+        Interface_declaration_cannot_have_implements_clause: { code: 1176, category: ts.DiagnosticCategory.Error, key: "Interface declaration cannot have 'implements' clause." },
+        Binary_digit_expected: { code: 1177, category: ts.DiagnosticCategory.Error, key: "Binary digit expected." },
+        Octal_digit_expected: { code: 1178, category: ts.DiagnosticCategory.Error, key: "Octal digit expected." },
+        Unexpected_token_expected: { code: 1179, category: ts.DiagnosticCategory.Error, key: "Unexpected token. '{' expected." },
+        Property_destructuring_pattern_expected: { code: 1180, category: ts.DiagnosticCategory.Error, key: "Property destructuring pattern expected." },
+        Array_element_destructuring_pattern_expected: { code: 1181, category: ts.DiagnosticCategory.Error, key: "Array element destructuring pattern expected." },
+        A_destructuring_declaration_must_have_an_initializer: { code: 1182, category: ts.DiagnosticCategory.Error, key: "A destructuring declaration must have an initializer." },
+        Destructuring_declarations_are_not_allowed_in_ambient_contexts: { code: 1183, category: ts.DiagnosticCategory.Error, key: "Destructuring declarations are not allowed in ambient contexts." },
+        An_implementation_cannot_be_declared_in_ambient_contexts: { code: 1184, category: ts.DiagnosticCategory.Error, key: "An implementation cannot be declared in ambient contexts." },
+        Modifiers_cannot_appear_here: { code: 1184, category: ts.DiagnosticCategory.Error, key: "Modifiers cannot appear here." },
+        Merge_conflict_marker_encountered: { code: 1185, category: ts.DiagnosticCategory.Error, key: "Merge conflict marker encountered." },
+        A_rest_element_cannot_have_an_initializer: { code: 1186, category: ts.DiagnosticCategory.Error, key: "A rest element cannot have an initializer." },
+        A_parameter_property_may_not_be_a_binding_pattern: { code: 1187, category: ts.DiagnosticCategory.Error, key: "A parameter property may not be a binding pattern." },
+        Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement: { code: 1188, category: ts.DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...of' statement." },
+        The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer: { code: 1189, category: ts.DiagnosticCategory.Error, key: "The variable declaration of a 'for...in' statement cannot have an initializer." },
+        The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer: { code: 1190, category: ts.DiagnosticCategory.Error, key: "The variable declaration of a 'for...of' statement cannot have an initializer." },
+        An_import_declaration_cannot_have_modifiers: { code: 1191, category: ts.DiagnosticCategory.Error, key: "An import declaration cannot have modifiers." },
+        External_module_0_has_no_default_export: { code: 1192, category: ts.DiagnosticCategory.Error, key: "External module '{0}' has no default export." },
+        An_export_declaration_cannot_have_modifiers: { code: 1193, category: ts.DiagnosticCategory.Error, key: "An export declaration cannot have modifiers." },
+        Export_declarations_are_not_permitted_in_an_internal_module: { code: 1194, category: ts.DiagnosticCategory.Error, key: "Export declarations are not permitted in an internal module." },
+        Catch_clause_variable_name_must_be_an_identifier: { code: 1195, category: ts.DiagnosticCategory.Error, key: "Catch clause variable name must be an identifier." },
+        Catch_clause_variable_cannot_have_a_type_annotation: { code: 1196, category: ts.DiagnosticCategory.Error, key: "Catch clause variable cannot have a type annotation." },
+        Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: ts.DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
+        An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: ts.DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
+        Unterminated_Unicode_escape_sequence: { code: 1199, category: ts.DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
+        Line_terminator_not_permitted_before_arrow: { code: 1200, category: ts.DiagnosticCategory.Error, key: "Line terminator not permitted before arrow." },
+        Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: ts.DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
+        Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: ts.DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
+        Cannot_compile_external_modules_into_amd_commonjs_or_umd_when_targeting_ES6_or_higher: { code: 1204, category: ts.DiagnosticCategory.Error, key: "Cannot compile external modules into 'amd', 'commonjs' or 'umd' when targeting 'ES6' or higher." },
+        Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1205, category: ts.DiagnosticCategory.Error, key: "Decorators are only available when targeting ECMAScript 5 and higher." },
+        Decorators_are_not_valid_here: { code: 1206, category: ts.DiagnosticCategory.Error, key: "Decorators are not valid here." },
+        Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name: { code: 1207, category: ts.DiagnosticCategory.Error, key: "Decorators cannot be applied to multiple get/set accessors of the same name." },
+        Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided: { code: 1208, category: ts.DiagnosticCategory.Error, key: "Cannot compile non-external modules when the '--separateCompilation' flag is provided." },
+        Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided: { code: 1209, category: ts.DiagnosticCategory.Error, key: "Ambient const enums are not allowed when the '--separateCompilation' flag is provided." },
+        Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode: { code: 1210, category: ts.DiagnosticCategory.Error, key: "Invalid use of '{0}'. Class definitions are automatically in strict mode." },
+        A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: ts.DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
+        Identifier_expected_0_is_a_reserved_word_in_strict_mode: { code: 1212, category: ts.DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode" },
+        Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1213, category: ts.DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
+        Identifier_expected_0_is_a_reserved_word_in_strict_mode_External_Module_is_automatically_in_strict_mode: { code: 1214, category: ts.DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. External Module is automatically in strict mode." },
+        Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: ts.DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
+        Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: ts.DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
+        Type_expected_0_is_a_reserved_word_in_strict_mode_Module_is_automatically_in_strict_mode: { code: 1217, category: ts.DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode." },
+        Duplicate_identifier_0: { code: 2300, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
+        Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: ts.DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
+        Static_members_cannot_reference_class_type_parameters: { code: 2302, category: ts.DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
+        Circular_definition_of_import_alias_0: { code: 2303, category: ts.DiagnosticCategory.Error, key: "Circular definition of import alias '{0}'." },
+        Cannot_find_name_0: { code: 2304, category: ts.DiagnosticCategory.Error, key: "Cannot find name '{0}'." },
+        Module_0_has_no_exported_member_1: { code: 2305, category: ts.DiagnosticCategory.Error, key: "Module '{0}' has no exported member '{1}'." },
+        File_0_is_not_an_external_module: { code: 2306, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not an external module." },
+        Cannot_find_external_module_0: { code: 2307, category: ts.DiagnosticCategory.Error, key: "Cannot find external module '{0}'." },
+        A_module_cannot_have_more_than_one_export_assignment: { code: 2308, category: ts.DiagnosticCategory.Error, key: "A module cannot have more than one export assignment." },
+        An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements: { code: 2309, category: ts.DiagnosticCategory.Error, key: "An export assignment cannot be used in a module with other exported elements." },
+        Type_0_recursively_references_itself_as_a_base_type: { code: 2310, category: ts.DiagnosticCategory.Error, key: "Type '{0}' recursively references itself as a base type." },
+        A_class_may_only_extend_another_class: { code: 2311, category: ts.DiagnosticCategory.Error, key: "A class may only extend another class." },
+        An_interface_may_only_extend_a_class_or_another_interface: { code: 2312, category: ts.DiagnosticCategory.Error, key: "An interface may only extend a class or another interface." },
+        Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list: { code: 2313, category: ts.DiagnosticCategory.Error, key: "Constraint of a type parameter cannot reference any type parameter from the same type parameter list." },
+        Generic_type_0_requires_1_type_argument_s: { code: 2314, category: ts.DiagnosticCategory.Error, key: "Generic type '{0}' requires {1} type argument(s)." },
+        Type_0_is_not_generic: { code: 2315, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not generic." },
+        Global_type_0_must_be_a_class_or_interface_type: { code: 2316, category: ts.DiagnosticCategory.Error, key: "Global type '{0}' must be a class or interface type." },
+        Global_type_0_must_have_1_type_parameter_s: { code: 2317, category: ts.DiagnosticCategory.Error, key: "Global type '{0}' must have {1} type parameter(s)." },
+        Cannot_find_global_type_0: { code: 2318, category: ts.DiagnosticCategory.Error, key: "Cannot find global type '{0}'." },
+        Named_property_0_of_types_1_and_2_are_not_identical: { code: 2319, category: ts.DiagnosticCategory.Error, key: "Named property '{0}' of types '{1}' and '{2}' are not identical." },
+        Interface_0_cannot_simultaneously_extend_types_1_and_2: { code: 2320, category: ts.DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'." },
+        Excessive_stack_depth_comparing_types_0_and_1: { code: 2321, category: ts.DiagnosticCategory.Error, key: "Excessive stack depth comparing types '{0}' and '{1}'." },
+        Type_0_is_not_assignable_to_type_1: { code: 2322, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}'." },
+        Property_0_is_missing_in_type_1: { code: 2324, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is missing in type '{1}'." },
+        Property_0_is_private_in_type_1_but_not_in_type_2: { code: 2325, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is private in type '{1}' but not in type '{2}'." },
+        Types_of_property_0_are_incompatible: { code: 2326, category: ts.DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible." },
+        Property_0_is_optional_in_type_1_but_required_in_type_2: { code: 2327, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is optional in type '{1}' but required in type '{2}'." },
+        Types_of_parameters_0_and_1_are_incompatible: { code: 2328, category: ts.DiagnosticCategory.Error, key: "Types of parameters '{0}' and '{1}' are incompatible." },
+        Index_signature_is_missing_in_type_0: { code: 2329, category: ts.DiagnosticCategory.Error, key: "Index signature is missing in type '{0}'." },
+        Index_signatures_are_incompatible: { code: 2330, category: ts.DiagnosticCategory.Error, key: "Index signatures are incompatible." },
+        this_cannot_be_referenced_in_a_module_body: { code: 2331, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in a module body." },
+        this_cannot_be_referenced_in_current_location: { code: 2332, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in current location." },
+        this_cannot_be_referenced_in_constructor_arguments: { code: 2333, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in constructor arguments." },
+        this_cannot_be_referenced_in_a_static_property_initializer: { code: 2334, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in a static property initializer." },
+        super_can_only_be_referenced_in_a_derived_class: { code: 2335, category: ts.DiagnosticCategory.Error, key: "'super' can only be referenced in a derived class." },
+        super_cannot_be_referenced_in_constructor_arguments: { code: 2336, category: ts.DiagnosticCategory.Error, key: "'super' cannot be referenced in constructor arguments." },
+        Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors: { code: 2337, category: ts.DiagnosticCategory.Error, key: "Super calls are not permitted outside constructors or in nested functions inside constructors" },
+        super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class: { code: 2338, category: ts.DiagnosticCategory.Error, key: "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class" },
+        Property_0_does_not_exist_on_type_1: { code: 2339, category: ts.DiagnosticCategory.Error, key: "Property '{0}' does not exist on type '{1}'." },
+        Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword: { code: 2340, category: ts.DiagnosticCategory.Error, key: "Only public and protected methods of the base class are accessible via the 'super' keyword" },
+        Property_0_is_private_and_only_accessible_within_class_1: { code: 2341, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is private and only accessible within class '{1}'." },
+        An_index_expression_argument_must_be_of_type_string_number_symbol_or_any: { code: 2342, category: ts.DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', 'symbol, or 'any'." },
+        Type_0_does_not_satisfy_the_constraint_1: { code: 2344, category: ts.DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}'." },
+        Argument_of_type_0_is_not_assignable_to_parameter_of_type_1: { code: 2345, category: ts.DiagnosticCategory.Error, key: "Argument of type '{0}' is not assignable to parameter of type '{1}'." },
+        Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: ts.DiagnosticCategory.Error, key: "Supplied parameters do not match any signature of call target." },
+        Untyped_function_calls_may_not_accept_type_arguments: { code: 2347, category: ts.DiagnosticCategory.Error, key: "Untyped function calls may not accept type arguments." },
+        Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: { code: 2348, category: ts.DiagnosticCategory.Error, key: "Value of type '{0}' is not callable. Did you mean to include 'new'?" },
+        Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { code: 2349, category: ts.DiagnosticCategory.Error, key: "Cannot invoke an expression whose type lacks a call signature." },
+        Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: ts.DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
+        Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: ts.DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
+        Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: ts.DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
+        No_best_common_type_exists_among_return_expressions: { code: 2354, category: ts.DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
+        A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: ts.DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
+        An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: ts.DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
+        The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: { code: 2357, category: ts.DiagnosticCategory.Error, key: "The operand of an increment or decrement operator must be a variable, property or indexer." },
+        The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2358, category: ts.DiagnosticCategory.Error, key: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter." },
+        The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: { code: 2359, category: ts.DiagnosticCategory.Error, key: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type." },
+        The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol: { code: 2360, category: ts.DiagnosticCategory.Error, key: "The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'." },
+        The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2361, category: ts.DiagnosticCategory.Error, key: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter" },
+        The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2362, category: ts.DiagnosticCategory.Error, key: "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
+        The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2363, category: ts.DiagnosticCategory.Error, key: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
+        Invalid_left_hand_side_of_assignment_expression: { code: 2364, category: ts.DiagnosticCategory.Error, key: "Invalid left-hand side of assignment expression." },
+        Operator_0_cannot_be_applied_to_types_1_and_2: { code: 2365, category: ts.DiagnosticCategory.Error, key: "Operator '{0}' cannot be applied to types '{1}' and '{2}'." },
+        Type_parameter_name_cannot_be_0: { code: 2368, category: ts.DiagnosticCategory.Error, key: "Type parameter name cannot be '{0}'" },
+        A_parameter_property_is_only_allowed_in_a_constructor_implementation: { code: 2369, category: ts.DiagnosticCategory.Error, key: "A parameter property is only allowed in a constructor implementation." },
+        A_rest_parameter_must_be_of_an_array_type: { code: 2370, category: ts.DiagnosticCategory.Error, key: "A rest parameter must be of an array type." },
+        A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation: { code: 2371, category: ts.DiagnosticCategory.Error, key: "A parameter initializer is only allowed in a function or constructor implementation." },
+        Parameter_0_cannot_be_referenced_in_its_initializer: { code: 2372, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' cannot be referenced in its initializer." },
+        Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: { code: 2373, category: ts.DiagnosticCategory.Error, key: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it." },
+        Duplicate_string_index_signature: { code: 2374, category: ts.DiagnosticCategory.Error, key: "Duplicate string index signature." },
+        Duplicate_number_index_signature: { code: 2375, category: ts.DiagnosticCategory.Error, key: "Duplicate number index signature." },
+        A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties: { code: 2376, category: ts.DiagnosticCategory.Error, key: "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties." },
+        Constructors_for_derived_classes_must_contain_a_super_call: { code: 2377, category: ts.DiagnosticCategory.Error, key: "Constructors for derived classes must contain a 'super' call." },
+        A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2378, category: ts.DiagnosticCategory.Error, key: "A 'get' accessor must return a value or consist of a single 'throw' statement." },
+        Getter_and_setter_accessors_do_not_agree_in_visibility: { code: 2379, category: ts.DiagnosticCategory.Error, key: "Getter and setter accessors do not agree in visibility." },
+        get_and_set_accessor_must_have_the_same_type: { code: 2380, category: ts.DiagnosticCategory.Error, key: "'get' and 'set' accessor must have the same type." },
+        A_signature_with_an_implementation_cannot_use_a_string_literal_type: { code: 2381, category: ts.DiagnosticCategory.Error, key: "A signature with an implementation cannot use a string literal type." },
+        Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature: { code: 2382, category: ts.DiagnosticCategory.Error, key: "Specialized overload signature is not assignable to any non-specialized signature." },
+        Overload_signatures_must_all_be_exported_or_not_exported: { code: 2383, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be exported or not exported." },
+        Overload_signatures_must_all_be_ambient_or_non_ambient: { code: 2384, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be ambient or non-ambient." },
+        Overload_signatures_must_all_be_public_private_or_protected: { code: 2385, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be public, private or protected." },
+        Overload_signatures_must_all_be_optional_or_required: { code: 2386, category: ts.DiagnosticCategory.Error, key: "Overload signatures must all be optional or required." },
+        Function_overload_must_be_static: { code: 2387, category: ts.DiagnosticCategory.Error, key: "Function overload must be static." },
+        Function_overload_must_not_be_static: { code: 2388, category: ts.DiagnosticCategory.Error, key: "Function overload must not be static." },
+        Function_implementation_name_must_be_0: { code: 2389, category: ts.DiagnosticCategory.Error, key: "Function implementation name must be '{0}'." },
+        Constructor_implementation_is_missing: { code: 2390, category: ts.DiagnosticCategory.Error, key: "Constructor implementation is missing." },
+        Function_implementation_is_missing_or_not_immediately_following_the_declaration: { code: 2391, category: ts.DiagnosticCategory.Error, key: "Function implementation is missing or not immediately following the declaration." },
+        Multiple_constructor_implementations_are_not_allowed: { code: 2392, category: ts.DiagnosticCategory.Error, key: "Multiple constructor implementations are not allowed." },
+        Duplicate_function_implementation: { code: 2393, category: ts.DiagnosticCategory.Error, key: "Duplicate function implementation." },
+        Overload_signature_is_not_compatible_with_function_implementation: { code: 2394, category: ts.DiagnosticCategory.Error, key: "Overload signature is not compatible with function implementation." },
+        Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local: { code: 2395, category: ts.DiagnosticCategory.Error, key: "Individual declarations in merged declaration {0} must be all exported or all local." },
+        Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: { code: 2396, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters." },
+        Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: { code: 2399, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference." },
+        Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: { code: 2400, category: ts.DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference." },
+        Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference: { code: 2401, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference." },
+        Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference: { code: 2402, category: ts.DiagnosticCategory.Error, key: "Expression resolves to '_super' that compiler uses to capture base class reference." },
+        Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2: { code: 2403, category: ts.DiagnosticCategory.Error, key: "Subsequent variable declarations must have the same type.  Variable '{0}' must be of type '{1}', but here has type '{2}'." },
+        The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation: { code: 2404, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot use a type annotation." },
+        The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any: { code: 2405, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement must be of type 'string' or 'any'." },
+        Invalid_left_hand_side_in_for_in_statement: { code: 2406, category: ts.DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...in' statement." },
+        The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2407, category: ts.DiagnosticCategory.Error, key: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." },
+        Setters_cannot_return_a_value: { code: 2408, category: ts.DiagnosticCategory.Error, key: "Setters cannot return a value." },
+        Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2409, category: ts.DiagnosticCategory.Error, key: "Return type of constructor signature must be assignable to the instance type of the class" },
+        All_symbols_within_a_with_block_will_be_resolved_to_any: { code: 2410, category: ts.DiagnosticCategory.Error, key: "All symbols within a 'with' block will be resolved to 'any'." },
+        Property_0_of_type_1_is_not_assignable_to_string_index_type_2: { code: 2411, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'." },
+        Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: { code: 2412, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'." },
+        Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: ts.DiagnosticCategory.Error, key: "Numeric index type '{0}' is not assignable to string index type '{1}'." },
+        Class_name_cannot_be_0: { code: 2414, category: ts.DiagnosticCategory.Error, key: "Class name cannot be '{0}'" },
+        Class_0_incorrectly_extends_base_class_1: { code: 2415, category: ts.DiagnosticCategory.Error, key: "Class '{0}' incorrectly extends base class '{1}'." },
+        Class_static_side_0_incorrectly_extends_base_class_static_side_1: { code: 2417, category: ts.DiagnosticCategory.Error, key: "Class static side '{0}' incorrectly extends base class static side '{1}'." },
+        Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0: { code: 2419, category: ts.DiagnosticCategory.Error, key: "Type name '{0}' in extends clause does not reference constructor function for '{0}'." },
+        Class_0_incorrectly_implements_interface_1: { code: 2420, category: ts.DiagnosticCategory.Error, key: "Class '{0}' incorrectly implements interface '{1}'." },
+        A_class_may_only_implement_another_class_or_interface: { code: 2422, category: ts.DiagnosticCategory.Error, key: "A class may only implement another class or interface." },
+        Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor: { code: 2423, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor." },
+        Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property: { code: 2424, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property." },
+        Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2425, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function." },
+        Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2426, category: ts.DiagnosticCategory.Error, key: "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function." },
+        Interface_name_cannot_be_0: { code: 2427, category: ts.DiagnosticCategory.Error, key: "Interface name cannot be '{0}'" },
+        All_declarations_of_an_interface_must_have_identical_type_parameters: { code: 2428, category: ts.DiagnosticCategory.Error, key: "All declarations of an interface must have identical type parameters." },
+        Interface_0_incorrectly_extends_interface_1: { code: 2430, category: ts.DiagnosticCategory.Error, key: "Interface '{0}' incorrectly extends interface '{1}'." },
+        Enum_name_cannot_be_0: { code: 2431, category: ts.DiagnosticCategory.Error, key: "Enum name cannot be '{0}'" },
+        In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element: { code: 2432, category: ts.DiagnosticCategory.Error, key: "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element." },
+        A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged: { code: 2433, category: ts.DiagnosticCategory.Error, key: "A module declaration cannot be in a different file from a class or function with which it is merged" },
+        A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged: { code: 2434, category: ts.DiagnosticCategory.Error, key: "A module declaration cannot be located prior to a class or function with which it is merged" },
+        Ambient_external_modules_cannot_be_nested_in_other_modules: { code: 2435, category: ts.DiagnosticCategory.Error, key: "Ambient external modules cannot be nested in other modules." },
+        Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2436, category: ts.DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." },
+        Module_0_is_hidden_by_a_local_declaration_with_the_same_name: { code: 2437, category: ts.DiagnosticCategory.Error, key: "Module '{0}' is hidden by a local declaration with the same name" },
+        Import_name_cannot_be_0: { code: 2438, category: ts.DiagnosticCategory.Error, key: "Import name cannot be '{0}'" },
+        Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: ts.DiagnosticCategory.Error, key: "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name." },
+        Import_declaration_conflicts_with_local_declaration_of_0: { code: 2440, category: ts.DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" },
+        Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: { code: 2441, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module." },
+        Types_have_separate_declarations_of_a_private_property_0: { code: 2442, category: ts.DiagnosticCategory.Error, key: "Types have separate declarations of a private property '{0}'." },
+        Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2: { code: 2443, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected but type '{1}' is not a class derived from '{2}'." },
+        Property_0_is_protected_in_type_1_but_public_in_type_2: { code: 2444, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected in type '{1}' but public in type '{2}'." },
+        Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2445, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses." },
+        Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: { code: 2446, category: ts.DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible through an instance of class '{1}'." },
+        The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: { code: 2447, category: ts.DiagnosticCategory.Error, key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead." },
+        Block_scoped_variable_0_used_before_its_declaration: { code: 2448, category: ts.DiagnosticCategory.Error, key: "Block-scoped variable '{0}' used before its declaration." },
+        The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant: { code: 2449, category: ts.DiagnosticCategory.Error, key: "The operand of an increment or decrement operator cannot be a constant." },
+        Left_hand_side_of_assignment_expression_cannot_be_a_constant: { code: 2450, category: ts.DiagnosticCategory.Error, key: "Left-hand side of assignment expression cannot be a constant." },
+        Cannot_redeclare_block_scoped_variable_0: { code: 2451, category: ts.DiagnosticCategory.Error, key: "Cannot redeclare block-scoped variable '{0}'." },
+        An_enum_member_cannot_have_a_numeric_name: { code: 2452, category: ts.DiagnosticCategory.Error, key: "An enum member cannot have a numeric name." },
+        The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly: { code: 2453, category: ts.DiagnosticCategory.Error, key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly." },
+        Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0: { code: 2455, category: ts.DiagnosticCategory.Error, key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'." },
+        Type_alias_0_circularly_references_itself: { code: 2456, category: ts.DiagnosticCategory.Error, key: "Type alias '{0}' circularly references itself." },
+        Type_alias_name_cannot_be_0: { code: 2457, category: ts.DiagnosticCategory.Error, key: "Type alias name cannot be '{0}'" },
+        An_AMD_module_cannot_have_multiple_name_assignments: { code: 2458, category: ts.DiagnosticCategory.Error, key: "An AMD module cannot have multiple name assignments." },
+        Type_0_has_no_property_1_and_no_string_index_signature: { code: 2459, category: ts.DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}' and no string index signature." },
+        Type_0_has_no_property_1: { code: 2460, category: ts.DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}'." },
+        Type_0_is_not_an_array_type: { code: 2461, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not an array type." },
+        A_rest_element_must_be_last_in_an_array_destructuring_pattern: { code: 2462, category: ts.DiagnosticCategory.Error, key: "A rest element must be last in an array destructuring pattern" },
+        A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature: { code: 2463, category: ts.DiagnosticCategory.Error, key: "A binding pattern parameter cannot be optional in an implementation signature." },
+        A_computed_property_name_must_be_of_type_string_number_symbol_or_any: { code: 2464, category: ts.DiagnosticCategory.Error, key: "A computed property name must be of type 'string', 'number', 'symbol', or 'any'." },
+        this_cannot_be_referenced_in_a_computed_property_name: { code: 2465, category: ts.DiagnosticCategory.Error, key: "'this' cannot be referenced in a computed property name." },
+        super_cannot_be_referenced_in_a_computed_property_name: { code: 2466, category: ts.DiagnosticCategory.Error, key: "'super' cannot be referenced in a computed property name." },
+        A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type: { code: 2467, category: ts.DiagnosticCategory.Error, key: "A computed property name cannot reference a type parameter from its containing type." },
+        Cannot_find_global_value_0: { code: 2468, category: ts.DiagnosticCategory.Error, key: "Cannot find global value '{0}'." },
+        The_0_operator_cannot_be_applied_to_type_symbol: { code: 2469, category: ts.DiagnosticCategory.Error, key: "The '{0}' operator cannot be applied to type 'symbol'." },
+        Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object: { code: 2470, category: ts.DiagnosticCategory.Error, key: "'Symbol' reference does not refer to the global Symbol constructor object." },
+        A_computed_property_name_of_the_form_0_must_be_of_type_symbol: { code: 2471, category: ts.DiagnosticCategory.Error, key: "A computed property name of the form '{0}' must be of type 'symbol'." },
+        Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher: { code: 2472, category: ts.DiagnosticCategory.Error, key: "Spread operator in 'new' expressions is only available when targeting ECMAScript 6 and higher." },
+        Enum_declarations_must_all_be_const_or_non_const: { code: 2473, category: ts.DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
+        In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 2474, category: ts.DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression." },
+        const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment: { code: 2475, category: ts.DiagnosticCategory.Error, key: "'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment." },
+        A_const_enum_member_can_only_be_accessed_using_a_string_literal: { code: 2476, category: ts.DiagnosticCategory.Error, key: "A const enum member can only be accessed using a string literal." },
+        const_enum_member_initializer_was_evaluated_to_a_non_finite_value: { code: 2477, category: ts.DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to a non-finite value." },
+        const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: { code: 2478, category: ts.DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to disallowed value 'NaN'." },
+        Property_0_does_not_exist_on_const_enum_1: { code: 2479, category: ts.DiagnosticCategory.Error, key: "Property '{0}' does not exist on 'const' enum '{1}'." },
+        let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: { code: 2480, category: ts.DiagnosticCategory.Error, key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations." },
+        Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1: { code: 2481, category: ts.DiagnosticCategory.Error, key: "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'." },
+        The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation: { code: 2483, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot use a type annotation." },
+        Export_declaration_conflicts_with_exported_declaration_of_0: { code: 2484, category: ts.DiagnosticCategory.Error, key: "Export declaration conflicts with exported declaration of '{0}'" },
+        The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: { code: 2485, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant." },
+        The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant: { code: 2486, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a previously defined constant." },
+        Invalid_left_hand_side_in_for_of_statement: { code: 2487, category: ts.DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...of' statement." },
+        Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator: { code: 2488, category: ts.DiagnosticCategory.Error, key: "Type must have a '[Symbol.iterator]()' method that returns an iterator." },
+        An_iterator_must_have_a_next_method: { code: 2489, category: ts.DiagnosticCategory.Error, key: "An iterator must have a 'next()' method." },
+        The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: { code: 2490, category: ts.DiagnosticCategory.Error, key: "The type returned by the 'next()' method of an iterator must have a 'value' property." },
+        The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: { code: 2491, category: ts.DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern." },
+        Cannot_redeclare_identifier_0_in_catch_clause: { code: 2492, category: ts.DiagnosticCategory.Error, key: "Cannot redeclare identifier '{0}' in catch clause" },
+        Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2: { code: 2493, category: ts.DiagnosticCategory.Error, key: "Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'." },
+        Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher: { code: 2494, category: ts.DiagnosticCategory.Error, key: "Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher." },
+        Type_0_is_not_an_array_type_or_a_string_type: { code: 2495, category: ts.DiagnosticCategory.Error, key: "Type '{0}' is not an array type or a string type." },
+        The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression: { code: 2496, category: ts.DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an arrow function in ES3 and ES5. Consider using a standard function expression." },
+        External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct: { code: 2497, category: ts.DiagnosticCategory.Error, key: "External module '{0}' resolves to a non-module entity and cannot be imported using this construct." },
+        External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk: { code: 2498, category: ts.DiagnosticCategory.Error, key: "External module '{0}' uses 'export =' and cannot be used with 'export *'." },
+        An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2499, category: ts.DiagnosticCategory.Error, key: "An interface can only extend an identifier/qualified-name with optional type arguments." },
+        A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2500, category: ts.DiagnosticCategory.Error, key: "A class can only implement an identifier/qualified-name with optional type arguments." },
+        A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: ts.DiagnosticCategory.Error, key: "A rest element cannot contain a binding pattern." },
+        Import_declaration_0_is_using_private_name_1: { code: 4000, category: ts.DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
+        Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
+        Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4006, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4008, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4010, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
+        Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4012, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using private name '{1}'." },
+        Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4014, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4016, category: ts.DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using private name '{1}'." },
+        Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4019, category: ts.DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using private name '{1}'." },
+        Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4020, category: ts.DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using private name '{1}'." },
+        Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1: { code: 4022, category: ts.DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using private name '{1}'." },
+        Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4023, category: ts.DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from external module {2} but cannot be named." },
+        Exported_variable_0_has_or_is_using_name_1_from_private_module_2: { code: 4024, category: ts.DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from private module '{2}'." },
+        Exported_variable_0_has_or_is_using_private_name_1: { code: 4025, category: ts.DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using private name '{1}'." },
+        Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4026, category: ts.DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4027, category: ts.DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
+        Public_static_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4028, category: ts.DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using private name '{1}'." },
+        Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4029, category: ts.DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4030, category: ts.DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
+        Public_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4031, category: ts.DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using private name '{1}'." },
+        Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4032, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using name '{1}' from private module '{2}'." },
+        Property_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4033, category: ts.DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using private name '{1}'." },
+        Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4034, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4035, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using private name '{1}'." },
+        Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4036, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4037, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using private name '{1}'." },
+        Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4038, category: ts.DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4039, category: ts.DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4040, category: ts.DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using private name '{0}'." },
+        Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4041, category: ts.DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4042, category: ts.DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4043, category: ts.DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using private name '{0}'." },
+        Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4044, category: ts.DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4045, category: ts.DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using private name '{0}'." },
+        Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4046, category: ts.DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4047, category: ts.DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using private name '{0}'." },
+        Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4048, category: ts.DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4049, category: ts.DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using private name '{0}'." },
+        Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4050, category: ts.DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4051, category: ts.DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0: { code: 4052, category: ts.DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using private name '{0}'." },
+        Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4053, category: ts.DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4054, category: ts.DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0: { code: 4055, category: ts.DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using private name '{0}'." },
+        Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4056, category: ts.DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0: { code: 4057, category: ts.DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using private name '{0}'." },
+        Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4058, category: ts.DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1: { code: 4059, category: ts.DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_exported_function_has_or_is_using_private_name_0: { code: 4060, category: ts.DiagnosticCategory.Error, key: "Return type of exported function has or is using private name '{0}'." },
+        Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4061, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4062, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1: { code: 4063, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using private name '{1}'." },
+        Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4064, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4065, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
+        Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4066, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4067, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
+        Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4068, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4069, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4070, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
+        Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4071, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4072, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4073, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using private name '{1}'." },
+        Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4074, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4075, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using private name '{1}'." },
+        Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4076, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 4077, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4078, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using private name '{1}'." },
+        Exported_type_alias_0_has_or_is_using_private_name_1: { code: 4081, category: ts.DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using private name '{1}'." },
+        Default_export_of_the_module_has_or_is_using_private_name_0: { code: 4082, category: ts.DiagnosticCategory.Error, key: "Default export of the module has or is using private name '{0}'." },
+        Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher: { code: 4091, category: ts.DiagnosticCategory.Error, key: "Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher." },
+        The_current_host_does_not_support_the_0_option: { code: 5001, category: ts.DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
+        Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: ts.DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
+        Cannot_read_file_0_Colon_1: { code: 5012, category: ts.DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
+        Unsupported_file_encoding: { code: 5013, category: ts.DiagnosticCategory.Error, key: "Unsupported file encoding." },
+        Failed_to_parse_file_0_Colon_1: { code: 5014, category: ts.DiagnosticCategory.Error, key: "Failed to parse file '{0}': {1}." },
+        Unknown_compiler_option_0: { code: 5023, category: ts.DiagnosticCategory.Error, key: "Unknown compiler option '{0}'." },
+        Compiler_option_0_requires_a_value_of_type_1: { code: 5024, category: ts.DiagnosticCategory.Error, key: "Compiler option '{0}' requires a value of type {1}." },
+        Could_not_write_file_0_Colon_1: { code: 5033, category: ts.DiagnosticCategory.Error, key: "Could not write file '{0}': {1}" },
+        Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5038, category: ts.DiagnosticCategory.Error, key: "Option 'mapRoot' cannot be specified without specifying 'sourcemap' option." },
+        Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5039, category: ts.DiagnosticCategory.Error, key: "Option 'sourceRoot' cannot be specified without specifying 'sourcemap' option." },
+        Option_noEmit_cannot_be_specified_with_option_out_or_outDir: { code: 5040, category: ts.DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'out' or 'outDir'." },
+        Option_noEmit_cannot_be_specified_with_option_declaration: { code: 5041, category: ts.DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'declaration'." },
+        Option_project_cannot_be_mixed_with_source_files_on_a_command_line: { code: 5042, category: ts.DiagnosticCategory.Error, key: "Option 'project' cannot be mixed with source files on a command line." },
+        Option_sourceMap_cannot_be_specified_with_option_separateCompilation: { code: 5043, category: ts.DiagnosticCategory.Error, key: "Option 'sourceMap' cannot be specified with option 'separateCompilation'." },
+        Option_declaration_cannot_be_specified_with_option_separateCompilation: { code: 5044, category: ts.DiagnosticCategory.Error, key: "Option 'declaration' cannot be specified with option 'separateCompilation'." },
+        Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation: { code: 5045, category: ts.DiagnosticCategory.Error, key: "Option 'noEmitOnError' cannot be specified with option 'separateCompilation'." },
+        Option_out_cannot_be_specified_with_option_separateCompilation: { code: 5046, category: ts.DiagnosticCategory.Error, key: "Option 'out' cannot be specified with option 'separateCompilation'." },
+        Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5047, category: ts.DiagnosticCategory.Error, key: "Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher." },
+        Concatenate_and_emit_output_to_single_file: { code: 6001, category: ts.DiagnosticCategory.Message, key: "Concatenate and emit output to single file." },
+        Generates_corresponding_d_ts_file: { code: 6002, category: ts.DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." },
+        Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: ts.DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." },
+        Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations: { code: 6004, category: ts.DiagnosticCategory.Message, key: "Specifies the location where debugger should locate TypeScript files instead of source locations." },
+        Watch_input_files: { code: 6005, category: ts.DiagnosticCategory.Message, key: "Watch input files." },
+        Redirect_output_structure_to_the_directory: { code: 6006, category: ts.DiagnosticCategory.Message, key: "Redirect output structure to the directory." },
+        Do_not_erase_const_enum_declarations_in_generated_code: { code: 6007, category: ts.DiagnosticCategory.Message, key: "Do not erase const enum declarations in generated code." },
+        Do_not_emit_outputs_if_any_type_checking_errors_were_reported: { code: 6008, category: ts.DiagnosticCategory.Message, key: "Do not emit outputs if any type checking errors were reported." },
+        Do_not_emit_comments_to_output: { code: 6009, category: ts.DiagnosticCategory.Message, key: "Do not emit comments to output." },
+        Do_not_emit_outputs: { code: 6010, category: ts.DiagnosticCategory.Message, key: "Do not emit outputs." },
+        Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental: { code: 6015, category: ts.DiagnosticCategory.Message, key: "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)" },
+        Specify_module_code_generation_Colon_commonjs_amd_or_umd: { code: 6016, category: ts.DiagnosticCategory.Message, key: "Specify module code generation: 'commonjs', 'amd', or 'umd'." },
+        Print_this_message: { code: 6017, category: ts.DiagnosticCategory.Message, key: "Print this message." },
+        Print_the_compiler_s_version: { code: 6019, category: ts.DiagnosticCategory.Message, key: "Print the compiler's version." },
+        Compile_the_project_in_the_given_directory: { code: 6020, category: ts.DiagnosticCategory.Message, key: "Compile the project in the given directory." },
+        Syntax_Colon_0: { code: 6023, category: ts.DiagnosticCategory.Message, key: "Syntax: {0}" },
+        options: { code: 6024, category: ts.DiagnosticCategory.Message, key: "options" },
+        file: { code: 6025, category: ts.DiagnosticCategory.Message, key: "file" },
+        Examples_Colon_0: { code: 6026, category: ts.DiagnosticCategory.Message, key: "Examples: {0}" },
+        Options_Colon: { code: 6027, category: ts.DiagnosticCategory.Message, key: "Options:" },
+        Version_0: { code: 6029, category: ts.DiagnosticCategory.Message, key: "Version {0}" },
+        Insert_command_line_options_and_files_from_a_file: { code: 6030, category: ts.DiagnosticCategory.Message, key: "Insert command line options and files from a file." },
+        File_change_detected_Starting_incremental_compilation: { code: 6032, category: ts.DiagnosticCategory.Message, key: "File change detected. Starting incremental compilation..." },
+        KIND: { code: 6034, category: ts.DiagnosticCategory.Message, key: "KIND" },
+        FILE: { code: 6035, category: ts.DiagnosticCategory.Message, key: "FILE" },
+        VERSION: { code: 6036, category: ts.DiagnosticCategory.Message, key: "VERSION" },
+        LOCATION: { code: 6037, category: ts.DiagnosticCategory.Message, key: "LOCATION" },
+        DIRECTORY: { code: 6038, category: ts.DiagnosticCategory.Message, key: "DIRECTORY" },
+        Compilation_complete_Watching_for_file_changes: { code: 6042, category: ts.DiagnosticCategory.Message, key: "Compilation complete. Watching for file changes." },
+        Generates_corresponding_map_file: { code: 6043, category: ts.DiagnosticCategory.Message, key: "Generates corresponding '.map' file." },
+        Compiler_option_0_expects_an_argument: { code: 6044, category: ts.DiagnosticCategory.Error, key: "Compiler option '{0}' expects an argument." },
+        Unterminated_quoted_string_in_response_file_0: { code: 6045, category: ts.DiagnosticCategory.Error, key: "Unterminated quoted string in response file '{0}'." },
+        Argument_for_module_option_must_be_commonjs_amd_or_umd: { code: 6046, category: ts.DiagnosticCategory.Error, key: "Argument for '--module' option must be 'commonjs', 'amd', or 'umd'." },
+        Argument_for_target_option_must_be_ES3_ES5_or_ES6: { code: 6047, category: ts.DiagnosticCategory.Error, key: "Argument for '--target' option must be 'ES3', 'ES5', or 'ES6'." },
+        Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1: { code: 6048, category: ts.DiagnosticCategory.Error, key: "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'." },
+        Unsupported_locale_0: { code: 6049, category: ts.DiagnosticCategory.Error, key: "Unsupported locale '{0}'." },
+        Unable_to_open_file_0: { code: 6050, category: ts.DiagnosticCategory.Error, key: "Unable to open file '{0}'." },
+        Corrupted_locale_file_0: { code: 6051, category: ts.DiagnosticCategory.Error, key: "Corrupted locale file {0}." },
+        Raise_error_on_expressions_and_declarations_with_an_implied_any_type: { code: 6052, category: ts.DiagnosticCategory.Message, key: "Raise error on expressions and declarations with an implied 'any' type." },
+        File_0_not_found: { code: 6053, category: ts.DiagnosticCategory.Error, key: "File '{0}' not found." },
+        File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: ts.DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." },
+        Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: ts.DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." },
+        Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: ts.DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." },
+        Preserve_new_lines_when_emitting_code: { code: 6057, category: ts.DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." },
+        Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: ts.DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." },
+        File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: ts.DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." },
+        Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
+        Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
+        Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
+        new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type: { code: 7009, category: ts.DiagnosticCategory.Error, key: "'new' expression, whose target lacks a construct signature, implicitly has an 'any' type." },
+        _0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type: { code: 7010, category: ts.DiagnosticCategory.Error, key: "'{0}', which lacks return-type annotation, implicitly has an '{1}' return type." },
+        Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type: { code: 7011, category: ts.DiagnosticCategory.Error, key: "Function expression, which lacks return-type annotation, implicitly has an '{0}' return type." },
+        Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7013, category: ts.DiagnosticCategory.Error, key: "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type." },
+        Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation: { code: 7016, category: ts.DiagnosticCategory.Error, key: "Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation." },
+        Index_signature_of_object_type_implicitly_has_an_any_type: { code: 7017, category: ts.DiagnosticCategory.Error, key: "Index signature of object type implicitly has an 'any' type." },
+        Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: ts.DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
+        Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: ts.DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
+        Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: ts.DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
+        _0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 7021, category: ts.DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation." },
+        _0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer: { code: 7022, category: ts.DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer." },
+        _0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7023, category: ts.DiagnosticCategory.Error, key: "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
+        Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: ts.DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
+        You_cannot_rename_this_element: { code: 8000, category: ts.DiagnosticCategory.Error, key: "You cannot rename this element." },
+        You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: { code: 8001, category: ts.DiagnosticCategory.Error, key: "You cannot rename elements that are defined in the standard TypeScript library." },
+        import_can_only_be_used_in_a_ts_file: { code: 8002, category: ts.DiagnosticCategory.Error, key: "'import ... =' can only be used in a .ts file." },
+        export_can_only_be_used_in_a_ts_file: { code: 8003, category: ts.DiagnosticCategory.Error, key: "'export=' can only be used in a .ts file." },
+        type_parameter_declarations_can_only_be_used_in_a_ts_file: { code: 8004, category: ts.DiagnosticCategory.Error, key: "'type parameter declarations' can only be used in a .ts file." },
+        implements_clauses_can_only_be_used_in_a_ts_file: { code: 8005, category: ts.DiagnosticCategory.Error, key: "'implements clauses' can only be used in a .ts file." },
+        interface_declarations_can_only_be_used_in_a_ts_file: { code: 8006, category: ts.DiagnosticCategory.Error, key: "'interface declarations' can only be used in a .ts file." },
+        module_declarations_can_only_be_used_in_a_ts_file: { code: 8007, category: ts.DiagnosticCategory.Error, key: "'module declarations' can only be used in a .ts file." },
+        type_aliases_can_only_be_used_in_a_ts_file: { code: 8008, category: ts.DiagnosticCategory.Error, key: "'type aliases' can only be used in a .ts file." },
+        _0_can_only_be_used_in_a_ts_file: { code: 8009, category: ts.DiagnosticCategory.Error, key: "'{0}' can only be used in a .ts file." },
+        types_can_only_be_used_in_a_ts_file: { code: 8010, category: ts.DiagnosticCategory.Error, key: "'types' can only be used in a .ts file." },
+        type_arguments_can_only_be_used_in_a_ts_file: { code: 8011, category: ts.DiagnosticCategory.Error, key: "'type arguments' can only be used in a .ts file." },
+        parameter_modifiers_can_only_be_used_in_a_ts_file: { code: 8012, category: ts.DiagnosticCategory.Error, key: "'parameter modifiers' can only be used in a .ts file." },
+        can_only_be_used_in_a_ts_file: { code: 8013, category: ts.DiagnosticCategory.Error, key: "'?' can only be used in a .ts file." },
+        property_declarations_can_only_be_used_in_a_ts_file: { code: 8014, category: ts.DiagnosticCategory.Error, key: "'property declarations' can only be used in a .ts file." },
+        enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: ts.DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." },
+        type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: ts.DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." },
+        decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: ts.DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." },
+        yield_expressions_are_not_currently_supported: { code: 9000, category: ts.DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
+        Generators_are_not_currently_supported: { code: 9001, category: ts.DiagnosticCategory.Error, key: "Generators are not currently supported." },
+        Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: ts.DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." },
+        class_expressions_are_not_currently_supported: { code: 9003, category: ts.DiagnosticCategory.Error, key: "'class' expressions are not currently supported." },
+        class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration: { code: 9004, category: ts.DiagnosticCategory.Error, key: "'class' declarations are only supported directly inside a module or as a top level declaration." },
+    };
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/emitter.js b/dist/typescript/compiler/emitter.js
new file mode 100644
index 000000000..8ccc93668
--- /dev/null
+++ b/dist/typescript/compiler/emitter.js
@@ -0,0 +1,4184 @@
+/// <reference path="checker.ts"/>
+/// <reference path="declarationEmitter.ts"/>
+var ts;
+(function (ts) {
+    function isExternalModuleOrDeclarationFile(sourceFile) {
+        return ts.isExternalModule(sourceFile) || ts.isDeclarationFile(sourceFile);
+    }
+    ts.isExternalModuleOrDeclarationFile = isExternalModuleOrDeclarationFile;
+    var TempFlags;
+    (function (TempFlags) {
+        TempFlags[TempFlags["Auto"] = 0] = "Auto";
+        TempFlags[TempFlags["CountMask"] = 268435455] = "CountMask";
+        TempFlags[TempFlags["_i"] = 268435456] = "_i";
+        TempFlags[TempFlags["_n"] = 536870912] = "_n";
+    })(TempFlags || (TempFlags = {}));
+    function emitFiles(resolver, host, targetSourceFile) {
+        var extendsHelper = "\nvar __extends = this.__extends || function (d, b) {\n    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n    function __() { this.constructor = d; }\n    __.prototype = b.prototype;\n    d.prototype = new __();\n};";
+        var decorateHelper = "\nif (typeof __decorate !== \"function\") __decorate = function (decorators, target, key, desc) {\n    if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") return Reflect.decorate(decorators, target, key, desc);\n    switch (arguments.length) {\n        case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);\n        case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);\n        case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);\n    }\n};";
+        var metadataHelper = "\nif (typeof __metadata !== \"function\") __metadata = function (k, v) {\n    if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};";
+        var paramHelper = "\nif (typeof __param !== \"function\") __param = function (paramIndex, decorator) {\n    return function (target, key) { decorator(target, key, paramIndex); }\n};";
+        var compilerOptions = host.getCompilerOptions();
+        var languageVersion = compilerOptions.target || 0;
+        var sourceMapDataList = compilerOptions.sourceMap ? [] : undefined;
+        var diagnostics = [];
+        var newLine = host.getNewLine();
+        if (targetSourceFile === undefined) {
+            ts.forEach(host.getSourceFiles(), function (sourceFile) {
+                if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) {
+                    var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, ".js");
+                    emitFile(jsFilePath, sourceFile);
+                }
+            });
+            if (compilerOptions.out) {
+                emitFile(compilerOptions.out);
+            }
+        }
+        else {
+            if (ts.shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
+                var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
+                emitFile(jsFilePath, targetSourceFile);
+            }
+            else if (!ts.isDeclarationFile(targetSourceFile) && compilerOptions.out) {
+                emitFile(compilerOptions.out);
+            }
+        }
+        diagnostics = ts.sortAndDeduplicateDiagnostics(diagnostics);
+        return {
+            emitSkipped: false,
+            diagnostics: diagnostics,
+            sourceMaps: sourceMapDataList
+        };
+        function isNodeDescendentOf(node, ancestor) {
+            while (node) {
+                if (node === ancestor)
+                    return true;
+                node = node.parent;
+            }
+            return false;
+        }
+        function isUniqueLocalName(name, container) {
+            for (var node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
+                if (node.locals && ts.hasProperty(node.locals, name)) {
+                    if (node.locals[name].flags & (107455 | 1048576 | 8388608)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        function emitJavaScript(jsFilePath, root) {
+            var writer = ts.createTextWriter(newLine);
+            var write = writer.write;
+            var writeTextOfNode = writer.writeTextOfNode;
+            var writeLine = writer.writeLine;
+            var increaseIndent = writer.increaseIndent;
+            var decreaseIndent = writer.decreaseIndent;
+            var currentSourceFile;
+            var generatedNameSet = {};
+            var nodeToGeneratedName = [];
+            var blockScopedVariableToGeneratedName;
+            var computedPropertyNamesToGeneratedNames;
+            var extendsEmitted = false;
+            var decorateEmitted = false;
+            var paramEmitted = false;
+            var tempFlags = 0;
+            var tempVariables;
+            var tempParameters;
+            var externalImports;
+            var exportSpecifiers;
+            var exportEquals;
+            var hasExportStars;
+            var writeEmittedFiles = writeJavaScriptFile;
+            var detachedCommentsInfo;
+            var writeComment = ts.writeCommentRange;
+            var emit = emitNodeWithoutSourceMap;
+            var emitStart = function (node) { };
+            var emitEnd = function (node) { };
+            var emitToken = emitTokenText;
+            var scopeEmitStart = function (scopeDeclaration, scopeName) { };
+            var scopeEmitEnd = function () { };
+            var sourceMapData;
+            if (compilerOptions.sourceMap) {
+                initializeEmitterWithSourceMaps();
+            }
+            if (root) {
+                emitSourceFile(root);
+            }
+            else {
+                ts.forEach(host.getSourceFiles(), function (sourceFile) {
+                    if (!isExternalModuleOrDeclarationFile(sourceFile)) {
+                        emitSourceFile(sourceFile);
+                    }
+                });
+            }
+            writeLine();
+            writeEmittedFiles(writer.getText(), compilerOptions.emitBOM);
+            return;
+            function emitSourceFile(sourceFile) {
+                currentSourceFile = sourceFile;
+                emit(sourceFile);
+            }
+            function isUniqueName(name) {
+                return !resolver.hasGlobalName(name) &&
+                    !ts.hasProperty(currentSourceFile.identifiers, name) &&
+                    !ts.hasProperty(generatedNameSet, name);
+            }
+            function makeTempVariableName(flags) {
+                if (flags && !(tempFlags & flags)) {
+                    var name = flags === 268435456 ? "_i" : "_n";
+                    if (isUniqueName(name)) {
+                        tempFlags |= flags;
+                        return name;
+                    }
+                }
+                while (true) {
+                    var count = tempFlags & 268435455;
+                    tempFlags++;
+                    if (count !== 8 && count !== 13) {
+                        var name_1 = count < 26 ? "_" + String.fromCharCode(97 + count) : "_" + (count - 26);
+                        if (isUniqueName(name_1)) {
+                            return name_1;
+                        }
+                    }
+                }
+            }
+            function makeUniqueName(baseName) {
+                if (baseName.charCodeAt(baseName.length - 1) !== 95) {
+                    baseName += "_";
+                }
+                var i = 1;
+                while (true) {
+                    var generatedName = baseName + i;
+                    if (isUniqueName(generatedName)) {
+                        return generatedNameSet[generatedName] = generatedName;
+                    }
+                    i++;
+                }
+            }
+            function assignGeneratedName(node, name) {
+                nodeToGeneratedName[ts.getNodeId(node)] = ts.unescapeIdentifier(name);
+            }
+            function generateNameForFunctionOrClassDeclaration(node) {
+                if (!node.name) {
+                    assignGeneratedName(node, makeUniqueName("default"));
+                }
+            }
+            function generateNameForModuleOrEnum(node) {
+                if (node.name.kind === 65) {
+                    var name_2 = node.name.text;
+                    assignGeneratedName(node, isUniqueLocalName(name_2, node) ? name_2 : makeUniqueName(name_2));
+                }
+            }
+            function generateNameForImportOrExportDeclaration(node) {
+                var expr = ts.getExternalModuleName(node);
+                var baseName = expr.kind === 8 ?
+                    ts.escapeIdentifier(ts.makeIdentifierFromModuleName(expr.text)) : "module";
+                assignGeneratedName(node, makeUniqueName(baseName));
+            }
+            function generateNameForImportDeclaration(node) {
+                if (node.importClause) {
+                    generateNameForImportOrExportDeclaration(node);
+                }
+            }
+            function generateNameForExportDeclaration(node) {
+                if (node.moduleSpecifier) {
+                    generateNameForImportOrExportDeclaration(node);
+                }
+            }
+            function generateNameForExportAssignment(node) {
+                if (node.expression && node.expression.kind !== 65) {
+                    assignGeneratedName(node, makeUniqueName("default"));
+                }
+            }
+            function generateNameForNode(node) {
+                switch (node.kind) {
+                    case 200:
+                    case 201:
+                    case 174:
+                        generateNameForFunctionOrClassDeclaration(node);
+                        break;
+                    case 205:
+                        generateNameForModuleOrEnum(node);
+                        generateNameForNode(node.body);
+                        break;
+                    case 204:
+                        generateNameForModuleOrEnum(node);
+                        break;
+                    case 209:
+                        generateNameForImportDeclaration(node);
+                        break;
+                    case 215:
+                        generateNameForExportDeclaration(node);
+                        break;
+                    case 214:
+                        generateNameForExportAssignment(node);
+                        break;
+                }
+            }
+            function getGeneratedNameForNode(node) {
+                var nodeId = ts.getNodeId(node);
+                if (!nodeToGeneratedName[nodeId]) {
+                    generateNameForNode(node);
+                }
+                return nodeToGeneratedName[nodeId];
+            }
+            function initializeEmitterWithSourceMaps() {
+                var sourceMapDir;
+                var sourceMapSourceIndex = -1;
+                var sourceMapNameIndexMap = {};
+                var sourceMapNameIndices = [];
+                function getSourceMapNameIndex() {
+                    return sourceMapNameIndices.length ? sourceMapNameIndices[sourceMapNameIndices.length - 1] : -1;
+                }
+                var lastRecordedSourceMapSpan;
+                var lastEncodedSourceMapSpan = {
+                    emittedLine: 1,
+                    emittedColumn: 1,
+                    sourceLine: 1,
+                    sourceColumn: 1,
+                    sourceIndex: 0
+                };
+                var lastEncodedNameIndex = 0;
+                function encodeLastRecordedSourceMapSpan() {
+                    if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
+                        return;
+                    }
+                    var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
+                    if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
+                        if (sourceMapData.sourceMapMappings) {
+                            sourceMapData.sourceMapMappings += ",";
+                        }
+                    }
+                    else {
+                        for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
+                            sourceMapData.sourceMapMappings += ";";
+                        }
+                        prevEncodedEmittedColumn = 1;
+                    }
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
+                    if (lastRecordedSourceMapSpan.nameIndex >= 0) {
+                        sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
+                        lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
+                    }
+                    lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
+                    sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
+                    function base64VLQFormatEncode(inValue) {
+                        function base64FormatEncode(inValue) {
+                            if (inValue < 64) {
+                                return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(inValue);
+                            }
+                            throw TypeError(inValue + ": not a 64 based value");
+                        }
+                        if (inValue < 0) {
+                            inValue = ((-inValue) << 1) + 1;
+                        }
+                        else {
+                            inValue = inValue << 1;
+                        }
+                        var encodedStr = "";
+                        do {
+                            var currentDigit = inValue & 31;
+                            inValue = inValue >> 5;
+                            if (inValue > 0) {
+                                currentDigit = currentDigit | 32;
+                            }
+                            encodedStr = encodedStr + base64FormatEncode(currentDigit);
+                        } while (inValue > 0);
+                        return encodedStr;
+                    }
+                }
+                function recordSourceMapSpan(pos) {
+                    var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos);
+                    sourceLinePos.line++;
+                    sourceLinePos.character++;
+                    var emittedLine = writer.getLine();
+                    var emittedColumn = writer.getColumn();
+                    if (!lastRecordedSourceMapSpan ||
+                        lastRecordedSourceMapSpan.emittedLine != emittedLine ||
+                        lastRecordedSourceMapSpan.emittedColumn != emittedColumn ||
+                        (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
+                            (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
+                                (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
+                        encodeLastRecordedSourceMapSpan();
+                        lastRecordedSourceMapSpan = {
+                            emittedLine: emittedLine,
+                            emittedColumn: emittedColumn,
+                            sourceLine: sourceLinePos.line,
+                            sourceColumn: sourceLinePos.character,
+                            nameIndex: getSourceMapNameIndex(),
+                            sourceIndex: sourceMapSourceIndex
+                        };
+                    }
+                    else {
+                        lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
+                        lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
+                        lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
+                    }
+                }
+                function recordEmitNodeStartSpan(node) {
+                    recordSourceMapSpan(ts.skipTrivia(currentSourceFile.text, node.pos));
+                }
+                function recordEmitNodeEndSpan(node) {
+                    recordSourceMapSpan(node.end);
+                }
+                function writeTextWithSpanRecord(tokenKind, startPos, emitFn) {
+                    var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
+                    recordSourceMapSpan(tokenStartPos);
+                    var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
+                    recordSourceMapSpan(tokenEndPos);
+                    return tokenEndPos;
+                }
+                function recordNewSourceFileStart(node) {
+                    var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
+                    sourceMapData.sourceMapSources.push(ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, node.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, true));
+                    sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
+                    sourceMapData.inputSourceFileNames.push(node.fileName);
+                }
+                function recordScopeNameOfNode(node, scopeName) {
+                    function recordScopeNameIndex(scopeNameIndex) {
+                        sourceMapNameIndices.push(scopeNameIndex);
+                    }
+                    function recordScopeNameStart(scopeName) {
+                        var scopeNameIndex = -1;
+                        if (scopeName) {
+                            var parentIndex = getSourceMapNameIndex();
+                            if (parentIndex !== -1) {
+                                var name_3 = node.name;
+                                if (!name_3 || name_3.kind !== 127) {
+                                    scopeName = "." + scopeName;
+                                }
+                                scopeName = sourceMapData.sourceMapNames[parentIndex] + scopeName;
+                            }
+                            scopeNameIndex = ts.getProperty(sourceMapNameIndexMap, scopeName);
+                            if (scopeNameIndex === undefined) {
+                                scopeNameIndex = sourceMapData.sourceMapNames.length;
+                                sourceMapData.sourceMapNames.push(scopeName);
+                                sourceMapNameIndexMap[scopeName] = scopeNameIndex;
+                            }
+                        }
+                        recordScopeNameIndex(scopeNameIndex);
+                    }
+                    if (scopeName) {
+                        recordScopeNameStart(scopeName);
+                    }
+                    else if (node.kind === 200 ||
+                        node.kind === 162 ||
+                        node.kind === 134 ||
+                        node.kind === 133 ||
+                        node.kind === 136 ||
+                        node.kind === 137 ||
+                        node.kind === 205 ||
+                        node.kind === 201 ||
+                        node.kind === 204) {
+                        if (node.name) {
+                            var name_4 = node.name;
+                            scopeName = name_4.kind === 127
+                                ? ts.getTextOfNode(name_4)
+                                : node.name.text;
+                        }
+                        recordScopeNameStart(scopeName);
+                    }
+                    else {
+                        recordScopeNameIndex(getSourceMapNameIndex());
+                    }
+                }
+                function recordScopeNameEnd() {
+                    sourceMapNameIndices.pop();
+                }
+                ;
+                function writeCommentRangeWithMap(curentSourceFile, writer, comment, newLine) {
+                    recordSourceMapSpan(comment.pos);
+                    ts.writeCommentRange(currentSourceFile, writer, comment, newLine);
+                    recordSourceMapSpan(comment.end);
+                }
+                function serializeSourceMapContents(version, file, sourceRoot, sources, names, mappings) {
+                    if (typeof JSON !== "undefined") {
+                        return JSON.stringify({
+                            version: version,
+                            file: file,
+                            sourceRoot: sourceRoot,
+                            sources: sources,
+                            names: names,
+                            mappings: mappings
+                        });
+                    }
+                    return "{\"version\":" + version + ",\"file\":\"" + ts.escapeString(file) + "\",\"sourceRoot\":\"" + ts.escapeString(sourceRoot) + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + ts.escapeString(mappings) + "\"}";
+                    function serializeStringArray(list) {
+                        var output = "";
+                        for (var i = 0, n = list.length; i < n; i++) {
+                            if (i) {
+                                output += ",";
+                            }
+                            output += "\"" + ts.escapeString(list[i]) + "\"";
+                        }
+                        return output;
+                    }
+                }
+                function writeJavaScriptAndSourceMapFile(emitOutput, writeByteOrderMark) {
+                    encodeLastRecordedSourceMapSpan();
+                    ts.writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(3, sourceMapData.sourceMapFile, sourceMapData.sourceMapSourceRoot, sourceMapData.sourceMapSources, sourceMapData.sourceMapNames, sourceMapData.sourceMapMappings), false);
+                    sourceMapDataList.push(sourceMapData);
+                    writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL, writeByteOrderMark);
+                }
+                var sourceMapJsFile = ts.getBaseFileName(ts.normalizeSlashes(jsFilePath));
+                sourceMapData = {
+                    sourceMapFilePath: jsFilePath + ".map",
+                    jsSourceMappingURL: sourceMapJsFile + ".map",
+                    sourceMapFile: sourceMapJsFile,
+                    sourceMapSourceRoot: compilerOptions.sourceRoot || "",
+                    sourceMapSources: [],
+                    inputSourceFileNames: [],
+                    sourceMapNames: [],
+                    sourceMapMappings: "",
+                    sourceMapDecodedMappings: []
+                };
+                sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
+                if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47) {
+                    sourceMapData.sourceMapSourceRoot += ts.directorySeparator;
+                }
+                if (compilerOptions.mapRoot) {
+                    sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot);
+                    if (root) {
+                        sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(root, host, sourceMapDir));
+                    }
+                    if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) {
+                        sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
+                        sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(jsFilePath)), ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), host.getCurrentDirectory(), host.getCanonicalFileName, true);
+                    }
+                    else {
+                        sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
+                    }
+                }
+                else {
+                    sourceMapDir = ts.getDirectoryPath(ts.normalizePath(jsFilePath));
+                }
+                function emitNodeWithSourceMap(node, allowGeneratedIdentifiers) {
+                    if (node) {
+                        if (ts.nodeIsSynthesized(node)) {
+                            return emitNodeWithoutSourceMap(node, false);
+                        }
+                        if (node.kind != 227) {
+                            recordEmitNodeStartSpan(node);
+                            emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers);
+                            recordEmitNodeEndSpan(node);
+                        }
+                        else {
+                            recordNewSourceFileStart(node);
+                            emitNodeWithoutSourceMap(node, false);
+                        }
+                    }
+                }
+                writeEmittedFiles = writeJavaScriptAndSourceMapFile;
+                emit = emitNodeWithSourceMap;
+                emitStart = recordEmitNodeStartSpan;
+                emitEnd = recordEmitNodeEndSpan;
+                emitToken = writeTextWithSpanRecord;
+                scopeEmitStart = recordScopeNameOfNode;
+                scopeEmitEnd = recordScopeNameEnd;
+                writeComment = writeCommentRangeWithMap;
+            }
+            function writeJavaScriptFile(emitOutput, writeByteOrderMark) {
+                ts.writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
+            }
+            function createTempVariable(flags) {
+                var result = ts.createSynthesizedNode(65);
+                result.text = makeTempVariableName(flags);
+                return result;
+            }
+            function recordTempDeclaration(name) {
+                if (!tempVariables) {
+                    tempVariables = [];
+                }
+                tempVariables.push(name);
+            }
+            function createAndRecordTempVariable(flags) {
+                var temp = createTempVariable(flags);
+                recordTempDeclaration(temp);
+                return temp;
+            }
+            function emitTempDeclarations(newLine) {
+                if (tempVariables) {
+                    if (newLine) {
+                        writeLine();
+                    }
+                    else {
+                        write(" ");
+                    }
+                    write("var ");
+                    emitCommaList(tempVariables);
+                    write(";");
+                }
+            }
+            function emitTokenText(tokenKind, startPos, emitFn) {
+                var tokenString = ts.tokenToString(tokenKind);
+                if (emitFn) {
+                    emitFn();
+                }
+                else {
+                    write(tokenString);
+                }
+                return startPos + tokenString.length;
+            }
+            function emitOptional(prefix, node) {
+                if (node) {
+                    write(prefix);
+                    emit(node);
+                }
+            }
+            function emitParenthesizedIf(node, parenthesized) {
+                if (parenthesized) {
+                    write("(");
+                }
+                emit(node);
+                if (parenthesized) {
+                    write(")");
+                }
+            }
+            function emitTrailingCommaIfPresent(nodeList) {
+                if (nodeList.hasTrailingComma) {
+                    write(",");
+                }
+            }
+            function emitLinePreservingList(parent, nodes, allowTrailingComma, spacesBetweenBraces) {
+                ts.Debug.assert(nodes.length > 0);
+                increaseIndent();
+                if (nodeStartPositionsAreOnSameLine(parent, nodes[0])) {
+                    if (spacesBetweenBraces) {
+                        write(" ");
+                    }
+                }
+                else {
+                    writeLine();
+                }
+                for (var i = 0, n = nodes.length; i < n; i++) {
+                    if (i) {
+                        if (nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i])) {
+                            write(", ");
+                        }
+                        else {
+                            write(",");
+                            writeLine();
+                        }
+                    }
+                    emit(nodes[i]);
+                }
+                if (nodes.hasTrailingComma && allowTrailingComma) {
+                    write(",");
+                }
+                decreaseIndent();
+                if (nodeEndPositionsAreOnSameLine(parent, ts.lastOrUndefined(nodes))) {
+                    if (spacesBetweenBraces) {
+                        write(" ");
+                    }
+                }
+                else {
+                    writeLine();
+                }
+            }
+            function emitList(nodes, start, count, multiLine, trailingComma, leadingComma, noTrailingNewLine, emitNode) {
+                if (!emitNode) {
+                    emitNode = emit;
+                }
+                for (var i = 0; i < count; i++) {
+                    if (multiLine) {
+                        if (i || leadingComma) {
+                            write(",");
+                        }
+                        writeLine();
+                    }
+                    else {
+                        if (i || leadingComma) {
+                            write(", ");
+                        }
+                    }
+                    emitNode(nodes[start + i]);
+                    leadingComma = true;
+                }
+                if (trailingComma) {
+                    write(",");
+                }
+                if (multiLine && !noTrailingNewLine) {
+                    writeLine();
+                }
+                return count;
+            }
+            function emitCommaList(nodes) {
+                if (nodes) {
+                    emitList(nodes, 0, nodes.length, false, false);
+                }
+            }
+            function emitLines(nodes) {
+                emitLinesStartingAt(nodes, 0);
+            }
+            function emitLinesStartingAt(nodes, startIndex) {
+                for (var i = startIndex; i < nodes.length; i++) {
+                    writeLine();
+                    emit(nodes[i]);
+                }
+            }
+            function isBinaryOrOctalIntegerLiteral(node, text) {
+                if (node.kind === 7 && text.length > 1) {
+                    switch (text.charCodeAt(1)) {
+                        case 98:
+                        case 66:
+                        case 111:
+                        case 79:
+                            return true;
+                    }
+                }
+                return false;
+            }
+            function emitLiteral(node) {
+                var text = getLiteralText(node);
+                if (compilerOptions.sourceMap && (node.kind === 8 || ts.isTemplateLiteralKind(node.kind))) {
+                    writer.writeLiteral(text);
+                }
+                else if (languageVersion < 2 && isBinaryOrOctalIntegerLiteral(node, text)) {
+                    write(node.text);
+                }
+                else {
+                    write(text);
+                }
+            }
+            function getLiteralText(node) {
+                if (languageVersion < 2 && (ts.isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
+                    return getQuotedEscapedLiteralText('"', node.text, '"');
+                }
+                if (node.parent) {
+                    return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
+                }
+                switch (node.kind) {
+                    case 8:
+                        return getQuotedEscapedLiteralText('"', node.text, '"');
+                    case 10:
+                        return getQuotedEscapedLiteralText('`', node.text, '`');
+                    case 11:
+                        return getQuotedEscapedLiteralText('`', node.text, '${');
+                    case 12:
+                        return getQuotedEscapedLiteralText('}', node.text, '${');
+                    case 13:
+                        return getQuotedEscapedLiteralText('}', node.text, '`');
+                    case 7:
+                        return node.text;
+                }
+                ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for.");
+            }
+            function getQuotedEscapedLiteralText(leftQuote, text, rightQuote) {
+                return leftQuote + ts.escapeNonAsciiCharacters(ts.escapeString(text)) + rightQuote;
+            }
+            function emitDownlevelRawTemplateLiteral(node) {
+                var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
+                var isLast = node.kind === 10 || node.kind === 13;
+                text = text.substring(1, text.length - (isLast ? 1 : 2));
+                text = text.replace(/\r\n?/g, "\n");
+                text = ts.escapeString(text);
+                write('"' + text + '"');
+            }
+            function emitDownlevelTaggedTemplateArray(node, literalEmitter) {
+                write("[");
+                if (node.template.kind === 10) {
+                    literalEmitter(node.template);
+                }
+                else {
+                    literalEmitter(node.template.head);
+                    ts.forEach(node.template.templateSpans, function (child) {
+                        write(", ");
+                        literalEmitter(child.literal);
+                    });
+                }
+                write("]");
+            }
+            function emitDownlevelTaggedTemplate(node) {
+                var tempVariable = createAndRecordTempVariable(0);
+                write("(");
+                emit(tempVariable);
+                write(" = ");
+                emitDownlevelTaggedTemplateArray(node, emit);
+                write(", ");
+                emit(tempVariable);
+                write(".raw = ");
+                emitDownlevelTaggedTemplateArray(node, emitDownlevelRawTemplateLiteral);
+                write(", ");
+                emitParenthesizedIf(node.tag, needsParenthesisForPropertyAccessOrInvocation(node.tag));
+                write("(");
+                emit(tempVariable);
+                if (node.template.kind === 171) {
+                    ts.forEach(node.template.templateSpans, function (templateSpan) {
+                        write(", ");
+                        var needsParens = templateSpan.expression.kind === 169
+                            && templateSpan.expression.operatorToken.kind === 23;
+                        emitParenthesizedIf(templateSpan.expression, needsParens);
+                    });
+                }
+                write("))");
+            }
+            function emitTemplateExpression(node) {
+                if (languageVersion >= 2) {
+                    ts.forEachChild(node, emit);
+                    return;
+                }
+                var emitOuterParens = ts.isExpression(node.parent)
+                    && templateNeedsParens(node, node.parent);
+                if (emitOuterParens) {
+                    write("(");
+                }
+                var headEmitted = false;
+                if (shouldEmitTemplateHead()) {
+                    emitLiteral(node.head);
+                    headEmitted = true;
+                }
+                for (var i = 0, n = node.templateSpans.length; i < n; i++) {
+                    var templateSpan = node.templateSpans[i];
+                    var needsParens = templateSpan.expression.kind !== 161
+                        && comparePrecedenceToBinaryPlus(templateSpan.expression) !== 1;
+                    if (i > 0 || headEmitted) {
+                        write(" + ");
+                    }
+                    emitParenthesizedIf(templateSpan.expression, needsParens);
+                    if (templateSpan.literal.text.length !== 0) {
+                        write(" + ");
+                        emitLiteral(templateSpan.literal);
+                    }
+                }
+                if (emitOuterParens) {
+                    write(")");
+                }
+                function shouldEmitTemplateHead() {
+                    // If this expression has an empty head literal and the first template span has a non-empty
+                    // literal, then emitting the empty head literal is not necessary.
+                    //     `${ foo } and ${ bar }`
+                    // can be emitted as
+                    //     foo + " and " + bar
+                    // This is because it is only required that one of the first two operands in the emit
+                    // output must be a string literal, so that the other operand and all following operands
+                    // are forced into strings.
+                    //
+                    // If the first template span has an empty literal, then the head must still be emitted.
+                    //     `${ foo }${ bar }`
+                    // must still be emitted as
+                    //     "" + foo + bar
+                    ts.Debug.assert(node.templateSpans.length !== 0);
+                    return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0;
+                }
+                function templateNeedsParens(template, parent) {
+                    switch (parent.kind) {
+                        case 157:
+                        case 158:
+                            return parent.expression === template;
+                        case 159:
+                        case 161:
+                            return false;
+                        default:
+                            return comparePrecedenceToBinaryPlus(parent) !== -1;
+                    }
+                }
+                function comparePrecedenceToBinaryPlus(expression) {
+                    switch (expression.kind) {
+                        case 169:
+                            switch (expression.operatorToken.kind) {
+                                case 35:
+                                case 36:
+                                case 37:
+                                    return 1;
+                                case 33:
+                                case 34:
+                                    return 0;
+                                default:
+                                    return -1;
+                            }
+                        case 172:
+                        case 170:
+                            return -1;
+                        default:
+                            return 1;
+                    }
+                }
+            }
+            function emitTemplateSpan(span) {
+                emit(span.expression);
+                emit(span.literal);
+            }
+            function emitExpressionForPropertyName(node) {
+                ts.Debug.assert(node.kind !== 152);
+                if (node.kind === 8) {
+                    emitLiteral(node);
+                }
+                else if (node.kind === 127) {
+                    if (ts.nodeIsDecorated(node.parent)) {
+                        if (!computedPropertyNamesToGeneratedNames) {
+                            computedPropertyNamesToGeneratedNames = [];
+                        }
+                        var generatedName = computedPropertyNamesToGeneratedNames[ts.getNodeId(node)];
+                        if (generatedName) {
+                            write(generatedName);
+                            return;
+                        }
+                        generatedName = createAndRecordTempVariable(0).text;
+                        computedPropertyNamesToGeneratedNames[ts.getNodeId(node)] = generatedName;
+                        write(generatedName);
+                        write(" = ");
+                    }
+                    emit(node.expression);
+                }
+                else {
+                    write("\"");
+                    if (node.kind === 7) {
+                        write(node.text);
+                    }
+                    else {
+                        writeTextOfNode(currentSourceFile, node);
+                    }
+                    write("\"");
+                }
+            }
+            function isNotExpressionIdentifier(node) {
+                var parent = node.parent;
+                switch (parent.kind) {
+                    case 129:
+                    case 198:
+                    case 152:
+                    case 132:
+                    case 131:
+                    case 224:
+                    case 225:
+                    case 226:
+                    case 134:
+                    case 133:
+                    case 200:
+                    case 136:
+                    case 137:
+                    case 162:
+                    case 201:
+                    case 202:
+                    case 204:
+                    case 205:
+                    case 208:
+                    case 210:
+                    case 211:
+                        return parent.name === node;
+                    case 213:
+                    case 217:
+                        return parent.name === node || parent.propertyName === node;
+                    case 190:
+                    case 189:
+                    case 214:
+                        return false;
+                    case 194:
+                        return node.parent.label === node;
+                }
+            }
+            function emitExpressionIdentifier(node) {
+                var substitution = resolver.getExpressionNameSubstitution(node, getGeneratedNameForNode);
+                if (substitution) {
+                    write(substitution);
+                }
+                else {
+                    writeTextOfNode(currentSourceFile, node);
+                }
+            }
+            function getGeneratedNameForIdentifier(node) {
+                if (ts.nodeIsSynthesized(node) || !blockScopedVariableToGeneratedName) {
+                    return undefined;
+                }
+                var variableId = resolver.getBlockScopedVariableId(node);
+                if (variableId === undefined) {
+                    return undefined;
+                }
+                return blockScopedVariableToGeneratedName[variableId];
+            }
+            function emitIdentifier(node, allowGeneratedIdentifiers) {
+                if (allowGeneratedIdentifiers) {
+                    var generatedName = getGeneratedNameForIdentifier(node);
+                    if (generatedName) {
+                        write(generatedName);
+                        return;
+                    }
+                }
+                if (!node.parent) {
+                    write(node.text);
+                }
+                else if (!isNotExpressionIdentifier(node)) {
+                    emitExpressionIdentifier(node);
+                }
+                else {
+                    writeTextOfNode(currentSourceFile, node);
+                }
+            }
+            function emitThis(node) {
+                if (resolver.getNodeCheckFlags(node) & 2) {
+                    write("_this");
+                }
+                else {
+                    write("this");
+                }
+            }
+            function emitSuper(node) {
+                if (languageVersion >= 2) {
+                    write("super");
+                }
+                else {
+                    var flags = resolver.getNodeCheckFlags(node);
+                    if (flags & 16) {
+                        write("_super.prototype");
+                    }
+                    else {
+                        write("_super");
+                    }
+                }
+            }
+            function emitObjectBindingPattern(node) {
+                write("{ ");
+                var elements = node.elements;
+                emitList(elements, 0, elements.length, false, elements.hasTrailingComma);
+                write(" }");
+            }
+            function emitArrayBindingPattern(node) {
+                write("[");
+                var elements = node.elements;
+                emitList(elements, 0, elements.length, false, elements.hasTrailingComma);
+                write("]");
+            }
+            function emitBindingElement(node) {
+                if (node.propertyName) {
+                    emit(node.propertyName, false);
+                    write(": ");
+                }
+                if (node.dotDotDotToken) {
+                    write("...");
+                }
+                if (ts.isBindingPattern(node.name)) {
+                    emit(node.name);
+                }
+                else {
+                    emitModuleMemberName(node);
+                }
+                emitOptional(" = ", node.initializer);
+            }
+            function emitSpreadElementExpression(node) {
+                write("...");
+                emit(node.expression);
+            }
+            function emitYieldExpression(node) {
+                write(ts.tokenToString(110));
+                if (node.asteriskToken) {
+                    write("*");
+                }
+                if (node.expression) {
+                    write(" ");
+                    emit(node.expression);
+                }
+            }
+            function needsParenthesisForPropertyAccessOrInvocation(node) {
+                switch (node.kind) {
+                    case 65:
+                    case 153:
+                    case 155:
+                    case 156:
+                    case 157:
+                    case 161:
+                        return false;
+                }
+                return true;
+            }
+            function emitListWithSpread(elements, multiLine, trailingComma) {
+                var pos = 0;
+                var group = 0;
+                var length = elements.length;
+                while (pos < length) {
+                    if (group === 1) {
+                        write(".concat(");
+                    }
+                    else if (group > 1) {
+                        write(", ");
+                    }
+                    var e = elements[pos];
+                    if (e.kind === 173) {
+                        e = e.expression;
+                        emitParenthesizedIf(e, group === 0 && needsParenthesisForPropertyAccessOrInvocation(e));
+                        pos++;
+                    }
+                    else {
+                        var i = pos;
+                        while (i < length && elements[i].kind !== 173) {
+                            i++;
+                        }
+                        write("[");
+                        if (multiLine) {
+                            increaseIndent();
+                        }
+                        emitList(elements, pos, i - pos, multiLine, trailingComma && i === length);
+                        if (multiLine) {
+                            decreaseIndent();
+                        }
+                        write("]");
+                        pos = i;
+                    }
+                    group++;
+                }
+                if (group > 1) {
+                    write(")");
+                }
+            }
+            function isSpreadElementExpression(node) {
+                return node.kind === 173;
+            }
+            function emitArrayLiteral(node) {
+                var elements = node.elements;
+                if (elements.length === 0) {
+                    write("[]");
+                }
+                else if (languageVersion >= 2 || !ts.forEach(elements, isSpreadElementExpression)) {
+                    write("[");
+                    emitLinePreservingList(node, node.elements, elements.hasTrailingComma, false);
+                    write("]");
+                }
+                else {
+                    emitListWithSpread(elements, (node.flags & 512) !== 0, elements.hasTrailingComma);
+                }
+            }
+            function emitObjectLiteralBody(node, numElements) {
+                if (numElements === 0) {
+                    write("{}");
+                    return;
+                }
+                write("{");
+                if (numElements > 0) {
+                    var properties = node.properties;
+                    if (numElements === properties.length) {
+                        emitLinePreservingList(node, properties, languageVersion >= 1, true);
+                    }
+                    else {
+                        var multiLine = (node.flags & 512) !== 0;
+                        if (!multiLine) {
+                            write(" ");
+                        }
+                        else {
+                            increaseIndent();
+                        }
+                        emitList(properties, 0, numElements, multiLine, false);
+                        if (!multiLine) {
+                            write(" ");
+                        }
+                        else {
+                            decreaseIndent();
+                        }
+                    }
+                }
+                write("}");
+            }
+            function emitDownlevelObjectLiteralWithComputedProperties(node, firstComputedPropertyIndex) {
+                var multiLine = (node.flags & 512) !== 0;
+                var properties = node.properties;
+                write("(");
+                if (multiLine) {
+                    increaseIndent();
+                }
+                var tempVar = createAndRecordTempVariable(0);
+                emit(tempVar);
+                write(" = ");
+                emitObjectLiteralBody(node, firstComputedPropertyIndex);
+                for (var i = firstComputedPropertyIndex, n = properties.length; i < n; i++) {
+                    writeComma();
+                    var property = properties[i];
+                    emitStart(property);
+                    if (property.kind === 136 || property.kind === 137) {
+                        var accessors = ts.getAllAccessorDeclarations(node.properties, property);
+                        if (property !== accessors.firstAccessor) {
+                            continue;
+                        }
+                        write("Object.defineProperty(");
+                        emit(tempVar);
+                        write(", ");
+                        emitStart(node.name);
+                        emitExpressionForPropertyName(property.name);
+                        emitEnd(property.name);
+                        write(", {");
+                        increaseIndent();
+                        if (accessors.getAccessor) {
+                            writeLine();
+                            emitLeadingComments(accessors.getAccessor);
+                            write("get: ");
+                            emitStart(accessors.getAccessor);
+                            write("function ");
+                            emitSignatureAndBody(accessors.getAccessor);
+                            emitEnd(accessors.getAccessor);
+                            emitTrailingComments(accessors.getAccessor);
+                            write(",");
+                        }
+                        if (accessors.setAccessor) {
+                            writeLine();
+                            emitLeadingComments(accessors.setAccessor);
+                            write("set: ");
+                            emitStart(accessors.setAccessor);
+                            write("function ");
+                            emitSignatureAndBody(accessors.setAccessor);
+                            emitEnd(accessors.setAccessor);
+                            emitTrailingComments(accessors.setAccessor);
+                            write(",");
+                        }
+                        writeLine();
+                        write("enumerable: true,");
+                        writeLine();
+                        write("configurable: true");
+                        decreaseIndent();
+                        writeLine();
+                        write("})");
+                        emitEnd(property);
+                    }
+                    else {
+                        emitLeadingComments(property);
+                        emitStart(property.name);
+                        emit(tempVar);
+                        emitMemberAccessForPropertyName(property.name);
+                        emitEnd(property.name);
+                        write(" = ");
+                        if (property.kind === 224) {
+                            emit(property.initializer);
+                        }
+                        else if (property.kind === 225) {
+                            emitExpressionIdentifier(property.name);
+                        }
+                        else if (property.kind === 134) {
+                            emitFunctionDeclaration(property);
+                        }
+                        else {
+                            ts.Debug.fail("ObjectLiteralElement type not accounted for: " + property.kind);
+                        }
+                    }
+                    emitEnd(property);
+                }
+                writeComma();
+                emit(tempVar);
+                if (multiLine) {
+                    decreaseIndent();
+                    writeLine();
+                }
+                write(")");
+                function writeComma() {
+                    if (multiLine) {
+                        write(",");
+                        writeLine();
+                    }
+                    else {
+                        write(", ");
+                    }
+                }
+            }
+            function emitObjectLiteral(node) {
+                var properties = node.properties;
+                if (languageVersion < 2) {
+                    var numProperties = properties.length;
+                    var numInitialNonComputedProperties = numProperties;
+                    for (var i = 0, n = properties.length; i < n; i++) {
+                        if (properties[i].name.kind === 127) {
+                            numInitialNonComputedProperties = i;
+                            break;
+                        }
+                    }
+                    var hasComputedProperty = numInitialNonComputedProperties !== properties.length;
+                    if (hasComputedProperty) {
+                        emitDownlevelObjectLiteralWithComputedProperties(node, numInitialNonComputedProperties);
+                        return;
+                    }
+                }
+                emitObjectLiteralBody(node, properties.length);
+            }
+            function createBinaryExpression(left, operator, right, startsOnNewLine) {
+                var result = ts.createSynthesizedNode(169, startsOnNewLine);
+                result.operatorToken = ts.createSynthesizedNode(operator);
+                result.left = left;
+                result.right = right;
+                return result;
+            }
+            function createPropertyAccessExpression(expression, name) {
+                var result = ts.createSynthesizedNode(155);
+                result.expression = parenthesizeForAccess(expression);
+                result.dotToken = ts.createSynthesizedNode(20);
+                result.name = name;
+                return result;
+            }
+            function createElementAccessExpression(expression, argumentExpression) {
+                var result = ts.createSynthesizedNode(156);
+                result.expression = parenthesizeForAccess(expression);
+                result.argumentExpression = argumentExpression;
+                return result;
+            }
+            function parenthesizeForAccess(expr) {
+                if (ts.isLeftHandSideExpression(expr) && expr.kind !== 158 && expr.kind !== 7) {
+                    return expr;
+                }
+                var node = ts.createSynthesizedNode(161);
+                node.expression = expr;
+                return node;
+            }
+            function emitComputedPropertyName(node) {
+                write("[");
+                emitExpressionForPropertyName(node);
+                write("]");
+            }
+            function emitMethod(node) {
+                if (languageVersion >= 2 && node.asteriskToken) {
+                    write("*");
+                }
+                emit(node.name, false);
+                if (languageVersion < 2) {
+                    write(": function ");
+                }
+                emitSignatureAndBody(node);
+            }
+            function emitPropertyAssignment(node) {
+                emit(node.name, false);
+                write(": ");
+                emit(node.initializer);
+            }
+            function emitShorthandPropertyAssignment(node) {
+                emit(node.name, false);
+                if (languageVersion < 2) {
+                    write(": ");
+                    var generatedName = getGeneratedNameForIdentifier(node.name);
+                    if (generatedName) {
+                        write(generatedName);
+                    }
+                    else {
+                        emitExpressionIdentifier(node.name);
+                    }
+                }
+                else if (resolver.getExpressionNameSubstitution(node.name, getGeneratedNameForNode)) {
+                    write(": ");
+                    emitExpressionIdentifier(node.name);
+                }
+            }
+            function tryEmitConstantValue(node) {
+                if (compilerOptions.separateCompilation) {
+                    return false;
+                }
+                var constantValue = resolver.getConstantValue(node);
+                if (constantValue !== undefined) {
+                    write(constantValue.toString());
+                    if (!compilerOptions.removeComments) {
+                        var propertyName = node.kind === 155 ? ts.declarationNameToString(node.name) : ts.getTextOfNode(node.argumentExpression);
+                        write(" /* " + propertyName + " */");
+                    }
+                    return true;
+                }
+                return false;
+            }
+            function indentIfOnDifferentLines(parent, node1, node2, valueToWriteWhenNotIndenting) {
+                var realNodesAreOnDifferentLines = !ts.nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2);
+                var synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2);
+                if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) {
+                    increaseIndent();
+                    writeLine();
+                    return true;
+                }
+                else {
+                    if (valueToWriteWhenNotIndenting) {
+                        write(valueToWriteWhenNotIndenting);
+                    }
+                    return false;
+                }
+            }
+            function emitPropertyAccess(node) {
+                if (tryEmitConstantValue(node)) {
+                    return;
+                }
+                emit(node.expression);
+                var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
+                write(".");
+                var indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
+                emit(node.name, false);
+                decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
+            }
+            function emitQualifiedName(node) {
+                emit(node.left);
+                write(".");
+                emit(node.right);
+            }
+            function emitIndexedAccess(node) {
+                if (tryEmitConstantValue(node)) {
+                    return;
+                }
+                emit(node.expression);
+                write("[");
+                emit(node.argumentExpression);
+                write("]");
+            }
+            function hasSpreadElement(elements) {
+                return ts.forEach(elements, function (e) { return e.kind === 173; });
+            }
+            function skipParentheses(node) {
+                while (node.kind === 161 || node.kind === 160) {
+                    node = node.expression;
+                }
+                return node;
+            }
+            function emitCallTarget(node) {
+                if (node.kind === 65 || node.kind === 93 || node.kind === 91) {
+                    emit(node);
+                    return node;
+                }
+                var temp = createAndRecordTempVariable(0);
+                write("(");
+                emit(temp);
+                write(" = ");
+                emit(node);
+                write(")");
+                return temp;
+            }
+            function emitCallWithSpread(node) {
+                var target;
+                var expr = skipParentheses(node.expression);
+                if (expr.kind === 155) {
+                    target = emitCallTarget(expr.expression);
+                    write(".");
+                    emit(expr.name);
+                }
+                else if (expr.kind === 156) {
+                    target = emitCallTarget(expr.expression);
+                    write("[");
+                    emit(expr.argumentExpression);
+                    write("]");
+                }
+                else if (expr.kind === 91) {
+                    target = expr;
+                    write("_super");
+                }
+                else {
+                    emit(node.expression);
+                }
+                write(".apply(");
+                if (target) {
+                    if (target.kind === 91) {
+                        emitThis(target);
+                    }
+                    else {
+                        emit(target);
+                    }
+                }
+                else {
+                    write("void 0");
+                }
+                write(", ");
+                emitListWithSpread(node.arguments, false, false);
+                write(")");
+            }
+            function emitCallExpression(node) {
+                if (languageVersion < 2 && hasSpreadElement(node.arguments)) {
+                    emitCallWithSpread(node);
+                    return;
+                }
+                var superCall = false;
+                if (node.expression.kind === 91) {
+                    emitSuper(node.expression);
+                    superCall = true;
+                }
+                else {
+                    emit(node.expression);
+                    superCall = node.expression.kind === 155 && node.expression.expression.kind === 91;
+                }
+                if (superCall && languageVersion < 2) {
+                    write(".call(");
+                    emitThis(node.expression);
+                    if (node.arguments.length) {
+                        write(", ");
+                        emitCommaList(node.arguments);
+                    }
+                    write(")");
+                }
+                else {
+                    write("(");
+                    emitCommaList(node.arguments);
+                    write(")");
+                }
+            }
+            function emitNewExpression(node) {
+                write("new ");
+                emit(node.expression);
+                if (node.arguments) {
+                    write("(");
+                    emitCommaList(node.arguments);
+                    write(")");
+                }
+            }
+            function emitTaggedTemplateExpression(node) {
+                if (languageVersion >= 2) {
+                    emit(node.tag);
+                    write(" ");
+                    emit(node.template);
+                }
+                else {
+                    emitDownlevelTaggedTemplate(node);
+                }
+            }
+            function emitParenExpression(node) {
+                if (!node.parent || node.parent.kind !== 163) {
+                    if (node.expression.kind === 160) {
+                        var operand = node.expression.expression;
+                        while (operand.kind == 160) {
+                            operand = operand.expression;
+                        }
+                        if (operand.kind !== 167 &&
+                            operand.kind !== 166 &&
+                            operand.kind !== 165 &&
+                            operand.kind !== 164 &&
+                            operand.kind !== 168 &&
+                            operand.kind !== 158 &&
+                            !(operand.kind === 157 && node.parent.kind === 158) &&
+                            !(operand.kind === 162 && node.parent.kind === 157)) {
+                            emit(operand);
+                            return;
+                        }
+                    }
+                }
+                write("(");
+                emit(node.expression);
+                write(")");
+            }
+            function emitDeleteExpression(node) {
+                write(ts.tokenToString(74));
+                write(" ");
+                emit(node.expression);
+            }
+            function emitVoidExpression(node) {
+                write(ts.tokenToString(99));
+                write(" ");
+                emit(node.expression);
+            }
+            function emitTypeOfExpression(node) {
+                write(ts.tokenToString(97));
+                write(" ");
+                emit(node.expression);
+            }
+            function emitPrefixUnaryExpression(node) {
+                write(ts.tokenToString(node.operator));
+                if (node.operand.kind === 167) {
+                    var operand = node.operand;
+                    if (node.operator === 33 && (operand.operator === 33 || operand.operator === 38)) {
+                        write(" ");
+                    }
+                    else if (node.operator === 34 && (operand.operator === 34 || operand.operator === 39)) {
+                        write(" ");
+                    }
+                }
+                emit(node.operand);
+            }
+            function emitPostfixUnaryExpression(node) {
+                emit(node.operand);
+                write(ts.tokenToString(node.operator));
+            }
+            function emitBinaryExpression(node) {
+                if (languageVersion < 2 && node.operatorToken.kind === 53 &&
+                    (node.left.kind === 154 || node.left.kind === 153)) {
+                    emitDestructuring(node, node.parent.kind === 182);
+                }
+                else {
+                    emit(node.left);
+                    var indentedBeforeOperator = indentIfOnDifferentLines(node, node.left, node.operatorToken, node.operatorToken.kind !== 23 ? " " : undefined);
+                    write(ts.tokenToString(node.operatorToken.kind));
+                    var indentedAfterOperator = indentIfOnDifferentLines(node, node.operatorToken, node.right, " ");
+                    emit(node.right);
+                    decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator);
+                }
+            }
+            function synthesizedNodeStartsOnNewLine(node) {
+                return ts.nodeIsSynthesized(node) && node.startsOnNewLine;
+            }
+            function emitConditionalExpression(node) {
+                emit(node.condition);
+                var indentedBeforeQuestion = indentIfOnDifferentLines(node, node.condition, node.questionToken, " ");
+                write("?");
+                var indentedAfterQuestion = indentIfOnDifferentLines(node, node.questionToken, node.whenTrue, " ");
+                emit(node.whenTrue);
+                decreaseIndentIf(indentedBeforeQuestion, indentedAfterQuestion);
+                var indentedBeforeColon = indentIfOnDifferentLines(node, node.whenTrue, node.colonToken, " ");
+                write(":");
+                var indentedAfterColon = indentIfOnDifferentLines(node, node.colonToken, node.whenFalse, " ");
+                emit(node.whenFalse);
+                decreaseIndentIf(indentedBeforeColon, indentedAfterColon);
+            }
+            function decreaseIndentIf(value1, value2) {
+                if (value1) {
+                    decreaseIndent();
+                }
+                if (value2) {
+                    decreaseIndent();
+                }
+            }
+            function isSingleLineEmptyBlock(node) {
+                if (node && node.kind === 179) {
+                    var block = node;
+                    return block.statements.length === 0 && nodeEndIsOnSameLineAsNodeStart(block, block);
+                }
+            }
+            function emitBlock(node) {
+                if (isSingleLineEmptyBlock(node)) {
+                    emitToken(14, node.pos);
+                    write(" ");
+                    emitToken(15, node.statements.end);
+                    return;
+                }
+                emitToken(14, node.pos);
+                increaseIndent();
+                scopeEmitStart(node.parent);
+                if (node.kind === 206) {
+                    ts.Debug.assert(node.parent.kind === 205);
+                    emitCaptureThisForNodeIfNecessary(node.parent);
+                }
+                emitLines(node.statements);
+                if (node.kind === 206) {
+                    emitTempDeclarations(true);
+                }
+                decreaseIndent();
+                writeLine();
+                emitToken(15, node.statements.end);
+                scopeEmitEnd();
+            }
+            function emitEmbeddedStatement(node) {
+                if (node.kind === 179) {
+                    write(" ");
+                    emit(node);
+                }
+                else {
+                    increaseIndent();
+                    writeLine();
+                    emit(node);
+                    decreaseIndent();
+                }
+            }
+            function emitExpressionStatement(node) {
+                emitParenthesizedIf(node.expression, node.expression.kind === 163);
+                write(";");
+            }
+            function emitIfStatement(node) {
+                var endPos = emitToken(84, node.pos);
+                write(" ");
+                endPos = emitToken(16, endPos);
+                emit(node.expression);
+                emitToken(17, node.expression.end);
+                emitEmbeddedStatement(node.thenStatement);
+                if (node.elseStatement) {
+                    writeLine();
+                    emitToken(76, node.thenStatement.end);
+                    if (node.elseStatement.kind === 183) {
+                        write(" ");
+                        emit(node.elseStatement);
+                    }
+                    else {
+                        emitEmbeddedStatement(node.elseStatement);
+                    }
+                }
+            }
+            function emitDoStatement(node) {
+                write("do");
+                emitEmbeddedStatement(node.statement);
+                if (node.statement.kind === 179) {
+                    write(" ");
+                }
+                else {
+                    writeLine();
+                }
+                write("while (");
+                emit(node.expression);
+                write(");");
+            }
+            function emitWhileStatement(node) {
+                write("while (");
+                emit(node.expression);
+                write(")");
+                emitEmbeddedStatement(node.statement);
+            }
+            function emitStartOfVariableDeclarationList(decl, startPos) {
+                var tokenKind = 98;
+                if (decl && languageVersion >= 2) {
+                    if (ts.isLet(decl)) {
+                        tokenKind = 104;
+                    }
+                    else if (ts.isConst(decl)) {
+                        tokenKind = 70;
+                    }
+                }
+                if (startPos !== undefined) {
+                    emitToken(tokenKind, startPos);
+                }
+                else {
+                    switch (tokenKind) {
+                        case 98:
+                            return write("var ");
+                        case 104:
+                            return write("let ");
+                        case 70:
+                            return write("const ");
+                    }
+                }
+            }
+            function emitForStatement(node) {
+                var endPos = emitToken(82, node.pos);
+                write(" ");
+                endPos = emitToken(16, endPos);
+                if (node.initializer && node.initializer.kind === 199) {
+                    var variableDeclarationList = node.initializer;
+                    var declarations = variableDeclarationList.declarations;
+                    emitStartOfVariableDeclarationList(declarations[0], endPos);
+                    write(" ");
+                    emitCommaList(declarations);
+                }
+                else if (node.initializer) {
+                    emit(node.initializer);
+                }
+                write(";");
+                emitOptional(" ", node.condition);
+                write(";");
+                emitOptional(" ", node.incrementor);
+                write(")");
+                emitEmbeddedStatement(node.statement);
+            }
+            function emitForInOrForOfStatement(node) {
+                if (languageVersion < 2 && node.kind === 188) {
+                    return emitDownLevelForOfStatement(node);
+                }
+                var endPos = emitToken(82, node.pos);
+                write(" ");
+                endPos = emitToken(16, endPos);
+                if (node.initializer.kind === 199) {
+                    var variableDeclarationList = node.initializer;
+                    if (variableDeclarationList.declarations.length >= 1) {
+                        var decl = variableDeclarationList.declarations[0];
+                        emitStartOfVariableDeclarationList(decl, endPos);
+                        write(" ");
+                        emit(decl);
+                    }
+                }
+                else {
+                    emit(node.initializer);
+                }
+                if (node.kind === 187) {
+                    write(" in ");
+                }
+                else {
+                    write(" of ");
+                }
+                emit(node.expression);
+                emitToken(17, node.expression.end);
+                emitEmbeddedStatement(node.statement);
+            }
+            function emitDownLevelForOfStatement(node) {
+                // The following ES6 code:
+                //
+                //    for (let v of expr) { }
+                //
+                // should be emitted as
+                //
+                //    for (let _i = 0, _a = expr; _i < _a.length; _i++) {
+                //        let v = _a[_i];
+                //    }
+                //
+                // where _a and _i are temps emitted to capture the RHS and the counter,
+                // respectively.
+                // When the left hand side is an expression instead of a let declaration,
+                // the "let v" is not emitted.
+                // When the left hand side is a let/const, the v is renamed if there is
+                // another v in scope.
+                // Note that all assignments to the LHS are emitted in the body, including
+                // all destructuring.
+                // Note also that because an extra statement is needed to assign to the LHS,
+                // for-of bodies are always emitted as blocks.
+                var endPos = emitToken(82, node.pos);
+                write(" ");
+                endPos = emitToken(16, endPos);
+                var rhsIsIdentifier = node.expression.kind === 65;
+                var counter = createTempVariable(268435456);
+                var rhsReference = rhsIsIdentifier ? node.expression : createTempVariable(0);
+                emitStart(node.expression);
+                write("var ");
+                emitNodeWithoutSourceMap(counter);
+                write(" = 0");
+                emitEnd(node.expression);
+                if (!rhsIsIdentifier) {
+                    write(", ");
+                    emitStart(node.expression);
+                    emitNodeWithoutSourceMap(rhsReference);
+                    write(" = ");
+                    emitNodeWithoutSourceMap(node.expression);
+                    emitEnd(node.expression);
+                }
+                write("; ");
+                emitStart(node.initializer);
+                emitNodeWithoutSourceMap(counter);
+                write(" < ");
+                emitNodeWithoutSourceMap(rhsReference);
+                write(".length");
+                emitEnd(node.initializer);
+                write("; ");
+                emitStart(node.initializer);
+                emitNodeWithoutSourceMap(counter);
+                write("++");
+                emitEnd(node.initializer);
+                emitToken(17, node.expression.end);
+                write(" {");
+                writeLine();
+                increaseIndent();
+                var rhsIterationValue = createElementAccessExpression(rhsReference, counter);
+                emitStart(node.initializer);
+                if (node.initializer.kind === 199) {
+                    write("var ");
+                    var variableDeclarationList = node.initializer;
+                    if (variableDeclarationList.declarations.length > 0) {
+                        var declaration = variableDeclarationList.declarations[0];
+                        if (ts.isBindingPattern(declaration.name)) {
+                            emitDestructuring(declaration, false, rhsIterationValue);
+                        }
+                        else {
+                            emitNodeWithoutSourceMap(declaration);
+                            write(" = ");
+                            emitNodeWithoutSourceMap(rhsIterationValue);
+                        }
+                    }
+                    else {
+                        emitNodeWithoutSourceMap(createTempVariable(0));
+                        write(" = ");
+                        emitNodeWithoutSourceMap(rhsIterationValue);
+                    }
+                }
+                else {
+                    var assignmentExpression = createBinaryExpression(node.initializer, 53, rhsIterationValue, false);
+                    if (node.initializer.kind === 153 || node.initializer.kind === 154) {
+                        emitDestructuring(assignmentExpression, true, undefined);
+                    }
+                    else {
+                        emitNodeWithoutSourceMap(assignmentExpression);
+                    }
+                }
+                emitEnd(node.initializer);
+                write(";");
+                if (node.statement.kind === 179) {
+                    emitLines(node.statement.statements);
+                }
+                else {
+                    writeLine();
+                    emit(node.statement);
+                }
+                writeLine();
+                decreaseIndent();
+                write("}");
+            }
+            function emitBreakOrContinueStatement(node) {
+                emitToken(node.kind === 190 ? 66 : 71, node.pos);
+                emitOptional(" ", node.label);
+                write(";");
+            }
+            function emitReturnStatement(node) {
+                emitToken(90, node.pos);
+                emitOptional(" ", node.expression);
+                write(";");
+            }
+            function emitWithStatement(node) {
+                write("with (");
+                emit(node.expression);
+                write(")");
+                emitEmbeddedStatement(node.statement);
+            }
+            function emitSwitchStatement(node) {
+                var endPos = emitToken(92, node.pos);
+                write(" ");
+                emitToken(16, endPos);
+                emit(node.expression);
+                endPos = emitToken(17, node.expression.end);
+                write(" ");
+                emitCaseBlock(node.caseBlock, endPos);
+            }
+            function emitCaseBlock(node, startPos) {
+                emitToken(14, startPos);
+                increaseIndent();
+                emitLines(node.clauses);
+                decreaseIndent();
+                writeLine();
+                emitToken(15, node.clauses.end);
+            }
+            function nodeStartPositionsAreOnSameLine(node1, node2) {
+                return ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node1.pos)) ===
+                    ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos));
+            }
+            function nodeEndPositionsAreOnSameLine(node1, node2) {
+                return ts.getLineOfLocalPosition(currentSourceFile, node1.end) ===
+                    ts.getLineOfLocalPosition(currentSourceFile, node2.end);
+            }
+            function nodeEndIsOnSameLineAsNodeStart(node1, node2) {
+                return ts.getLineOfLocalPosition(currentSourceFile, node1.end) ===
+                    ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos));
+            }
+            function emitCaseOrDefaultClause(node) {
+                if (node.kind === 220) {
+                    write("case ");
+                    emit(node.expression);
+                    write(":");
+                }
+                else {
+                    write("default:");
+                }
+                if (node.statements.length === 1 && nodeStartPositionsAreOnSameLine(node, node.statements[0])) {
+                    write(" ");
+                    emit(node.statements[0]);
+                }
+                else {
+                    increaseIndent();
+                    emitLines(node.statements);
+                    decreaseIndent();
+                }
+            }
+            function emitThrowStatement(node) {
+                write("throw ");
+                emit(node.expression);
+                write(";");
+            }
+            function emitTryStatement(node) {
+                write("try ");
+                emit(node.tryBlock);
+                emit(node.catchClause);
+                if (node.finallyBlock) {
+                    writeLine();
+                    write("finally ");
+                    emit(node.finallyBlock);
+                }
+            }
+            function emitCatchClause(node) {
+                writeLine();
+                var endPos = emitToken(68, node.pos);
+                write(" ");
+                emitToken(16, endPos);
+                emit(node.variableDeclaration);
+                emitToken(17, node.variableDeclaration ? node.variableDeclaration.end : endPos);
+                write(" ");
+                emitBlock(node.block);
+            }
+            function emitDebuggerStatement(node) {
+                emitToken(72, node.pos);
+                write(";");
+            }
+            function emitLabelledStatement(node) {
+                emit(node.label);
+                write(": ");
+                emit(node.statement);
+            }
+            function getContainingModule(node) {
+                do {
+                    node = node.parent;
+                } while (node && node.kind !== 205);
+                return node;
+            }
+            function emitContainingModuleName(node) {
+                var container = getContainingModule(node);
+                write(container ? getGeneratedNameForNode(container) : "exports");
+            }
+            function emitModuleMemberName(node) {
+                emitStart(node.name);
+                if (ts.getCombinedNodeFlags(node) & 1) {
+                    var container = getContainingModule(node);
+                    if (container) {
+                        write(getGeneratedNameForNode(container));
+                        write(".");
+                    }
+                    else if (languageVersion < 2) {
+                        write("exports.");
+                    }
+                }
+                emitNodeWithoutSourceMap(node.name);
+                emitEnd(node.name);
+            }
+            function createVoidZero() {
+                var zero = ts.createSynthesizedNode(7);
+                zero.text = "0";
+                var result = ts.createSynthesizedNode(166);
+                result.expression = zero;
+                return result;
+            }
+            function emitExportMemberAssignment(node) {
+                if (node.flags & 1) {
+                    writeLine();
+                    emitStart(node);
+                    if (node.flags & 256) {
+                        if (languageVersion === 0) {
+                            write("exports[\"default\"]");
+                        }
+                        else {
+                            write("exports.default");
+                        }
+                    }
+                    else {
+                        emitModuleMemberName(node);
+                    }
+                    write(" = ");
+                    emitDeclarationName(node);
+                    emitEnd(node);
+                    write(";");
+                }
+            }
+            function emitExportMemberAssignments(name) {
+                if (!exportEquals && exportSpecifiers && ts.hasProperty(exportSpecifiers, name.text)) {
+                    for (var _a = 0, _b = exportSpecifiers[name.text]; _a < _b.length; _a++) {
+                        var specifier = _b[_a];
+                        writeLine();
+                        emitStart(specifier.name);
+                        emitContainingModuleName(specifier);
+                        write(".");
+                        emitNodeWithoutSourceMap(specifier.name);
+                        emitEnd(specifier.name);
+                        write(" = ");
+                        emitExpressionIdentifier(name);
+                        write(";");
+                    }
+                }
+            }
+            function emitDestructuring(root, isAssignmentExpressionStatement, value) {
+                var emitCount = 0;
+                var isDeclaration = (root.kind === 198 && !(ts.getCombinedNodeFlags(root) & 1)) || root.kind === 129;
+                if (root.kind === 169) {
+                    emitAssignmentExpression(root);
+                }
+                else {
+                    ts.Debug.assert(!isAssignmentExpressionStatement);
+                    emitBindingElement(root, value);
+                }
+                function emitAssignment(name, value) {
+                    if (emitCount++) {
+                        write(", ");
+                    }
+                    renameNonTopLevelLetAndConst(name);
+                    if (name.parent && (name.parent.kind === 198 || name.parent.kind === 152)) {
+                        emitModuleMemberName(name.parent);
+                    }
+                    else {
+                        emit(name);
+                    }
+                    write(" = ");
+                    emit(value);
+                }
+                function ensureIdentifier(expr) {
+                    if (expr.kind !== 65) {
+                        var identifier = createTempVariable(0);
+                        if (!isDeclaration) {
+                            recordTempDeclaration(identifier);
+                        }
+                        emitAssignment(identifier, expr);
+                        expr = identifier;
+                    }
+                    return expr;
+                }
+                function createDefaultValueCheck(value, defaultValue) {
+                    value = ensureIdentifier(value);
+                    var equals = ts.createSynthesizedNode(169);
+                    equals.left = value;
+                    equals.operatorToken = ts.createSynthesizedNode(30);
+                    equals.right = createVoidZero();
+                    return createConditionalExpression(equals, defaultValue, value);
+                }
+                function createConditionalExpression(condition, whenTrue, whenFalse) {
+                    var cond = ts.createSynthesizedNode(170);
+                    cond.condition = condition;
+                    cond.questionToken = ts.createSynthesizedNode(50);
+                    cond.whenTrue = whenTrue;
+                    cond.colonToken = ts.createSynthesizedNode(51);
+                    cond.whenFalse = whenFalse;
+                    return cond;
+                }
+                function createNumericLiteral(value) {
+                    var node = ts.createSynthesizedNode(7);
+                    node.text = "" + value;
+                    return node;
+                }
+                function createPropertyAccessForDestructuringProperty(object, propName) {
+                    if (propName.kind !== 65) {
+                        return createElementAccessExpression(object, propName);
+                    }
+                    return createPropertyAccessExpression(object, propName);
+                }
+                function createSliceCall(value, sliceIndex) {
+                    var call = ts.createSynthesizedNode(157);
+                    var sliceIdentifier = ts.createSynthesizedNode(65);
+                    sliceIdentifier.text = "slice";
+                    call.expression = createPropertyAccessExpression(value, sliceIdentifier);
+                    call.arguments = ts.createSynthesizedNodeArray();
+                    call.arguments[0] = createNumericLiteral(sliceIndex);
+                    return call;
+                }
+                function emitObjectLiteralAssignment(target, value) {
+                    var properties = target.properties;
+                    if (properties.length !== 1) {
+                        value = ensureIdentifier(value);
+                    }
+                    for (var _a = 0; _a < properties.length; _a++) {
+                        var p = properties[_a];
+                        if (p.kind === 224 || p.kind === 225) {
+                            var propName = (p.name);
+                            emitDestructuringAssignment(p.initializer || propName, createPropertyAccessForDestructuringProperty(value, propName));
+                        }
+                    }
+                }
+                function emitArrayLiteralAssignment(target, value) {
+                    var elements = target.elements;
+                    if (elements.length !== 1) {
+                        value = ensureIdentifier(value);
+                    }
+                    for (var i = 0; i < elements.length; i++) {
+                        var e = elements[i];
+                        if (e.kind !== 175) {
+                            if (e.kind !== 173) {
+                                emitDestructuringAssignment(e, createElementAccessExpression(value, createNumericLiteral(i)));
+                            }
+                            else if (i === elements.length - 1) {
+                                emitDestructuringAssignment(e.expression, createSliceCall(value, i));
+                            }
+                        }
+                    }
+                }
+                function emitDestructuringAssignment(target, value) {
+                    if (target.kind === 169 && target.operatorToken.kind === 53) {
+                        value = createDefaultValueCheck(value, target.right);
+                        target = target.left;
+                    }
+                    if (target.kind === 154) {
+                        emitObjectLiteralAssignment(target, value);
+                    }
+                    else if (target.kind === 153) {
+                        emitArrayLiteralAssignment(target, value);
+                    }
+                    else {
+                        emitAssignment(target, value);
+                    }
+                }
+                function emitAssignmentExpression(root) {
+                    var target = root.left;
+                    var value = root.right;
+                    if (isAssignmentExpressionStatement) {
+                        emitDestructuringAssignment(target, value);
+                    }
+                    else {
+                        if (root.parent.kind !== 161) {
+                            write("(");
+                        }
+                        value = ensureIdentifier(value);
+                        emitDestructuringAssignment(target, value);
+                        write(", ");
+                        emit(value);
+                        if (root.parent.kind !== 161) {
+                            write(")");
+                        }
+                    }
+                }
+                function emitBindingElement(target, value) {
+                    if (target.initializer) {
+                        value = value ? createDefaultValueCheck(value, target.initializer) : target.initializer;
+                    }
+                    else if (!value) {
+                        value = createVoidZero();
+                    }
+                    if (ts.isBindingPattern(target.name)) {
+                        var pattern = target.name;
+                        var elements = pattern.elements;
+                        if (elements.length !== 1) {
+                            value = ensureIdentifier(value);
+                        }
+                        for (var i = 0; i < elements.length; i++) {
+                            var element = elements[i];
+                            if (pattern.kind === 150) {
+                                var propName = element.propertyName || element.name;
+                                emitBindingElement(element, createPropertyAccessForDestructuringProperty(value, propName));
+                            }
+                            else if (element.kind !== 175) {
+                                if (!element.dotDotDotToken) {
+                                    emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i)));
+                                }
+                                else if (i === elements.length - 1) {
+                                    emitBindingElement(element, createSliceCall(value, i));
+                                }
+                            }
+                        }
+                    }
+                    else {
+                        emitAssignment(target.name, value);
+                    }
+                }
+            }
+            function emitVariableDeclaration(node) {
+                if (ts.isBindingPattern(node.name)) {
+                    if (languageVersion < 2) {
+                        emitDestructuring(node, false);
+                    }
+                    else {
+                        emit(node.name);
+                        emitOptional(" = ", node.initializer);
+                    }
+                }
+                else {
+                    renameNonTopLevelLetAndConst(node.name);
+                    emitModuleMemberName(node);
+                    var initializer = node.initializer;
+                    if (!initializer && languageVersion < 2) {
+                        var isUninitializedLet = (resolver.getNodeCheckFlags(node) & 256) &&
+                            (getCombinedFlagsForIdentifier(node.name) & 4096);
+                        if (isUninitializedLet &&
+                            node.parent.parent.kind !== 187 &&
+                            node.parent.parent.kind !== 188) {
+                            initializer = createVoidZero();
+                        }
+                    }
+                    emitOptional(" = ", initializer);
+                }
+            }
+            function emitExportVariableAssignments(node) {
+                if (node.kind === 175) {
+                    return;
+                }
+                var name = node.name;
+                if (name.kind === 65) {
+                    emitExportMemberAssignments(name);
+                }
+                else if (ts.isBindingPattern(name)) {
+                    ts.forEach(name.elements, emitExportVariableAssignments);
+                }
+            }
+            function getCombinedFlagsForIdentifier(node) {
+                if (!node.parent || (node.parent.kind !== 198 && node.parent.kind !== 152)) {
+                    return 0;
+                }
+                return ts.getCombinedNodeFlags(node.parent);
+            }
+            function renameNonTopLevelLetAndConst(node) {
+                if (languageVersion >= 2 ||
+                    ts.nodeIsSynthesized(node) ||
+                    node.kind !== 65 ||
+                    (node.parent.kind !== 198 && node.parent.kind !== 152)) {
+                    return;
+                }
+                var combinedFlags = getCombinedFlagsForIdentifier(node);
+                if (((combinedFlags & 12288) === 0) || combinedFlags & 1) {
+                    return;
+                }
+                var list = ts.getAncestor(node, 199);
+                if (list.parent.kind === 180) {
+                    var isSourceFileLevelBinding = list.parent.parent.kind === 227;
+                    var isModuleLevelBinding = list.parent.parent.kind === 206;
+                    var isFunctionLevelBinding = list.parent.parent.kind === 179 && ts.isFunctionLike(list.parent.parent.parent);
+                    if (isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding) {
+                        return;
+                    }
+                }
+                var blockScopeContainer = ts.getEnclosingBlockScopeContainer(node);
+                var parent = blockScopeContainer.kind === 227
+                    ? blockScopeContainer
+                    : blockScopeContainer.parent;
+                if (resolver.resolvesToSomeValue(parent, node.text)) {
+                    var variableId = resolver.getBlockScopedVariableId(node);
+                    if (!blockScopedVariableToGeneratedName) {
+                        blockScopedVariableToGeneratedName = [];
+                    }
+                    var generatedName = makeUniqueName(node.text);
+                    blockScopedVariableToGeneratedName[variableId] = generatedName;
+                }
+            }
+            function isES6ExportedDeclaration(node) {
+                return !!(node.flags & 1) &&
+                    languageVersion >= 2 &&
+                    node.parent.kind === 227;
+            }
+            function emitVariableStatement(node) {
+                if (!(node.flags & 1)) {
+                    emitStartOfVariableDeclarationList(node.declarationList);
+                }
+                else if (isES6ExportedDeclaration(node)) {
+                    write("export ");
+                    emitStartOfVariableDeclarationList(node.declarationList);
+                }
+                emitCommaList(node.declarationList.declarations);
+                write(";");
+                if (languageVersion < 2 && node.parent === currentSourceFile) {
+                    ts.forEach(node.declarationList.declarations, emitExportVariableAssignments);
+                }
+            }
+            function emitParameter(node) {
+                if (languageVersion < 2) {
+                    if (ts.isBindingPattern(node.name)) {
+                        var name_5 = createTempVariable(0);
+                        if (!tempParameters) {
+                            tempParameters = [];
+                        }
+                        tempParameters.push(name_5);
+                        emit(name_5);
+                    }
+                    else {
+                        emit(node.name);
+                    }
+                }
+                else {
+                    if (node.dotDotDotToken) {
+                        write("...");
+                    }
+                    emit(node.name);
+                    emitOptional(" = ", node.initializer);
+                }
+            }
+            function emitDefaultValueAssignments(node) {
+                if (languageVersion < 2) {
+                    var tempIndex = 0;
+                    ts.forEach(node.parameters, function (p) {
+                        if (p.dotDotDotToken) {
+                            return;
+                        }
+                        if (ts.isBindingPattern(p.name)) {
+                            writeLine();
+                            write("var ");
+                            emitDestructuring(p, false, tempParameters[tempIndex]);
+                            write(";");
+                            tempIndex++;
+                        }
+                        else if (p.initializer) {
+                            writeLine();
+                            emitStart(p);
+                            write("if (");
+                            emitNodeWithoutSourceMap(p.name);
+                            write(" === void 0)");
+                            emitEnd(p);
+                            write(" { ");
+                            emitStart(p);
+                            emitNodeWithoutSourceMap(p.name);
+                            write(" = ");
+                            emitNodeWithoutSourceMap(p.initializer);
+                            emitEnd(p);
+                            write("; }");
+                        }
+                    });
+                }
+            }
+            function emitRestParameter(node) {
+                if (languageVersion < 2 && ts.hasRestParameters(node)) {
+                    var restIndex = node.parameters.length - 1;
+                    var restParam = node.parameters[restIndex];
+                    if (ts.isBindingPattern(restParam.name)) {
+                        return;
+                    }
+                    var tempName = createTempVariable(268435456).text;
+                    writeLine();
+                    emitLeadingComments(restParam);
+                    emitStart(restParam);
+                    write("var ");
+                    emitNodeWithoutSourceMap(restParam.name);
+                    write(" = [];");
+                    emitEnd(restParam);
+                    emitTrailingComments(restParam);
+                    writeLine();
+                    write("for (");
+                    emitStart(restParam);
+                    write("var " + tempName + " = " + restIndex + ";");
+                    emitEnd(restParam);
+                    write(" ");
+                    emitStart(restParam);
+                    write(tempName + " < arguments.length;");
+                    emitEnd(restParam);
+                    write(" ");
+                    emitStart(restParam);
+                    write(tempName + "++");
+                    emitEnd(restParam);
+                    write(") {");
+                    increaseIndent();
+                    writeLine();
+                    emitStart(restParam);
+                    emitNodeWithoutSourceMap(restParam.name);
+                    write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];");
+                    emitEnd(restParam);
+                    decreaseIndent();
+                    writeLine();
+                    write("}");
+                }
+            }
+            function emitAccessor(node) {
+                write(node.kind === 136 ? "get " : "set ");
+                emit(node.name, false);
+                emitSignatureAndBody(node);
+            }
+            function shouldEmitAsArrowFunction(node) {
+                return node.kind === 163 && languageVersion >= 2;
+            }
+            function emitDeclarationName(node) {
+                if (node.name) {
+                    emitNodeWithoutSourceMap(node.name);
+                }
+                else {
+                    write(getGeneratedNameForNode(node));
+                }
+            }
+            function shouldEmitFunctionName(node) {
+                if (node.kind === 162) {
+                    return !!node.name;
+                }
+                if (node.kind === 200) {
+                    return !!node.name || languageVersion < 2;
+                }
+            }
+            function emitFunctionDeclaration(node) {
+                if (ts.nodeIsMissing(node.body)) {
+                    return emitOnlyPinnedOrTripleSlashComments(node);
+                }
+                if (node.kind !== 134 && node.kind !== 133) {
+                    emitLeadingComments(node);
+                }
+                if (!shouldEmitAsArrowFunction(node)) {
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                        if (node.flags & 256) {
+                            write("default ");
+                        }
+                    }
+                    write("function");
+                    if (languageVersion >= 2 && node.asteriskToken) {
+                        write("*");
+                    }
+                    write(" ");
+                }
+                if (shouldEmitFunctionName(node)) {
+                    emitDeclarationName(node);
+                }
+                emitSignatureAndBody(node);
+                if (languageVersion < 2 && node.kind === 200 && node.parent === currentSourceFile && node.name) {
+                    emitExportMemberAssignments(node.name);
+                }
+                if (node.kind !== 134 && node.kind !== 133) {
+                    emitTrailingComments(node);
+                }
+            }
+            function emitCaptureThisForNodeIfNecessary(node) {
+                if (resolver.getNodeCheckFlags(node) & 4) {
+                    writeLine();
+                    emitStart(node);
+                    write("var _this = this;");
+                    emitEnd(node);
+                }
+            }
+            function emitSignatureParameters(node) {
+                increaseIndent();
+                write("(");
+                if (node) {
+                    var parameters = node.parameters;
+                    var omitCount = languageVersion < 2 && ts.hasRestParameters(node) ? 1 : 0;
+                    emitList(parameters, 0, parameters.length - omitCount, false, false);
+                }
+                write(")");
+                decreaseIndent();
+            }
+            function emitSignatureParametersForArrow(node) {
+                if (node.parameters.length === 1 && node.pos === node.parameters[0].pos) {
+                    emit(node.parameters[0]);
+                    return;
+                }
+                emitSignatureParameters(node);
+            }
+            function emitSignatureAndBody(node) {
+                var saveTempFlags = tempFlags;
+                var saveTempVariables = tempVariables;
+                var saveTempParameters = tempParameters;
+                tempFlags = 0;
+                tempVariables = undefined;
+                tempParameters = undefined;
+                if (shouldEmitAsArrowFunction(node)) {
+                    emitSignatureParametersForArrow(node);
+                    write(" =>");
+                }
+                else {
+                    emitSignatureParameters(node);
+                }
+                if (!node.body) {
+                    write(" { }");
+                }
+                else if (node.body.kind === 179) {
+                    emitBlockFunctionBody(node, node.body);
+                }
+                else {
+                    emitExpressionFunctionBody(node, node.body);
+                }
+                if (!isES6ExportedDeclaration(node)) {
+                    emitExportMemberAssignment(node);
+                }
+                tempFlags = saveTempFlags;
+                tempVariables = saveTempVariables;
+                tempParameters = saveTempParameters;
+            }
+            function emitFunctionBodyPreamble(node) {
+                emitCaptureThisForNodeIfNecessary(node);
+                emitDefaultValueAssignments(node);
+                emitRestParameter(node);
+            }
+            function emitExpressionFunctionBody(node, body) {
+                if (languageVersion < 2) {
+                    emitDownLevelExpressionFunctionBody(node, body);
+                    return;
+                }
+                write(" ");
+                var current = body;
+                while (current.kind === 160) {
+                    current = current.expression;
+                }
+                emitParenthesizedIf(body, current.kind === 154);
+            }
+            function emitDownLevelExpressionFunctionBody(node, body) {
+                write(" {");
+                scopeEmitStart(node);
+                increaseIndent();
+                var outPos = writer.getTextPos();
+                emitDetachedComments(node.body);
+                emitFunctionBodyPreamble(node);
+                var preambleEmitted = writer.getTextPos() !== outPos;
+                decreaseIndent();
+                if (!preambleEmitted && nodeStartPositionsAreOnSameLine(node, body)) {
+                    write(" ");
+                    emitStart(body);
+                    write("return ");
+                    emit(body);
+                    emitEnd(body);
+                    write(";");
+                    emitTempDeclarations(false);
+                    write(" ");
+                }
+                else {
+                    increaseIndent();
+                    writeLine();
+                    emitLeadingComments(node.body);
+                    write("return ");
+                    emit(body);
+                    write(";");
+                    emitTrailingComments(node.body);
+                    emitTempDeclarations(true);
+                    decreaseIndent();
+                    writeLine();
+                }
+                emitStart(node.body);
+                write("}");
+                emitEnd(node.body);
+                scopeEmitEnd();
+            }
+            function emitBlockFunctionBody(node, body) {
+                write(" {");
+                scopeEmitStart(node);
+                var initialTextPos = writer.getTextPos();
+                increaseIndent();
+                emitDetachedComments(body.statements);
+                var startIndex = emitDirectivePrologues(body.statements, true);
+                emitFunctionBodyPreamble(node);
+                decreaseIndent();
+                var preambleEmitted = writer.getTextPos() !== initialTextPos;
+                if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)) {
+                    for (var _a = 0, _b = body.statements; _a < _b.length; _a++) {
+                        var statement = _b[_a];
+                        write(" ");
+                        emit(statement);
+                    }
+                    emitTempDeclarations(false);
+                    write(" ");
+                    emitLeadingCommentsOfPosition(body.statements.end);
+                }
+                else {
+                    increaseIndent();
+                    emitLinesStartingAt(body.statements, startIndex);
+                    emitTempDeclarations(true);
+                    writeLine();
+                    emitLeadingCommentsOfPosition(body.statements.end);
+                    decreaseIndent();
+                }
+                emitToken(15, body.statements.end);
+                scopeEmitEnd();
+            }
+            function findInitialSuperCall(ctor) {
+                if (ctor.body) {
+                    var statement = ctor.body.statements[0];
+                    if (statement && statement.kind === 182) {
+                        var expr = statement.expression;
+                        if (expr && expr.kind === 157) {
+                            var func = expr.expression;
+                            if (func && func.kind === 91) {
+                                return statement;
+                            }
+                        }
+                    }
+                }
+            }
+            function emitParameterPropertyAssignments(node) {
+                ts.forEach(node.parameters, function (param) {
+                    if (param.flags & 112) {
+                        writeLine();
+                        emitStart(param);
+                        emitStart(param.name);
+                        write("this.");
+                        emitNodeWithoutSourceMap(param.name);
+                        emitEnd(param.name);
+                        write(" = ");
+                        emit(param.name);
+                        write(";");
+                        emitEnd(param);
+                    }
+                });
+            }
+            function emitMemberAccessForPropertyName(memberName) {
+                if (memberName.kind === 8 || memberName.kind === 7) {
+                    write("[");
+                    emitNodeWithoutSourceMap(memberName);
+                    write("]");
+                }
+                else if (memberName.kind === 127) {
+                    emitComputedPropertyName(memberName);
+                }
+                else {
+                    write(".");
+                    emitNodeWithoutSourceMap(memberName);
+                }
+            }
+            function getInitializedProperties(node, static) {
+                var properties = [];
+                for (var _a = 0, _b = node.members; _a < _b.length; _a++) {
+                    var member = _b[_a];
+                    if (member.kind === 132 && static === ((member.flags & 128) !== 0) && member.initializer) {
+                        properties.push(member);
+                    }
+                }
+                return properties;
+            }
+            function emitPropertyDeclarations(node, properties) {
+                for (var _a = 0; _a < properties.length; _a++) {
+                    var property = properties[_a];
+                    emitPropertyDeclaration(node, property);
+                }
+            }
+            function emitPropertyDeclaration(node, property, receiver, isExpression) {
+                writeLine();
+                emitLeadingComments(property);
+                emitStart(property);
+                emitStart(property.name);
+                if (receiver) {
+                    emit(receiver);
+                }
+                else {
+                    if (property.flags & 128) {
+                        emitDeclarationName(node);
+                    }
+                    else {
+                        write("this");
+                    }
+                }
+                emitMemberAccessForPropertyName(property.name);
+                emitEnd(property.name);
+                write(" = ");
+                emit(property.initializer);
+                if (!isExpression) {
+                    write(";");
+                }
+                emitEnd(property);
+                emitTrailingComments(property);
+            }
+            function emitMemberFunctionsForES5AndLower(node) {
+                ts.forEach(node.members, function (member) {
+                    if (member.kind === 178) {
+                        writeLine();
+                        write(";");
+                    }
+                    else if (member.kind === 134 || node.kind === 133) {
+                        if (!member.body) {
+                            return emitOnlyPinnedOrTripleSlashComments(member);
+                        }
+                        writeLine();
+                        emitLeadingComments(member);
+                        emitStart(member);
+                        emitStart(member.name);
+                        emitClassMemberPrefix(node, member);
+                        emitMemberAccessForPropertyName(member.name);
+                        emitEnd(member.name);
+                        write(" = ");
+                        emitStart(member);
+                        emitFunctionDeclaration(member);
+                        emitEnd(member);
+                        emitEnd(member);
+                        write(";");
+                        emitTrailingComments(member);
+                    }
+                    else if (member.kind === 136 || member.kind === 137) {
+                        var accessors = ts.getAllAccessorDeclarations(node.members, member);
+                        if (member === accessors.firstAccessor) {
+                            writeLine();
+                            emitStart(member);
+                            write("Object.defineProperty(");
+                            emitStart(member.name);
+                            emitClassMemberPrefix(node, member);
+                            write(", ");
+                            emitExpressionForPropertyName(member.name);
+                            emitEnd(member.name);
+                            write(", {");
+                            increaseIndent();
+                            if (accessors.getAccessor) {
+                                writeLine();
+                                emitLeadingComments(accessors.getAccessor);
+                                write("get: ");
+                                emitStart(accessors.getAccessor);
+                                write("function ");
+                                emitSignatureAndBody(accessors.getAccessor);
+                                emitEnd(accessors.getAccessor);
+                                emitTrailingComments(accessors.getAccessor);
+                                write(",");
+                            }
+                            if (accessors.setAccessor) {
+                                writeLine();
+                                emitLeadingComments(accessors.setAccessor);
+                                write("set: ");
+                                emitStart(accessors.setAccessor);
+                                write("function ");
+                                emitSignatureAndBody(accessors.setAccessor);
+                                emitEnd(accessors.setAccessor);
+                                emitTrailingComments(accessors.setAccessor);
+                                write(",");
+                            }
+                            writeLine();
+                            write("enumerable: true,");
+                            writeLine();
+                            write("configurable: true");
+                            decreaseIndent();
+                            writeLine();
+                            write("});");
+                            emitEnd(member);
+                        }
+                    }
+                });
+            }
+            function emitMemberFunctionsForES6AndHigher(node) {
+                for (var _a = 0, _b = node.members; _a < _b.length; _a++) {
+                    var member = _b[_a];
+                    if ((member.kind === 134 || node.kind === 133) && !member.body) {
+                        emitOnlyPinnedOrTripleSlashComments(member);
+                    }
+                    else if (member.kind === 134 ||
+                        member.kind === 136 ||
+                        member.kind === 137) {
+                        writeLine();
+                        emitLeadingComments(member);
+                        emitStart(member);
+                        if (member.flags & 128) {
+                            write("static ");
+                        }
+                        if (member.kind === 136) {
+                            write("get ");
+                        }
+                        else if (member.kind === 137) {
+                            write("set ");
+                        }
+                        if (member.asteriskToken) {
+                            write("*");
+                        }
+                        emit(member.name);
+                        emitSignatureAndBody(member);
+                        emitEnd(member);
+                        emitTrailingComments(member);
+                    }
+                    else if (member.kind === 178) {
+                        writeLine();
+                        write(";");
+                    }
+                }
+            }
+            function emitConstructor(node, baseTypeElement) {
+                var saveTempFlags = tempFlags;
+                var saveTempVariables = tempVariables;
+                var saveTempParameters = tempParameters;
+                tempFlags = 0;
+                tempVariables = undefined;
+                tempParameters = undefined;
+                emitConstructorWorker(node, baseTypeElement);
+                tempFlags = saveTempFlags;
+                tempVariables = saveTempVariables;
+                tempParameters = saveTempParameters;
+            }
+            function emitConstructorWorker(node, baseTypeElement) {
+                var hasInstancePropertyWithInitializer = false;
+                ts.forEach(node.members, function (member) {
+                    if (member.kind === 135 && !member.body) {
+                        emitOnlyPinnedOrTripleSlashComments(member);
+                    }
+                    if (member.kind === 132 && member.initializer && (member.flags & 128) === 0) {
+                        hasInstancePropertyWithInitializer = true;
+                    }
+                });
+                var ctor = ts.getFirstConstructorWithBody(node);
+                if (languageVersion >= 2 && !ctor && !hasInstancePropertyWithInitializer) {
+                    return;
+                }
+                if (ctor) {
+                    emitLeadingComments(ctor);
+                }
+                emitStart(ctor || node);
+                if (languageVersion < 2) {
+                    write("function ");
+                    emitDeclarationName(node);
+                    emitSignatureParameters(ctor);
+                }
+                else {
+                    write("constructor");
+                    if (ctor) {
+                        emitSignatureParameters(ctor);
+                    }
+                    else {
+                        if (baseTypeElement) {
+                            write("(...args)");
+                        }
+                        else {
+                            write("()");
+                        }
+                    }
+                }
+                write(" {");
+                scopeEmitStart(node, "constructor");
+                increaseIndent();
+                if (ctor) {
+                    emitDetachedComments(ctor.body.statements);
+                }
+                emitCaptureThisForNodeIfNecessary(node);
+                if (ctor) {
+                    emitDefaultValueAssignments(ctor);
+                    emitRestParameter(ctor);
+                    if (baseTypeElement) {
+                        var superCall = findInitialSuperCall(ctor);
+                        if (superCall) {
+                            writeLine();
+                            emit(superCall);
+                        }
+                    }
+                    emitParameterPropertyAssignments(ctor);
+                }
+                else {
+                    if (baseTypeElement) {
+                        writeLine();
+                        emitStart(baseTypeElement);
+                        if (languageVersion < 2) {
+                            write("_super.apply(this, arguments);");
+                        }
+                        else {
+                            write("super(...args);");
+                        }
+                        emitEnd(baseTypeElement);
+                    }
+                }
+                emitPropertyDeclarations(node, getInitializedProperties(node, false));
+                if (ctor) {
+                    var statements = ctor.body.statements;
+                    if (superCall) {
+                        statements = statements.slice(1);
+                    }
+                    emitLines(statements);
+                }
+                emitTempDeclarations(true);
+                writeLine();
+                if (ctor) {
+                    emitLeadingCommentsOfPosition(ctor.body.statements.end);
+                }
+                decreaseIndent();
+                emitToken(15, ctor ? ctor.body.statements.end : node.members.end);
+                scopeEmitEnd();
+                emitEnd(ctor || node);
+                if (ctor) {
+                    emitTrailingComments(ctor);
+                }
+            }
+            function emitClassExpression(node) {
+                return emitClassLikeDeclaration(node);
+            }
+            function emitClassDeclaration(node) {
+                return emitClassLikeDeclaration(node);
+            }
+            function emitClassLikeDeclaration(node) {
+                if (languageVersion < 2) {
+                    emitClassLikeDeclarationBelowES6(node);
+                }
+                else {
+                    emitClassLikeDeclarationForES6AndHigher(node);
+                }
+            }
+            function emitClassLikeDeclarationForES6AndHigher(node) {
+                var thisNodeIsDecorated = ts.nodeIsDecorated(node);
+                if (node.kind === 201) {
+                    if (thisNodeIsDecorated) {
+                        if (isES6ExportedDeclaration(node) && !(node.flags & 256)) {
+                            write("export ");
+                        }
+                        write("let ");
+                        emitDeclarationName(node);
+                        write(" = ");
+                    }
+                    else if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                        if (node.flags & 256) {
+                            write("default ");
+                        }
+                    }
+                }
+                var staticProperties = getInitializedProperties(node, true);
+                var isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === 174;
+                var tempVariable;
+                if (isClassExpressionWithStaticProperties) {
+                    tempVariable = createAndRecordTempVariable(0);
+                    write("(");
+                    increaseIndent();
+                    emit(tempVariable);
+                    write(" = ");
+                }
+                write("class");
+                if ((node.name || !(node.flags & 256)) && !thisNodeIsDecorated) {
+                    write(" ");
+                    emitDeclarationName(node);
+                }
+                var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
+                if (baseTypeNode) {
+                    write(" extends ");
+                    emit(baseTypeNode.expression);
+                }
+                write(" {");
+                increaseIndent();
+                scopeEmitStart(node);
+                writeLine();
+                emitConstructor(node, baseTypeNode);
+                emitMemberFunctionsForES6AndHigher(node);
+                decreaseIndent();
+                writeLine();
+                emitToken(15, node.members.end);
+                scopeEmitEnd();
+                if (thisNodeIsDecorated) {
+                    write(";");
+                    if (node.name) {
+                        writeLine();
+                        write("Object.defineProperty(");
+                        emitDeclarationName(node);
+                        write(", \"name\", { value: \"");
+                        emitDeclarationName(node);
+                        write("\", configurable: true });");
+                        writeLine();
+                    }
+                }
+                if (isClassExpressionWithStaticProperties) {
+                    for (var _a = 0; _a < staticProperties.length; _a++) {
+                        var property = staticProperties[_a];
+                        write(",");
+                        writeLine();
+                        emitPropertyDeclaration(node, property, tempVariable, true);
+                    }
+                    write(",");
+                    writeLine();
+                    emit(tempVariable);
+                    decreaseIndent();
+                    write(")");
+                }
+                else {
+                    writeLine();
+                    emitPropertyDeclarations(node, staticProperties);
+                    emitDecoratorsOfClass(node);
+                }
+                if (!isES6ExportedDeclaration(node) && (node.flags & 1)) {
+                    writeLine();
+                    emitStart(node);
+                    emitModuleMemberName(node);
+                    write(" = ");
+                    emitDeclarationName(node);
+                    emitEnd(node);
+                    write(";");
+                }
+                else if (isES6ExportedDeclaration(node) && (node.flags & 256) && thisNodeIsDecorated) {
+                    writeLine();
+                    write("export default ");
+                    emitDeclarationName(node);
+                    write(";");
+                }
+            }
+            function emitClassLikeDeclarationBelowES6(node) {
+                if (node.kind === 201) {
+                    write("var ");
+                    emitDeclarationName(node);
+                    write(" = ");
+                }
+                write("(function (");
+                var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node);
+                if (baseTypeNode) {
+                    write("_super");
+                }
+                write(") {");
+                var saveTempFlags = tempFlags;
+                var saveTempVariables = tempVariables;
+                var saveTempParameters = tempParameters;
+                var saveComputedPropertyNamesToGeneratedNames = computedPropertyNamesToGeneratedNames;
+                tempFlags = 0;
+                tempVariables = undefined;
+                tempParameters = undefined;
+                computedPropertyNamesToGeneratedNames = undefined;
+                increaseIndent();
+                scopeEmitStart(node);
+                if (baseTypeNode) {
+                    writeLine();
+                    emitStart(baseTypeNode);
+                    write("__extends(");
+                    emitDeclarationName(node);
+                    write(", _super);");
+                    emitEnd(baseTypeNode);
+                }
+                writeLine();
+                emitConstructor(node, baseTypeNode);
+                emitMemberFunctionsForES5AndLower(node);
+                emitPropertyDeclarations(node, getInitializedProperties(node, true));
+                writeLine();
+                emitDecoratorsOfClass(node);
+                writeLine();
+                emitToken(15, node.members.end, function () {
+                    write("return ");
+                    emitDeclarationName(node);
+                });
+                write(";");
+                emitTempDeclarations(true);
+                tempFlags = saveTempFlags;
+                tempVariables = saveTempVariables;
+                tempParameters = saveTempParameters;
+                computedPropertyNamesToGeneratedNames = saveComputedPropertyNamesToGeneratedNames;
+                decreaseIndent();
+                writeLine();
+                emitToken(15, node.members.end);
+                scopeEmitEnd();
+                emitStart(node);
+                write(")(");
+                if (baseTypeNode) {
+                    emit(baseTypeNode.expression);
+                }
+                write(")");
+                if (node.kind === 201) {
+                    write(";");
+                }
+                emitEnd(node);
+                if (node.kind === 201) {
+                    emitExportMemberAssignment(node);
+                }
+                if (languageVersion < 2 && node.parent === currentSourceFile && node.name) {
+                    emitExportMemberAssignments(node.name);
+                }
+            }
+            function emitClassMemberPrefix(node, member) {
+                emitDeclarationName(node);
+                if (!(member.flags & 128)) {
+                    write(".prototype");
+                }
+            }
+            function emitDecoratorsOfClass(node) {
+                emitDecoratorsOfMembers(node, 0);
+                emitDecoratorsOfMembers(node, 128);
+                emitDecoratorsOfConstructor(node);
+            }
+            function emitDecoratorsOfConstructor(node) {
+                var decorators = node.decorators;
+                var constructor = ts.getFirstConstructorWithBody(node);
+                var hasDecoratedParameters = constructor && ts.forEach(constructor.parameters, ts.nodeIsDecorated);
+                if (!decorators && !hasDecoratedParameters) {
+                    return;
+                }
+                writeLine();
+                emitStart(node);
+                emitDeclarationName(node);
+                write(" = __decorate([");
+                increaseIndent();
+                writeLine();
+                var decoratorCount = decorators ? decorators.length : 0;
+                var argumentsWritten = emitList(decorators, 0, decoratorCount, true, false, false, true, function (decorator) {
+                    emitStart(decorator);
+                    emit(decorator.expression);
+                    emitEnd(decorator);
+                });
+                argumentsWritten += emitDecoratorsOfParameters(constructor, argumentsWritten > 0);
+                emitSerializedTypeMetadata(node, argumentsWritten >= 0);
+                decreaseIndent();
+                writeLine();
+                write("], ");
+                emitDeclarationName(node);
+                write(");");
+                emitEnd(node);
+                writeLine();
+            }
+            function emitDecoratorsOfMembers(node, staticFlag) {
+                for (var _a = 0, _b = node.members; _a < _b.length; _a++) {
+                    var member = _b[_a];
+                    if ((member.flags & 128) !== staticFlag) {
+                        continue;
+                    }
+                    if (!ts.nodeCanBeDecorated(member)) {
+                        continue;
+                    }
+                    if (!ts.nodeOrChildIsDecorated(member)) {
+                        continue;
+                    }
+                    var decorators = void 0;
+                    var functionLikeMember = void 0;
+                    if (ts.isAccessor(member)) {
+                        var accessors = ts.getAllAccessorDeclarations(node.members, member);
+                        if (member !== accessors.firstAccessor) {
+                            continue;
+                        }
+                        decorators = accessors.firstAccessor.decorators;
+                        if (!decorators && accessors.secondAccessor) {
+                            decorators = accessors.secondAccessor.decorators;
+                        }
+                        functionLikeMember = accessors.setAccessor;
+                    }
+                    else {
+                        decorators = member.decorators;
+                        if (member.kind === 134) {
+                            functionLikeMember = member;
+                        }
+                    }
+                    writeLine();
+                    emitStart(member);
+                    if (member.kind !== 132) {
+                        write("Object.defineProperty(");
+                        emitStart(member.name);
+                        emitClassMemberPrefix(node, member);
+                        write(", ");
+                        emitExpressionForPropertyName(member.name);
+                        emitEnd(member.name);
+                        write(",");
+                        increaseIndent();
+                        writeLine();
+                    }
+                    write("__decorate([");
+                    increaseIndent();
+                    writeLine();
+                    var decoratorCount = decorators ? decorators.length : 0;
+                    var argumentsWritten = emitList(decorators, 0, decoratorCount, true, false, false, true, function (decorator) {
+                        emitStart(decorator);
+                        emit(decorator.expression);
+                        emitEnd(decorator);
+                    });
+                    argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
+                    emitSerializedTypeMetadata(member, argumentsWritten > 0);
+                    decreaseIndent();
+                    writeLine();
+                    write("], ");
+                    emitStart(member.name);
+                    emitClassMemberPrefix(node, member);
+                    write(", ");
+                    emitExpressionForPropertyName(member.name);
+                    emitEnd(member.name);
+                    if (member.kind !== 132) {
+                        write(", Object.getOwnPropertyDescriptor(");
+                        emitStart(member.name);
+                        emitClassMemberPrefix(node, member);
+                        write(", ");
+                        emitExpressionForPropertyName(member.name);
+                        emitEnd(member.name);
+                        write("))");
+                        decreaseIndent();
+                    }
+                    write(");");
+                    emitEnd(member);
+                    writeLine();
+                }
+            }
+            function emitDecoratorsOfParameters(node, leadingComma) {
+                var argumentsWritten = 0;
+                if (node) {
+                    var parameterIndex = 0;
+                    for (var _a = 0, _b = node.parameters; _a < _b.length; _a++) {
+                        var parameter = _b[_a];
+                        if (ts.nodeIsDecorated(parameter)) {
+                            var decorators = parameter.decorators;
+                            argumentsWritten += emitList(decorators, 0, decorators.length, true, false, leadingComma, true, function (decorator) {
+                                emitStart(decorator);
+                                write("__param(" + parameterIndex + ", ");
+                                emit(decorator.expression);
+                                write(")");
+                                emitEnd(decorator);
+                            });
+                            leadingComma = true;
+                        }
+                        ++parameterIndex;
+                    }
+                }
+                return argumentsWritten;
+            }
+            function shouldEmitTypeMetadata(node) {
+                switch (node.kind) {
+                    case 134:
+                    case 136:
+                    case 137:
+                    case 132:
+                        return true;
+                }
+                return false;
+            }
+            function shouldEmitReturnTypeMetadata(node) {
+                switch (node.kind) {
+                    case 134:
+                        return true;
+                }
+                return false;
+            }
+            function shouldEmitParamTypesMetadata(node) {
+                switch (node.kind) {
+                    case 201:
+                    case 134:
+                    case 137:
+                        return true;
+                }
+                return false;
+            }
+            function emitSerializedTypeMetadata(node, writeComma) {
+                var argumentsWritten = 0;
+                if (compilerOptions.emitDecoratorMetadata) {
+                    if (shouldEmitTypeMetadata(node)) {
+                        var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
+                        if (serializedType) {
+                            if (writeComma) {
+                                write(", ");
+                            }
+                            writeLine();
+                            write("__metadata('design:type', ");
+                            emitSerializedType(node, serializedType);
+                            write(")");
+                            argumentsWritten++;
+                        }
+                    }
+                    if (shouldEmitParamTypesMetadata(node)) {
+                        var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
+                        if (serializedTypes) {
+                            if (writeComma || argumentsWritten) {
+                                write(", ");
+                            }
+                            writeLine();
+                            write("__metadata('design:paramtypes', [");
+                            for (var i = 0; i < serializedTypes.length; ++i) {
+                                if (i > 0) {
+                                    write(", ");
+                                }
+                                emitSerializedType(node, serializedTypes[i]);
+                            }
+                            write("])");
+                            argumentsWritten++;
+                        }
+                    }
+                    if (shouldEmitReturnTypeMetadata(node)) {
+                        var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
+                        if (serializedType) {
+                            if (writeComma || argumentsWritten) {
+                                write(", ");
+                            }
+                            writeLine();
+                            write("__metadata('design:returntype', ");
+                            emitSerializedType(node, serializedType);
+                            write(")");
+                            argumentsWritten++;
+                        }
+                    }
+                }
+                return argumentsWritten;
+            }
+            function serializeTypeNameSegment(location, path, index) {
+                switch (index) {
+                    case 0:
+                        return "typeof " + path[index] + " !== 'undefined' && " + path[index];
+                    case 1:
+                        return serializeTypeNameSegment(location, path, index - 1) + "." + path[index];
+                    default:
+                        var temp = createAndRecordTempVariable(0).text;
+                        return "(" + temp + " = " + serializeTypeNameSegment(location, path, index - 1) + ") && " + temp + "." + path[index];
+                }
+            }
+            function emitSerializedType(location, name) {
+                if (typeof name === "string") {
+                    write(name);
+                    return;
+                }
+                else {
+                    ts.Debug.assert(name.length > 0, "Invalid serialized type name");
+                    write("(" + serializeTypeNameSegment(location, name, name.length - 1) + ") || Object");
+                }
+            }
+            function emitInterfaceDeclaration(node) {
+                emitOnlyPinnedOrTripleSlashComments(node);
+            }
+            function shouldEmitEnumDeclaration(node) {
+                var isConstEnum = ts.isConst(node);
+                return !isConstEnum || compilerOptions.preserveConstEnums || compilerOptions.separateCompilation;
+            }
+            function emitEnumDeclaration(node) {
+                if (!shouldEmitEnumDeclaration(node)) {
+                    return;
+                }
+                if (!(node.flags & 1) || isES6ExportedDeclaration(node)) {
+                    emitStart(node);
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                    }
+                    write("var ");
+                    emit(node.name);
+                    emitEnd(node);
+                    write(";");
+                }
+                writeLine();
+                emitStart(node);
+                write("(function (");
+                emitStart(node.name);
+                write(getGeneratedNameForNode(node));
+                emitEnd(node.name);
+                write(") {");
+                increaseIndent();
+                scopeEmitStart(node);
+                emitLines(node.members);
+                decreaseIndent();
+                writeLine();
+                emitToken(15, node.members.end);
+                scopeEmitEnd();
+                write(")(");
+                emitModuleMemberName(node);
+                write(" || (");
+                emitModuleMemberName(node);
+                write(" = {}));");
+                emitEnd(node);
+                if (!isES6ExportedDeclaration(node) && node.flags & 1) {
+                    writeLine();
+                    emitStart(node);
+                    write("var ");
+                    emit(node.name);
+                    write(" = ");
+                    emitModuleMemberName(node);
+                    emitEnd(node);
+                    write(";");
+                }
+                if (languageVersion < 2 && node.parent === currentSourceFile) {
+                    emitExportMemberAssignments(node.name);
+                }
+            }
+            function emitEnumMember(node) {
+                var enumParent = node.parent;
+                emitStart(node);
+                write(getGeneratedNameForNode(enumParent));
+                write("[");
+                write(getGeneratedNameForNode(enumParent));
+                write("[");
+                emitExpressionForPropertyName(node.name);
+                write("] = ");
+                writeEnumMemberDeclarationValue(node);
+                write("] = ");
+                emitExpressionForPropertyName(node.name);
+                emitEnd(node);
+                write(";");
+            }
+            function writeEnumMemberDeclarationValue(member) {
+                var value = resolver.getConstantValue(member);
+                if (value !== undefined) {
+                    write(value.toString());
+                    return;
+                }
+                else if (member.initializer) {
+                    emit(member.initializer);
+                }
+                else {
+                    write("undefined");
+                }
+            }
+            function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) {
+                if (moduleDeclaration.body.kind === 205) {
+                    var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body);
+                    return recursiveInnerModule || moduleDeclaration.body;
+                }
+            }
+            function shouldEmitModuleDeclaration(node) {
+                return ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.separateCompilation);
+            }
+            function isModuleMergedWithES6Class(node) {
+                return languageVersion === 2 && !!(resolver.getNodeCheckFlags(node) & 2048);
+            }
+            function emitModuleDeclaration(node) {
+                var shouldEmit = shouldEmitModuleDeclaration(node);
+                if (!shouldEmit) {
+                    return emitOnlyPinnedOrTripleSlashComments(node);
+                }
+                if (!isModuleMergedWithES6Class(node)) {
+                    emitStart(node);
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                    }
+                    write("var ");
+                    emit(node.name);
+                    write(";");
+                    emitEnd(node);
+                    writeLine();
+                }
+                emitStart(node);
+                write("(function (");
+                emitStart(node.name);
+                write(getGeneratedNameForNode(node));
+                emitEnd(node.name);
+                write(") ");
+                if (node.body.kind === 206) {
+                    var saveTempFlags = tempFlags;
+                    var saveTempVariables = tempVariables;
+                    tempFlags = 0;
+                    tempVariables = undefined;
+                    emit(node.body);
+                    tempFlags = saveTempFlags;
+                    tempVariables = saveTempVariables;
+                }
+                else {
+                    write("{");
+                    increaseIndent();
+                    scopeEmitStart(node);
+                    emitCaptureThisForNodeIfNecessary(node);
+                    writeLine();
+                    emit(node.body);
+                    decreaseIndent();
+                    writeLine();
+                    var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body;
+                    emitToken(15, moduleBlock.statements.end);
+                    scopeEmitEnd();
+                }
+                write(")(");
+                if ((node.flags & 1) && !isES6ExportedDeclaration(node)) {
+                    emit(node.name);
+                    write(" = ");
+                }
+                emitModuleMemberName(node);
+                write(" || (");
+                emitModuleMemberName(node);
+                write(" = {}));");
+                emitEnd(node);
+                if (!isES6ExportedDeclaration(node) && node.name.kind === 65 && node.parent === currentSourceFile) {
+                    emitExportMemberAssignments(node.name);
+                }
+            }
+            function emitRequire(moduleName) {
+                if (moduleName.kind === 8) {
+                    write("require(");
+                    emitStart(moduleName);
+                    emitLiteral(moduleName);
+                    emitEnd(moduleName);
+                    emitToken(17, moduleName.end);
+                }
+                else {
+                    write("require()");
+                }
+            }
+            function getNamespaceDeclarationNode(node) {
+                if (node.kind === 208) {
+                    return node;
+                }
+                var importClause = node.importClause;
+                if (importClause && importClause.namedBindings && importClause.namedBindings.kind === 211) {
+                    return importClause.namedBindings;
+                }
+            }
+            function isDefaultImport(node) {
+                return node.kind === 209 && node.importClause && !!node.importClause.name;
+            }
+            function emitExportImportAssignments(node) {
+                if (ts.isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) {
+                    emitExportMemberAssignments(node.name);
+                }
+                ts.forEachChild(node, emitExportImportAssignments);
+            }
+            function emitImportDeclaration(node) {
+                if (languageVersion < 2) {
+                    return emitExternalImportDeclaration(node);
+                }
+                if (node.importClause) {
+                    var shouldEmitDefaultBindings = resolver.isReferencedAliasDeclaration(node.importClause);
+                    var shouldEmitNamedBindings = node.importClause.namedBindings && resolver.isReferencedAliasDeclaration(node.importClause.namedBindings, true);
+                    if (shouldEmitDefaultBindings || shouldEmitNamedBindings) {
+                        write("import ");
+                        emitStart(node.importClause);
+                        if (shouldEmitDefaultBindings) {
+                            emit(node.importClause.name);
+                            if (shouldEmitNamedBindings) {
+                                write(", ");
+                            }
+                        }
+                        if (shouldEmitNamedBindings) {
+                            emitLeadingComments(node.importClause.namedBindings);
+                            emitStart(node.importClause.namedBindings);
+                            if (node.importClause.namedBindings.kind === 211) {
+                                write("* as ");
+                                emit(node.importClause.namedBindings.name);
+                            }
+                            else {
+                                write("{ ");
+                                emitExportOrImportSpecifierList(node.importClause.namedBindings.elements, resolver.isReferencedAliasDeclaration);
+                                write(" }");
+                            }
+                            emitEnd(node.importClause.namedBindings);
+                            emitTrailingComments(node.importClause.namedBindings);
+                        }
+                        emitEnd(node.importClause);
+                        write(" from ");
+                        emit(node.moduleSpecifier);
+                        write(";");
+                    }
+                }
+                else {
+                    write("import ");
+                    emit(node.moduleSpecifier);
+                    write(";");
+                }
+            }
+            function emitExternalImportDeclaration(node) {
+                if (ts.contains(externalImports, node)) {
+                    var isExportedImport = node.kind === 208 && (node.flags & 1) !== 0;
+                    var namespaceDeclaration = getNamespaceDeclarationNode(node);
+                    if (compilerOptions.module !== 2) {
+                        emitLeadingComments(node);
+                        emitStart(node);
+                        if (namespaceDeclaration && !isDefaultImport(node)) {
+                            if (!isExportedImport)
+                                write("var ");
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                        }
+                        else {
+                            var isNakedImport = 209 && !node.importClause;
+                            if (!isNakedImport) {
+                                write("var ");
+                                write(getGeneratedNameForNode(node));
+                                write(" = ");
+                            }
+                        }
+                        emitRequire(ts.getExternalModuleName(node));
+                        if (namespaceDeclaration && isDefaultImport(node)) {
+                            write(", ");
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                            write(getGeneratedNameForNode(node));
+                        }
+                        write(";");
+                        emitEnd(node);
+                        emitExportImportAssignments(node);
+                        emitTrailingComments(node);
+                    }
+                    else {
+                        if (isExportedImport) {
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                            emit(namespaceDeclaration.name);
+                            write(";");
+                        }
+                        else if (namespaceDeclaration && isDefaultImport(node)) {
+                            write("var ");
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                            write(getGeneratedNameForNode(node));
+                            write(";");
+                        }
+                        emitExportImportAssignments(node);
+                    }
+                }
+            }
+            function emitImportEqualsDeclaration(node) {
+                if (ts.isExternalModuleImportEqualsDeclaration(node)) {
+                    emitExternalImportDeclaration(node);
+                    return;
+                }
+                if (resolver.isReferencedAliasDeclaration(node) ||
+                    (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
+                    emitLeadingComments(node);
+                    emitStart(node);
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                        write("var ");
+                    }
+                    else if (!(node.flags & 1)) {
+                        write("var ");
+                    }
+                    emitModuleMemberName(node);
+                    write(" = ");
+                    emit(node.moduleReference);
+                    write(";");
+                    emitEnd(node);
+                    emitExportImportAssignments(node);
+                    emitTrailingComments(node);
+                }
+            }
+            function emitExportDeclaration(node) {
+                if (languageVersion < 2) {
+                    if (node.moduleSpecifier && (!node.exportClause || resolver.isValueAliasDeclaration(node))) {
+                        emitStart(node);
+                        var generatedName = getGeneratedNameForNode(node);
+                        if (node.exportClause) {
+                            if (compilerOptions.module !== 2) {
+                                write("var ");
+                                write(generatedName);
+                                write(" = ");
+                                emitRequire(ts.getExternalModuleName(node));
+                                write(";");
+                            }
+                            for (var _a = 0, _b = node.exportClause.elements; _a < _b.length; _a++) {
+                                var specifier = _b[_a];
+                                if (resolver.isValueAliasDeclaration(specifier)) {
+                                    writeLine();
+                                    emitStart(specifier);
+                                    emitContainingModuleName(specifier);
+                                    write(".");
+                                    emitNodeWithoutSourceMap(specifier.name);
+                                    write(" = ");
+                                    write(generatedName);
+                                    write(".");
+                                    emitNodeWithoutSourceMap(specifier.propertyName || specifier.name);
+                                    write(";");
+                                    emitEnd(specifier);
+                                }
+                            }
+                        }
+                        else {
+                            writeLine();
+                            write("__export(");
+                            if (compilerOptions.module !== 2) {
+                                emitRequire(ts.getExternalModuleName(node));
+                            }
+                            else {
+                                write(generatedName);
+                            }
+                            write(");");
+                        }
+                        emitEnd(node);
+                    }
+                }
+                else {
+                    if (!node.exportClause || resolver.isValueAliasDeclaration(node)) {
+                        emitStart(node);
+                        write("export ");
+                        if (node.exportClause) {
+                            write("{ ");
+                            emitExportOrImportSpecifierList(node.exportClause.elements, resolver.isValueAliasDeclaration);
+                            write(" }");
+                        }
+                        else {
+                            write("*");
+                        }
+                        if (node.moduleSpecifier) {
+                            write(" from ");
+                            emitNodeWithoutSourceMap(node.moduleSpecifier);
+                        }
+                        write(";");
+                        emitEnd(node);
+                    }
+                }
+            }
+            function emitExportOrImportSpecifierList(specifiers, shouldEmit) {
+                ts.Debug.assert(languageVersion >= 2);
+                var needsComma = false;
+                for (var _a = 0; _a < specifiers.length; _a++) {
+                    var specifier = specifiers[_a];
+                    if (shouldEmit(specifier)) {
+                        if (needsComma) {
+                            write(", ");
+                        }
+                        emitStart(specifier);
+                        if (specifier.propertyName) {
+                            emitNodeWithoutSourceMap(specifier.propertyName);
+                            write(" as ");
+                        }
+                        emitNodeWithoutSourceMap(specifier.name);
+                        emitEnd(specifier);
+                        needsComma = true;
+                    }
+                }
+            }
+            function emitExportAssignment(node) {
+                if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) {
+                    if (languageVersion >= 2) {
+                        writeLine();
+                        emitStart(node);
+                        write("export default ");
+                        var expression = node.expression;
+                        emit(expression);
+                        if (expression.kind !== 200 &&
+                            expression.kind !== 201) {
+                            write(";");
+                        }
+                        emitEnd(node);
+                    }
+                    else {
+                        writeLine();
+                        emitStart(node);
+                        emitContainingModuleName(node);
+                        if (languageVersion === 0) {
+                            write("[\"default\"] = ");
+                        }
+                        else {
+                            write(".default = ");
+                        }
+                        emit(node.expression);
+                        write(";");
+                        emitEnd(node);
+                    }
+                }
+            }
+            function collectExternalModuleInfo(sourceFile) {
+                externalImports = [];
+                exportSpecifiers = {};
+                exportEquals = undefined;
+                hasExportStars = false;
+                for (var _a = 0, _b = sourceFile.statements; _a < _b.length; _a++) {
+                    var node = _b[_a];
+                    switch (node.kind) {
+                        case 209:
+                            if (!node.importClause ||
+                                resolver.isReferencedAliasDeclaration(node.importClause, true)) {
+                                externalImports.push(node);
+                            }
+                            break;
+                        case 208:
+                            if (node.moduleReference.kind === 219 && resolver.isReferencedAliasDeclaration(node)) {
+                                externalImports.push(node);
+                            }
+                            break;
+                        case 215:
+                            if (node.moduleSpecifier) {
+                                if (!node.exportClause) {
+                                    externalImports.push(node);
+                                    hasExportStars = true;
+                                }
+                                else if (resolver.isValueAliasDeclaration(node)) {
+                                    externalImports.push(node);
+                                }
+                            }
+                            else {
+                                for (var _c = 0, _d = node.exportClause.elements; _c < _d.length; _c++) {
+                                    var specifier = _d[_c];
+                                    var name_6 = (specifier.propertyName || specifier.name).text;
+                                    (exportSpecifiers[name_6] || (exportSpecifiers[name_6] = [])).push(specifier);
+                                }
+                            }
+                            break;
+                        case 214:
+                            if (node.isExportEquals && !exportEquals) {
+                                exportEquals = node;
+                            }
+                            break;
+                    }
+                }
+            }
+            function emitExportStarHelper() {
+                if (hasExportStars) {
+                    writeLine();
+                    write("function __export(m) {");
+                    increaseIndent();
+                    writeLine();
+                    write("for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];");
+                    decreaseIndent();
+                    writeLine();
+                    write("}");
+                }
+            }
+            function emitAMDDependencies(node, includeNonAmdDependencies) {
+                // An AMD define function has the following shape:
+                //     define(id?, dependencies?, factory);
+                //
+                // This has the shape of
+                //     define(name, ["module1", "module2"], function (module1Alias) {
+                // The location of the alias in the parameter list in the factory function needs to
+                // match the position of the module name in the dependency list.
+                //
+                // To ensure this is true in cases of modules with no aliases, e.g.:
+                // `import "module"` or `<amd-dependency path= "a.css" />`
+                // we need to add modules without alias names to the end of the dependencies list
+                var aliasedModuleNames = [];
+                var unaliasedModuleNames = [];
+                var importAliasNames = [];
+                for (var _a = 0, _b = node.amdDependencies; _a < _b.length; _a++) {
+                    var amdDependency = _b[_a];
+                    if (amdDependency.name) {
+                        aliasedModuleNames.push("\"" + amdDependency.path + "\"");
+                        importAliasNames.push(amdDependency.name);
+                    }
+                    else {
+                        unaliasedModuleNames.push("\"" + amdDependency.path + "\"");
+                    }
+                }
+                for (var _c = 0; _c < externalImports.length; _c++) {
+                    var importNode = externalImports[_c];
+                    var externalModuleName = "";
+                    var moduleName = ts.getExternalModuleName(importNode);
+                    if (moduleName.kind === 8) {
+                        externalModuleName = getLiteralText(moduleName);
+                    }
+                    var importAliasName = void 0;
+                    var namespaceDeclaration = getNamespaceDeclarationNode(importNode);
+                    if (namespaceDeclaration && !isDefaultImport(importNode)) {
+                        importAliasName = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name);
+                    }
+                    else {
+                        importAliasName = getGeneratedNameForNode(importNode);
+                    }
+                    if (includeNonAmdDependencies && importAliasName) {
+                        aliasedModuleNames.push(externalModuleName);
+                        importAliasNames.push(importAliasName);
+                    }
+                    else {
+                        unaliasedModuleNames.push(externalModuleName);
+                    }
+                }
+                write("[\"require\", \"exports\"");
+                if (aliasedModuleNames.length) {
+                    write(", ");
+                    write(aliasedModuleNames.join(", "));
+                }
+                if (unaliasedModuleNames.length) {
+                    write(", ");
+                    write(unaliasedModuleNames.join(", "));
+                }
+                write("], function (require, exports");
+                if (importAliasNames.length) {
+                    write(", ");
+                    write(importAliasNames.join(", "));
+                }
+            }
+            function emitAMDModule(node, startIndex) {
+                collectExternalModuleInfo(node);
+                writeLine();
+                write("define(");
+                if (node.amdModuleName) {
+                    write("\"" + node.amdModuleName + "\", ");
+                }
+                emitAMDDependencies(node, true);
+                write(") {");
+                increaseIndent();
+                emitExportStarHelper();
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(true);
+                emitExportEquals(true);
+                decreaseIndent();
+                writeLine();
+                write("});");
+            }
+            function emitCommonJSModule(node, startIndex) {
+                collectExternalModuleInfo(node);
+                emitExportStarHelper();
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(true);
+                emitExportEquals(false);
+            }
+            function emitUMDModule(node, startIndex) {
+                collectExternalModuleInfo(node);
+                writeLines("(function (deps, factory) {\n    if (typeof module === 'object' && typeof module.exports === 'object') {\n        var v = factory(require, exports); if (v !== undefined) module.exports = v;\n    }\n    else if (typeof define === 'function' && define.amd) {\n        define(deps, factory);\n    }\n})(");
+                emitAMDDependencies(node, false);
+                write(") {");
+                increaseIndent();
+                emitExportStarHelper();
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(true);
+                emitExportEquals(true);
+                decreaseIndent();
+                writeLine();
+                write("});");
+            }
+            function emitES6Module(node, startIndex) {
+                externalImports = undefined;
+                exportSpecifiers = undefined;
+                exportEquals = undefined;
+                hasExportStars = false;
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(true);
+            }
+            function emitExportEquals(emitAsReturn) {
+                if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
+                    writeLine();
+                    emitStart(exportEquals);
+                    write(emitAsReturn ? "return " : "module.exports = ");
+                    emit(exportEquals.expression);
+                    write(";");
+                    emitEnd(exportEquals);
+                }
+            }
+            function emitDirectivePrologues(statements, startWithNewLine) {
+                for (var i = 0; i < statements.length; ++i) {
+                    if (ts.isPrologueDirective(statements[i])) {
+                        if (startWithNewLine || i > 0) {
+                            writeLine();
+                        }
+                        emit(statements[i]);
+                    }
+                    else {
+                        return i;
+                    }
+                }
+                return statements.length;
+            }
+            function writeLines(text) {
+                var lines = text.split(/\r\n|\r|\n/g);
+                for (var i = 0; i < lines.length; ++i) {
+                    var line = lines[i];
+                    if (line.length) {
+                        writeLine();
+                        write(line);
+                    }
+                }
+            }
+            function emitSourceFileNode(node) {
+                writeLine();
+                emitDetachedComments(node);
+                var startIndex = emitDirectivePrologues(node.statements, false);
+                if ((languageVersion < 2) && (!extendsEmitted && resolver.getNodeCheckFlags(node) & 8)) {
+                    writeLines(extendsHelper);
+                    extendsEmitted = true;
+                }
+                if (!decorateEmitted && resolver.getNodeCheckFlags(node) & 512) {
+                    writeLines(decorateHelper);
+                    if (compilerOptions.emitDecoratorMetadata) {
+                        writeLines(metadataHelper);
+                    }
+                    decorateEmitted = true;
+                }
+                if (!paramEmitted && resolver.getNodeCheckFlags(node) & 1024) {
+                    writeLines(paramHelper);
+                    paramEmitted = true;
+                }
+                if (ts.isExternalModule(node)) {
+                    if (languageVersion >= 2) {
+                        emitES6Module(node, startIndex);
+                    }
+                    else if (compilerOptions.module === 2) {
+                        emitAMDModule(node, startIndex);
+                    }
+                    else if (compilerOptions.module === 3) {
+                        emitUMDModule(node, startIndex);
+                    }
+                    else {
+                        emitCommonJSModule(node, startIndex);
+                    }
+                }
+                else {
+                    externalImports = undefined;
+                    exportSpecifiers = undefined;
+                    exportEquals = undefined;
+                    hasExportStars = false;
+                    emitCaptureThisForNodeIfNecessary(node);
+                    emitLinesStartingAt(node.statements, startIndex);
+                    emitTempDeclarations(true);
+                }
+                emitLeadingComments(node.endOfFileToken);
+            }
+            function emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers) {
+                if (!node) {
+                    return;
+                }
+                if (node.flags & 2) {
+                    return emitOnlyPinnedOrTripleSlashComments(node);
+                }
+                var emitComments = shouldEmitLeadingAndTrailingComments(node);
+                if (emitComments) {
+                    emitLeadingComments(node);
+                }
+                emitJavaScriptWorker(node, allowGeneratedIdentifiers);
+                if (emitComments) {
+                    emitTrailingComments(node);
+                }
+            }
+            function shouldEmitLeadingAndTrailingComments(node) {
+                switch (node.kind) {
+                    case 202:
+                    case 200:
+                    case 209:
+                    case 208:
+                    case 203:
+                    case 214:
+                        return false;
+                    case 205:
+                        return shouldEmitModuleDeclaration(node);
+                    case 204:
+                        return shouldEmitEnumDeclaration(node);
+                }
+                if (node.kind !== 179 &&
+                    node.parent &&
+                    node.parent.kind === 163 &&
+                    node.parent.body === node &&
+                    compilerOptions.target <= 1) {
+                    return false;
+                }
+                return true;
+            }
+            function emitJavaScriptWorker(node, allowGeneratedIdentifiers) {
+                if (allowGeneratedIdentifiers === void 0) { allowGeneratedIdentifiers = true; }
+                switch (node.kind) {
+                    case 65:
+                        return emitIdentifier(node, allowGeneratedIdentifiers);
+                    case 129:
+                        return emitParameter(node);
+                    case 134:
+                    case 133:
+                        return emitMethod(node);
+                    case 136:
+                    case 137:
+                        return emitAccessor(node);
+                    case 93:
+                        return emitThis(node);
+                    case 91:
+                        return emitSuper(node);
+                    case 89:
+                        return write("null");
+                    case 95:
+                        return write("true");
+                    case 80:
+                        return write("false");
+                    case 7:
+                    case 8:
+                    case 9:
+                    case 10:
+                    case 11:
+                    case 12:
+                    case 13:
+                        return emitLiteral(node);
+                    case 171:
+                        return emitTemplateExpression(node);
+                    case 176:
+                        return emitTemplateSpan(node);
+                    case 126:
+                        return emitQualifiedName(node);
+                    case 150:
+                        return emitObjectBindingPattern(node);
+                    case 151:
+                        return emitArrayBindingPattern(node);
+                    case 152:
+                        return emitBindingElement(node);
+                    case 153:
+                        return emitArrayLiteral(node);
+                    case 154:
+                        return emitObjectLiteral(node);
+                    case 224:
+                        return emitPropertyAssignment(node);
+                    case 225:
+                        return emitShorthandPropertyAssignment(node);
+                    case 127:
+                        return emitComputedPropertyName(node);
+                    case 155:
+                        return emitPropertyAccess(node);
+                    case 156:
+                        return emitIndexedAccess(node);
+                    case 157:
+                        return emitCallExpression(node);
+                    case 158:
+                        return emitNewExpression(node);
+                    case 159:
+                        return emitTaggedTemplateExpression(node);
+                    case 160:
+                        return emit(node.expression);
+                    case 161:
+                        return emitParenExpression(node);
+                    case 200:
+                    case 162:
+                    case 163:
+                        return emitFunctionDeclaration(node);
+                    case 164:
+                        return emitDeleteExpression(node);
+                    case 165:
+                        return emitTypeOfExpression(node);
+                    case 166:
+                        return emitVoidExpression(node);
+                    case 167:
+                        return emitPrefixUnaryExpression(node);
+                    case 168:
+                        return emitPostfixUnaryExpression(node);
+                    case 169:
+                        return emitBinaryExpression(node);
+                    case 170:
+                        return emitConditionalExpression(node);
+                    case 173:
+                        return emitSpreadElementExpression(node);
+                    case 172:
+                        return emitYieldExpression(node);
+                    case 175:
+                        return;
+                    case 179:
+                    case 206:
+                        return emitBlock(node);
+                    case 180:
+                        return emitVariableStatement(node);
+                    case 181:
+                        return write(";");
+                    case 182:
+                        return emitExpressionStatement(node);
+                    case 183:
+                        return emitIfStatement(node);
+                    case 184:
+                        return emitDoStatement(node);
+                    case 185:
+                        return emitWhileStatement(node);
+                    case 186:
+                        return emitForStatement(node);
+                    case 188:
+                    case 187:
+                        return emitForInOrForOfStatement(node);
+                    case 189:
+                    case 190:
+                        return emitBreakOrContinueStatement(node);
+                    case 191:
+                        return emitReturnStatement(node);
+                    case 192:
+                        return emitWithStatement(node);
+                    case 193:
+                        return emitSwitchStatement(node);
+                    case 220:
+                    case 221:
+                        return emitCaseOrDefaultClause(node);
+                    case 194:
+                        return emitLabelledStatement(node);
+                    case 195:
+                        return emitThrowStatement(node);
+                    case 196:
+                        return emitTryStatement(node);
+                    case 223:
+                        return emitCatchClause(node);
+                    case 197:
+                        return emitDebuggerStatement(node);
+                    case 198:
+                        return emitVariableDeclaration(node);
+                    case 174:
+                        return emitClassExpression(node);
+                    case 201:
+                        return emitClassDeclaration(node);
+                    case 202:
+                        return emitInterfaceDeclaration(node);
+                    case 204:
+                        return emitEnumDeclaration(node);
+                    case 226:
+                        return emitEnumMember(node);
+                    case 205:
+                        return emitModuleDeclaration(node);
+                    case 209:
+                        return emitImportDeclaration(node);
+                    case 208:
+                        return emitImportEqualsDeclaration(node);
+                    case 215:
+                        return emitExportDeclaration(node);
+                    case 214:
+                        return emitExportAssignment(node);
+                    case 227:
+                        return emitSourceFileNode(node);
+                }
+            }
+            function hasDetachedComments(pos) {
+                return detachedCommentsInfo !== undefined && detachedCommentsInfo[detachedCommentsInfo.length - 1].nodePos === pos;
+            }
+            function getLeadingCommentsWithoutDetachedComments() {
+                var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
+                if (detachedCommentsInfo.length - 1) {
+                    detachedCommentsInfo.pop();
+                }
+                else {
+                    detachedCommentsInfo = undefined;
+                }
+                return leadingComments;
+            }
+            function filterComments(ranges, onlyPinnedOrTripleSlashComments) {
+                if (ranges && onlyPinnedOrTripleSlashComments) {
+                    ranges = ts.filter(ranges, isPinnedOrTripleSlashComment);
+                    if (ranges.length === 0) {
+                        return undefined;
+                    }
+                }
+                return ranges;
+            }
+            function getLeadingCommentsToEmit(node) {
+                if (node.parent) {
+                    if (node.parent.kind === 227 || node.pos !== node.parent.pos) {
+                        if (hasDetachedComments(node.pos)) {
+                            return getLeadingCommentsWithoutDetachedComments();
+                        }
+                        else {
+                            return ts.getLeadingCommentRangesOfNode(node, currentSourceFile);
+                        }
+                    }
+                }
+            }
+            function getTrailingCommentsToEmit(node) {
+                if (node.parent) {
+                    if (node.parent.kind === 227 || node.end !== node.parent.end) {
+                        return ts.getTrailingCommentRanges(currentSourceFile.text, node.end);
+                    }
+                }
+            }
+            function emitOnlyPinnedOrTripleSlashComments(node) {
+                emitLeadingCommentsWorker(node, true);
+            }
+            function emitLeadingComments(node) {
+                return emitLeadingCommentsWorker(node, compilerOptions.removeComments);
+            }
+            function emitLeadingCommentsWorker(node, onlyPinnedOrTripleSlashComments) {
+                var leadingComments = filterComments(getLeadingCommentsToEmit(node), onlyPinnedOrTripleSlashComments);
+                ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
+                ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment);
+            }
+            function emitTrailingComments(node) {
+                var trailingComments = filterComments(getTrailingCommentsToEmit(node), compilerOptions.removeComments);
+                ts.emitComments(currentSourceFile, writer, trailingComments, false, newLine, writeComment);
+            }
+            function emitLeadingCommentsOfPosition(pos) {
+                var leadingComments;
+                if (hasDetachedComments(pos)) {
+                    leadingComments = getLeadingCommentsWithoutDetachedComments();
+                }
+                else {
+                    leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, pos);
+                }
+                leadingComments = filterComments(leadingComments, compilerOptions.removeComments);
+                ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments);
+                ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment);
+            }
+            function emitDetachedComments(node) {
+                var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos);
+                if (leadingComments) {
+                    var detachedComments = [];
+                    var lastComment;
+                    ts.forEach(leadingComments, function (comment) {
+                        if (lastComment) {
+                            var lastCommentLine = ts.getLineOfLocalPosition(currentSourceFile, lastComment.end);
+                            var commentLine = ts.getLineOfLocalPosition(currentSourceFile, comment.pos);
+                            if (commentLine >= lastCommentLine + 2) {
+                                return detachedComments;
+                            }
+                        }
+                        detachedComments.push(comment);
+                        lastComment = comment;
+                    });
+                    if (detachedComments.length) {
+                        var lastCommentLine = ts.getLineOfLocalPosition(currentSourceFile, detachedComments[detachedComments.length - 1].end);
+                        var nodeLine = ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node.pos));
+                        if (nodeLine >= lastCommentLine + 2) {
+                            ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
+                            ts.emitComments(currentSourceFile, writer, detachedComments, true, newLine, writeComment);
+                            var currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: detachedComments[detachedComments.length - 1].end };
+                            if (detachedCommentsInfo) {
+                                detachedCommentsInfo.push(currentDetachedCommentInfo);
+                            }
+                            else {
+                                detachedCommentsInfo = [currentDetachedCommentInfo];
+                            }
+                        }
+                    }
+                }
+            }
+            function isPinnedOrTripleSlashComment(comment) {
+                if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42) {
+                    return currentSourceFile.text.charCodeAt(comment.pos + 2) === 33;
+                }
+                else if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 47 &&
+                    comment.pos + 2 < comment.end &&
+                    currentSourceFile.text.charCodeAt(comment.pos + 2) === 47 &&
+                    currentSourceFile.text.substring(comment.pos, comment.end).match(ts.fullTripleSlashReferencePathRegEx)) {
+                    return true;
+                }
+            }
+        }
+        function emitFile(jsFilePath, sourceFile) {
+            emitJavaScript(jsFilePath, sourceFile);
+            if (compilerOptions.declaration) {
+                ts.writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics);
+            }
+        }
+    }
+    ts.emitFiles = emitFiles;
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/parser.js b/dist/typescript/compiler/parser.js
new file mode 100644
index 000000000..2731f6e2b
--- /dev/null
+++ b/dist/typescript/compiler/parser.js
@@ -0,0 +1,3733 @@
+/// <reference path="scanner.ts"/>
+/// <reference path="utilities.ts"/>
+var ts;
+(function (ts) {
+    var nodeConstructors = new Array(229);
+    ts.parseTime = 0;
+    function getNodeConstructor(kind) {
+        return nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind));
+    }
+    ts.getNodeConstructor = getNodeConstructor;
+    function createNode(kind) {
+        return new (getNodeConstructor(kind))();
+    }
+    ts.createNode = createNode;
+    function visitNode(cbNode, node) {
+        if (node) {
+            return cbNode(node);
+        }
+    }
+    function visitNodeArray(cbNodes, nodes) {
+        if (nodes) {
+            return cbNodes(nodes);
+        }
+    }
+    function visitEachNode(cbNode, nodes) {
+        if (nodes) {
+            for (var _i = 0; _i < nodes.length; _i++) {
+                var node = nodes[_i];
+                var result = cbNode(node);
+                if (result) {
+                    return result;
+                }
+            }
+        }
+    }
+    function forEachChild(node, cbNode, cbNodeArray) {
+        if (!node) {
+            return;
+        }
+        var visitNodes = cbNodeArray ? visitNodeArray : visitEachNode;
+        var cbNodes = cbNodeArray || cbNode;
+        switch (node.kind) {
+            case 126:
+                return visitNode(cbNode, node.left) ||
+                    visitNode(cbNode, node.right);
+            case 128:
+                return visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.constraint) ||
+                    visitNode(cbNode, node.expression);
+            case 129:
+            case 132:
+            case 131:
+            case 224:
+            case 225:
+            case 198:
+            case 152:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.propertyName) ||
+                    visitNode(cbNode, node.dotDotDotToken) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.questionToken) ||
+                    visitNode(cbNode, node.type) ||
+                    visitNode(cbNode, node.initializer);
+            case 142:
+            case 143:
+            case 138:
+            case 139:
+            case 140:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNodes(cbNodes, node.typeParameters) ||
+                    visitNodes(cbNodes, node.parameters) ||
+                    visitNode(cbNode, node.type);
+            case 134:
+            case 133:
+            case 135:
+            case 136:
+            case 137:
+            case 162:
+            case 200:
+            case 163:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.asteriskToken) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.questionToken) ||
+                    visitNodes(cbNodes, node.typeParameters) ||
+                    visitNodes(cbNodes, node.parameters) ||
+                    visitNode(cbNode, node.type) ||
+                    visitNode(cbNode, node.equalsGreaterThanToken) ||
+                    visitNode(cbNode, node.body);
+            case 141:
+                return visitNode(cbNode, node.typeName) ||
+                    visitNodes(cbNodes, node.typeArguments);
+            case 144:
+                return visitNode(cbNode, node.exprName);
+            case 145:
+                return visitNodes(cbNodes, node.members);
+            case 146:
+                return visitNode(cbNode, node.elementType);
+            case 147:
+                return visitNodes(cbNodes, node.elementTypes);
+            case 148:
+                return visitNodes(cbNodes, node.types);
+            case 149:
+                return visitNode(cbNode, node.type);
+            case 150:
+            case 151:
+                return visitNodes(cbNodes, node.elements);
+            case 153:
+                return visitNodes(cbNodes, node.elements);
+            case 154:
+                return visitNodes(cbNodes, node.properties);
+            case 155:
+                return visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.dotToken) ||
+                    visitNode(cbNode, node.name);
+            case 156:
+                return visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.argumentExpression);
+            case 157:
+            case 158:
+                return visitNode(cbNode, node.expression) ||
+                    visitNodes(cbNodes, node.typeArguments) ||
+                    visitNodes(cbNodes, node.arguments);
+            case 159:
+                return visitNode(cbNode, node.tag) ||
+                    visitNode(cbNode, node.template);
+            case 160:
+                return visitNode(cbNode, node.type) ||
+                    visitNode(cbNode, node.expression);
+            case 161:
+                return visitNode(cbNode, node.expression);
+            case 164:
+                return visitNode(cbNode, node.expression);
+            case 165:
+                return visitNode(cbNode, node.expression);
+            case 166:
+                return visitNode(cbNode, node.expression);
+            case 167:
+                return visitNode(cbNode, node.operand);
+            case 172:
+                return visitNode(cbNode, node.asteriskToken) ||
+                    visitNode(cbNode, node.expression);
+            case 168:
+                return visitNode(cbNode, node.operand);
+            case 169:
+                return visitNode(cbNode, node.left) ||
+                    visitNode(cbNode, node.operatorToken) ||
+                    visitNode(cbNode, node.right);
+            case 170:
+                return visitNode(cbNode, node.condition) ||
+                    visitNode(cbNode, node.questionToken) ||
+                    visitNode(cbNode, node.whenTrue) ||
+                    visitNode(cbNode, node.colonToken) ||
+                    visitNode(cbNode, node.whenFalse);
+            case 173:
+                return visitNode(cbNode, node.expression);
+            case 179:
+            case 206:
+                return visitNodes(cbNodes, node.statements);
+            case 227:
+                return visitNodes(cbNodes, node.statements) ||
+                    visitNode(cbNode, node.endOfFileToken);
+            case 180:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.declarationList);
+            case 199:
+                return visitNodes(cbNodes, node.declarations);
+            case 182:
+                return visitNode(cbNode, node.expression);
+            case 183:
+                return visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.thenStatement) ||
+                    visitNode(cbNode, node.elseStatement);
+            case 184:
+                return visitNode(cbNode, node.statement) ||
+                    visitNode(cbNode, node.expression);
+            case 185:
+                return visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.statement);
+            case 186:
+                return visitNode(cbNode, node.initializer) ||
+                    visitNode(cbNode, node.condition) ||
+                    visitNode(cbNode, node.incrementor) ||
+                    visitNode(cbNode, node.statement);
+            case 187:
+                return visitNode(cbNode, node.initializer) ||
+                    visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.statement);
+            case 188:
+                return visitNode(cbNode, node.initializer) ||
+                    visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.statement);
+            case 189:
+            case 190:
+                return visitNode(cbNode, node.label);
+            case 191:
+                return visitNode(cbNode, node.expression);
+            case 192:
+                return visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.statement);
+            case 193:
+                return visitNode(cbNode, node.expression) ||
+                    visitNode(cbNode, node.caseBlock);
+            case 207:
+                return visitNodes(cbNodes, node.clauses);
+            case 220:
+                return visitNode(cbNode, node.expression) ||
+                    visitNodes(cbNodes, node.statements);
+            case 221:
+                return visitNodes(cbNodes, node.statements);
+            case 194:
+                return visitNode(cbNode, node.label) ||
+                    visitNode(cbNode, node.statement);
+            case 195:
+                return visitNode(cbNode, node.expression);
+            case 196:
+                return visitNode(cbNode, node.tryBlock) ||
+                    visitNode(cbNode, node.catchClause) ||
+                    visitNode(cbNode, node.finallyBlock);
+            case 223:
+                return visitNode(cbNode, node.variableDeclaration) ||
+                    visitNode(cbNode, node.block);
+            case 130:
+                return visitNode(cbNode, node.expression);
+            case 201:
+            case 174:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNodes(cbNodes, node.typeParameters) ||
+                    visitNodes(cbNodes, node.heritageClauses) ||
+                    visitNodes(cbNodes, node.members);
+            case 202:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNodes(cbNodes, node.typeParameters) ||
+                    visitNodes(cbNodes, node.heritageClauses) ||
+                    visitNodes(cbNodes, node.members);
+            case 203:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.type);
+            case 204:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNodes(cbNodes, node.members);
+            case 226:
+                return visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.initializer);
+            case 205:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.body);
+            case 208:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.moduleReference);
+            case 209:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.importClause) ||
+                    visitNode(cbNode, node.moduleSpecifier);
+            case 210:
+                return visitNode(cbNode, node.name) ||
+                    visitNode(cbNode, node.namedBindings);
+            case 211:
+                return visitNode(cbNode, node.name);
+            case 212:
+            case 216:
+                return visitNodes(cbNodes, node.elements);
+            case 215:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.exportClause) ||
+                    visitNode(cbNode, node.moduleSpecifier);
+            case 213:
+            case 217:
+                return visitNode(cbNode, node.propertyName) ||
+                    visitNode(cbNode, node.name);
+            case 214:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, node.expression);
+            case 171:
+                return visitNode(cbNode, node.head) || visitNodes(cbNodes, node.templateSpans);
+            case 176:
+                return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal);
+            case 127:
+                return visitNode(cbNode, node.expression);
+            case 222:
+                return visitNodes(cbNodes, node.types);
+            case 177:
+                return visitNode(cbNode, node.expression) ||
+                    visitNodes(cbNodes, node.typeArguments);
+            case 219:
+                return visitNode(cbNode, node.expression);
+            case 218:
+                return visitNodes(cbNodes, node.decorators);
+        }
+    }
+    ts.forEachChild = forEachChild;
+    function createSourceFile(fileName, sourceText, languageVersion, setParentNodes) {
+        if (setParentNodes === void 0) { setParentNodes = false; }
+        var start = new Date().getTime();
+        var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes);
+        ts.parseTime += new Date().getTime() - start;
+        return result;
+    }
+    ts.createSourceFile = createSourceFile;
+    function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) {
+        return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
+    }
+    ts.updateSourceFile = updateSourceFile;
+    var Parser;
+    (function (Parser) {
+        var scanner = ts.createScanner(2, true);
+        var disallowInAndDecoratorContext = 2 | 16;
+        var sourceFile;
+        var syntaxCursor;
+        var token;
+        var sourceText;
+        var nodeCount;
+        var identifiers;
+        var identifierCount;
+        var parsingContext;
+        var contextFlags = 0;
+        var parseErrorBeforeNextFinishedNode = false;
+        function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) {
+            sourceText = _sourceText;
+            syntaxCursor = _syntaxCursor;
+            parsingContext = 0;
+            identifiers = {};
+            identifierCount = 0;
+            nodeCount = 0;
+            contextFlags = 0;
+            parseErrorBeforeNextFinishedNode = false;
+            createSourceFile(fileName, languageVersion);
+            scanner.setText(sourceText);
+            scanner.setOnError(scanError);
+            scanner.setScriptTarget(languageVersion);
+            token = nextToken();
+            processReferenceComments(sourceFile);
+            sourceFile.statements = parseList(0, true, parseSourceElement);
+            ts.Debug.assert(token === 1);
+            sourceFile.endOfFileToken = parseTokenNode();
+            setExternalModuleIndicator(sourceFile);
+            sourceFile.nodeCount = nodeCount;
+            sourceFile.identifierCount = identifierCount;
+            sourceFile.identifiers = identifiers;
+            if (setParentNodes) {
+                fixupParentReferences(sourceFile);
+            }
+            syntaxCursor = undefined;
+            scanner.setText("");
+            scanner.setOnError(undefined);
+            var result = sourceFile;
+            sourceFile = undefined;
+            identifiers = undefined;
+            syntaxCursor = undefined;
+            sourceText = undefined;
+            return result;
+        }
+        Parser.parseSourceFile = parseSourceFile;
+        function fixupParentReferences(sourceFile) {
+            // normally parent references are set during binding. However, for clients that only need
+            // a syntax tree, and no semantic features, then the binding process is an unnecessary
+            // overhead.  This functions allows us to set all the parents, without all the expense of
+            // binding.
+            var parent = sourceFile;
+            forEachChild(sourceFile, visitNode);
+            return;
+            function visitNode(n) {
+                if (n.parent !== parent) {
+                    n.parent = parent;
+                    var saveParent = parent;
+                    parent = n;
+                    forEachChild(n, visitNode);
+                    parent = saveParent;
+                }
+            }
+        }
+        function createSourceFile(fileName, languageVersion) {
+            sourceFile = createNode(227, 0);
+            sourceFile.pos = 0;
+            sourceFile.end = sourceText.length;
+            sourceFile.text = sourceText;
+            sourceFile.parseDiagnostics = [];
+            sourceFile.bindDiagnostics = [];
+            sourceFile.languageVersion = languageVersion;
+            sourceFile.fileName = ts.normalizePath(fileName);
+            sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 2048 : 0;
+        }
+        function setContextFlag(val, flag) {
+            if (val) {
+                contextFlags |= flag;
+            }
+            else {
+                contextFlags &= ~flag;
+            }
+        }
+        function setStrictModeContext(val) {
+            setContextFlag(val, 1);
+        }
+        function setDisallowInContext(val) {
+            setContextFlag(val, 2);
+        }
+        function setYieldContext(val) {
+            setContextFlag(val, 4);
+        }
+        function setGeneratorParameterContext(val) {
+            setContextFlag(val, 8);
+        }
+        function setDecoratorContext(val) {
+            setContextFlag(val, 16);
+        }
+        function doOutsideOfContext(flags, func) {
+            var currentContextFlags = contextFlags & flags;
+            if (currentContextFlags) {
+                setContextFlag(false, currentContextFlags);
+                var result = func();
+                setContextFlag(true, currentContextFlags);
+                return result;
+            }
+            return func();
+        }
+        function allowInAnd(func) {
+            if (contextFlags & 2) {
+                setDisallowInContext(false);
+                var result = func();
+                setDisallowInContext(true);
+                return result;
+            }
+            return func();
+        }
+        function disallowInAnd(func) {
+            if (contextFlags & 2) {
+                return func();
+            }
+            setDisallowInContext(true);
+            var result = func();
+            setDisallowInContext(false);
+            return result;
+        }
+        function doInYieldContext(func) {
+            if (contextFlags & 4) {
+                return func();
+            }
+            setYieldContext(true);
+            var result = func();
+            setYieldContext(false);
+            return result;
+        }
+        function doOutsideOfYieldContext(func) {
+            if (contextFlags & 4) {
+                setYieldContext(false);
+                var result = func();
+                setYieldContext(true);
+                return result;
+            }
+            return func();
+        }
+        function doInDecoratorContext(func) {
+            if (contextFlags & 16) {
+                return func();
+            }
+            setDecoratorContext(true);
+            var result = func();
+            setDecoratorContext(false);
+            return result;
+        }
+        function inYieldContext() {
+            return (contextFlags & 4) !== 0;
+        }
+        function inStrictModeContext() {
+            return (contextFlags & 1) !== 0;
+        }
+        function inGeneratorParameterContext() {
+            return (contextFlags & 8) !== 0;
+        }
+        function inDisallowInContext() {
+            return (contextFlags & 2) !== 0;
+        }
+        function inDecoratorContext() {
+            return (contextFlags & 16) !== 0;
+        }
+        function parseErrorAtCurrentToken(message, arg0) {
+            var start = scanner.getTokenPos();
+            var length = scanner.getTextPos() - start;
+            parseErrorAtPosition(start, length, message, arg0);
+        }
+        function parseErrorAtPosition(start, length, message, arg0) {
+            var lastError = ts.lastOrUndefined(sourceFile.parseDiagnostics);
+            if (!lastError || start !== lastError.start) {
+                sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0));
+            }
+            parseErrorBeforeNextFinishedNode = true;
+        }
+        function scanError(message, length) {
+            var pos = scanner.getTextPos();
+            parseErrorAtPosition(pos, length || 0, message);
+        }
+        function getNodePos() {
+            return scanner.getStartPos();
+        }
+        function getNodeEnd() {
+            return scanner.getStartPos();
+        }
+        function nextToken() {
+            return token = scanner.scan();
+        }
+        function getTokenPos(pos) {
+            return ts.skipTrivia(sourceText, pos);
+        }
+        function reScanGreaterToken() {
+            return token = scanner.reScanGreaterToken();
+        }
+        function reScanSlashToken() {
+            return token = scanner.reScanSlashToken();
+        }
+        function reScanTemplateToken() {
+            return token = scanner.reScanTemplateToken();
+        }
+        function speculationHelper(callback, isLookAhead) {
+            var saveToken = token;
+            var saveParseDiagnosticsLength = sourceFile.parseDiagnostics.length;
+            var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
+            var saveContextFlags = contextFlags;
+            var result = isLookAhead
+                ? scanner.lookAhead(callback)
+                : scanner.tryScan(callback);
+            ts.Debug.assert(saveContextFlags === contextFlags);
+            if (!result || isLookAhead) {
+                token = saveToken;
+                sourceFile.parseDiagnostics.length = saveParseDiagnosticsLength;
+                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
+            }
+            return result;
+        }
+        function lookAhead(callback) {
+            return speculationHelper(callback, true);
+        }
+        function tryParse(callback) {
+            return speculationHelper(callback, false);
+        }
+        function isIdentifier() {
+            if (token === 65) {
+                return true;
+            }
+            if (token === 110 && inYieldContext()) {
+                return false;
+            }
+            return token > 101;
+        }
+        function parseExpected(kind, diagnosticMessage) {
+            if (token === kind) {
+                nextToken();
+                return true;
+            }
+            if (diagnosticMessage) {
+                parseErrorAtCurrentToken(diagnosticMessage);
+            }
+            else {
+                parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind));
+            }
+            return false;
+        }
+        function parseOptional(t) {
+            if (token === t) {
+                nextToken();
+                return true;
+            }
+            return false;
+        }
+        function parseOptionalToken(t) {
+            if (token === t) {
+                return parseTokenNode();
+            }
+            return undefined;
+        }
+        function parseExpectedToken(t, reportAtCurrentPosition, diagnosticMessage, arg0) {
+            return parseOptionalToken(t) ||
+                createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0);
+        }
+        function parseTokenNode() {
+            var node = createNode(token);
+            nextToken();
+            return finishNode(node);
+        }
+        function canParseSemicolon() {
+            if (token === 22) {
+                return true;
+            }
+            return token === 15 || token === 1 || scanner.hasPrecedingLineBreak();
+        }
+        function parseSemicolon() {
+            if (canParseSemicolon()) {
+                if (token === 22) {
+                    nextToken();
+                }
+                return true;
+            }
+            else {
+                return parseExpected(22);
+            }
+        }
+        function createNode(kind, pos) {
+            nodeCount++;
+            var node = new (nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)))();
+            if (!(pos >= 0)) {
+                pos = scanner.getStartPos();
+            }
+            node.pos = pos;
+            node.end = pos;
+            return node;
+        }
+        function finishNode(node) {
+            node.end = scanner.getStartPos();
+            if (contextFlags) {
+                node.parserContextFlags = contextFlags;
+            }
+            if (parseErrorBeforeNextFinishedNode) {
+                parseErrorBeforeNextFinishedNode = false;
+                node.parserContextFlags |= 32;
+            }
+            return node;
+        }
+        function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, arg0) {
+            if (reportAtCurrentPosition) {
+                parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0);
+            }
+            else {
+                parseErrorAtCurrentToken(diagnosticMessage, arg0);
+            }
+            var result = createNode(kind, scanner.getStartPos());
+            result.text = "";
+            return finishNode(result);
+        }
+        function internIdentifier(text) {
+            text = ts.escapeIdentifier(text);
+            return ts.hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
+        }
+        function createIdentifier(isIdentifier, diagnosticMessage) {
+            identifierCount++;
+            if (isIdentifier) {
+                var node = createNode(65);
+                if (token !== 65) {
+                    node.originalKeywordKind = token;
+                }
+                node.text = internIdentifier(scanner.getTokenValue());
+                nextToken();
+                return finishNode(node);
+            }
+            return createMissingNode(65, false, diagnosticMessage || ts.Diagnostics.Identifier_expected);
+        }
+        function parseIdentifier(diagnosticMessage) {
+            return createIdentifier(isIdentifier(), diagnosticMessage);
+        }
+        function parseIdentifierName() {
+            return createIdentifier(isIdentifierOrKeyword());
+        }
+        function isLiteralPropertyName() {
+            return isIdentifierOrKeyword() ||
+                token === 8 ||
+                token === 7;
+        }
+        function parsePropertyName() {
+            if (token === 8 || token === 7) {
+                return parseLiteralNode(true);
+            }
+            if (token === 18) {
+                return parseComputedPropertyName();
+            }
+            return parseIdentifierName();
+        }
+        function parseComputedPropertyName() {
+            var node = createNode(127);
+            parseExpected(18);
+            var yieldContext = inYieldContext();
+            if (inGeneratorParameterContext()) {
+                setYieldContext(false);
+            }
+            node.expression = allowInAnd(parseExpression);
+            if (inGeneratorParameterContext()) {
+                setYieldContext(yieldContext);
+            }
+            parseExpected(19);
+            return finishNode(node);
+        }
+        function parseContextualModifier(t) {
+            return token === t && tryParse(nextTokenCanFollowModifier);
+        }
+        function nextTokenCanFollowModifier() {
+            nextToken();
+            return canFollowModifier();
+        }
+        function parseAnyContextualModifier() {
+            return ts.isModifier(token) && tryParse(nextTokenCanFollowContextualModifier);
+        }
+        function nextTokenCanFollowContextualModifier() {
+            if (token === 70) {
+                return nextToken() === 77;
+            }
+            if (token === 78) {
+                nextToken();
+                if (token === 73) {
+                    return lookAhead(nextTokenIsClassOrFunction);
+                }
+                return token !== 35 && token !== 14 && canFollowModifier();
+            }
+            if (token === 73) {
+                return nextTokenIsClassOrFunction();
+            }
+            nextToken();
+            return canFollowModifier();
+        }
+        function canFollowModifier() {
+            return token === 18
+                || token === 14
+                || token === 35
+                || isLiteralPropertyName();
+        }
+        function nextTokenIsClassOrFunction() {
+            nextToken();
+            return token === 69 || token === 83;
+        }
+        function isListElement(parsingContext, inErrorRecovery) {
+            var node = currentNode(parsingContext);
+            if (node) {
+                return true;
+            }
+            switch (parsingContext) {
+                case 0:
+                case 1:
+                    return isSourceElement(inErrorRecovery);
+                case 2:
+                case 4:
+                    return isStartOfStatement(inErrorRecovery);
+                case 3:
+                    return token === 67 || token === 73;
+                case 5:
+                    return isStartOfTypeMember();
+                case 6:
+                    return lookAhead(isClassMemberStart) || (token === 22 && !inErrorRecovery);
+                case 7:
+                    return token === 18 || isLiteralPropertyName();
+                case 13:
+                    return token === 18 || token === 35 || isLiteralPropertyName();
+                case 10:
+                    return isLiteralPropertyName();
+                case 8:
+                    if (token === 14) {
+                        return lookAhead(isValidHeritageClauseObjectLiteral);
+                    }
+                    if (!inErrorRecovery) {
+                        return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
+                    }
+                    else {
+                        return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
+                    }
+                case 9:
+                    return isIdentifierOrPattern();
+                case 11:
+                    return token === 23 || token === 21 || isIdentifierOrPattern();
+                case 16:
+                    return isIdentifier();
+                case 12:
+                case 14:
+                    return token === 23 || token === 21 || isStartOfExpression();
+                case 15:
+                    return isStartOfParameter();
+                case 17:
+                case 18:
+                    return token === 23 || isStartOfType();
+                case 19:
+                    return isHeritageClause();
+                case 20:
+                    return isIdentifierOrKeyword();
+            }
+            ts.Debug.fail("Non-exhaustive case in 'isListElement'.");
+        }
+        function isValidHeritageClauseObjectLiteral() {
+            ts.Debug.assert(token === 14);
+            if (nextToken() === 15) {
+                var next = nextToken();
+                return next === 23 || next === 14 || next === 79 || next === 102;
+            }
+            return true;
+        }
+        function nextTokenIsIdentifier() {
+            nextToken();
+            return isIdentifier();
+        }
+        function isHeritageClauseExtendsOrImplementsKeyword() {
+            if (token === 102 ||
+                token === 79) {
+                return lookAhead(nextTokenIsStartOfExpression);
+            }
+            return false;
+        }
+        function nextTokenIsStartOfExpression() {
+            nextToken();
+            return isStartOfExpression();
+        }
+        function isListTerminator(kind) {
+            if (token === 1) {
+                return true;
+            }
+            switch (kind) {
+                case 1:
+                case 2:
+                case 3:
+                case 5:
+                case 6:
+                case 7:
+                case 13:
+                case 10:
+                case 20:
+                    return token === 15;
+                case 4:
+                    return token === 15 || token === 67 || token === 73;
+                case 8:
+                    return token === 14 || token === 79 || token === 102;
+                case 9:
+                    return isVariableDeclaratorListTerminator();
+                case 16:
+                    return token === 25 || token === 16 || token === 14 || token === 79 || token === 102;
+                case 12:
+                    return token === 17 || token === 22;
+                case 14:
+                case 18:
+                case 11:
+                    return token === 19;
+                case 15:
+                    return token === 17 || token === 19;
+                case 17:
+                    return token === 25 || token === 16;
+                case 19:
+                    return token === 14 || token === 15;
+            }
+        }
+        function isVariableDeclaratorListTerminator() {
+            if (canParseSemicolon()) {
+                return true;
+            }
+            if (isInOrOfKeyword(token)) {
+                return true;
+            }
+            if (token === 32) {
+                return true;
+            }
+            return false;
+        }
+        function isInSomeParsingContext() {
+            for (var kind = 0; kind < 21; kind++) {
+                if (parsingContext & (1 << kind)) {
+                    if (isListElement(kind, true) || isListTerminator(kind)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        function parseList(kind, checkForStrictMode, parseElement) {
+            var saveParsingContext = parsingContext;
+            parsingContext |= 1 << kind;
+            var result = [];
+            result.pos = getNodePos();
+            var savedStrictModeContext = inStrictModeContext();
+            while (!isListTerminator(kind)) {
+                if (isListElement(kind, false)) {
+                    var element = parseListElement(kind, parseElement);
+                    result.push(element);
+                    if (checkForStrictMode && !inStrictModeContext()) {
+                        if (ts.isPrologueDirective(element)) {
+                            if (isUseStrictPrologueDirective(sourceFile, element)) {
+                                setStrictModeContext(true);
+                                checkForStrictMode = false;
+                            }
+                        }
+                        else {
+                            checkForStrictMode = false;
+                        }
+                    }
+                    continue;
+                }
+                if (abortParsingListOrMoveToNextToken(kind)) {
+                    break;
+                }
+            }
+            setStrictModeContext(savedStrictModeContext);
+            result.end = getNodeEnd();
+            parsingContext = saveParsingContext;
+            return result;
+        }
+        function isUseStrictPrologueDirective(sourceFile, node) {
+            ts.Debug.assert(ts.isPrologueDirective(node));
+            var nodeText = ts.getSourceTextOfNodeFromSourceFile(sourceFile, node.expression);
+            return nodeText === '"use strict"' || nodeText === "'use strict'";
+        }
+        function parseListElement(parsingContext, parseElement) {
+            var node = currentNode(parsingContext);
+            if (node) {
+                return consumeNode(node);
+            }
+            return parseElement();
+        }
+        function currentNode(parsingContext) {
+            if (parseErrorBeforeNextFinishedNode) {
+                return undefined;
+            }
+            if (!syntaxCursor) {
+                return undefined;
+            }
+            var node = syntaxCursor.currentNode(scanner.getStartPos());
+            if (ts.nodeIsMissing(node)) {
+                return undefined;
+            }
+            if (node.intersectsChange) {
+                return undefined;
+            }
+            if (ts.containsParseError(node)) {
+                return undefined;
+            }
+            var nodeContextFlags = node.parserContextFlags & 63;
+            if (nodeContextFlags !== contextFlags) {
+                return undefined;
+            }
+            if (!canReuseNode(node, parsingContext)) {
+                return undefined;
+            }
+            return node;
+        }
+        function consumeNode(node) {
+            scanner.setTextPos(node.end);
+            nextToken();
+            return node;
+        }
+        function canReuseNode(node, parsingContext) {
+            switch (parsingContext) {
+                case 1:
+                    return isReusableModuleElement(node);
+                case 6:
+                    return isReusableClassMember(node);
+                case 3:
+                    return isReusableSwitchClause(node);
+                case 2:
+                case 4:
+                    return isReusableStatement(node);
+                case 7:
+                    return isReusableEnumMember(node);
+                case 5:
+                    return isReusableTypeMember(node);
+                case 9:
+                    return isReusableVariableDeclaration(node);
+                case 15:
+                    return isReusableParameter(node);
+                case 19:
+                case 16:
+                case 18:
+                case 17:
+                case 12:
+                case 13:
+                case 8:
+            }
+            return false;
+        }
+        function isReusableModuleElement(node) {
+            if (node) {
+                switch (node.kind) {
+                    case 209:
+                    case 208:
+                    case 215:
+                    case 214:
+                    case 201:
+                    case 202:
+                    case 205:
+                    case 204:
+                        return true;
+                }
+                return isReusableStatement(node);
+            }
+            return false;
+        }
+        function isReusableClassMember(node) {
+            if (node) {
+                switch (node.kind) {
+                    case 135:
+                    case 140:
+                    case 134:
+                    case 136:
+                    case 137:
+                    case 132:
+                    case 178:
+                        return true;
+                }
+            }
+            return false;
+        }
+        function isReusableSwitchClause(node) {
+            if (node) {
+                switch (node.kind) {
+                    case 220:
+                    case 221:
+                        return true;
+                }
+            }
+            return false;
+        }
+        function isReusableStatement(node) {
+            if (node) {
+                switch (node.kind) {
+                    case 200:
+                    case 180:
+                    case 179:
+                    case 183:
+                    case 182:
+                    case 195:
+                    case 191:
+                    case 193:
+                    case 190:
+                    case 189:
+                    case 187:
+                    case 188:
+                    case 186:
+                    case 185:
+                    case 192:
+                    case 181:
+                    case 196:
+                    case 194:
+                    case 184:
+                    case 197:
+                        return true;
+                }
+            }
+            return false;
+        }
+        function isReusableEnumMember(node) {
+            return node.kind === 226;
+        }
+        function isReusableTypeMember(node) {
+            if (node) {
+                switch (node.kind) {
+                    case 139:
+                    case 133:
+                    case 140:
+                    case 131:
+                    case 138:
+                        return true;
+                }
+            }
+            return false;
+        }
+        function isReusableVariableDeclaration(node) {
+            if (node.kind !== 198) {
+                return false;
+            }
+            var variableDeclarator = node;
+            return variableDeclarator.initializer === undefined;
+        }
+        function isReusableParameter(node) {
+            if (node.kind !== 129) {
+                return false;
+            }
+            var parameter = node;
+            return parameter.initializer === undefined;
+        }
+        function abortParsingListOrMoveToNextToken(kind) {
+            parseErrorAtCurrentToken(parsingContextErrors(kind));
+            if (isInSomeParsingContext()) {
+                return true;
+            }
+            nextToken();
+            return false;
+        }
+        function parsingContextErrors(context) {
+            switch (context) {
+                case 0: return ts.Diagnostics.Declaration_or_statement_expected;
+                case 1: return ts.Diagnostics.Declaration_or_statement_expected;
+                case 2: return ts.Diagnostics.Statement_expected;
+                case 3: return ts.Diagnostics.case_or_default_expected;
+                case 4: return ts.Diagnostics.Statement_expected;
+                case 5: return ts.Diagnostics.Property_or_signature_expected;
+                case 6: return ts.Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
+                case 7: return ts.Diagnostics.Enum_member_expected;
+                case 8: return ts.Diagnostics.Expression_expected;
+                case 9: return ts.Diagnostics.Variable_declaration_expected;
+                case 10: return ts.Diagnostics.Property_destructuring_pattern_expected;
+                case 11: return ts.Diagnostics.Array_element_destructuring_pattern_expected;
+                case 12: return ts.Diagnostics.Argument_expression_expected;
+                case 13: return ts.Diagnostics.Property_assignment_expected;
+                case 14: return ts.Diagnostics.Expression_or_comma_expected;
+                case 15: return ts.Diagnostics.Parameter_declaration_expected;
+                case 16: return ts.Diagnostics.Type_parameter_declaration_expected;
+                case 17: return ts.Diagnostics.Type_argument_expected;
+                case 18: return ts.Diagnostics.Type_expected;
+                case 19: return ts.Diagnostics.Unexpected_token_expected;
+                case 20: return ts.Diagnostics.Identifier_expected;
+            }
+        }
+        ;
+        function parseDelimitedList(kind, parseElement, considerSemicolonAsDelimeter) {
+            var saveParsingContext = parsingContext;
+            parsingContext |= 1 << kind;
+            var result = [];
+            result.pos = getNodePos();
+            var commaStart = -1;
+            while (true) {
+                if (isListElement(kind, false)) {
+                    result.push(parseListElement(kind, parseElement));
+                    commaStart = scanner.getTokenPos();
+                    if (parseOptional(23)) {
+                        continue;
+                    }
+                    commaStart = -1;
+                    if (isListTerminator(kind)) {
+                        break;
+                    }
+                    parseExpected(23);
+                    if (considerSemicolonAsDelimeter && token === 22 && !scanner.hasPrecedingLineBreak()) {
+                        nextToken();
+                    }
+                    continue;
+                }
+                if (isListTerminator(kind)) {
+                    break;
+                }
+                if (abortParsingListOrMoveToNextToken(kind)) {
+                    break;
+                }
+            }
+            if (commaStart >= 0) {
+                result.hasTrailingComma = true;
+            }
+            result.end = getNodeEnd();
+            parsingContext = saveParsingContext;
+            return result;
+        }
+        function createMissingList() {
+            var pos = getNodePos();
+            var result = [];
+            result.pos = pos;
+            result.end = pos;
+            return result;
+        }
+        function parseBracketedList(kind, parseElement, open, close) {
+            if (parseExpected(open)) {
+                var result = parseDelimitedList(kind, parseElement);
+                parseExpected(close);
+                return result;
+            }
+            return createMissingList();
+        }
+        function parseEntityName(allowReservedWords, diagnosticMessage) {
+            var entity = parseIdentifier(diagnosticMessage);
+            while (parseOptional(20)) {
+                var node = createNode(126, entity.pos);
+                node.left = entity;
+                node.right = parseRightSideOfDot(allowReservedWords);
+                entity = finishNode(node);
+            }
+            return entity;
+        }
+        function parseRightSideOfDot(allowIdentifierNames) {
+            if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord()) {
+                var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
+                if (matchesPattern) {
+                    return createMissingNode(65, true, ts.Diagnostics.Identifier_expected);
+                }
+            }
+            return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
+        }
+        function parseTemplateExpression() {
+            var template = createNode(171);
+            template.head = parseLiteralNode();
+            ts.Debug.assert(template.head.kind === 11, "Template head has wrong token kind");
+            var templateSpans = [];
+            templateSpans.pos = getNodePos();
+            do {
+                templateSpans.push(parseTemplateSpan());
+            } while (templateSpans[templateSpans.length - 1].literal.kind === 12);
+            templateSpans.end = getNodeEnd();
+            template.templateSpans = templateSpans;
+            return finishNode(template);
+        }
+        function parseTemplateSpan() {
+            var span = createNode(176);
+            span.expression = allowInAnd(parseExpression);
+            var literal;
+            if (token === 15) {
+                reScanTemplateToken();
+                literal = parseLiteralNode();
+            }
+            else {
+                literal = parseExpectedToken(13, false, ts.Diagnostics._0_expected, ts.tokenToString(15));
+            }
+            span.literal = literal;
+            return finishNode(span);
+        }
+        function parseLiteralNode(internName) {
+            var node = createNode(token);
+            var text = scanner.getTokenValue();
+            node.text = internName ? internIdentifier(text) : text;
+            if (scanner.hasExtendedUnicodeEscape()) {
+                node.hasExtendedUnicodeEscape = true;
+            }
+            if (scanner.isUnterminated()) {
+                node.isUnterminated = true;
+            }
+            var tokenPos = scanner.getTokenPos();
+            nextToken();
+            finishNode(node);
+            if (node.kind === 7
+                && sourceText.charCodeAt(tokenPos) === 48
+                && ts.isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) {
+                node.flags |= 16384;
+            }
+            return node;
+        }
+        function parseTypeReference() {
+            var node = createNode(141);
+            node.typeName = parseEntityName(false, ts.Diagnostics.Type_expected);
+            if (!scanner.hasPrecedingLineBreak() && token === 24) {
+                node.typeArguments = parseBracketedList(17, parseType, 24, 25);
+            }
+            return finishNode(node);
+        }
+        function parseTypeQuery() {
+            var node = createNode(144);
+            parseExpected(97);
+            node.exprName = parseEntityName(true);
+            return finishNode(node);
+        }
+        function parseTypeParameter() {
+            var node = createNode(128);
+            node.name = parseIdentifier();
+            if (parseOptional(79)) {
+                if (isStartOfType() || !isStartOfExpression()) {
+                    node.constraint = parseType();
+                }
+                else {
+                    node.expression = parseUnaryExpressionOrHigher();
+                }
+            }
+            return finishNode(node);
+        }
+        function parseTypeParameters() {
+            if (token === 24) {
+                return parseBracketedList(16, parseTypeParameter, 24, 25);
+            }
+        }
+        function parseParameterType() {
+            if (parseOptional(51)) {
+                return token === 8
+                    ? parseLiteralNode(true)
+                    : parseType();
+            }
+            return undefined;
+        }
+        function isStartOfParameter() {
+            return token === 21 || isIdentifierOrPattern() || ts.isModifier(token) || token === 52;
+        }
+        function setModifiers(node, modifiers) {
+            if (modifiers) {
+                node.flags |= modifiers.flags;
+                node.modifiers = modifiers;
+            }
+        }
+        function parseParameter() {
+            var node = createNode(129);
+            node.decorators = parseDecorators();
+            setModifiers(node, parseModifiers());
+            node.dotDotDotToken = parseOptionalToken(21);
+            node.name = inGeneratorParameterContext() ? doInYieldContext(parseIdentifierOrPattern) : parseIdentifierOrPattern();
+            if (ts.getFullWidth(node.name) === 0 && node.flags === 0 && ts.isModifier(token)) {
+                nextToken();
+            }
+            node.questionToken = parseOptionalToken(50);
+            node.type = parseParameterType();
+            node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) : parseParameterInitializer();
+            return finishNode(node);
+        }
+        function parseParameterInitializer() {
+            return parseInitializer(true);
+        }
+        function fillSignature(returnToken, yieldAndGeneratorParameterContext, requireCompleteParameterList, signature) {
+            var returnTokenRequired = returnToken === 32;
+            signature.typeParameters = parseTypeParameters();
+            signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList);
+            if (returnTokenRequired) {
+                parseExpected(returnToken);
+                signature.type = parseType();
+            }
+            else if (parseOptional(returnToken)) {
+                signature.type = parseType();
+            }
+        }
+        function parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList) {
+            if (parseExpected(16)) {
+                var savedYieldContext = inYieldContext();
+                var savedGeneratorParameterContext = inGeneratorParameterContext();
+                setYieldContext(yieldAndGeneratorParameterContext);
+                setGeneratorParameterContext(yieldAndGeneratorParameterContext);
+                var result = parseDelimitedList(15, parseParameter);
+                setYieldContext(savedYieldContext);
+                setGeneratorParameterContext(savedGeneratorParameterContext);
+                if (!parseExpected(17) && requireCompleteParameterList) {
+                    return undefined;
+                }
+                return result;
+            }
+            return requireCompleteParameterList ? undefined : createMissingList();
+        }
+        function parseTypeMemberSemicolon() {
+            if (parseOptional(23)) {
+                return;
+            }
+            parseSemicolon();
+        }
+        function parseSignatureMember(kind) {
+            var node = createNode(kind);
+            if (kind === 139) {
+                parseExpected(88);
+            }
+            fillSignature(51, false, false, node);
+            parseTypeMemberSemicolon();
+            return finishNode(node);
+        }
+        function isIndexSignature() {
+            if (token !== 18) {
+                return false;
+            }
+            return lookAhead(isUnambiguouslyIndexSignature);
+        }
+        function isUnambiguouslyIndexSignature() {
+            nextToken();
+            if (token === 21 || token === 19) {
+                return true;
+            }
+            if (ts.isModifier(token)) {
+                nextToken();
+                if (isIdentifier()) {
+                    return true;
+                }
+            }
+            else if (!isIdentifier()) {
+                return false;
+            }
+            else {
+                nextToken();
+            }
+            if (token === 51 || token === 23) {
+                return true;
+            }
+            if (token !== 50) {
+                return false;
+            }
+            nextToken();
+            return token === 51 || token === 23 || token === 19;
+        }
+        function parseIndexSignatureDeclaration(fullStart, decorators, modifiers) {
+            var node = createNode(140, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.parameters = parseBracketedList(15, parseParameter, 18, 19);
+            node.type = parseTypeAnnotation();
+            parseTypeMemberSemicolon();
+            return finishNode(node);
+        }
+        function parsePropertyOrMethodSignature() {
+            var fullStart = scanner.getStartPos();
+            var name = parsePropertyName();
+            var questionToken = parseOptionalToken(50);
+            if (token === 16 || token === 24) {
+                var method = createNode(133, fullStart);
+                method.name = name;
+                method.questionToken = questionToken;
+                fillSignature(51, false, false, method);
+                parseTypeMemberSemicolon();
+                return finishNode(method);
+            }
+            else {
+                var property = createNode(131, fullStart);
+                property.name = name;
+                property.questionToken = questionToken;
+                property.type = parseTypeAnnotation();
+                parseTypeMemberSemicolon();
+                return finishNode(property);
+            }
+        }
+        function isStartOfTypeMember() {
+            switch (token) {
+                case 16:
+                case 24:
+                case 18:
+                    return true;
+                default:
+                    if (ts.isModifier(token)) {
+                        var result = lookAhead(isStartOfIndexSignatureDeclaration);
+                        if (result) {
+                            return result;
+                        }
+                    }
+                    return isLiteralPropertyName() && lookAhead(isTypeMemberWithLiteralPropertyName);
+            }
+        }
+        function isStartOfIndexSignatureDeclaration() {
+            while (ts.isModifier(token)) {
+                nextToken();
+            }
+            return isIndexSignature();
+        }
+        function isTypeMemberWithLiteralPropertyName() {
+            nextToken();
+            return token === 16 ||
+                token === 24 ||
+                token === 50 ||
+                token === 51 ||
+                canParseSemicolon();
+        }
+        function parseTypeMember() {
+            switch (token) {
+                case 16:
+                case 24:
+                    return parseSignatureMember(138);
+                case 18:
+                    return isIndexSignature()
+                        ? parseIndexSignatureDeclaration(scanner.getStartPos(), undefined, undefined)
+                        : parsePropertyOrMethodSignature();
+                case 88:
+                    if (lookAhead(isStartOfConstructSignature)) {
+                        return parseSignatureMember(139);
+                    }
+                case 8:
+                case 7:
+                    return parsePropertyOrMethodSignature();
+                default:
+                    if (ts.isModifier(token)) {
+                        var result = tryParse(parseIndexSignatureWithModifiers);
+                        if (result) {
+                            return result;
+                        }
+                    }
+                    if (isIdentifierOrKeyword()) {
+                        return parsePropertyOrMethodSignature();
+                    }
+            }
+        }
+        function parseIndexSignatureWithModifiers() {
+            var fullStart = scanner.getStartPos();
+            var decorators = parseDecorators();
+            var modifiers = parseModifiers();
+            return isIndexSignature()
+                ? parseIndexSignatureDeclaration(fullStart, decorators, modifiers)
+                : undefined;
+        }
+        function isStartOfConstructSignature() {
+            nextToken();
+            return token === 16 || token === 24;
+        }
+        function parseTypeLiteral() {
+            var node = createNode(145);
+            node.members = parseObjectTypeMembers();
+            return finishNode(node);
+        }
+        function parseObjectTypeMembers() {
+            var members;
+            if (parseExpected(14)) {
+                members = parseList(5, false, parseTypeMember);
+                parseExpected(15);
+            }
+            else {
+                members = createMissingList();
+            }
+            return members;
+        }
+        function parseTupleType() {
+            var node = createNode(147);
+            node.elementTypes = parseBracketedList(18, parseType, 18, 19);
+            return finishNode(node);
+        }
+        function parseParenthesizedType() {
+            var node = createNode(149);
+            parseExpected(16);
+            node.type = parseType();
+            parseExpected(17);
+            return finishNode(node);
+        }
+        function parseFunctionOrConstructorType(kind) {
+            var node = createNode(kind);
+            if (kind === 143) {
+                parseExpected(88);
+            }
+            fillSignature(32, false, false, node);
+            return finishNode(node);
+        }
+        function parseKeywordAndNoDot() {
+            var node = parseTokenNode();
+            return token === 20 ? undefined : node;
+        }
+        function parseNonArrayType() {
+            switch (token) {
+                case 112:
+                case 121:
+                case 119:
+                case 113:
+                case 122:
+                    var node = tryParse(parseKeywordAndNoDot);
+                    return node || parseTypeReference();
+                case 99:
+                    return parseTokenNode();
+                case 97:
+                    return parseTypeQuery();
+                case 14:
+                    return parseTypeLiteral();
+                case 18:
+                    return parseTupleType();
+                case 16:
+                    return parseParenthesizedType();
+                default:
+                    return parseTypeReference();
+            }
+        }
+        function isStartOfType() {
+            switch (token) {
+                case 112:
+                case 121:
+                case 119:
+                case 113:
+                case 122:
+                case 99:
+                case 97:
+                case 14:
+                case 18:
+                case 24:
+                case 88:
+                    return true;
+                case 16:
+                    return lookAhead(isStartOfParenthesizedOrFunctionType);
+                default:
+                    return isIdentifier();
+            }
+        }
+        function isStartOfParenthesizedOrFunctionType() {
+            nextToken();
+            return token === 17 || isStartOfParameter() || isStartOfType();
+        }
+        function parseArrayTypeOrHigher() {
+            var type = parseNonArrayType();
+            while (!scanner.hasPrecedingLineBreak() && parseOptional(18)) {
+                parseExpected(19);
+                var node = createNode(146, type.pos);
+                node.elementType = type;
+                type = finishNode(node);
+            }
+            return type;
+        }
+        function parseUnionTypeOrHigher() {
+            var type = parseArrayTypeOrHigher();
+            if (token === 44) {
+                var types = [type];
+                types.pos = type.pos;
+                while (parseOptional(44)) {
+                    types.push(parseArrayTypeOrHigher());
+                }
+                types.end = getNodeEnd();
+                var node = createNode(148, type.pos);
+                node.types = types;
+                type = finishNode(node);
+            }
+            return type;
+        }
+        function isStartOfFunctionType() {
+            if (token === 24) {
+                return true;
+            }
+            return token === 16 && lookAhead(isUnambiguouslyStartOfFunctionType);
+        }
+        function isUnambiguouslyStartOfFunctionType() {
+            nextToken();
+            if (token === 17 || token === 21) {
+                return true;
+            }
+            if (isIdentifier() || ts.isModifier(token)) {
+                nextToken();
+                if (token === 51 || token === 23 ||
+                    token === 50 || token === 53 ||
+                    isIdentifier() || ts.isModifier(token)) {
+                    return true;
+                }
+                if (token === 17) {
+                    nextToken();
+                    if (token === 32) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        function parseType() {
+            var savedYieldContext = inYieldContext();
+            var savedGeneratorParameterContext = inGeneratorParameterContext();
+            setYieldContext(false);
+            setGeneratorParameterContext(false);
+            var result = parseTypeWorker();
+            setYieldContext(savedYieldContext);
+            setGeneratorParameterContext(savedGeneratorParameterContext);
+            return result;
+        }
+        function parseTypeWorker() {
+            if (isStartOfFunctionType()) {
+                return parseFunctionOrConstructorType(142);
+            }
+            if (token === 88) {
+                return parseFunctionOrConstructorType(143);
+            }
+            return parseUnionTypeOrHigher();
+        }
+        function parseTypeAnnotation() {
+            return parseOptional(51) ? parseType() : undefined;
+        }
+        function isStartOfLeftHandSideExpression() {
+            switch (token) {
+                case 93:
+                case 91:
+                case 89:
+                case 95:
+                case 80:
+                case 7:
+                case 8:
+                case 10:
+                case 11:
+                case 16:
+                case 18:
+                case 14:
+                case 83:
+                case 69:
+                case 88:
+                case 36:
+                case 57:
+                case 65:
+                    return true;
+                default:
+                    return isIdentifier();
+            }
+        }
+        function isStartOfExpression() {
+            if (isStartOfLeftHandSideExpression()) {
+                return true;
+            }
+            switch (token) {
+                case 33:
+                case 34:
+                case 47:
+                case 46:
+                case 74:
+                case 97:
+                case 99:
+                case 38:
+                case 39:
+                case 24:
+                case 110:
+                    return true;
+                default:
+                    if (isBinaryOperator()) {
+                        return true;
+                    }
+                    return isIdentifier();
+            }
+        }
+        function isStartOfExpressionStatement() {
+            return token !== 14 &&
+                token !== 83 &&
+                token !== 69 &&
+                token !== 52 &&
+                isStartOfExpression();
+        }
+        function parseExpression() {
+            // Expression[in]:
+            //      AssignmentExpression[in]
+            //      Expression[in] , AssignmentExpression[in]
+            var saveDecoratorContext = inDecoratorContext();
+            if (saveDecoratorContext) {
+                setDecoratorContext(false);
+            }
+            var expr = parseAssignmentExpressionOrHigher();
+            var operatorToken;
+            while ((operatorToken = parseOptionalToken(23))) {
+                expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher());
+            }
+            if (saveDecoratorContext) {
+                setDecoratorContext(true);
+            }
+            return expr;
+        }
+        function parseInitializer(inParameter) {
+            if (token !== 53) {
+                if (scanner.hasPrecedingLineBreak() || (inParameter && token === 14) || !isStartOfExpression()) {
+                    return undefined;
+                }
+            }
+            parseExpected(53);
+            return parseAssignmentExpressionOrHigher();
+        }
+        function parseAssignmentExpressionOrHigher() {
+            //  AssignmentExpression[in,yield]:
+            //      1) ConditionalExpression[?in,?yield]
+            //      2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
+            //      3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
+            //      4) ArrowFunctionExpression[?in,?yield]
+            //      5) [+Yield] YieldExpression[?In]
+            //
+            // Note: for ease of implementation we treat productions '2' and '3' as the same thing.
+            // (i.e. they're both BinaryExpressions with an assignment operator in it).
+            if (isYieldExpression()) {
+                return parseYieldExpression();
+            }
+            var arrowExpression = tryParseParenthesizedArrowFunctionExpression();
+            if (arrowExpression) {
+                return arrowExpression;
+            }
+            var expr = parseBinaryExpressionOrHigher(0);
+            if (expr.kind === 65 && token === 32) {
+                return parseSimpleArrowFunctionExpression(expr);
+            }
+            if (ts.isLeftHandSideExpression(expr) && ts.isAssignmentOperator(reScanGreaterToken())) {
+                return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher());
+            }
+            return parseConditionalExpressionRest(expr);
+        }
+        function isYieldExpression() {
+            if (token === 110) {
+                if (inYieldContext()) {
+                    return true;
+                }
+                if (inStrictModeContext()) {
+                    return true;
+                }
+                return lookAhead(nextTokenIsIdentifierOnSameLine);
+            }
+            return false;
+        }
+        function nextTokenIsIdentifierOnSameLine() {
+            nextToken();
+            return !scanner.hasPrecedingLineBreak() && isIdentifier();
+        }
+        function nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine() {
+            nextToken();
+            return !scanner.hasPrecedingLineBreak() &&
+                (isIdentifier() || token === 14 || token === 18);
+        }
+        function parseYieldExpression() {
+            var node = createNode(172);
+            nextToken();
+            if (!scanner.hasPrecedingLineBreak() &&
+                (token === 35 || isStartOfExpression())) {
+                node.asteriskToken = parseOptionalToken(35);
+                node.expression = parseAssignmentExpressionOrHigher();
+                return finishNode(node);
+            }
+            else {
+                return finishNode(node);
+            }
+        }
+        function parseSimpleArrowFunctionExpression(identifier) {
+            ts.Debug.assert(token === 32, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
+            var node = createNode(163, identifier.pos);
+            var parameter = createNode(129, identifier.pos);
+            parameter.name = identifier;
+            finishNode(parameter);
+            node.parameters = [parameter];
+            node.parameters.pos = parameter.pos;
+            node.parameters.end = parameter.end;
+            node.equalsGreaterThanToken = parseExpectedToken(32, false, ts.Diagnostics._0_expected, "=>");
+            node.body = parseArrowFunctionExpressionBody();
+            return finishNode(node);
+        }
+        function tryParseParenthesizedArrowFunctionExpression() {
+            var triState = isParenthesizedArrowFunctionExpression();
+            if (triState === 0) {
+                return undefined;
+            }
+            var arrowFunction = triState === 1
+                ? parseParenthesizedArrowFunctionExpressionHead(true)
+                : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead);
+            if (!arrowFunction) {
+                return undefined;
+            }
+            var lastToken = token;
+            arrowFunction.equalsGreaterThanToken = parseExpectedToken(32, false, ts.Diagnostics._0_expected, "=>");
+            arrowFunction.body = (lastToken === 32 || lastToken === 14)
+                ? parseArrowFunctionExpressionBody()
+                : parseIdentifier();
+            return finishNode(arrowFunction);
+        }
+        function isParenthesizedArrowFunctionExpression() {
+            if (token === 16 || token === 24) {
+                return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
+            }
+            if (token === 32) {
+                return 1;
+            }
+            return 0;
+        }
+        function isParenthesizedArrowFunctionExpressionWorker() {
+            var first = token;
+            var second = nextToken();
+            if (first === 16) {
+                if (second === 17) {
+                    var third = nextToken();
+                    switch (third) {
+                        case 32:
+                        case 51:
+                        case 14:
+                            return 1;
+                        default:
+                            return 0;
+                    }
+                }
+                if (second === 18 || second === 14) {
+                    return 2;
+                }
+                if (second === 21) {
+                    return 1;
+                }
+                if (!isIdentifier()) {
+                    return 0;
+                }
+                if (nextToken() === 51) {
+                    return 1;
+                }
+                return 2;
+            }
+            else {
+                ts.Debug.assert(first === 24);
+                if (!isIdentifier()) {
+                    return 0;
+                }
+                return 2;
+            }
+        }
+        function parsePossibleParenthesizedArrowFunctionExpressionHead() {
+            return parseParenthesizedArrowFunctionExpressionHead(false);
+        }
+        function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity) {
+            var node = createNode(163);
+            fillSignature(51, false, !allowAmbiguity, node);
+            if (!node.parameters) {
+                return undefined;
+            }
+            if (!allowAmbiguity && token !== 32 && token !== 14) {
+                return undefined;
+            }
+            return node;
+        }
+        function parseArrowFunctionExpressionBody() {
+            if (token === 14) {
+                return parseFunctionBlock(false, false);
+            }
+            if (isStartOfStatement(true) &&
+                !isStartOfExpressionStatement() &&
+                token !== 83 &&
+                token !== 69) {
+                return parseFunctionBlock(false, true);
+            }
+            return parseAssignmentExpressionOrHigher();
+        }
+        function parseConditionalExpressionRest(leftOperand) {
+            var questionToken = parseOptionalToken(50);
+            if (!questionToken) {
+                return leftOperand;
+            }
+            var node = createNode(170, leftOperand.pos);
+            node.condition = leftOperand;
+            node.questionToken = questionToken;
+            node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher);
+            node.colonToken = parseExpectedToken(51, false, ts.Diagnostics._0_expected, ts.tokenToString(51));
+            node.whenFalse = parseAssignmentExpressionOrHigher();
+            return finishNode(node);
+        }
+        function parseBinaryExpressionOrHigher(precedence) {
+            var leftOperand = parseUnaryExpressionOrHigher();
+            return parseBinaryExpressionRest(precedence, leftOperand);
+        }
+        function isInOrOfKeyword(t) {
+            return t === 86 || t === 125;
+        }
+        function parseBinaryExpressionRest(precedence, leftOperand) {
+            while (true) {
+                reScanGreaterToken();
+                var newPrecedence = getBinaryOperatorPrecedence();
+                if (newPrecedence <= precedence) {
+                    break;
+                }
+                if (token === 86 && inDisallowInContext()) {
+                    break;
+                }
+                leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
+            }
+            return leftOperand;
+        }
+        function isBinaryOperator() {
+            if (inDisallowInContext() && token === 86) {
+                return false;
+            }
+            return getBinaryOperatorPrecedence() > 0;
+        }
+        function getBinaryOperatorPrecedence() {
+            switch (token) {
+                case 49:
+                    return 1;
+                case 48:
+                    return 2;
+                case 44:
+                    return 3;
+                case 45:
+                    return 4;
+                case 43:
+                    return 5;
+                case 28:
+                case 29:
+                case 30:
+                case 31:
+                    return 6;
+                case 24:
+                case 25:
+                case 26:
+                case 27:
+                case 87:
+                case 86:
+                    return 7;
+                case 40:
+                case 41:
+                case 42:
+                    return 8;
+                case 33:
+                case 34:
+                    return 9;
+                case 35:
+                case 36:
+                case 37:
+                    return 10;
+            }
+            return -1;
+        }
+        function makeBinaryExpression(left, operatorToken, right) {
+            var node = createNode(169, left.pos);
+            node.left = left;
+            node.operatorToken = operatorToken;
+            node.right = right;
+            return finishNode(node);
+        }
+        function parsePrefixUnaryExpression() {
+            var node = createNode(167);
+            node.operator = token;
+            nextToken();
+            node.operand = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+        function parseDeleteExpression() {
+            var node = createNode(164);
+            nextToken();
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+        function parseTypeOfExpression() {
+            var node = createNode(165);
+            nextToken();
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+        function parseVoidExpression() {
+            var node = createNode(166);
+            nextToken();
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+        function parseUnaryExpressionOrHigher() {
+            switch (token) {
+                case 33:
+                case 34:
+                case 47:
+                case 46:
+                case 38:
+                case 39:
+                    return parsePrefixUnaryExpression();
+                case 74:
+                    return parseDeleteExpression();
+                case 97:
+                    return parseTypeOfExpression();
+                case 99:
+                    return parseVoidExpression();
+                case 24:
+                    return parseTypeAssertion();
+                default:
+                    return parsePostfixExpressionOrHigher();
+            }
+        }
+        function parsePostfixExpressionOrHigher() {
+            var expression = parseLeftHandSideExpressionOrHigher();
+            ts.Debug.assert(ts.isLeftHandSideExpression(expression));
+            if ((token === 38 || token === 39) && !scanner.hasPrecedingLineBreak()) {
+                var node = createNode(168, expression.pos);
+                node.operand = expression;
+                node.operator = token;
+                nextToken();
+                return finishNode(node);
+            }
+            return expression;
+        }
+        function parseLeftHandSideExpressionOrHigher() {
+            var expression = token === 91
+                ? parseSuperExpression()
+                : parseMemberExpressionOrHigher();
+            return parseCallExpressionRest(expression);
+        }
+        function parseMemberExpressionOrHigher() {
+            var expression = parsePrimaryExpression();
+            return parseMemberExpressionRest(expression);
+        }
+        function parseSuperExpression() {
+            var expression = parseTokenNode();
+            if (token === 16 || token === 20) {
+                return expression;
+            }
+            var node = createNode(155, expression.pos);
+            node.expression = expression;
+            node.dotToken = parseExpectedToken(20, false, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
+            node.name = parseRightSideOfDot(true);
+            return finishNode(node);
+        }
+        function parseTypeAssertion() {
+            var node = createNode(160);
+            parseExpected(24);
+            node.type = parseType();
+            parseExpected(25);
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+        function parseMemberExpressionRest(expression) {
+            while (true) {
+                var dotToken = parseOptionalToken(20);
+                if (dotToken) {
+                    var propertyAccess = createNode(155, expression.pos);
+                    propertyAccess.expression = expression;
+                    propertyAccess.dotToken = dotToken;
+                    propertyAccess.name = parseRightSideOfDot(true);
+                    expression = finishNode(propertyAccess);
+                    continue;
+                }
+                if (!inDecoratorContext() && parseOptional(18)) {
+                    var indexedAccess = createNode(156, expression.pos);
+                    indexedAccess.expression = expression;
+                    if (token !== 19) {
+                        indexedAccess.argumentExpression = allowInAnd(parseExpression);
+                        if (indexedAccess.argumentExpression.kind === 8 || indexedAccess.argumentExpression.kind === 7) {
+                            var literal = indexedAccess.argumentExpression;
+                            literal.text = internIdentifier(literal.text);
+                        }
+                    }
+                    parseExpected(19);
+                    expression = finishNode(indexedAccess);
+                    continue;
+                }
+                if (token === 10 || token === 11) {
+                    var tagExpression = createNode(159, expression.pos);
+                    tagExpression.tag = expression;
+                    tagExpression.template = token === 10
+                        ? parseLiteralNode()
+                        : parseTemplateExpression();
+                    expression = finishNode(tagExpression);
+                    continue;
+                }
+                return expression;
+            }
+        }
+        function parseCallExpressionRest(expression) {
+            while (true) {
+                expression = parseMemberExpressionRest(expression);
+                if (token === 24) {
+                    var typeArguments = tryParse(parseTypeArgumentsInExpression);
+                    if (!typeArguments) {
+                        return expression;
+                    }
+                    var callExpr = createNode(157, expression.pos);
+                    callExpr.expression = expression;
+                    callExpr.typeArguments = typeArguments;
+                    callExpr.arguments = parseArgumentList();
+                    expression = finishNode(callExpr);
+                    continue;
+                }
+                else if (token === 16) {
+                    var callExpr = createNode(157, expression.pos);
+                    callExpr.expression = expression;
+                    callExpr.arguments = parseArgumentList();
+                    expression = finishNode(callExpr);
+                    continue;
+                }
+                return expression;
+            }
+        }
+        function parseArgumentList() {
+            parseExpected(16);
+            var result = parseDelimitedList(12, parseArgumentExpression);
+            parseExpected(17);
+            return result;
+        }
+        function parseTypeArgumentsInExpression() {
+            if (!parseOptional(24)) {
+                return undefined;
+            }
+            var typeArguments = parseDelimitedList(17, parseType);
+            if (!parseExpected(25)) {
+                return undefined;
+            }
+            return typeArguments && canFollowTypeArgumentsInExpression()
+                ? typeArguments
+                : undefined;
+        }
+        function canFollowTypeArgumentsInExpression() {
+            switch (token) {
+                case 16:
+                case 20:
+                case 17:
+                case 19:
+                case 51:
+                case 22:
+                case 50:
+                case 28:
+                case 30:
+                case 29:
+                case 31:
+                case 48:
+                case 49:
+                case 45:
+                case 43:
+                case 44:
+                case 15:
+                case 1:
+                    return true;
+                case 23:
+                case 14:
+                default:
+                    return false;
+            }
+        }
+        function parsePrimaryExpression() {
+            switch (token) {
+                case 7:
+                case 8:
+                case 10:
+                    return parseLiteralNode();
+                case 93:
+                case 91:
+                case 89:
+                case 95:
+                case 80:
+                    return parseTokenNode();
+                case 16:
+                    return parseParenthesizedExpression();
+                case 18:
+                    return parseArrayLiteralExpression();
+                case 14:
+                    return parseObjectLiteralExpression();
+                case 69:
+                    return parseClassExpression();
+                case 83:
+                    return parseFunctionExpression();
+                case 88:
+                    return parseNewExpression();
+                case 36:
+                case 57:
+                    if (reScanSlashToken() === 9) {
+                        return parseLiteralNode();
+                    }
+                    break;
+                case 11:
+                    return parseTemplateExpression();
+            }
+            return parseIdentifier(ts.Diagnostics.Expression_expected);
+        }
+        function parseParenthesizedExpression() {
+            var node = createNode(161);
+            parseExpected(16);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(17);
+            return finishNode(node);
+        }
+        function parseSpreadElement() {
+            var node = createNode(173);
+            parseExpected(21);
+            node.expression = parseAssignmentExpressionOrHigher();
+            return finishNode(node);
+        }
+        function parseArgumentOrArrayLiteralElement() {
+            return token === 21 ? parseSpreadElement() :
+                token === 23 ? createNode(175) :
+                    parseAssignmentExpressionOrHigher();
+        }
+        function parseArgumentExpression() {
+            return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
+        }
+        function parseArrayLiteralExpression() {
+            var node = createNode(153);
+            parseExpected(18);
+            if (scanner.hasPrecedingLineBreak())
+                node.flags |= 512;
+            node.elements = parseDelimitedList(14, parseArgumentOrArrayLiteralElement);
+            parseExpected(19);
+            return finishNode(node);
+        }
+        function tryParseAccessorDeclaration(fullStart, decorators, modifiers) {
+            if (parseContextualModifier(116)) {
+                return parseAccessorDeclaration(136, fullStart, decorators, modifiers);
+            }
+            else if (parseContextualModifier(120)) {
+                return parseAccessorDeclaration(137, fullStart, decorators, modifiers);
+            }
+            return undefined;
+        }
+        function parseObjectLiteralElement() {
+            var fullStart = scanner.getStartPos();
+            var decorators = parseDecorators();
+            var modifiers = parseModifiers();
+            var accessor = tryParseAccessorDeclaration(fullStart, decorators, modifiers);
+            if (accessor) {
+                return accessor;
+            }
+            var asteriskToken = parseOptionalToken(35);
+            var tokenIsIdentifier = isIdentifier();
+            var nameToken = token;
+            var propertyName = parsePropertyName();
+            var questionToken = parseOptionalToken(50);
+            if (asteriskToken || token === 16 || token === 24) {
+                return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, propertyName, questionToken);
+            }
+            if ((token === 23 || token === 15) && tokenIsIdentifier) {
+                var shorthandDeclaration = createNode(225, fullStart);
+                shorthandDeclaration.name = propertyName;
+                shorthandDeclaration.questionToken = questionToken;
+                return finishNode(shorthandDeclaration);
+            }
+            else {
+                var propertyAssignment = createNode(224, fullStart);
+                propertyAssignment.name = propertyName;
+                propertyAssignment.questionToken = questionToken;
+                parseExpected(51);
+                propertyAssignment.initializer = allowInAnd(parseAssignmentExpressionOrHigher);
+                return finishNode(propertyAssignment);
+            }
+        }
+        function parseObjectLiteralExpression() {
+            var node = createNode(154);
+            parseExpected(14);
+            if (scanner.hasPrecedingLineBreak()) {
+                node.flags |= 512;
+            }
+            node.properties = parseDelimitedList(13, parseObjectLiteralElement, true);
+            parseExpected(15);
+            return finishNode(node);
+        }
+        function parseFunctionExpression() {
+            var saveDecoratorContext = inDecoratorContext();
+            if (saveDecoratorContext) {
+                setDecoratorContext(false);
+            }
+            var node = createNode(162);
+            parseExpected(83);
+            node.asteriskToken = parseOptionalToken(35);
+            node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
+            fillSignature(51, !!node.asteriskToken, false, node);
+            node.body = parseFunctionBlock(!!node.asteriskToken, false);
+            if (saveDecoratorContext) {
+                setDecoratorContext(true);
+            }
+            return finishNode(node);
+        }
+        function parseOptionalIdentifier() {
+            return isIdentifier() ? parseIdentifier() : undefined;
+        }
+        function parseNewExpression() {
+            var node = createNode(158);
+            parseExpected(88);
+            node.expression = parseMemberExpressionOrHigher();
+            node.typeArguments = tryParse(parseTypeArgumentsInExpression);
+            if (node.typeArguments || token === 16) {
+                node.arguments = parseArgumentList();
+            }
+            return finishNode(node);
+        }
+        function parseBlock(ignoreMissingOpenBrace, checkForStrictMode, diagnosticMessage) {
+            var node = createNode(179);
+            if (parseExpected(14, diagnosticMessage) || ignoreMissingOpenBrace) {
+                node.statements = parseList(2, checkForStrictMode, parseStatement);
+                parseExpected(15);
+            }
+            else {
+                node.statements = createMissingList();
+            }
+            return finishNode(node);
+        }
+        function parseFunctionBlock(allowYield, ignoreMissingOpenBrace, diagnosticMessage) {
+            var savedYieldContext = inYieldContext();
+            setYieldContext(allowYield);
+            var saveDecoratorContext = inDecoratorContext();
+            if (saveDecoratorContext) {
+                setDecoratorContext(false);
+            }
+            var block = parseBlock(ignoreMissingOpenBrace, true, diagnosticMessage);
+            if (saveDecoratorContext) {
+                setDecoratorContext(true);
+            }
+            setYieldContext(savedYieldContext);
+            return block;
+        }
+        function parseEmptyStatement() {
+            var node = createNode(181);
+            parseExpected(22);
+            return finishNode(node);
+        }
+        function parseIfStatement() {
+            var node = createNode(183);
+            parseExpected(84);
+            parseExpected(16);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(17);
+            node.thenStatement = parseStatement();
+            node.elseStatement = parseOptional(76) ? parseStatement() : undefined;
+            return finishNode(node);
+        }
+        function parseDoStatement() {
+            var node = createNode(184);
+            parseExpected(75);
+            node.statement = parseStatement();
+            parseExpected(100);
+            parseExpected(16);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(17);
+            parseOptional(22);
+            return finishNode(node);
+        }
+        function parseWhileStatement() {
+            var node = createNode(185);
+            parseExpected(100);
+            parseExpected(16);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(17);
+            node.statement = parseStatement();
+            return finishNode(node);
+        }
+        function parseForOrForInOrForOfStatement() {
+            var pos = getNodePos();
+            parseExpected(82);
+            parseExpected(16);
+            var initializer = undefined;
+            if (token !== 22) {
+                if (token === 98 || token === 104 || token === 70) {
+                    initializer = parseVariableDeclarationList(true);
+                }
+                else {
+                    initializer = disallowInAnd(parseExpression);
+                }
+            }
+            var forOrForInOrForOfStatement;
+            if (parseOptional(86)) {
+                var forInStatement = createNode(187, pos);
+                forInStatement.initializer = initializer;
+                forInStatement.expression = allowInAnd(parseExpression);
+                parseExpected(17);
+                forOrForInOrForOfStatement = forInStatement;
+            }
+            else if (parseOptional(125)) {
+                var forOfStatement = createNode(188, pos);
+                forOfStatement.initializer = initializer;
+                forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
+                parseExpected(17);
+                forOrForInOrForOfStatement = forOfStatement;
+            }
+            else {
+                var forStatement = createNode(186, pos);
+                forStatement.initializer = initializer;
+                parseExpected(22);
+                if (token !== 22 && token !== 17) {
+                    forStatement.condition = allowInAnd(parseExpression);
+                }
+                parseExpected(22);
+                if (token !== 17) {
+                    forStatement.incrementor = allowInAnd(parseExpression);
+                }
+                parseExpected(17);
+                forOrForInOrForOfStatement = forStatement;
+            }
+            forOrForInOrForOfStatement.statement = parseStatement();
+            return finishNode(forOrForInOrForOfStatement);
+        }
+        function parseBreakOrContinueStatement(kind) {
+            var node = createNode(kind);
+            parseExpected(kind === 190 ? 66 : 71);
+            if (!canParseSemicolon()) {
+                node.label = parseIdentifier();
+            }
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function parseReturnStatement() {
+            var node = createNode(191);
+            parseExpected(90);
+            if (!canParseSemicolon()) {
+                node.expression = allowInAnd(parseExpression);
+            }
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function parseWithStatement() {
+            var node = createNode(192);
+            parseExpected(101);
+            parseExpected(16);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(17);
+            node.statement = parseStatement();
+            return finishNode(node);
+        }
+        function parseCaseClause() {
+            var node = createNode(220);
+            parseExpected(67);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(51);
+            node.statements = parseList(4, false, parseStatement);
+            return finishNode(node);
+        }
+        function parseDefaultClause() {
+            var node = createNode(221);
+            parseExpected(73);
+            parseExpected(51);
+            node.statements = parseList(4, false, parseStatement);
+            return finishNode(node);
+        }
+        function parseCaseOrDefaultClause() {
+            return token === 67 ? parseCaseClause() : parseDefaultClause();
+        }
+        function parseSwitchStatement() {
+            var node = createNode(193);
+            parseExpected(92);
+            parseExpected(16);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(17);
+            var caseBlock = createNode(207, scanner.getStartPos());
+            parseExpected(14);
+            caseBlock.clauses = parseList(3, false, parseCaseOrDefaultClause);
+            parseExpected(15);
+            node.caseBlock = finishNode(caseBlock);
+            return finishNode(node);
+        }
+        function parseThrowStatement() {
+            // ThrowStatement[Yield] :
+            //      throw [no LineTerminator here]Expression[In, ?Yield];
+            var node = createNode(195);
+            parseExpected(94);
+            node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression);
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function parseTryStatement() {
+            var node = createNode(196);
+            parseExpected(96);
+            node.tryBlock = parseBlock(false, false);
+            node.catchClause = token === 68 ? parseCatchClause() : undefined;
+            if (!node.catchClause || token === 81) {
+                parseExpected(81);
+                node.finallyBlock = parseBlock(false, false);
+            }
+            return finishNode(node);
+        }
+        function parseCatchClause() {
+            var result = createNode(223);
+            parseExpected(68);
+            if (parseExpected(16)) {
+                result.variableDeclaration = parseVariableDeclaration();
+            }
+            parseExpected(17);
+            result.block = parseBlock(false, false);
+            return finishNode(result);
+        }
+        function parseDebuggerStatement() {
+            var node = createNode(197);
+            parseExpected(72);
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function parseExpressionOrLabeledStatement() {
+            var fullStart = scanner.getStartPos();
+            var expression = allowInAnd(parseExpression);
+            if (expression.kind === 65 && parseOptional(51)) {
+                var labeledStatement = createNode(194, fullStart);
+                labeledStatement.label = expression;
+                labeledStatement.statement = parseStatement();
+                return finishNode(labeledStatement);
+            }
+            else {
+                var expressionStatement = createNode(182, fullStart);
+                expressionStatement.expression = expression;
+                parseSemicolon();
+                return finishNode(expressionStatement);
+            }
+        }
+        function isStartOfStatement(inErrorRecovery) {
+            if (ts.isModifier(token)) {
+                var result = lookAhead(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers);
+                if (result) {
+                    return true;
+                }
+            }
+            switch (token) {
+                case 22:
+                    return !inErrorRecovery;
+                case 14:
+                case 98:
+                case 104:
+                case 83:
+                case 69:
+                case 84:
+                case 75:
+                case 100:
+                case 82:
+                case 71:
+                case 66:
+                case 90:
+                case 101:
+                case 92:
+                case 94:
+                case 96:
+                case 72:
+                case 68:
+                case 81:
+                    return true;
+                case 70:
+                    var isConstEnum = lookAhead(nextTokenIsEnumKeyword);
+                    return !isConstEnum;
+                case 103:
+                case 117:
+                case 77:
+                case 123:
+                    if (isDeclarationStart()) {
+                        return false;
+                    }
+                case 108:
+                case 106:
+                case 107:
+                case 109:
+                    if (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine)) {
+                        return false;
+                    }
+                default:
+                    return isStartOfExpression();
+            }
+        }
+        function nextTokenIsEnumKeyword() {
+            nextToken();
+            return token === 77;
+        }
+        function nextTokenIsIdentifierOrKeywordOnSameLine() {
+            nextToken();
+            return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();
+        }
+        function parseStatement() {
+            switch (token) {
+                case 14:
+                    return parseBlock(false, false);
+                case 98:
+                case 70:
+                    return parseVariableStatement(scanner.getStartPos(), undefined, undefined);
+                case 83:
+                    return parseFunctionDeclaration(scanner.getStartPos(), undefined, undefined);
+                case 69:
+                    return parseClassDeclaration(scanner.getStartPos(), undefined, undefined);
+                case 22:
+                    return parseEmptyStatement();
+                case 84:
+                    return parseIfStatement();
+                case 75:
+                    return parseDoStatement();
+                case 100:
+                    return parseWhileStatement();
+                case 82:
+                    return parseForOrForInOrForOfStatement();
+                case 71:
+                    return parseBreakOrContinueStatement(189);
+                case 66:
+                    return parseBreakOrContinueStatement(190);
+                case 90:
+                    return parseReturnStatement();
+                case 101:
+                    return parseWithStatement();
+                case 92:
+                    return parseSwitchStatement();
+                case 94:
+                    return parseThrowStatement();
+                case 96:
+                case 68:
+                case 81:
+                    return parseTryStatement();
+                case 72:
+                    return parseDebuggerStatement();
+                case 104:
+                    if (isLetDeclaration()) {
+                        return parseVariableStatement(scanner.getStartPos(), undefined, undefined);
+                    }
+                default:
+                    if (ts.isModifier(token) || token === 52) {
+                        var result = tryParse(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers);
+                        if (result) {
+                            return result;
+                        }
+                    }
+                    return parseExpressionOrLabeledStatement();
+            }
+        }
+        function parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers() {
+            var start = scanner.getStartPos();
+            var decorators = parseDecorators();
+            var modifiers = parseModifiers();
+            switch (token) {
+                case 70:
+                    var nextTokenIsEnum = lookAhead(nextTokenIsEnumKeyword);
+                    if (nextTokenIsEnum) {
+                        return undefined;
+                    }
+                    return parseVariableStatement(start, decorators, modifiers);
+                case 104:
+                    if (!isLetDeclaration()) {
+                        return undefined;
+                    }
+                    return parseVariableStatement(start, decorators, modifiers);
+                case 98:
+                    return parseVariableStatement(start, decorators, modifiers);
+                case 83:
+                    return parseFunctionDeclaration(start, decorators, modifiers);
+                case 69:
+                    return parseClassDeclaration(start, decorators, modifiers);
+            }
+            return undefined;
+        }
+        function parseFunctionBlockOrSemicolon(isGenerator, diagnosticMessage) {
+            if (token !== 14 && canParseSemicolon()) {
+                parseSemicolon();
+                return;
+            }
+            return parseFunctionBlock(isGenerator, false, diagnosticMessage);
+        }
+        function parseArrayBindingElement() {
+            if (token === 23) {
+                return createNode(175);
+            }
+            var node = createNode(152);
+            node.dotDotDotToken = parseOptionalToken(21);
+            node.name = parseIdentifierOrPattern();
+            node.initializer = parseInitializer(false);
+            return finishNode(node);
+        }
+        function parseObjectBindingElement() {
+            var node = createNode(152);
+            var tokenIsIdentifier = isIdentifier();
+            var propertyName = parsePropertyName();
+            if (tokenIsIdentifier && token !== 51) {
+                node.name = propertyName;
+            }
+            else {
+                parseExpected(51);
+                node.propertyName = propertyName;
+                node.name = parseIdentifierOrPattern();
+            }
+            node.initializer = parseInitializer(false);
+            return finishNode(node);
+        }
+        function parseObjectBindingPattern() {
+            var node = createNode(150);
+            parseExpected(14);
+            node.elements = parseDelimitedList(10, parseObjectBindingElement);
+            parseExpected(15);
+            return finishNode(node);
+        }
+        function parseArrayBindingPattern() {
+            var node = createNode(151);
+            parseExpected(18);
+            node.elements = parseDelimitedList(11, parseArrayBindingElement);
+            parseExpected(19);
+            return finishNode(node);
+        }
+        function isIdentifierOrPattern() {
+            return token === 14 || token === 18 || isIdentifier();
+        }
+        function parseIdentifierOrPattern() {
+            if (token === 18) {
+                return parseArrayBindingPattern();
+            }
+            if (token === 14) {
+                return parseObjectBindingPattern();
+            }
+            return parseIdentifier();
+        }
+        function parseVariableDeclaration() {
+            var node = createNode(198);
+            node.name = parseIdentifierOrPattern();
+            node.type = parseTypeAnnotation();
+            if (!isInOrOfKeyword(token)) {
+                node.initializer = parseInitializer(false);
+            }
+            return finishNode(node);
+        }
+        function parseVariableDeclarationList(inForStatementInitializer) {
+            var node = createNode(199);
+            switch (token) {
+                case 98:
+                    break;
+                case 104:
+                    node.flags |= 4096;
+                    break;
+                case 70:
+                    node.flags |= 8192;
+                    break;
+                default:
+                    ts.Debug.fail();
+            }
+            nextToken();
+            if (token === 125 && lookAhead(canFollowContextualOfKeyword)) {
+                node.declarations = createMissingList();
+            }
+            else {
+                var savedDisallowIn = inDisallowInContext();
+                setDisallowInContext(inForStatementInitializer);
+                node.declarations = parseDelimitedList(9, parseVariableDeclaration);
+                setDisallowInContext(savedDisallowIn);
+            }
+            return finishNode(node);
+        }
+        function canFollowContextualOfKeyword() {
+            return nextTokenIsIdentifier() && nextToken() === 17;
+        }
+        function parseVariableStatement(fullStart, decorators, modifiers) {
+            var node = createNode(180, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.declarationList = parseVariableDeclarationList(false);
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function parseFunctionDeclaration(fullStart, decorators, modifiers) {
+            var node = createNode(200, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(83);
+            node.asteriskToken = parseOptionalToken(35);
+            node.name = node.flags & 256 ? parseOptionalIdentifier() : parseIdentifier();
+            fillSignature(51, !!node.asteriskToken, false, node);
+            node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken, ts.Diagnostics.or_expected);
+            return finishNode(node);
+        }
+        function parseConstructorDeclaration(pos, decorators, modifiers) {
+            var node = createNode(135, pos);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(114);
+            fillSignature(51, false, false, node);
+            node.body = parseFunctionBlockOrSemicolon(false, ts.Diagnostics.or_expected);
+            return finishNode(node);
+        }
+        function parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, diagnosticMessage) {
+            var method = createNode(134, fullStart);
+            method.decorators = decorators;
+            setModifiers(method, modifiers);
+            method.asteriskToken = asteriskToken;
+            method.name = name;
+            method.questionToken = questionToken;
+            fillSignature(51, !!asteriskToken, false, method);
+            method.body = parseFunctionBlockOrSemicolon(!!asteriskToken, diagnosticMessage);
+            return finishNode(method);
+        }
+        function parsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken) {
+            var property = createNode(132, fullStart);
+            property.decorators = decorators;
+            setModifiers(property, modifiers);
+            property.name = name;
+            property.questionToken = questionToken;
+            property.type = parseTypeAnnotation();
+            property.initializer = allowInAnd(parseNonParameterInitializer);
+            parseSemicolon();
+            return finishNode(property);
+        }
+        function parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers) {
+            var asteriskToken = parseOptionalToken(35);
+            var name = parsePropertyName();
+            var questionToken = parseOptionalToken(50);
+            if (asteriskToken || token === 16 || token === 24) {
+                return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, ts.Diagnostics.or_expected);
+            }
+            else {
+                return parsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken);
+            }
+        }
+        function parseNonParameterInitializer() {
+            return parseInitializer(false);
+        }
+        function parseAccessorDeclaration(kind, fullStart, decorators, modifiers) {
+            var node = createNode(kind, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.name = parsePropertyName();
+            fillSignature(51, false, false, node);
+            node.body = parseFunctionBlockOrSemicolon(false);
+            return finishNode(node);
+        }
+        function isClassMemberModifier(idToken) {
+            switch (idToken) {
+                case 108:
+                case 106:
+                case 107:
+                case 109:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+        function isClassMemberStart() {
+            var idToken;
+            if (token === 52) {
+                return true;
+            }
+            while (ts.isModifier(token)) {
+                idToken = token;
+                if (isClassMemberModifier(idToken)) {
+                    return true;
+                }
+                nextToken();
+            }
+            if (token === 35) {
+                return true;
+            }
+            if (isLiteralPropertyName()) {
+                idToken = token;
+                nextToken();
+            }
+            if (token === 18) {
+                return true;
+            }
+            if (idToken !== undefined) {
+                if (!ts.isKeyword(idToken) || idToken === 120 || idToken === 116) {
+                    return true;
+                }
+                switch (token) {
+                    case 16:
+                    case 24:
+                    case 51:
+                    case 53:
+                    case 50:
+                        return true;
+                    default:
+                        return canParseSemicolon();
+                }
+            }
+            return false;
+        }
+        function parseDecorators() {
+            var decorators;
+            while (true) {
+                var decoratorStart = getNodePos();
+                if (!parseOptional(52)) {
+                    break;
+                }
+                if (!decorators) {
+                    decorators = [];
+                    decorators.pos = scanner.getStartPos();
+                }
+                var decorator = createNode(130, decoratorStart);
+                decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher);
+                decorators.push(finishNode(decorator));
+            }
+            if (decorators) {
+                decorators.end = getNodeEnd();
+            }
+            return decorators;
+        }
+        function parseModifiers() {
+            var flags = 0;
+            var modifiers;
+            while (true) {
+                var modifierStart = scanner.getStartPos();
+                var modifierKind = token;
+                if (!parseAnyContextualModifier()) {
+                    break;
+                }
+                if (!modifiers) {
+                    modifiers = [];
+                    modifiers.pos = modifierStart;
+                }
+                flags |= ts.modifierToFlag(modifierKind);
+                modifiers.push(finishNode(createNode(modifierKind, modifierStart)));
+            }
+            if (modifiers) {
+                modifiers.flags = flags;
+                modifiers.end = scanner.getStartPos();
+            }
+            return modifiers;
+        }
+        function parseClassElement() {
+            if (token === 22) {
+                var result = createNode(178);
+                nextToken();
+                return finishNode(result);
+            }
+            var fullStart = getNodePos();
+            var decorators = parseDecorators();
+            var modifiers = parseModifiers();
+            var accessor = tryParseAccessorDeclaration(fullStart, decorators, modifiers);
+            if (accessor) {
+                return accessor;
+            }
+            if (token === 114) {
+                return parseConstructorDeclaration(fullStart, decorators, modifiers);
+            }
+            if (isIndexSignature()) {
+                return parseIndexSignatureDeclaration(fullStart, decorators, modifiers);
+            }
+            if (isIdentifierOrKeyword() ||
+                token === 8 ||
+                token === 7 ||
+                token === 35 ||
+                token === 18) {
+                return parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers);
+            }
+            if (decorators) {
+                var name_1 = createMissingNode(65, true, ts.Diagnostics.Declaration_expected);
+                return parsePropertyDeclaration(fullStart, decorators, modifiers, name_1, undefined);
+            }
+            ts.Debug.fail("Should not have attempted to parse class member declaration.");
+        }
+        function parseClassExpression() {
+            return parseClassDeclarationOrExpression(scanner.getStartPos(), undefined, undefined, 174);
+        }
+        function parseClassDeclaration(fullStart, decorators, modifiers) {
+            return parseClassDeclarationOrExpression(fullStart, decorators, modifiers, 201);
+        }
+        function parseClassDeclarationOrExpression(fullStart, decorators, modifiers, kind) {
+            var savedStrictModeContext = inStrictModeContext();
+            setStrictModeContext(true);
+            var node = createNode(kind, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(69);
+            node.name = parseOptionalIdentifier();
+            node.typeParameters = parseTypeParameters();
+            node.heritageClauses = parseHeritageClauses(true);
+            if (parseExpected(14)) {
+                node.members = inGeneratorParameterContext()
+                    ? doOutsideOfYieldContext(parseClassMembers)
+                    : parseClassMembers();
+                parseExpected(15);
+            }
+            else {
+                node.members = createMissingList();
+            }
+            var finishedNode = finishNode(node);
+            setStrictModeContext(savedStrictModeContext);
+            return finishedNode;
+        }
+        function parseHeritageClauses(isClassHeritageClause) {
+            // ClassTail[Yield,GeneratorParameter] : See 14.5
+            //      [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
+            //      [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
+            if (isHeritageClause()) {
+                return isClassHeritageClause && inGeneratorParameterContext()
+                    ? doOutsideOfYieldContext(parseHeritageClausesWorker)
+                    : parseHeritageClausesWorker();
+            }
+            return undefined;
+        }
+        function parseHeritageClausesWorker() {
+            return parseList(19, false, parseHeritageClause);
+        }
+        function parseHeritageClause() {
+            if (token === 79 || token === 102) {
+                var node = createNode(222);
+                node.token = token;
+                nextToken();
+                node.types = parseDelimitedList(8, parseHeritageClauseElement);
+                return finishNode(node);
+            }
+            return undefined;
+        }
+        function parseHeritageClauseElement() {
+            var node = createNode(177);
+            node.expression = parseLeftHandSideExpressionOrHigher();
+            if (token === 24) {
+                node.typeArguments = parseBracketedList(17, parseType, 24, 25);
+            }
+            return finishNode(node);
+        }
+        function isHeritageClause() {
+            return token === 79 || token === 102;
+        }
+        function parseClassMembers() {
+            return parseList(6, false, parseClassElement);
+        }
+        function parseInterfaceDeclaration(fullStart, decorators, modifiers) {
+            var node = createNode(202, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(103);
+            node.name = parseIdentifier();
+            node.typeParameters = parseTypeParameters();
+            node.heritageClauses = parseHeritageClauses(false);
+            node.members = parseObjectTypeMembers();
+            return finishNode(node);
+        }
+        function parseTypeAliasDeclaration(fullStart, decorators, modifiers) {
+            var node = createNode(203, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(123);
+            node.name = parseIdentifier();
+            parseExpected(53);
+            node.type = parseType();
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function parseEnumMember() {
+            var node = createNode(226, scanner.getStartPos());
+            node.name = parsePropertyName();
+            node.initializer = allowInAnd(parseNonParameterInitializer);
+            return finishNode(node);
+        }
+        function parseEnumDeclaration(fullStart, decorators, modifiers) {
+            var node = createNode(204, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(77);
+            node.name = parseIdentifier();
+            if (parseExpected(14)) {
+                node.members = parseDelimitedList(7, parseEnumMember);
+                parseExpected(15);
+            }
+            else {
+                node.members = createMissingList();
+            }
+            return finishNode(node);
+        }
+        function parseModuleBlock() {
+            var node = createNode(206, scanner.getStartPos());
+            if (parseExpected(14)) {
+                node.statements = parseList(1, false, parseModuleElement);
+                parseExpected(15);
+            }
+            else {
+                node.statements = createMissingList();
+            }
+            return finishNode(node);
+        }
+        function parseInternalModuleTail(fullStart, decorators, modifiers, flags) {
+            var node = createNode(205, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.flags |= flags;
+            node.name = parseIdentifier();
+            node.body = parseOptional(20)
+                ? parseInternalModuleTail(getNodePos(), undefined, undefined, 1)
+                : parseModuleBlock();
+            return finishNode(node);
+        }
+        function parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers) {
+            var node = createNode(205, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.name = parseLiteralNode(true);
+            node.body = parseModuleBlock();
+            return finishNode(node);
+        }
+        function parseModuleDeclaration(fullStart, decorators, modifiers) {
+            parseExpected(117);
+            return token === 8
+                ? parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers)
+                : parseInternalModuleTail(fullStart, decorators, modifiers, modifiers ? modifiers.flags : 0);
+        }
+        function isExternalModuleReference() {
+            return token === 118 &&
+                lookAhead(nextTokenIsOpenParen);
+        }
+        function nextTokenIsOpenParen() {
+            return nextToken() === 16;
+        }
+        function nextTokenIsCommaOrFromKeyword() {
+            nextToken();
+            return token === 23 ||
+                token === 124;
+        }
+        function parseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers) {
+            parseExpected(85);
+            var afterImportPos = scanner.getStartPos();
+            var identifier;
+            if (isIdentifier()) {
+                identifier = parseIdentifier();
+                if (token !== 23 && token !== 124) {
+                    var importEqualsDeclaration = createNode(208, fullStart);
+                    importEqualsDeclaration.decorators = decorators;
+                    setModifiers(importEqualsDeclaration, modifiers);
+                    importEqualsDeclaration.name = identifier;
+                    parseExpected(53);
+                    importEqualsDeclaration.moduleReference = parseModuleReference();
+                    parseSemicolon();
+                    return finishNode(importEqualsDeclaration);
+                }
+            }
+            var importDeclaration = createNode(209, fullStart);
+            importDeclaration.decorators = decorators;
+            setModifiers(importDeclaration, modifiers);
+            if (identifier ||
+                token === 35 ||
+                token === 14) {
+                importDeclaration.importClause = parseImportClause(identifier, afterImportPos);
+                parseExpected(124);
+            }
+            importDeclaration.moduleSpecifier = parseModuleSpecifier();
+            parseSemicolon();
+            return finishNode(importDeclaration);
+        }
+        function parseImportClause(identifier, fullStart) {
+            //ImportClause:
+            //  ImportedDefaultBinding
+            //  NameSpaceImport
+            //  NamedImports
+            //  ImportedDefaultBinding, NameSpaceImport
+            //  ImportedDefaultBinding, NamedImports
+            var importClause = createNode(210, fullStart);
+            if (identifier) {
+                importClause.name = identifier;
+            }
+            if (!importClause.name ||
+                parseOptional(23)) {
+                importClause.namedBindings = token === 35 ? parseNamespaceImport() : parseNamedImportsOrExports(212);
+            }
+            return finishNode(importClause);
+        }
+        function parseModuleReference() {
+            return isExternalModuleReference()
+                ? parseExternalModuleReference()
+                : parseEntityName(false);
+        }
+        function parseExternalModuleReference() {
+            var node = createNode(219);
+            parseExpected(118);
+            parseExpected(16);
+            node.expression = parseModuleSpecifier();
+            parseExpected(17);
+            return finishNode(node);
+        }
+        function parseModuleSpecifier() {
+            var result = parseExpression();
+            if (result.kind === 8) {
+                internIdentifier(result.text);
+            }
+            return result;
+        }
+        function parseNamespaceImport() {
+            var namespaceImport = createNode(211);
+            parseExpected(35);
+            parseExpected(111);
+            namespaceImport.name = parseIdentifier();
+            return finishNode(namespaceImport);
+        }
+        function parseNamedImportsOrExports(kind) {
+            var node = createNode(kind);
+            node.elements = parseBracketedList(20, kind === 212 ? parseImportSpecifier : parseExportSpecifier, 14, 15);
+            return finishNode(node);
+        }
+        function parseExportSpecifier() {
+            return parseImportOrExportSpecifier(217);
+        }
+        function parseImportSpecifier() {
+            return parseImportOrExportSpecifier(213);
+        }
+        function parseImportOrExportSpecifier(kind) {
+            var node = createNode(kind);
+            var checkIdentifierIsKeyword = ts.isKeyword(token) && !isIdentifier();
+            var checkIdentifierStart = scanner.getTokenPos();
+            var checkIdentifierEnd = scanner.getTextPos();
+            var identifierName = parseIdentifierName();
+            if (token === 111) {
+                node.propertyName = identifierName;
+                parseExpected(111);
+                checkIdentifierIsKeyword = ts.isKeyword(token) && !isIdentifier();
+                checkIdentifierStart = scanner.getTokenPos();
+                checkIdentifierEnd = scanner.getTextPos();
+                node.name = parseIdentifierName();
+            }
+            else {
+                node.name = identifierName;
+            }
+            if (kind === 213 && checkIdentifierIsKeyword) {
+                parseErrorAtPosition(checkIdentifierStart, checkIdentifierEnd - checkIdentifierStart, ts.Diagnostics.Identifier_expected);
+            }
+            return finishNode(node);
+        }
+        function parseExportDeclaration(fullStart, decorators, modifiers) {
+            var node = createNode(215, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            if (parseOptional(35)) {
+                parseExpected(124);
+                node.moduleSpecifier = parseModuleSpecifier();
+            }
+            else {
+                node.exportClause = parseNamedImportsOrExports(216);
+                if (parseOptional(124)) {
+                    node.moduleSpecifier = parseModuleSpecifier();
+                }
+            }
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function parseExportAssignment(fullStart, decorators, modifiers) {
+            var node = createNode(214, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            if (parseOptional(53)) {
+                node.isExportEquals = true;
+            }
+            else {
+                parseExpected(73);
+            }
+            node.expression = parseAssignmentExpressionOrHigher();
+            parseSemicolon();
+            return finishNode(node);
+        }
+        function isLetDeclaration() {
+            return inStrictModeContext() || lookAhead(nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine);
+        }
+        function isDeclarationStart(followsModifier) {
+            switch (token) {
+                case 98:
+                case 70:
+                case 83:
+                    return true;
+                case 104:
+                    return isLetDeclaration();
+                case 69:
+                case 103:
+                case 77:
+                case 123:
+                    return lookAhead(nextTokenIsIdentifierOrKeyword);
+                case 85:
+                    return lookAhead(nextTokenCanFollowImportKeyword);
+                case 117:
+                    return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral);
+                case 78:
+                    return lookAhead(nextTokenCanFollowExportKeyword);
+                case 115:
+                case 108:
+                case 106:
+                case 107:
+                case 109:
+                    return lookAhead(nextTokenIsDeclarationStart);
+                case 52:
+                    return !followsModifier;
+            }
+        }
+        function isIdentifierOrKeyword() {
+            return token >= 65;
+        }
+        function nextTokenIsIdentifierOrKeyword() {
+            nextToken();
+            return isIdentifierOrKeyword();
+        }
+        function nextTokenIsIdentifierOrKeywordOrStringLiteral() {
+            nextToken();
+            return isIdentifierOrKeyword() || token === 8;
+        }
+        function nextTokenCanFollowImportKeyword() {
+            nextToken();
+            return isIdentifierOrKeyword() || token === 8 ||
+                token === 35 || token === 14;
+        }
+        function nextTokenCanFollowExportKeyword() {
+            nextToken();
+            return token === 53 || token === 35 ||
+                token === 14 || token === 73 || isDeclarationStart(true);
+        }
+        function nextTokenIsDeclarationStart() {
+            nextToken();
+            return isDeclarationStart(true);
+        }
+        function nextTokenIsAsKeyword() {
+            return nextToken() === 111;
+        }
+        function parseDeclaration() {
+            var fullStart = getNodePos();
+            var decorators = parseDecorators();
+            var modifiers = parseModifiers();
+            if (token === 78) {
+                nextToken();
+                if (token === 73 || token === 53) {
+                    return parseExportAssignment(fullStart, decorators, modifiers);
+                }
+                if (token === 35 || token === 14) {
+                    return parseExportDeclaration(fullStart, decorators, modifiers);
+                }
+            }
+            switch (token) {
+                case 98:
+                case 104:
+                case 70:
+                    return parseVariableStatement(fullStart, decorators, modifiers);
+                case 83:
+                    return parseFunctionDeclaration(fullStart, decorators, modifiers);
+                case 69:
+                    return parseClassDeclaration(fullStart, decorators, modifiers);
+                case 103:
+                    return parseInterfaceDeclaration(fullStart, decorators, modifiers);
+                case 123:
+                    return parseTypeAliasDeclaration(fullStart, decorators, modifiers);
+                case 77:
+                    return parseEnumDeclaration(fullStart, decorators, modifiers);
+                case 117:
+                    return parseModuleDeclaration(fullStart, decorators, modifiers);
+                case 85:
+                    return parseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers);
+                default:
+                    if (decorators) {
+                        var node = createMissingNode(218, true, ts.Diagnostics.Declaration_expected);
+                        node.pos = fullStart;
+                        node.decorators = decorators;
+                        setModifiers(node, modifiers);
+                        return finishNode(node);
+                    }
+                    ts.Debug.fail("Mismatch between isDeclarationStart and parseDeclaration");
+            }
+        }
+        function isSourceElement(inErrorRecovery) {
+            return isDeclarationStart() || isStartOfStatement(inErrorRecovery);
+        }
+        function parseSourceElement() {
+            return parseSourceElementOrModuleElement();
+        }
+        function parseModuleElement() {
+            return parseSourceElementOrModuleElement();
+        }
+        function parseSourceElementOrModuleElement() {
+            return isDeclarationStart()
+                ? parseDeclaration()
+                : parseStatement();
+        }
+        function processReferenceComments(sourceFile) {
+            var triviaScanner = ts.createScanner(sourceFile.languageVersion, false, sourceText);
+            var referencedFiles = [];
+            var amdDependencies = [];
+            var amdModuleName;
+            while (true) {
+                var kind = triviaScanner.scan();
+                if (kind === 5 || kind === 4 || kind === 3) {
+                    continue;
+                }
+                if (kind !== 2) {
+                    break;
+                }
+                var range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
+                var comment = sourceText.substring(range.pos, range.end);
+                var referencePathMatchResult = ts.getFileReferenceFromReferencePath(comment, range);
+                if (referencePathMatchResult) {
+                    var fileReference = referencePathMatchResult.fileReference;
+                    sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
+                    var diagnosticMessage = referencePathMatchResult.diagnosticMessage;
+                    if (fileReference) {
+                        referencedFiles.push(fileReference);
+                    }
+                    if (diagnosticMessage) {
+                        sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
+                    }
+                }
+                else {
+                    var amdModuleNameRegEx = /^\/\/\/\s*<amd-module\s+name\s*=\s*('|")(.+?)\1/gim;
+                    var amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment);
+                    if (amdModuleNameMatchResult) {
+                        if (amdModuleName) {
+                            sourceFile.parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, ts.Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments));
+                        }
+                        amdModuleName = amdModuleNameMatchResult[2];
+                    }
+                    var amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s/gim;
+                    var pathRegex = /\spath\s*=\s*('|")(.+?)\1/gim;
+                    var nameRegex = /\sname\s*=\s*('|")(.+?)\1/gim;
+                    var amdDependencyMatchResult = amdDependencyRegEx.exec(comment);
+                    if (amdDependencyMatchResult) {
+                        var pathMatchResult = pathRegex.exec(comment);
+                        var nameMatchResult = nameRegex.exec(comment);
+                        if (pathMatchResult) {
+                            var amdDependency = { path: pathMatchResult[2], name: nameMatchResult ? nameMatchResult[2] : undefined };
+                            amdDependencies.push(amdDependency);
+                        }
+                    }
+                }
+            }
+            sourceFile.referencedFiles = referencedFiles;
+            sourceFile.amdDependencies = amdDependencies;
+            sourceFile.amdModuleName = amdModuleName;
+        }
+        function setExternalModuleIndicator(sourceFile) {
+            sourceFile.externalModuleIndicator = ts.forEach(sourceFile.statements, function (node) {
+                return node.flags & 1
+                    || node.kind === 208 && node.moduleReference.kind === 219
+                    || node.kind === 209
+                    || node.kind === 214
+                    || node.kind === 215
+                    ? node
+                    : undefined;
+            });
+        }
+        var ParsingContext;
+        (function (ParsingContext) {
+            ParsingContext[ParsingContext["SourceElements"] = 0] = "SourceElements";
+            ParsingContext[ParsingContext["ModuleElements"] = 1] = "ModuleElements";
+            ParsingContext[ParsingContext["BlockStatements"] = 2] = "BlockStatements";
+            ParsingContext[ParsingContext["SwitchClauses"] = 3] = "SwitchClauses";
+            ParsingContext[ParsingContext["SwitchClauseStatements"] = 4] = "SwitchClauseStatements";
+            ParsingContext[ParsingContext["TypeMembers"] = 5] = "TypeMembers";
+            ParsingContext[ParsingContext["ClassMembers"] = 6] = "ClassMembers";
+            ParsingContext[ParsingContext["EnumMembers"] = 7] = "EnumMembers";
+            ParsingContext[ParsingContext["HeritageClauseElement"] = 8] = "HeritageClauseElement";
+            ParsingContext[ParsingContext["VariableDeclarations"] = 9] = "VariableDeclarations";
+            ParsingContext[ParsingContext["ObjectBindingElements"] = 10] = "ObjectBindingElements";
+            ParsingContext[ParsingContext["ArrayBindingElements"] = 11] = "ArrayBindingElements";
+            ParsingContext[ParsingContext["ArgumentExpressions"] = 12] = "ArgumentExpressions";
+            ParsingContext[ParsingContext["ObjectLiteralMembers"] = 13] = "ObjectLiteralMembers";
+            ParsingContext[ParsingContext["ArrayLiteralMembers"] = 14] = "ArrayLiteralMembers";
+            ParsingContext[ParsingContext["Parameters"] = 15] = "Parameters";
+            ParsingContext[ParsingContext["TypeParameters"] = 16] = "TypeParameters";
+            ParsingContext[ParsingContext["TypeArguments"] = 17] = "TypeArguments";
+            ParsingContext[ParsingContext["TupleElementTypes"] = 18] = "TupleElementTypes";
+            ParsingContext[ParsingContext["HeritageClauses"] = 19] = "HeritageClauses";
+            ParsingContext[ParsingContext["ImportOrExportSpecifiers"] = 20] = "ImportOrExportSpecifiers";
+            ParsingContext[ParsingContext["Count"] = 21] = "Count";
+        })(ParsingContext || (ParsingContext = {}));
+        var Tristate;
+        (function (Tristate) {
+            Tristate[Tristate["False"] = 0] = "False";
+            Tristate[Tristate["True"] = 1] = "True";
+            Tristate[Tristate["Unknown"] = 2] = "Unknown";
+        })(Tristate || (Tristate = {}));
+    })(Parser || (Parser = {}));
+    var IncrementalParser;
+    (function (IncrementalParser) {
+        function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) {
+            aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2);
+            checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
+            if (ts.textChangeRangeIsUnchanged(textChangeRange)) {
+                return sourceFile;
+            }
+            if (sourceFile.statements.length === 0) {
+                return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true);
+            }
+            var incrementalSourceFile = sourceFile;
+            ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
+            incrementalSourceFile.hasBeenIncrementallyParsed = true;
+            var oldText = sourceFile.text;
+            var syntaxCursor = createSyntaxCursor(sourceFile);
+            var changeRange = extendToAffectedRange(sourceFile, textChangeRange);
+            checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
+            ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start);
+            ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span));
+            ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)));
+            var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
+            updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
+            var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true);
+            return result;
+        }
+        IncrementalParser.updateSourceFile = updateSourceFile;
+        function moveElementEntirelyPastChangeRange(element, isArray, delta, oldText, newText, aggressiveChecks) {
+            if (isArray) {
+                visitArray(element);
+            }
+            else {
+                visitNode(element);
+            }
+            return;
+            function visitNode(node) {
+                if (aggressiveChecks && shouldCheckNode(node)) {
+                    var text = oldText.substring(node.pos, node.end);
+                }
+                node._children = undefined;
+                node.pos += delta;
+                node.end += delta;
+                if (aggressiveChecks && shouldCheckNode(node)) {
+                    ts.Debug.assert(text === newText.substring(node.pos, node.end));
+                }
+                forEachChild(node, visitNode, visitArray);
+                checkNodePositions(node, aggressiveChecks);
+            }
+            function visitArray(array) {
+                array._children = undefined;
+                array.pos += delta;
+                array.end += delta;
+                for (var _i = 0; _i < array.length; _i++) {
+                    var node = array[_i];
+                    visitNode(node);
+                }
+            }
+        }
+        function shouldCheckNode(node) {
+            switch (node.kind) {
+                case 8:
+                case 7:
+                case 65:
+                    return true;
+            }
+            return false;
+        }
+        function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) {
+            ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
+            ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
+            ts.Debug.assert(element.pos <= element.end);
+            element.pos = Math.min(element.pos, changeRangeNewEnd);
+            if (element.end >= changeRangeOldEnd) {
+                element.end += delta;
+            }
+            else {
+                element.end = Math.min(element.end, changeRangeNewEnd);
+            }
+            ts.Debug.assert(element.pos <= element.end);
+            if (element.parent) {
+                ts.Debug.assert(element.pos >= element.parent.pos);
+                ts.Debug.assert(element.end <= element.parent.end);
+            }
+        }
+        function checkNodePositions(node, aggressiveChecks) {
+            if (aggressiveChecks) {
+                var pos = node.pos;
+                forEachChild(node, function (child) {
+                    ts.Debug.assert(child.pos >= pos);
+                    pos = child.end;
+                });
+                ts.Debug.assert(pos <= node.end);
+            }
+        }
+        function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) {
+            visitNode(sourceFile);
+            return;
+            function visitNode(child) {
+                ts.Debug.assert(child.pos <= child.end);
+                if (child.pos > changeRangeOldEnd) {
+                    moveElementEntirelyPastChangeRange(child, false, delta, oldText, newText, aggressiveChecks);
+                    return;
+                }
+                var fullEnd = child.end;
+                if (fullEnd >= changeStart) {
+                    child.intersectsChange = true;
+                    child._children = undefined;
+                    adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
+                    forEachChild(child, visitNode, visitArray);
+                    checkNodePositions(child, aggressiveChecks);
+                    return;
+                }
+                ts.Debug.assert(fullEnd < changeStart);
+            }
+            function visitArray(array) {
+                ts.Debug.assert(array.pos <= array.end);
+                if (array.pos > changeRangeOldEnd) {
+                    moveElementEntirelyPastChangeRange(array, true, delta, oldText, newText, aggressiveChecks);
+                    return;
+                }
+                var fullEnd = array.end;
+                if (fullEnd >= changeStart) {
+                    array.intersectsChange = true;
+                    array._children = undefined;
+                    adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
+                    for (var _i = 0; _i < array.length; _i++) {
+                        var node = array[_i];
+                        visitNode(node);
+                    }
+                    return;
+                }
+                ts.Debug.assert(fullEnd < changeStart);
+            }
+        }
+        function extendToAffectedRange(sourceFile, changeRange) {
+            var maxLookahead = 1;
+            var start = changeRange.span.start;
+            for (var i = 0; start > 0 && i <= maxLookahead; i++) {
+                var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
+                ts.Debug.assert(nearestNode.pos <= start);
+                var position = nearestNode.pos;
+                start = Math.max(0, position - 1);
+            }
+            var finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span));
+            var finalLength = changeRange.newLength + (changeRange.span.start - start);
+            return ts.createTextChangeRange(finalSpan, finalLength);
+        }
+        function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) {
+            var bestResult = sourceFile;
+            var lastNodeEntirelyBeforePosition;
+            forEachChild(sourceFile, visit);
+            if (lastNodeEntirelyBeforePosition) {
+                var lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition);
+                if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
+                    bestResult = lastChildOfLastEntireNodeBeforePosition;
+                }
+            }
+            return bestResult;
+            function getLastChild(node) {
+                while (true) {
+                    var lastChild = getLastChildWorker(node);
+                    if (lastChild) {
+                        node = lastChild;
+                    }
+                    else {
+                        return node;
+                    }
+                }
+            }
+            function getLastChildWorker(node) {
+                var last = undefined;
+                forEachChild(node, function (child) {
+                    if (ts.nodeIsPresent(child)) {
+                        last = child;
+                    }
+                });
+                return last;
+            }
+            function visit(child) {
+                if (ts.nodeIsMissing(child)) {
+                    return;
+                }
+                if (child.pos <= position) {
+                    if (child.pos >= bestResult.pos) {
+                        bestResult = child;
+                    }
+                    if (position < child.end) {
+                        forEachChild(child, visit);
+                        return true;
+                    }
+                    else {
+                        ts.Debug.assert(child.end <= position);
+                        lastNodeEntirelyBeforePosition = child;
+                    }
+                }
+                else {
+                    ts.Debug.assert(child.pos > position);
+                    return true;
+                }
+            }
+        }
+        function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) {
+            var oldText = sourceFile.text;
+            if (textChangeRange) {
+                ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length);
+                if (aggressiveChecks || ts.Debug.shouldAssert(3)) {
+                    var oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
+                    var newTextPrefix = newText.substr(0, textChangeRange.span.start);
+                    ts.Debug.assert(oldTextPrefix === newTextPrefix);
+                    var oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length);
+                    var newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length);
+                    ts.Debug.assert(oldTextSuffix === newTextSuffix);
+                }
+            }
+        }
+        function createSyntaxCursor(sourceFile) {
+            var currentArray = sourceFile.statements;
+            var currentArrayIndex = 0;
+            ts.Debug.assert(currentArrayIndex < currentArray.length);
+            var current = currentArray[currentArrayIndex];
+            var lastQueriedPosition = -1;
+            return {
+                currentNode: function (position) {
+                    if (position !== lastQueriedPosition) {
+                        if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
+                            currentArrayIndex++;
+                            current = currentArray[currentArrayIndex];
+                        }
+                        if (!current || current.pos !== position) {
+                            findHighestListElementThatStartsAtPosition(position);
+                        }
+                    }
+                    lastQueriedPosition = position;
+                    ts.Debug.assert(!current || current.pos === position);
+                    return current;
+                }
+            };
+            function findHighestListElementThatStartsAtPosition(position) {
+                currentArray = undefined;
+                currentArrayIndex = -1;
+                current = undefined;
+                forEachChild(sourceFile, visitNode, visitArray);
+                return;
+                function visitNode(node) {
+                    if (position >= node.pos && position < node.end) {
+                        forEachChild(node, visitNode, visitArray);
+                        return true;
+                    }
+                    return false;
+                }
+                function visitArray(array) {
+                    if (position >= array.pos && position < array.end) {
+                        for (var i = 0, n = array.length; i < n; i++) {
+                            var child = array[i];
+                            if (child) {
+                                if (child.pos === position) {
+                                    currentArray = array;
+                                    currentArrayIndex = i;
+                                    current = child;
+                                    return true;
+                                }
+                                else {
+                                    if (child.pos < position && position < child.end) {
+                                        forEachChild(child, visitNode, visitArray);
+                                        return true;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+        var InvalidPosition;
+        (function (InvalidPosition) {
+            InvalidPosition[InvalidPosition["Value"] = -1] = "Value";
+        })(InvalidPosition || (InvalidPosition = {}));
+    })(IncrementalParser || (IncrementalParser = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/program.js b/dist/typescript/compiler/program.js
new file mode 100644
index 000000000..564ba3673
--- /dev/null
+++ b/dist/typescript/compiler/program.js
@@ -0,0 +1,488 @@
+/// <reference path="sys.ts" />
+/// <reference path="emitter.ts" />
+var ts;
+(function (ts) {
+    ts.programTime = 0;
+    ts.emitTime = 0;
+    ts.ioReadTime = 0;
+    ts.ioWriteTime = 0;
+    ts.version = "1.5.0";
+    function findConfigFile(searchPath) {
+        var fileName = "tsconfig.json";
+        while (true) {
+            if (ts.sys.fileExists(fileName)) {
+                return fileName;
+            }
+            var parentPath = ts.getDirectoryPath(searchPath);
+            if (parentPath === searchPath) {
+                break;
+            }
+            searchPath = parentPath;
+            fileName = "../" + fileName;
+        }
+        return undefined;
+    }
+    ts.findConfigFile = findConfigFile;
+    function createCompilerHost(options, setParentNodes) {
+        var currentDirectory;
+        var existingDirectories = {};
+        function getCanonicalFileName(fileName) {
+            return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+        }
+        var unsupportedFileEncodingErrorCode = -2147024809;
+        function getSourceFile(fileName, languageVersion, onError) {
+            var text;
+            try {
+                var start = new Date().getTime();
+                text = ts.sys.readFile(fileName, options.charset);
+                ts.ioReadTime += new Date().getTime() - start;
+            }
+            catch (e) {
+                if (onError) {
+                    onError(e.number === unsupportedFileEncodingErrorCode
+                        ? ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_file_encoding).messageText
+                        : e.message);
+                }
+                text = "";
+            }
+            return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined;
+        }
+        function directoryExists(directoryPath) {
+            if (ts.hasProperty(existingDirectories, directoryPath)) {
+                return true;
+            }
+            if (ts.sys.directoryExists(directoryPath)) {
+                existingDirectories[directoryPath] = true;
+                return true;
+            }
+            return false;
+        }
+        function ensureDirectoriesExist(directoryPath) {
+            if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) {
+                var parentDirectory = ts.getDirectoryPath(directoryPath);
+                ensureDirectoriesExist(parentDirectory);
+                ts.sys.createDirectory(directoryPath);
+            }
+        }
+        function writeFile(fileName, data, writeByteOrderMark, onError) {
+            try {
+                var start = new Date().getTime();
+                ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName)));
+                ts.sys.writeFile(fileName, data, writeByteOrderMark);
+                ts.ioWriteTime += new Date().getTime() - start;
+            }
+            catch (e) {
+                if (onError) {
+                    onError(e.message);
+                }
+            }
+        }
+        return {
+            getSourceFile: getSourceFile,
+            getDefaultLibFileName: function (options) { return ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath())), ts.getDefaultLibFileName(options)); },
+            writeFile: writeFile,
+            getCurrentDirectory: function () { return currentDirectory || (currentDirectory = ts.sys.getCurrentDirectory()); },
+            useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; },
+            getCanonicalFileName: getCanonicalFileName,
+            getNewLine: function () { return ts.sys.newLine; }
+        };
+    }
+    ts.createCompilerHost = createCompilerHost;
+    function getPreEmitDiagnostics(program) {
+        var diagnostics = program.getSyntacticDiagnostics().concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics());
+        if (program.getCompilerOptions().declaration) {
+            diagnostics.concat(program.getDeclarationDiagnostics());
+        }
+        return ts.sortAndDeduplicateDiagnostics(diagnostics);
+    }
+    ts.getPreEmitDiagnostics = getPreEmitDiagnostics;
+    function flattenDiagnosticMessageText(messageText, newLine) {
+        if (typeof messageText === "string") {
+            return messageText;
+        }
+        else {
+            var diagnosticChain = messageText;
+            var result = "";
+            var indent = 0;
+            while (diagnosticChain) {
+                if (indent) {
+                    result += newLine;
+                    for (var i = 0; i < indent; i++) {
+                        result += "  ";
+                    }
+                }
+                result += diagnosticChain.messageText;
+                indent++;
+                diagnosticChain = diagnosticChain.next;
+            }
+            return result;
+        }
+    }
+    ts.flattenDiagnosticMessageText = flattenDiagnosticMessageText;
+    function createProgram(rootNames, options, host) {
+        var program;
+        var files = [];
+        var filesByName = {};
+        var diagnostics = ts.createDiagnosticCollection();
+        var seenNoDefaultLib = options.noLib;
+        var commonSourceDirectory;
+        var diagnosticsProducingTypeChecker;
+        var noDiagnosticsTypeChecker;
+        var start = new Date().getTime();
+        host = host || createCompilerHost(options);
+        ts.forEach(rootNames, function (name) { return processRootFile(name, false); });
+        if (!seenNoDefaultLib) {
+            processRootFile(host.getDefaultLibFileName(options), true);
+        }
+        verifyCompilerOptions();
+        ts.programTime += new Date().getTime() - start;
+        program = {
+            getSourceFile: getSourceFile,
+            getSourceFiles: function () { return files; },
+            getCompilerOptions: function () { return options; },
+            getSyntacticDiagnostics: getSyntacticDiagnostics,
+            getGlobalDiagnostics: getGlobalDiagnostics,
+            getSemanticDiagnostics: getSemanticDiagnostics,
+            getDeclarationDiagnostics: getDeclarationDiagnostics,
+            getTypeChecker: getTypeChecker,
+            getDiagnosticsProducingTypeChecker: getDiagnosticsProducingTypeChecker,
+            getCommonSourceDirectory: function () { return commonSourceDirectory; },
+            emit: emit,
+            getCurrentDirectory: function () { return host.getCurrentDirectory(); },
+            getNodeCount: function () { return getDiagnosticsProducingTypeChecker().getNodeCount(); },
+            getIdentifierCount: function () { return getDiagnosticsProducingTypeChecker().getIdentifierCount(); },
+            getSymbolCount: function () { return getDiagnosticsProducingTypeChecker().getSymbolCount(); },
+            getTypeCount: function () { return getDiagnosticsProducingTypeChecker().getTypeCount(); },
+        };
+        return program;
+        function getEmitHost(writeFileCallback) {
+            return {
+                getCanonicalFileName: function (fileName) { return host.getCanonicalFileName(fileName); },
+                getCommonSourceDirectory: program.getCommonSourceDirectory,
+                getCompilerOptions: program.getCompilerOptions,
+                getCurrentDirectory: function () { return host.getCurrentDirectory(); },
+                getNewLine: function () { return host.getNewLine(); },
+                getSourceFile: program.getSourceFile,
+                getSourceFiles: program.getSourceFiles,
+                writeFile: writeFileCallback || (function (fileName, data, writeByteOrderMark, onError) { return host.writeFile(fileName, data, writeByteOrderMark, onError); }),
+            };
+        }
+        function getDiagnosticsProducingTypeChecker() {
+            return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, true));
+        }
+        function getTypeChecker() {
+            return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, false));
+        }
+        function emit(sourceFile, writeFileCallback) {
+            if (options.noEmitOnError && getPreEmitDiagnostics(this).length > 0) {
+                return { diagnostics: [], sourceMaps: undefined, emitSkipped: true };
+            }
+            var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
+            var start = new Date().getTime();
+            var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile);
+            ts.emitTime += new Date().getTime() - start;
+            return emitResult;
+        }
+        function getSourceFile(fileName) {
+            fileName = host.getCanonicalFileName(fileName);
+            return ts.hasProperty(filesByName, fileName) ? filesByName[fileName] : undefined;
+        }
+        function getDiagnosticsHelper(sourceFile, getDiagnostics) {
+            if (sourceFile) {
+                return getDiagnostics(sourceFile);
+            }
+            var allDiagnostics = [];
+            ts.forEach(program.getSourceFiles(), function (sourceFile) {
+                ts.addRange(allDiagnostics, getDiagnostics(sourceFile));
+            });
+            return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
+        }
+        function getSyntacticDiagnostics(sourceFile) {
+            return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile);
+        }
+        function getSemanticDiagnostics(sourceFile) {
+            return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile);
+        }
+        function getDeclarationDiagnostics(sourceFile) {
+            return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile);
+        }
+        function getSyntacticDiagnosticsForFile(sourceFile) {
+            return sourceFile.parseDiagnostics;
+        }
+        function getSemanticDiagnosticsForFile(sourceFile) {
+            var typeChecker = getDiagnosticsProducingTypeChecker();
+            ts.Debug.assert(!!sourceFile.bindDiagnostics);
+            var bindDiagnostics = sourceFile.bindDiagnostics;
+            var checkDiagnostics = typeChecker.getDiagnostics(sourceFile);
+            var programDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
+            return bindDiagnostics.concat(checkDiagnostics).concat(programDiagnostics);
+        }
+        function getDeclarationDiagnosticsForFile(sourceFile) {
+            if (!ts.isDeclarationFile(sourceFile)) {
+                var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
+                var writeFile = function () { };
+                return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile);
+            }
+        }
+        function getGlobalDiagnostics() {
+            var typeChecker = getDiagnosticsProducingTypeChecker();
+            var allDiagnostics = [];
+            ts.addRange(allDiagnostics, typeChecker.getGlobalDiagnostics());
+            ts.addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
+            return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
+        }
+        function hasExtension(fileName) {
+            return ts.getBaseFileName(fileName).indexOf(".") >= 0;
+        }
+        function processRootFile(fileName, isDefaultLib) {
+            processSourceFile(ts.normalizePath(fileName), isDefaultLib);
+        }
+        function processSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd) {
+            var start;
+            var length;
+            if (refEnd !== undefined && refPos !== undefined) {
+                start = refPos;
+                length = refEnd - refPos;
+            }
+            var diagnostic;
+            if (hasExtension(fileName)) {
+                if (!options.allowNonTsExtensions && !ts.fileExtensionIs(host.getCanonicalFileName(fileName), ".ts")) {
+                    diagnostic = ts.Diagnostics.File_0_must_have_extension_ts_or_d_ts;
+                }
+                else if (!findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
+                    diagnostic = ts.Diagnostics.File_0_not_found;
+                }
+                else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
+                    diagnostic = ts.Diagnostics.A_file_cannot_have_a_reference_to_itself;
+                }
+            }
+            else {
+                if (options.allowNonTsExtensions && !findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
+                    diagnostic = ts.Diagnostics.File_0_not_found;
+                }
+                else if (!findSourceFile(fileName + ".ts", isDefaultLib, refFile, refPos, refEnd) && !findSourceFile(fileName + ".d.ts", isDefaultLib, refFile, refPos, refEnd)) {
+                    diagnostic = ts.Diagnostics.File_0_not_found;
+                    fileName += ".ts";
+                }
+            }
+            if (diagnostic) {
+                if (refFile) {
+                    diagnostics.add(ts.createFileDiagnostic(refFile, start, length, diagnostic, fileName));
+                }
+                else {
+                    diagnostics.add(ts.createCompilerDiagnostic(diagnostic, fileName));
+                }
+            }
+        }
+        function findSourceFile(fileName, isDefaultLib, refFile, refStart, refLength) {
+            var canonicalName = host.getCanonicalFileName(fileName);
+            if (ts.hasProperty(filesByName, canonicalName)) {
+                return getSourceFileFromCache(fileName, canonicalName, false);
+            }
+            else {
+                var normalizedAbsolutePath = ts.getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
+                var canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
+                if (ts.hasProperty(filesByName, canonicalAbsolutePath)) {
+                    return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, true);
+                }
+                var file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, function (hostErrorMessage) {
+                    if (refFile) {
+                        diagnostics.add(ts.createFileDiagnostic(refFile, refStart, refLength, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
+                    }
+                    else {
+                        diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
+                    }
+                });
+                if (file) {
+                    seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
+                    filesByName[canonicalAbsolutePath] = file;
+                    if (!options.noResolve) {
+                        var basePath = ts.getDirectoryPath(fileName);
+                        processReferencedFiles(file, basePath);
+                        processImportedModules(file, basePath);
+                    }
+                    if (isDefaultLib) {
+                        files.unshift(file);
+                    }
+                    else {
+                        files.push(file);
+                    }
+                }
+                return file;
+            }
+            function getSourceFileFromCache(fileName, canonicalName, useAbsolutePath) {
+                var file = filesByName[canonicalName];
+                if (file && host.useCaseSensitiveFileNames()) {
+                    var sourceFileName = useAbsolutePath ? ts.getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
+                    if (canonicalName !== sourceFileName) {
+                        diagnostics.add(ts.createFileDiagnostic(refFile, refStart, refLength, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, sourceFileName));
+                    }
+                }
+                return file;
+            }
+        }
+        function processReferencedFiles(file, basePath) {
+            ts.forEach(file.referencedFiles, function (ref) {
+                var referencedFileName = ts.isRootedDiskPath(ref.fileName) ? ref.fileName : ts.combinePaths(basePath, ref.fileName);
+                processSourceFile(ts.normalizePath(referencedFileName), false, file, ref.pos, ref.end);
+            });
+        }
+        function processImportedModules(file, basePath) {
+            ts.forEach(file.statements, function (node) {
+                if (node.kind === 209 || node.kind === 208 || node.kind === 215) {
+                    var moduleNameExpr = ts.getExternalModuleName(node);
+                    if (moduleNameExpr && moduleNameExpr.kind === 8) {
+                        var moduleNameText = moduleNameExpr.text;
+                        if (moduleNameText) {
+                            var searchPath = basePath;
+                            while (true) {
+                                var searchName = ts.normalizePath(ts.combinePaths(searchPath, moduleNameText));
+                                if (findModuleSourceFile(searchName + ".ts", moduleNameExpr) || findModuleSourceFile(searchName + ".d.ts", moduleNameExpr)) {
+                                    break;
+                                }
+                                var parentPath = ts.getDirectoryPath(searchPath);
+                                if (parentPath === searchPath) {
+                                    break;
+                                }
+                                searchPath = parentPath;
+                            }
+                        }
+                    }
+                }
+                else if (node.kind === 205 && node.name.kind === 8 && (node.flags & 2 || ts.isDeclarationFile(file))) {
+                    ts.forEachChild(node.body, function (node) {
+                        if (ts.isExternalModuleImportEqualsDeclaration(node) &&
+                            ts.getExternalModuleImportEqualsDeclarationExpression(node).kind === 8) {
+                            var nameLiteral = ts.getExternalModuleImportEqualsDeclarationExpression(node);
+                            var moduleName = nameLiteral.text;
+                            if (moduleName) {
+                                var searchName = ts.normalizePath(ts.combinePaths(basePath, moduleName));
+                                var tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
+                                if (!tsFile) {
+                                    findModuleSourceFile(searchName + ".d.ts", nameLiteral);
+                                }
+                            }
+                        }
+                    });
+                }
+            });
+            function findModuleSourceFile(fileName, nameLiteral) {
+                return findSourceFile(fileName, false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos);
+            }
+        }
+        function computeCommonSourceDirectory(sourceFiles) {
+            var commonPathComponents;
+            var currentDirectory = host.getCurrentDirectory();
+            ts.forEach(files, function (sourceFile) {
+                if (ts.isDeclarationFile(sourceFile)) {
+                    return;
+                }
+                var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile.fileName, currentDirectory);
+                sourcePathComponents.pop();
+                if (!commonPathComponents) {
+                    commonPathComponents = sourcePathComponents;
+                    return;
+                }
+                for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) {
+                    if (commonPathComponents[i] !== sourcePathComponents[i]) {
+                        if (i === 0) {
+                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
+                            return;
+                        }
+                        commonPathComponents.length = i;
+                        break;
+                    }
+                }
+                if (sourcePathComponents.length < commonPathComponents.length) {
+                    commonPathComponents.length = sourcePathComponents.length;
+                }
+            });
+            return ts.getNormalizedPathFromPathComponents(commonPathComponents);
+        }
+        function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) {
+            var allFilesBelongToPath = true;
+            if (sourceFiles) {
+                var currentDirectory = host.getCurrentDirectory();
+                var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory));
+                for (var _i = 0; _i < sourceFiles.length; _i++) {
+                    var sourceFile = sourceFiles[_i];
+                    if (!ts.isDeclarationFile(sourceFile)) {
+                        var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
+                        if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) {
+                            diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir));
+                            allFilesBelongToPath = false;
+                        }
+                    }
+                }
+            }
+            return allFilesBelongToPath;
+        }
+        function verifyCompilerOptions() {
+            if (options.separateCompilation) {
+                if (options.sourceMap) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_sourceMap_cannot_be_specified_with_option_separateCompilation));
+                }
+                if (options.declaration) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_declaration_cannot_be_specified_with_option_separateCompilation));
+                }
+                if (options.noEmitOnError) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation));
+                }
+                if (options.out) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_out_cannot_be_specified_with_option_separateCompilation));
+                }
+            }
+            if (!options.sourceMap && (options.mapRoot || options.sourceRoot)) {
+                if (options.mapRoot) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option));
+                }
+                if (options.sourceRoot) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option));
+                }
+                return;
+            }
+            var languageVersion = options.target || 0;
+            var firstExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) ? f : undefined; });
+            if (options.separateCompilation) {
+                if (!options.module && languageVersion < 2) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher));
+                }
+                var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; });
+                if (firstNonExternalModuleSourceFile) {
+                    var span = ts.getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile);
+                    diagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided));
+                }
+            }
+            else if (firstExternalModuleSourceFile && languageVersion < 2 && !options.module) {
+                var span = ts.getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
+                diagnostics.add(ts.createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
+            }
+            if (options.module && languageVersion >= 2) {
+                diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_compile_external_modules_into_amd_commonjs_or_umd_when_targeting_ES6_or_higher));
+            }
+            if (options.outDir ||
+                options.sourceRoot ||
+                (options.mapRoot &&
+                    (!options.out || firstExternalModuleSourceFile !== undefined))) {
+                if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) {
+                    commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory());
+                }
+                else {
+                    commonSourceDirectory = computeCommonSourceDirectory(files);
+                }
+                if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) {
+                    commonSourceDirectory += ts.directorySeparator;
+                }
+            }
+            if (options.noEmit) {
+                if (options.out || options.outDir) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmit_cannot_be_specified_with_option_out_or_outDir));
+                }
+                if (options.declaration) {
+                    diagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_noEmit_cannot_be_specified_with_option_declaration));
+                }
+            }
+        }
+    }
+    ts.createProgram = createProgram;
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/scanner.js b/dist/typescript/compiler/scanner.js
new file mode 100644
index 000000000..a466f1c1e
--- /dev/null
+++ b/dist/typescript/compiler/scanner.js
@@ -0,0 +1,1245 @@
+/// <reference path="core.ts"/>
+/// <reference path="diagnosticInformationMap.generated.ts"/>
+var ts;
+(function (ts) {
+    var textToToken = {
+        "any": 112,
+        "as": 111,
+        "boolean": 113,
+        "break": 66,
+        "case": 67,
+        "catch": 68,
+        "class": 69,
+        "continue": 71,
+        "const": 70,
+        "constructor": 114,
+        "debugger": 72,
+        "declare": 115,
+        "default": 73,
+        "delete": 74,
+        "do": 75,
+        "else": 76,
+        "enum": 77,
+        "export": 78,
+        "extends": 79,
+        "false": 80,
+        "finally": 81,
+        "for": 82,
+        "from": 124,
+        "function": 83,
+        "get": 116,
+        "if": 84,
+        "implements": 102,
+        "import": 85,
+        "in": 86,
+        "instanceof": 87,
+        "interface": 103,
+        "let": 104,
+        "module": 117,
+        "new": 88,
+        "null": 89,
+        "number": 119,
+        "package": 105,
+        "private": 106,
+        "protected": 107,
+        "public": 108,
+        "require": 118,
+        "return": 90,
+        "set": 120,
+        "static": 109,
+        "string": 121,
+        "super": 91,
+        "switch": 92,
+        "symbol": 122,
+        "this": 93,
+        "throw": 94,
+        "true": 95,
+        "try": 96,
+        "type": 123,
+        "typeof": 97,
+        "var": 98,
+        "void": 99,
+        "while": 100,
+        "with": 101,
+        "yield": 110,
+        "of": 125,
+        "{": 14,
+        "}": 15,
+        "(": 16,
+        ")": 17,
+        "[": 18,
+        "]": 19,
+        ".": 20,
+        "...": 21,
+        ";": 22,
+        ",": 23,
+        "<": 24,
+        ">": 25,
+        "<=": 26,
+        ">=": 27,
+        "==": 28,
+        "!=": 29,
+        "===": 30,
+        "!==": 31,
+        "=>": 32,
+        "+": 33,
+        "-": 34,
+        "*": 35,
+        "/": 36,
+        "%": 37,
+        "++": 38,
+        "--": 39,
+        "<<": 40,
+        ">>": 41,
+        ">>>": 42,
+        "&": 43,
+        "|": 44,
+        "^": 45,
+        "!": 46,
+        "~": 47,
+        "&&": 48,
+        "||": 49,
+        "?": 50,
+        ":": 51,
+        "=": 53,
+        "+=": 54,
+        "-=": 55,
+        "*=": 56,
+        "/=": 57,
+        "%=": 58,
+        "<<=": 59,
+        ">>=": 60,
+        ">>>=": 61,
+        "&=": 62,
+        "|=": 63,
+        "^=": 64,
+        "@": 52,
+    };
+    var unicodeES3IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
+    var unicodeES3IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
+    var unicodeES5IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
+    var unicodeES5IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,];
+    function lookupInUnicodeMap(code, map) {
+        if (code < map[0]) {
+            return false;
+        }
+        var lo = 0;
+        var hi = map.length;
+        var mid;
+        while (lo + 1 < hi) {
+            mid = lo + (hi - lo) / 2;
+            mid -= mid % 2;
+            if (map[mid] <= code && code <= map[mid + 1]) {
+                return true;
+            }
+            if (code < map[mid]) {
+                hi = mid;
+            }
+            else {
+                lo = mid + 2;
+            }
+        }
+        return false;
+    }
+    function isUnicodeIdentifierStart(code, languageVersion) {
+        return languageVersion >= 1 ?
+            lookupInUnicodeMap(code, unicodeES5IdentifierStart) :
+            lookupInUnicodeMap(code, unicodeES3IdentifierStart);
+    }
+    ts.isUnicodeIdentifierStart = isUnicodeIdentifierStart;
+    function isUnicodeIdentifierPart(code, languageVersion) {
+        return languageVersion >= 1 ?
+            lookupInUnicodeMap(code, unicodeES5IdentifierPart) :
+            lookupInUnicodeMap(code, unicodeES3IdentifierPart);
+    }
+    function makeReverseMap(source) {
+        var result = [];
+        for (var name_1 in source) {
+            if (source.hasOwnProperty(name_1)) {
+                result[source[name_1]] = name_1;
+            }
+        }
+        return result;
+    }
+    var tokenStrings = makeReverseMap(textToToken);
+    function tokenToString(t) {
+        return tokenStrings[t];
+    }
+    ts.tokenToString = tokenToString;
+    function stringToToken(s) {
+        return textToToken[s];
+    }
+    ts.stringToToken = stringToToken;
+    function computeLineStarts(text) {
+        var result = new Array();
+        var pos = 0;
+        var lineStart = 0;
+        while (pos < text.length) {
+            var ch = text.charCodeAt(pos++);
+            switch (ch) {
+                case 13:
+                    if (text.charCodeAt(pos) === 10) {
+                        pos++;
+                    }
+                case 10:
+                    result.push(lineStart);
+                    lineStart = pos;
+                    break;
+                default:
+                    if (ch > 127 && isLineBreak(ch)) {
+                        result.push(lineStart);
+                        lineStart = pos;
+                    }
+                    break;
+            }
+        }
+        result.push(lineStart);
+        return result;
+    }
+    ts.computeLineStarts = computeLineStarts;
+    function getPositionOfLineAndCharacter(sourceFile, line, character) {
+        return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character);
+    }
+    ts.getPositionOfLineAndCharacter = getPositionOfLineAndCharacter;
+    function computePositionOfLineAndCharacter(lineStarts, line, character) {
+        ts.Debug.assert(line >= 0 && line < lineStarts.length);
+        return lineStarts[line] + character;
+    }
+    ts.computePositionOfLineAndCharacter = computePositionOfLineAndCharacter;
+    function getLineStarts(sourceFile) {
+        return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
+    }
+    ts.getLineStarts = getLineStarts;
+    function computeLineAndCharacterOfPosition(lineStarts, position) {
+        var lineNumber = ts.binarySearch(lineStarts, position);
+        if (lineNumber < 0) {
+            lineNumber = ~lineNumber - 1;
+        }
+        return {
+            line: lineNumber,
+            character: position - lineStarts[lineNumber]
+        };
+    }
+    ts.computeLineAndCharacterOfPosition = computeLineAndCharacterOfPosition;
+    function getLineAndCharacterOfPosition(sourceFile, position) {
+        return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
+    }
+    ts.getLineAndCharacterOfPosition = getLineAndCharacterOfPosition;
+    var hasOwnProperty = Object.prototype.hasOwnProperty;
+    function isWhiteSpace(ch) {
+        return ch === 32 ||
+            ch === 9 ||
+            ch === 11 ||
+            ch === 12 ||
+            ch === 160 ||
+            ch === 133 ||
+            ch === 5760 ||
+            ch >= 8192 && ch <= 8203 ||
+            ch === 8239 ||
+            ch === 8287 ||
+            ch === 12288 ||
+            ch === 65279;
+    }
+    ts.isWhiteSpace = isWhiteSpace;
+    function isLineBreak(ch) {
+        // ES5 7.3:
+        // The ECMAScript line terminator characters are listed in Table 3.
+        //     Table 3: Line Terminator Characters
+        //     Code Unit Value     Name                    Formal Name
+        //     \u000A              Line Feed               <LF>
+        //     \u000D              Carriage Return         <CR>
+        //     \u2028              Line separator          <LS>
+        //     \u2029              Paragraph separator     <PS>
+        // Only the characters in Table 3 are treated as line terminators. Other new line or line 
+        // breaking characters are treated as white space but not as line terminators. 
+        return ch === 10 ||
+            ch === 13 ||
+            ch === 8232 ||
+            ch === 8233;
+    }
+    ts.isLineBreak = isLineBreak;
+    function isDigit(ch) {
+        return ch >= 48 && ch <= 57;
+    }
+    function isOctalDigit(ch) {
+        return ch >= 48 && ch <= 55;
+    }
+    ts.isOctalDigit = isOctalDigit;
+    function skipTrivia(text, pos, stopAfterLineBreak) {
+        while (true) {
+            var ch = text.charCodeAt(pos);
+            switch (ch) {
+                case 13:
+                    if (text.charCodeAt(pos + 1) === 10) {
+                        pos++;
+                    }
+                case 10:
+                    pos++;
+                    if (stopAfterLineBreak) {
+                        return pos;
+                    }
+                    continue;
+                case 9:
+                case 11:
+                case 12:
+                case 32:
+                    pos++;
+                    continue;
+                case 47:
+                    if (text.charCodeAt(pos + 1) === 47) {
+                        pos += 2;
+                        while (pos < text.length) {
+                            if (isLineBreak(text.charCodeAt(pos))) {
+                                break;
+                            }
+                            pos++;
+                        }
+                        continue;
+                    }
+                    if (text.charCodeAt(pos + 1) === 42) {
+                        pos += 2;
+                        while (pos < text.length) {
+                            if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) {
+                                pos += 2;
+                                break;
+                            }
+                            pos++;
+                        }
+                        continue;
+                    }
+                    break;
+                case 60:
+                case 61:
+                case 62:
+                    if (isConflictMarkerTrivia(text, pos)) {
+                        pos = scanConflictMarkerTrivia(text, pos);
+                        continue;
+                    }
+                    break;
+                default:
+                    if (ch > 127 && (isWhiteSpace(ch) || isLineBreak(ch))) {
+                        pos++;
+                        continue;
+                    }
+                    break;
+            }
+            return pos;
+        }
+    }
+    ts.skipTrivia = skipTrivia;
+    var mergeConflictMarkerLength = "<<<<<<<".length;
+    function isConflictMarkerTrivia(text, pos) {
+        ts.Debug.assert(pos >= 0);
+        if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) {
+            var ch = text.charCodeAt(pos);
+            if ((pos + mergeConflictMarkerLength) < text.length) {
+                for (var i = 0, n = mergeConflictMarkerLength; i < n; i++) {
+                    if (text.charCodeAt(pos + i) !== ch) {
+                        return false;
+                    }
+                }
+                return ch === 61 ||
+                    text.charCodeAt(pos + mergeConflictMarkerLength) === 32;
+            }
+        }
+        return false;
+    }
+    function scanConflictMarkerTrivia(text, pos, error) {
+        if (error) {
+            error(ts.Diagnostics.Merge_conflict_marker_encountered, mergeConflictMarkerLength);
+        }
+        var ch = text.charCodeAt(pos);
+        var len = text.length;
+        if (ch === 60 || ch === 62) {
+            while (pos < len && !isLineBreak(text.charCodeAt(pos))) {
+                pos++;
+            }
+        }
+        else {
+            ts.Debug.assert(ch === 61);
+            while (pos < len) {
+                var ch_1 = text.charCodeAt(pos);
+                if (ch_1 === 62 && isConflictMarkerTrivia(text, pos)) {
+                    break;
+                }
+                pos++;
+            }
+        }
+        return pos;
+    }
+    function getCommentRanges(text, pos, trailing) {
+        var result;
+        var collecting = trailing || pos === 0;
+        while (true) {
+            var ch = text.charCodeAt(pos);
+            switch (ch) {
+                case 13:
+                    if (text.charCodeAt(pos + 1) === 10) {
+                        pos++;
+                    }
+                case 10:
+                    pos++;
+                    if (trailing) {
+                        return result;
+                    }
+                    collecting = true;
+                    if (result && result.length) {
+                        result[result.length - 1].hasTrailingNewLine = true;
+                    }
+                    continue;
+                case 9:
+                case 11:
+                case 12:
+                case 32:
+                    pos++;
+                    continue;
+                case 47:
+                    var nextChar = text.charCodeAt(pos + 1);
+                    var hasTrailingNewLine = false;
+                    if (nextChar === 47 || nextChar === 42) {
+                        var kind = nextChar === 47 ? 2 : 3;
+                        var startPos = pos;
+                        pos += 2;
+                        if (nextChar === 47) {
+                            while (pos < text.length) {
+                                if (isLineBreak(text.charCodeAt(pos))) {
+                                    hasTrailingNewLine = true;
+                                    break;
+                                }
+                                pos++;
+                            }
+                        }
+                        else {
+                            while (pos < text.length) {
+                                if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) {
+                                    pos += 2;
+                                    break;
+                                }
+                                pos++;
+                            }
+                        }
+                        if (collecting) {
+                            if (!result) {
+                                result = [];
+                            }
+                            result.push({ pos: startPos, end: pos, hasTrailingNewLine: hasTrailingNewLine, kind: kind });
+                        }
+                        continue;
+                    }
+                    break;
+                default:
+                    if (ch > 127 && (isWhiteSpace(ch) || isLineBreak(ch))) {
+                        if (result && result.length && isLineBreak(ch)) {
+                            result[result.length - 1].hasTrailingNewLine = true;
+                        }
+                        pos++;
+                        continue;
+                    }
+                    break;
+            }
+            return result;
+        }
+    }
+    function getLeadingCommentRanges(text, pos) {
+        return getCommentRanges(text, pos, false);
+    }
+    ts.getLeadingCommentRanges = getLeadingCommentRanges;
+    function getTrailingCommentRanges(text, pos) {
+        return getCommentRanges(text, pos, true);
+    }
+    ts.getTrailingCommentRanges = getTrailingCommentRanges;
+    function isIdentifierStart(ch, languageVersion) {
+        return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 ||
+            ch === 36 || ch === 95 ||
+            ch > 127 && isUnicodeIdentifierStart(ch, languageVersion);
+    }
+    ts.isIdentifierStart = isIdentifierStart;
+    function isIdentifierPart(ch, languageVersion) {
+        return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 ||
+            ch >= 48 && ch <= 57 || ch === 36 || ch === 95 ||
+            ch > 127 && isUnicodeIdentifierPart(ch, languageVersion);
+    }
+    ts.isIdentifierPart = isIdentifierPart;
+    function createScanner(languageVersion, skipTrivia, text, onError, start, length) {
+        var pos;
+        var end;
+        var startPos;
+        var tokenPos;
+        var token;
+        var tokenValue;
+        var precedingLineBreak;
+        var hasExtendedUnicodeEscape;
+        var tokenIsUnterminated;
+        setText(text, start, length);
+        return {
+            getStartPos: function () { return startPos; },
+            getTextPos: function () { return pos; },
+            getToken: function () { return token; },
+            getTokenPos: function () { return tokenPos; },
+            getTokenText: function () { return text.substring(tokenPos, pos); },
+            getTokenValue: function () { return tokenValue; },
+            hasExtendedUnicodeEscape: function () { return hasExtendedUnicodeEscape; },
+            hasPrecedingLineBreak: function () { return precedingLineBreak; },
+            isIdentifier: function () { return token === 65 || token > 101; },
+            isReservedWord: function () { return token >= 66 && token <= 101; },
+            isUnterminated: function () { return tokenIsUnterminated; },
+            reScanGreaterToken: reScanGreaterToken,
+            reScanSlashToken: reScanSlashToken,
+            reScanTemplateToken: reScanTemplateToken,
+            scan: scan,
+            setText: setText,
+            setScriptTarget: setScriptTarget,
+            setOnError: setOnError,
+            setTextPos: setTextPos,
+            tryScan: tryScan,
+            lookAhead: lookAhead,
+        };
+        function error(message, length) {
+            if (onError) {
+                onError(message, length || 0);
+            }
+        }
+        function isIdentifierStart(ch) {
+            return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 ||
+                ch === 36 || ch === 95 ||
+                ch > 127 && isUnicodeIdentifierStart(ch, languageVersion);
+        }
+        function isIdentifierPart(ch) {
+            return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 ||
+                ch >= 48 && ch <= 57 || ch === 36 || ch === 95 ||
+                ch > 127 && isUnicodeIdentifierPart(ch, languageVersion);
+        }
+        function scanNumber() {
+            var start = pos;
+            while (isDigit(text.charCodeAt(pos)))
+                pos++;
+            if (text.charCodeAt(pos) === 46) {
+                pos++;
+                while (isDigit(text.charCodeAt(pos)))
+                    pos++;
+            }
+            var end = pos;
+            if (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101) {
+                pos++;
+                if (text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45)
+                    pos++;
+                if (isDigit(text.charCodeAt(pos))) {
+                    pos++;
+                    while (isDigit(text.charCodeAt(pos)))
+                        pos++;
+                    end = pos;
+                }
+                else {
+                    error(ts.Diagnostics.Digit_expected);
+                }
+            }
+            return +(text.substring(start, end));
+        }
+        function scanOctalDigits() {
+            var start = pos;
+            while (isOctalDigit(text.charCodeAt(pos))) {
+                pos++;
+            }
+            return +(text.substring(start, pos));
+        }
+        function scanExactNumberOfHexDigits(count) {
+            return scanHexDigits(count, false);
+        }
+        function scanMinimumNumberOfHexDigits(count) {
+            return scanHexDigits(count, true);
+        }
+        function scanHexDigits(minCount, scanAsManyAsPossible) {
+            var digits = 0;
+            var value = 0;
+            while (digits < minCount || scanAsManyAsPossible) {
+                var ch = text.charCodeAt(pos);
+                if (ch >= 48 && ch <= 57) {
+                    value = value * 16 + ch - 48;
+                }
+                else if (ch >= 65 && ch <= 70) {
+                    value = value * 16 + ch - 65 + 10;
+                }
+                else if (ch >= 97 && ch <= 102) {
+                    value = value * 16 + ch - 97 + 10;
+                }
+                else {
+                    break;
+                }
+                pos++;
+                digits++;
+            }
+            if (digits < minCount) {
+                value = -1;
+            }
+            return value;
+        }
+        function scanString() {
+            var quote = text.charCodeAt(pos++);
+            var result = "";
+            var start = pos;
+            while (true) {
+                if (pos >= end) {
+                    result += text.substring(start, pos);
+                    tokenIsUnterminated = true;
+                    error(ts.Diagnostics.Unterminated_string_literal);
+                    break;
+                }
+                var ch = text.charCodeAt(pos);
+                if (ch === quote) {
+                    result += text.substring(start, pos);
+                    pos++;
+                    break;
+                }
+                if (ch === 92) {
+                    result += text.substring(start, pos);
+                    result += scanEscapeSequence();
+                    start = pos;
+                    continue;
+                }
+                if (isLineBreak(ch)) {
+                    result += text.substring(start, pos);
+                    tokenIsUnterminated = true;
+                    error(ts.Diagnostics.Unterminated_string_literal);
+                    break;
+                }
+                pos++;
+            }
+            return result;
+        }
+        function scanTemplateAndSetTokenValue() {
+            var startedWithBacktick = text.charCodeAt(pos) === 96;
+            pos++;
+            var start = pos;
+            var contents = "";
+            var resultingToken;
+            while (true) {
+                if (pos >= end) {
+                    contents += text.substring(start, pos);
+                    tokenIsUnterminated = true;
+                    error(ts.Diagnostics.Unterminated_template_literal);
+                    resultingToken = startedWithBacktick ? 10 : 13;
+                    break;
+                }
+                var currChar = text.charCodeAt(pos);
+                if (currChar === 96) {
+                    contents += text.substring(start, pos);
+                    pos++;
+                    resultingToken = startedWithBacktick ? 10 : 13;
+                    break;
+                }
+                if (currChar === 36 && pos + 1 < end && text.charCodeAt(pos + 1) === 123) {
+                    contents += text.substring(start, pos);
+                    pos += 2;
+                    resultingToken = startedWithBacktick ? 11 : 12;
+                    break;
+                }
+                if (currChar === 92) {
+                    contents += text.substring(start, pos);
+                    contents += scanEscapeSequence();
+                    start = pos;
+                    continue;
+                }
+                if (currChar === 13) {
+                    contents += text.substring(start, pos);
+                    pos++;
+                    if (pos < end && text.charCodeAt(pos) === 10) {
+                        pos++;
+                    }
+                    contents += "\n";
+                    start = pos;
+                    continue;
+                }
+                pos++;
+            }
+            ts.Debug.assert(resultingToken !== undefined);
+            tokenValue = contents;
+            return resultingToken;
+        }
+        function scanEscapeSequence() {
+            pos++;
+            if (pos >= end) {
+                error(ts.Diagnostics.Unexpected_end_of_text);
+                return "";
+            }
+            var ch = text.charCodeAt(pos++);
+            switch (ch) {
+                case 48:
+                    return "\0";
+                case 98:
+                    return "\b";
+                case 116:
+                    return "\t";
+                case 110:
+                    return "\n";
+                case 118:
+                    return "\v";
+                case 102:
+                    return "\f";
+                case 114:
+                    return "\r";
+                case 39:
+                    return "\'";
+                case 34:
+                    return "\"";
+                case 117:
+                    if (pos < end && text.charCodeAt(pos) === 123) {
+                        hasExtendedUnicodeEscape = true;
+                        pos++;
+                        return scanExtendedUnicodeEscape();
+                    }
+                    return scanHexadecimalEscape(4);
+                case 120:
+                    return scanHexadecimalEscape(2);
+                case 13:
+                    if (pos < end && text.charCodeAt(pos) === 10) {
+                        pos++;
+                    }
+                case 10:
+                case 8232:
+                case 8233:
+                    return "";
+                default:
+                    return String.fromCharCode(ch);
+            }
+        }
+        function scanHexadecimalEscape(numDigits) {
+            var escapedValue = scanExactNumberOfHexDigits(numDigits);
+            if (escapedValue >= 0) {
+                return String.fromCharCode(escapedValue);
+            }
+            else {
+                error(ts.Diagnostics.Hexadecimal_digit_expected);
+                return "";
+            }
+        }
+        function scanExtendedUnicodeEscape() {
+            var escapedValue = scanMinimumNumberOfHexDigits(1);
+            var isInvalidExtendedEscape = false;
+            if (escapedValue < 0) {
+                error(ts.Diagnostics.Hexadecimal_digit_expected);
+                isInvalidExtendedEscape = true;
+            }
+            else if (escapedValue > 0x10FFFF) {
+                error(ts.Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive);
+                isInvalidExtendedEscape = true;
+            }
+            if (pos >= end) {
+                error(ts.Diagnostics.Unexpected_end_of_text);
+                isInvalidExtendedEscape = true;
+            }
+            else if (text.charCodeAt(pos) == 125) {
+                pos++;
+            }
+            else {
+                error(ts.Diagnostics.Unterminated_Unicode_escape_sequence);
+                isInvalidExtendedEscape = true;
+            }
+            if (isInvalidExtendedEscape) {
+                return "";
+            }
+            return utf16EncodeAsString(escapedValue);
+        }
+        function utf16EncodeAsString(codePoint) {
+            ts.Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF);
+            if (codePoint <= 65535) {
+                return String.fromCharCode(codePoint);
+            }
+            var codeUnit1 = Math.floor((codePoint - 65536) / 1024) + 0xD800;
+            var codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00;
+            return String.fromCharCode(codeUnit1, codeUnit2);
+        }
+        function peekUnicodeEscape() {
+            if (pos + 5 < end && text.charCodeAt(pos + 1) === 117) {
+                var start_1 = pos;
+                pos += 2;
+                var value = scanExactNumberOfHexDigits(4);
+                pos = start_1;
+                return value;
+            }
+            return -1;
+        }
+        function scanIdentifierParts() {
+            var result = "";
+            var start = pos;
+            while (pos < end) {
+                var ch = text.charCodeAt(pos);
+                if (isIdentifierPart(ch)) {
+                    pos++;
+                }
+                else if (ch === 92) {
+                    ch = peekUnicodeEscape();
+                    if (!(ch >= 0 && isIdentifierPart(ch))) {
+                        break;
+                    }
+                    result += text.substring(start, pos);
+                    result += String.fromCharCode(ch);
+                    pos += 6;
+                    start = pos;
+                }
+                else {
+                    break;
+                }
+            }
+            result += text.substring(start, pos);
+            return result;
+        }
+        function getIdentifierToken() {
+            var len = tokenValue.length;
+            if (len >= 2 && len <= 11) {
+                var ch = tokenValue.charCodeAt(0);
+                if (ch >= 97 && ch <= 122 && hasOwnProperty.call(textToToken, tokenValue)) {
+                    return token = textToToken[tokenValue];
+                }
+            }
+            return token = 65;
+        }
+        function scanBinaryOrOctalDigits(base) {
+            ts.Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8");
+            var value = 0;
+            var numberOfDigits = 0;
+            while (true) {
+                var ch = text.charCodeAt(pos);
+                var valueOfCh = ch - 48;
+                if (!isDigit(ch) || valueOfCh >= base) {
+                    break;
+                }
+                value = value * base + valueOfCh;
+                pos++;
+                numberOfDigits++;
+            }
+            if (numberOfDigits === 0) {
+                return -1;
+            }
+            return value;
+        }
+        function scan() {
+            startPos = pos;
+            hasExtendedUnicodeEscape = false;
+            precedingLineBreak = false;
+            tokenIsUnterminated = false;
+            while (true) {
+                tokenPos = pos;
+                if (pos >= end) {
+                    return token = 1;
+                }
+                var ch = text.charCodeAt(pos);
+                switch (ch) {
+                    case 10:
+                    case 13:
+                        precedingLineBreak = true;
+                        if (skipTrivia) {
+                            pos++;
+                            continue;
+                        }
+                        else {
+                            if (ch === 13 && pos + 1 < end && text.charCodeAt(pos + 1) === 10) {
+                                pos += 2;
+                            }
+                            else {
+                                pos++;
+                            }
+                            return token = 4;
+                        }
+                    case 9:
+                    case 11:
+                    case 12:
+                    case 32:
+                        if (skipTrivia) {
+                            pos++;
+                            continue;
+                        }
+                        else {
+                            while (pos < end && isWhiteSpace(text.charCodeAt(pos))) {
+                                pos++;
+                            }
+                            return token = 5;
+                        }
+                    case 33:
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            if (text.charCodeAt(pos + 2) === 61) {
+                                return pos += 3, token = 31;
+                            }
+                            return pos += 2, token = 29;
+                        }
+                        return pos++, token = 46;
+                    case 34:
+                    case 39:
+                        tokenValue = scanString();
+                        return token = 8;
+                    case 96:
+                        return token = scanTemplateAndSetTokenValue();
+                    case 37:
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 58;
+                        }
+                        return pos++, token = 37;
+                    case 38:
+                        if (text.charCodeAt(pos + 1) === 38) {
+                            return pos += 2, token = 48;
+                        }
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 62;
+                        }
+                        return pos++, token = 43;
+                    case 40:
+                        return pos++, token = 16;
+                    case 41:
+                        return pos++, token = 17;
+                    case 42:
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 56;
+                        }
+                        return pos++, token = 35;
+                    case 43:
+                        if (text.charCodeAt(pos + 1) === 43) {
+                            return pos += 2, token = 38;
+                        }
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 54;
+                        }
+                        return pos++, token = 33;
+                    case 44:
+                        return pos++, token = 23;
+                    case 45:
+                        if (text.charCodeAt(pos + 1) === 45) {
+                            return pos += 2, token = 39;
+                        }
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 55;
+                        }
+                        return pos++, token = 34;
+                    case 46:
+                        if (isDigit(text.charCodeAt(pos + 1))) {
+                            tokenValue = "" + scanNumber();
+                            return token = 7;
+                        }
+                        if (text.charCodeAt(pos + 1) === 46 && text.charCodeAt(pos + 2) === 46) {
+                            return pos += 3, token = 21;
+                        }
+                        return pos++, token = 20;
+                    case 47:
+                        if (text.charCodeAt(pos + 1) === 47) {
+                            pos += 2;
+                            while (pos < end) {
+                                if (isLineBreak(text.charCodeAt(pos))) {
+                                    break;
+                                }
+                                pos++;
+                            }
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = 2;
+                            }
+                        }
+                        if (text.charCodeAt(pos + 1) === 42) {
+                            pos += 2;
+                            var commentClosed = false;
+                            while (pos < end) {
+                                var ch_2 = text.charCodeAt(pos);
+                                if (ch_2 === 42 && text.charCodeAt(pos + 1) === 47) {
+                                    pos += 2;
+                                    commentClosed = true;
+                                    break;
+                                }
+                                if (isLineBreak(ch_2)) {
+                                    precedingLineBreak = true;
+                                }
+                                pos++;
+                            }
+                            if (!commentClosed) {
+                                error(ts.Diagnostics.Asterisk_Slash_expected);
+                            }
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                tokenIsUnterminated = !commentClosed;
+                                return token = 3;
+                            }
+                        }
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 57;
+                        }
+                        return pos++, token = 36;
+                    case 48:
+                        if (pos + 2 < end && (text.charCodeAt(pos + 1) === 88 || text.charCodeAt(pos + 1) === 120)) {
+                            pos += 2;
+                            var value = scanMinimumNumberOfHexDigits(1);
+                            if (value < 0) {
+                                error(ts.Diagnostics.Hexadecimal_digit_expected);
+                                value = 0;
+                            }
+                            tokenValue = "" + value;
+                            return token = 7;
+                        }
+                        else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 66 || text.charCodeAt(pos + 1) === 98)) {
+                            pos += 2;
+                            var value = scanBinaryOrOctalDigits(2);
+                            if (value < 0) {
+                                error(ts.Diagnostics.Binary_digit_expected);
+                                value = 0;
+                            }
+                            tokenValue = "" + value;
+                            return token = 7;
+                        }
+                        else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 79 || text.charCodeAt(pos + 1) === 111)) {
+                            pos += 2;
+                            var value = scanBinaryOrOctalDigits(8);
+                            if (value < 0) {
+                                error(ts.Diagnostics.Octal_digit_expected);
+                                value = 0;
+                            }
+                            tokenValue = "" + value;
+                            return token = 7;
+                        }
+                        if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) {
+                            tokenValue = "" + scanOctalDigits();
+                            return token = 7;
+                        }
+                    case 49:
+                    case 50:
+                    case 51:
+                    case 52:
+                    case 53:
+                    case 54:
+                    case 55:
+                    case 56:
+                    case 57:
+                        tokenValue = "" + scanNumber();
+                        return token = 7;
+                    case 58:
+                        return pos++, token = 51;
+                    case 59:
+                        return pos++, token = 22;
+                    case 60:
+                        if (isConflictMarkerTrivia(text, pos)) {
+                            pos = scanConflictMarkerTrivia(text, pos, error);
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = 6;
+                            }
+                        }
+                        if (text.charCodeAt(pos + 1) === 60) {
+                            if (text.charCodeAt(pos + 2) === 61) {
+                                return pos += 3, token = 59;
+                            }
+                            return pos += 2, token = 40;
+                        }
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 26;
+                        }
+                        return pos++, token = 24;
+                    case 61:
+                        if (isConflictMarkerTrivia(text, pos)) {
+                            pos = scanConflictMarkerTrivia(text, pos, error);
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = 6;
+                            }
+                        }
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            if (text.charCodeAt(pos + 2) === 61) {
+                                return pos += 3, token = 30;
+                            }
+                            return pos += 2, token = 28;
+                        }
+                        if (text.charCodeAt(pos + 1) === 62) {
+                            return pos += 2, token = 32;
+                        }
+                        return pos++, token = 53;
+                    case 62:
+                        if (isConflictMarkerTrivia(text, pos)) {
+                            pos = scanConflictMarkerTrivia(text, pos, error);
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = 6;
+                            }
+                        }
+                        return pos++, token = 25;
+                    case 63:
+                        return pos++, token = 50;
+                    case 91:
+                        return pos++, token = 18;
+                    case 93:
+                        return pos++, token = 19;
+                    case 94:
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 64;
+                        }
+                        return pos++, token = 45;
+                    case 123:
+                        return pos++, token = 14;
+                    case 124:
+                        if (text.charCodeAt(pos + 1) === 124) {
+                            return pos += 2, token = 49;
+                        }
+                        if (text.charCodeAt(pos + 1) === 61) {
+                            return pos += 2, token = 63;
+                        }
+                        return pos++, token = 44;
+                    case 125:
+                        return pos++, token = 15;
+                    case 126:
+                        return pos++, token = 47;
+                    case 64:
+                        return pos++, token = 52;
+                    case 92:
+                        var cookedChar = peekUnicodeEscape();
+                        if (cookedChar >= 0 && isIdentifierStart(cookedChar)) {
+                            pos += 6;
+                            tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts();
+                            return token = getIdentifierToken();
+                        }
+                        error(ts.Diagnostics.Invalid_character);
+                        return pos++, token = 0;
+                    default:
+                        if (isIdentifierStart(ch)) {
+                            pos++;
+                            while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos)))
+                                pos++;
+                            tokenValue = text.substring(tokenPos, pos);
+                            if (ch === 92) {
+                                tokenValue += scanIdentifierParts();
+                            }
+                            return token = getIdentifierToken();
+                        }
+                        else if (isWhiteSpace(ch)) {
+                            pos++;
+                            continue;
+                        }
+                        else if (isLineBreak(ch)) {
+                            precedingLineBreak = true;
+                            pos++;
+                            continue;
+                        }
+                        error(ts.Diagnostics.Invalid_character);
+                        return pos++, token = 0;
+                }
+            }
+        }
+        function reScanGreaterToken() {
+            if (token === 25) {
+                if (text.charCodeAt(pos) === 62) {
+                    if (text.charCodeAt(pos + 1) === 62) {
+                        if (text.charCodeAt(pos + 2) === 61) {
+                            return pos += 3, token = 61;
+                        }
+                        return pos += 2, token = 42;
+                    }
+                    if (text.charCodeAt(pos + 1) === 61) {
+                        return pos += 2, token = 60;
+                    }
+                    return pos++, token = 41;
+                }
+                if (text.charCodeAt(pos) === 61) {
+                    return pos++, token = 27;
+                }
+            }
+            return token;
+        }
+        function reScanSlashToken() {
+            if (token === 36 || token === 57) {
+                var p = tokenPos + 1;
+                var inEscape = false;
+                var inCharacterClass = false;
+                while (true) {
+                    if (p >= end) {
+                        tokenIsUnterminated = true;
+                        error(ts.Diagnostics.Unterminated_regular_expression_literal);
+                        break;
+                    }
+                    var ch = text.charCodeAt(p);
+                    if (isLineBreak(ch)) {
+                        tokenIsUnterminated = true;
+                        error(ts.Diagnostics.Unterminated_regular_expression_literal);
+                        break;
+                    }
+                    if (inEscape) {
+                        inEscape = false;
+                    }
+                    else if (ch === 47 && !inCharacterClass) {
+                        p++;
+                        break;
+                    }
+                    else if (ch === 91) {
+                        inCharacterClass = true;
+                    }
+                    else if (ch === 92) {
+                        inEscape = true;
+                    }
+                    else if (ch === 93) {
+                        inCharacterClass = false;
+                    }
+                    p++;
+                }
+                while (p < end && isIdentifierPart(text.charCodeAt(p))) {
+                    p++;
+                }
+                pos = p;
+                tokenValue = text.substring(tokenPos, pos);
+                token = 9;
+            }
+            return token;
+        }
+        function reScanTemplateToken() {
+            ts.Debug.assert(token === 15, "'reScanTemplateToken' should only be called on a '}'");
+            pos = tokenPos;
+            return token = scanTemplateAndSetTokenValue();
+        }
+        function speculationHelper(callback, isLookahead) {
+            var savePos = pos;
+            var saveStartPos = startPos;
+            var saveTokenPos = tokenPos;
+            var saveToken = token;
+            var saveTokenValue = tokenValue;
+            var savePrecedingLineBreak = precedingLineBreak;
+            var result = callback();
+            if (!result || isLookahead) {
+                pos = savePos;
+                startPos = saveStartPos;
+                tokenPos = saveTokenPos;
+                token = saveToken;
+                tokenValue = saveTokenValue;
+                precedingLineBreak = savePrecedingLineBreak;
+            }
+            return result;
+        }
+        function lookAhead(callback) {
+            return speculationHelper(callback, true);
+        }
+        function tryScan(callback) {
+            return speculationHelper(callback, false);
+        }
+        function setText(newText, start, length) {
+            text = newText || "";
+            end = length === undefined ? text.length : start + length;
+            setTextPos(start || 0);
+        }
+        function setOnError(errorCallback) {
+            onError = errorCallback;
+        }
+        function setScriptTarget(scriptTarget) {
+            languageVersion = scriptTarget;
+        }
+        function setTextPos(textPos) {
+            ts.Debug.assert(textPos >= 0);
+            pos = textPos;
+            startPos = textPos;
+            tokenPos = textPos;
+            token = 0;
+            precedingLineBreak = false;
+            tokenValue = undefined;
+            hasExtendedUnicodeEscape = false;
+            tokenIsUnterminated = false;
+        }
+    }
+    ts.createScanner = createScanner;
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/sys.js b/dist/typescript/compiler/sys.js
new file mode 100644
index 000000000..d4765b752
--- /dev/null
+++ b/dist/typescript/compiler/sys.js
@@ -0,0 +1,252 @@
+/// <reference path="core.ts"/>
+var ts;
+(function (ts) {
+    ts.sys = (function () {
+        function getWScriptSystem() {
+            var fso = new ActiveXObject("Scripting.FileSystemObject");
+            var fileStream = new ActiveXObject("ADODB.Stream");
+            fileStream.Type = 2;
+            var binaryStream = new ActiveXObject("ADODB.Stream");
+            binaryStream.Type = 1;
+            var args = [];
+            for (var i = 0; i < WScript.Arguments.length; i++) {
+                args[i] = WScript.Arguments.Item(i);
+            }
+            function readFile(fileName, encoding) {
+                if (!fso.FileExists(fileName)) {
+                    return undefined;
+                }
+                fileStream.Open();
+                try {
+                    if (encoding) {
+                        fileStream.Charset = encoding;
+                        fileStream.LoadFromFile(fileName);
+                    }
+                    else {
+                        fileStream.Charset = "x-ansi";
+                        fileStream.LoadFromFile(fileName);
+                        var bom = fileStream.ReadText(2) || "";
+                        fileStream.Position = 0;
+                        fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
+                    }
+                    return fileStream.ReadText();
+                }
+                catch (e) {
+                    throw e;
+                }
+                finally {
+                    fileStream.Close();
+                }
+            }
+            function writeFile(fileName, data, writeByteOrderMark) {
+                fileStream.Open();
+                binaryStream.Open();
+                try {
+                    fileStream.Charset = "utf-8";
+                    fileStream.WriteText(data);
+                    if (writeByteOrderMark) {
+                        fileStream.Position = 0;
+                    }
+                    else {
+                        fileStream.Position = 3;
+                    }
+                    fileStream.CopyTo(binaryStream);
+                    binaryStream.SaveToFile(fileName, 2);
+                }
+                finally {
+                    binaryStream.Close();
+                    fileStream.Close();
+                }
+            }
+            function getNames(collection) {
+                var result = [];
+                for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
+                    result.push(e.item().Name);
+                }
+                return result.sort();
+            }
+            function readDirectory(path, extension) {
+                var result = [];
+                visitDirectory(path);
+                return result;
+                function visitDirectory(path) {
+                    var folder = fso.GetFolder(path || ".");
+                    var files = getNames(folder.files);
+                    for (var _i = 0; _i < files.length; _i++) {
+                        var name_1 = files[_i];
+                        if (!extension || ts.fileExtensionIs(name_1, extension)) {
+                            result.push(ts.combinePaths(path, name_1));
+                        }
+                    }
+                    var subfolders = getNames(folder.subfolders);
+                    for (var _a = 0; _a < subfolders.length; _a++) {
+                        var current = subfolders[_a];
+                        visitDirectory(ts.combinePaths(path, current));
+                    }
+                }
+            }
+            return {
+                args: args,
+                newLine: "\r\n",
+                useCaseSensitiveFileNames: false,
+                write: function (s) {
+                    WScript.StdOut.Write(s);
+                },
+                readFile: readFile,
+                writeFile: writeFile,
+                resolvePath: function (path) {
+                    return fso.GetAbsolutePathName(path);
+                },
+                fileExists: function (path) {
+                    return fso.FileExists(path);
+                },
+                directoryExists: function (path) {
+                    return fso.FolderExists(path);
+                },
+                createDirectory: function (directoryName) {
+                    if (!this.directoryExists(directoryName)) {
+                        fso.CreateFolder(directoryName);
+                    }
+                },
+                getExecutingFilePath: function () {
+                    return WScript.ScriptFullName;
+                },
+                getCurrentDirectory: function () {
+                    return new ActiveXObject("WScript.Shell").CurrentDirectory;
+                },
+                readDirectory: readDirectory,
+                exit: function (exitCode) {
+                    try {
+                        WScript.Quit(exitCode);
+                    }
+                    catch (e) {
+                    }
+                }
+            };
+        }
+        function getNodeSystem() {
+            var _fs = require("fs");
+            var _path = require("path");
+            var _os = require('os');
+            var platform = _os.platform();
+            var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin";
+            function readFile(fileName, encoding) {
+                if (!_fs.existsSync(fileName)) {
+                    return undefined;
+                }
+                var buffer = _fs.readFileSync(fileName);
+                var len = buffer.length;
+                if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
+                    len &= ~1;
+                    for (var i = 0; i < len; i += 2) {
+                        var temp = buffer[i];
+                        buffer[i] = buffer[i + 1];
+                        buffer[i + 1] = temp;
+                    }
+                    return buffer.toString("utf16le", 2);
+                }
+                if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
+                    return buffer.toString("utf16le", 2);
+                }
+                if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
+                    return buffer.toString("utf8", 3);
+                }
+                return buffer.toString("utf8");
+            }
+            function writeFile(fileName, data, writeByteOrderMark) {
+                if (writeByteOrderMark) {
+                    data = '\uFEFF' + data;
+                }
+                _fs.writeFileSync(fileName, data, "utf8");
+            }
+            function readDirectory(path, extension) {
+                var result = [];
+                visitDirectory(path);
+                return result;
+                function visitDirectory(path) {
+                    var files = _fs.readdirSync(path || ".").sort();
+                    var directories = [];
+                    for (var _i = 0; _i < files.length; _i++) {
+                        var current = files[_i];
+                        var name = ts.combinePaths(path, current);
+                        var stat = _fs.lstatSync(name);
+                        if (stat.isFile()) {
+                            if (!extension || ts.fileExtensionIs(name, extension)) {
+                                result.push(name);
+                            }
+                        }
+                        else if (stat.isDirectory()) {
+                            directories.push(name);
+                        }
+                    }
+                    for (var _a = 0; _a < directories.length; _a++) {
+                        var current = directories[_a];
+                        visitDirectory(current);
+                    }
+                }
+            }
+            return {
+                args: process.argv.slice(2),
+                newLine: _os.EOL,
+                useCaseSensitiveFileNames: useCaseSensitiveFileNames,
+                write: function (s) {
+                    _fs.writeSync(1, s);
+                },
+                readFile: readFile,
+                writeFile: writeFile,
+                watchFile: function (fileName, callback) {
+                    _fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged);
+                    return {
+                        close: function () { _fs.unwatchFile(fileName, fileChanged); }
+                    };
+                    function fileChanged(curr, prev) {
+                        if (+curr.mtime <= +prev.mtime) {
+                            return;
+                        }
+                        callback(fileName);
+                    }
+                    ;
+                },
+                resolvePath: function (path) {
+                    return _path.resolve(path);
+                },
+                fileExists: function (path) {
+                    return _fs.existsSync(path);
+                },
+                directoryExists: function (path) {
+                    return _fs.existsSync(path) && _fs.statSync(path).isDirectory();
+                },
+                createDirectory: function (directoryName) {
+                    if (!this.directoryExists(directoryName)) {
+                        _fs.mkdirSync(directoryName);
+                    }
+                },
+                getExecutingFilePath: function () {
+                    return __filename;
+                },
+                getCurrentDirectory: function () {
+                    return process.cwd();
+                },
+                readDirectory: readDirectory,
+                getMemoryUsage: function () {
+                    if (global.gc) {
+                        global.gc();
+                    }
+                    return process.memoryUsage().heapUsed;
+                },
+                exit: function (exitCode) {
+                    process.exit(exitCode);
+                }
+            };
+        }
+        if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
+            return getWScriptSystem();
+        }
+        else if (typeof module !== "undefined" && module.exports) {
+            return getNodeSystem();
+        }
+        else {
+            return undefined;
+        }
+    })();
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/tsc.js b/dist/typescript/compiler/tsc.js
new file mode 100644
index 000000000..543206ec0
--- /dev/null
+++ b/dist/typescript/compiler/tsc.js
@@ -0,0 +1,365 @@
+/// <reference path="program.ts"/>
+/// <reference path="commandLineParser.ts"/>
+var ts;
+(function (ts) {
+    function validateLocaleAndSetLanguage(locale, errors) {
+        var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase());
+        if (!matchResult) {
+            errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, 'en', 'ja-jp'));
+            return false;
+        }
+        var language = matchResult[1];
+        var territory = matchResult[3];
+        if (!trySetLanguageAndTerritory(language, territory, errors) &&
+            !trySetLanguageAndTerritory(language, undefined, errors)) {
+            errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_locale_0, locale));
+            return false;
+        }
+        return true;
+    }
+    function trySetLanguageAndTerritory(language, territory, errors) {
+        var compilerFilePath = ts.normalizePath(ts.sys.getExecutingFilePath());
+        var containingDirectoryPath = ts.getDirectoryPath(compilerFilePath);
+        var filePath = ts.combinePaths(containingDirectoryPath, language);
+        if (territory) {
+            filePath = filePath + "-" + territory;
+        }
+        filePath = ts.sys.resolvePath(ts.combinePaths(filePath, "diagnosticMessages.generated.json"));
+        if (!ts.sys.fileExists(filePath)) {
+            return false;
+        }
+        try {
+            var fileContents = ts.sys.readFile(filePath);
+        }
+        catch (e) {
+            errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unable_to_open_file_0, filePath));
+            return false;
+        }
+        try {
+            ts.localizedDiagnosticMessages = JSON.parse(fileContents);
+        }
+        catch (e) {
+            errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Corrupted_locale_file_0, filePath));
+            return false;
+        }
+        return true;
+    }
+    function countLines(program) {
+        var count = 0;
+        ts.forEach(program.getSourceFiles(), function (file) {
+            count += ts.getLineStarts(file).length;
+        });
+        return count;
+    }
+    function getDiagnosticText(message) {
+        var args = [];
+        for (var _i = 1; _i < arguments.length; _i++) {
+            args[_i - 1] = arguments[_i];
+        }
+        var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments);
+        return diagnostic.messageText;
+    }
+    function reportDiagnostic(diagnostic) {
+        var output = "";
+        if (diagnostic.file) {
+            var loc = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
+            output += diagnostic.file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + "): ";
+        }
+        var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase();
+        output += category + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine;
+        ts.sys.write(output);
+    }
+    function reportDiagnostics(diagnostics) {
+        for (var i = 0; i < diagnostics.length; i++) {
+            reportDiagnostic(diagnostics[i]);
+        }
+    }
+    function padLeft(s, length) {
+        while (s.length < length) {
+            s = " " + s;
+        }
+        return s;
+    }
+    function padRight(s, length) {
+        while (s.length < length) {
+            s = s + " ";
+        }
+        return s;
+    }
+    function reportStatisticalValue(name, value) {
+        ts.sys.write(padRight(name + ":", 12) + padLeft(value.toString(), 10) + ts.sys.newLine);
+    }
+    function reportCountStatistic(name, count) {
+        reportStatisticalValue(name, "" + count);
+    }
+    function reportTimeStatistic(name, time) {
+        reportStatisticalValue(name, (time / 1000).toFixed(2) + "s");
+    }
+    function isJSONSupported() {
+        return typeof JSON === "object" && typeof JSON.parse === "function";
+    }
+    function executeCommandLine(args) {
+        var commandLine = ts.parseCommandLine(args);
+        var configFileName;
+        var configFileWatcher;
+        var cachedProgram;
+        var rootFileNames;
+        var compilerOptions;
+        var compilerHost;
+        var hostGetSourceFile;
+        var timerHandle;
+        if (commandLine.options.locale) {
+            if (!isJSONSupported()) {
+                reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
+                return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
+            }
+            validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
+        }
+        if (commandLine.errors.length > 0) {
+            reportDiagnostics(commandLine.errors);
+            return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
+        }
+        if (commandLine.options.version) {
+            reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Version_0, ts.version));
+            return ts.sys.exit(ts.ExitStatus.Success);
+        }
+        if (commandLine.options.help) {
+            printVersion();
+            printHelp();
+            return ts.sys.exit(ts.ExitStatus.Success);
+        }
+        if (commandLine.options.project) {
+            if (!isJSONSupported()) {
+                reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--project"));
+                return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
+            }
+            configFileName = ts.normalizePath(ts.combinePaths(commandLine.options.project, "tsconfig.json"));
+            if (commandLine.fileNames.length !== 0) {
+                reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
+                return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
+            }
+        }
+        else if (commandLine.fileNames.length === 0 && isJSONSupported()) {
+            var searchPath = ts.normalizePath(ts.sys.getCurrentDirectory());
+            configFileName = ts.findConfigFile(searchPath);
+        }
+        if (commandLine.fileNames.length === 0 && !configFileName) {
+            printVersion();
+            printHelp();
+            return ts.sys.exit(ts.ExitStatus.Success);
+        }
+        if (commandLine.options.watch) {
+            if (!ts.sys.watchFile) {
+                reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
+                return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
+            }
+            if (configFileName) {
+                configFileWatcher = ts.sys.watchFile(configFileName, configFileChanged);
+            }
+        }
+        performCompilation();
+        function performCompilation() {
+            if (!cachedProgram) {
+                if (configFileName) {
+                    var result = ts.readConfigFile(configFileName);
+                    if (result.error) {
+                        reportDiagnostic(result.error);
+                        return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
+                    }
+                    var configObject = result.config;
+                    var configParseResult = ts.parseConfigFile(configObject, ts.sys, ts.getDirectoryPath(configFileName));
+                    if (configParseResult.errors.length > 0) {
+                        reportDiagnostics(configParseResult.errors);
+                        return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
+                    }
+                    rootFileNames = configParseResult.fileNames;
+                    compilerOptions = ts.extend(commandLine.options, configParseResult.options);
+                }
+                else {
+                    rootFileNames = commandLine.fileNames;
+                    compilerOptions = commandLine.options;
+                }
+                compilerHost = ts.createCompilerHost(compilerOptions);
+                hostGetSourceFile = compilerHost.getSourceFile;
+                compilerHost.getSourceFile = getSourceFile;
+            }
+            var compileResult = compile(rootFileNames, compilerOptions, compilerHost);
+            if (!compilerOptions.watch) {
+                return ts.sys.exit(compileResult.exitStatus);
+            }
+            setCachedProgram(compileResult.program);
+            reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Compilation_complete_Watching_for_file_changes));
+        }
+        function getSourceFile(fileName, languageVersion, onError) {
+            if (cachedProgram) {
+                var sourceFile = cachedProgram.getSourceFile(fileName);
+                if (sourceFile && sourceFile.fileWatcher) {
+                    return sourceFile;
+                }
+            }
+            var sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
+            if (sourceFile && compilerOptions.watch) {
+                sourceFile.fileWatcher = ts.sys.watchFile(sourceFile.fileName, function () { return sourceFileChanged(sourceFile); });
+            }
+            return sourceFile;
+        }
+        function setCachedProgram(program) {
+            if (cachedProgram) {
+                var newSourceFiles = program ? program.getSourceFiles() : undefined;
+                ts.forEach(cachedProgram.getSourceFiles(), function (sourceFile) {
+                    if (!(newSourceFiles && ts.contains(newSourceFiles, sourceFile))) {
+                        if (sourceFile.fileWatcher) {
+                            sourceFile.fileWatcher.close();
+                            sourceFile.fileWatcher = undefined;
+                        }
+                    }
+                });
+            }
+            cachedProgram = program;
+        }
+        function sourceFileChanged(sourceFile) {
+            sourceFile.fileWatcher.close();
+            sourceFile.fileWatcher = undefined;
+            startTimer();
+        }
+        function configFileChanged() {
+            setCachedProgram(undefined);
+            startTimer();
+        }
+        function startTimer() {
+            if (timerHandle) {
+                clearTimeout(timerHandle);
+            }
+            timerHandle = setTimeout(recompile, 250);
+        }
+        function recompile() {
+            timerHandle = undefined;
+            reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation));
+            performCompilation();
+        }
+    }
+    ts.executeCommandLine = executeCommandLine;
+    function compile(fileNames, compilerOptions, compilerHost) {
+        ts.ioReadTime = 0;
+        ts.ioWriteTime = 0;
+        ts.programTime = 0;
+        ts.bindTime = 0;
+        ts.checkTime = 0;
+        ts.emitTime = 0;
+        var program = ts.createProgram(fileNames, compilerOptions, compilerHost);
+        var exitStatus = compileProgram();
+        if (compilerOptions.listFiles) {
+            ts.forEach(program.getSourceFiles(), function (file) {
+                ts.sys.write(file.fileName + ts.sys.newLine);
+            });
+        }
+        if (compilerOptions.diagnostics) {
+            var memoryUsed = ts.sys.getMemoryUsage ? ts.sys.getMemoryUsage() : -1;
+            reportCountStatistic("Files", program.getSourceFiles().length);
+            reportCountStatistic("Lines", countLines(program));
+            reportCountStatistic("Nodes", program.getNodeCount());
+            reportCountStatistic("Identifiers", program.getIdentifierCount());
+            reportCountStatistic("Symbols", program.getSymbolCount());
+            reportCountStatistic("Types", program.getTypeCount());
+            if (memoryUsed >= 0) {
+                reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K");
+            }
+            reportTimeStatistic("I/O read", ts.ioReadTime);
+            reportTimeStatistic("I/O write", ts.ioWriteTime);
+            reportTimeStatistic("Parse time", ts.programTime);
+            reportTimeStatistic("Bind time", ts.bindTime);
+            reportTimeStatistic("Check time", ts.checkTime);
+            reportTimeStatistic("Emit time", ts.emitTime);
+            reportTimeStatistic("Total time", ts.programTime + ts.bindTime + ts.checkTime + ts.emitTime);
+        }
+        return { program: program, exitStatus: exitStatus };
+        function compileProgram() {
+            var diagnostics = program.getSyntacticDiagnostics();
+            reportDiagnostics(diagnostics);
+            if (diagnostics.length === 0) {
+                var diagnostics = program.getGlobalDiagnostics();
+                reportDiagnostics(diagnostics);
+                if (diagnostics.length === 0) {
+                    var diagnostics = program.getSemanticDiagnostics();
+                    reportDiagnostics(diagnostics);
+                }
+            }
+            if (compilerOptions.noEmit) {
+                return diagnostics.length
+                    ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped
+                    : ts.ExitStatus.Success;
+            }
+            var emitOutput = program.emit();
+            reportDiagnostics(emitOutput.diagnostics);
+            if (emitOutput.emitSkipped) {
+                return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped;
+            }
+            if (diagnostics.length > 0 || emitOutput.diagnostics.length > 0) {
+                return ts.ExitStatus.DiagnosticsPresent_OutputsGenerated;
+            }
+            return ts.ExitStatus.Success;
+        }
+    }
+    function printVersion() {
+        ts.sys.write(getDiagnosticText(ts.Diagnostics.Version_0, ts.version) + ts.sys.newLine);
+    }
+    function printHelp() {
+        var output = "";
+        var syntaxLength = getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, "").length;
+        var examplesLength = getDiagnosticText(ts.Diagnostics.Examples_Colon_0, "").length;
+        var marginLength = Math.max(syntaxLength, examplesLength);
+        var syntax = makePadding(marginLength - syntaxLength);
+        syntax += "tsc [" + getDiagnosticText(ts.Diagnostics.options) + "] [" + getDiagnosticText(ts.Diagnostics.file) + " ...]";
+        output += getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, syntax);
+        output += ts.sys.newLine + ts.sys.newLine;
+        var padding = makePadding(marginLength);
+        output += getDiagnosticText(ts.Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + ts.sys.newLine;
+        output += padding + "tsc --out file.js file.ts" + ts.sys.newLine;
+        output += padding + "tsc @args.txt" + ts.sys.newLine;
+        output += ts.sys.newLine;
+        output += getDiagnosticText(ts.Diagnostics.Options_Colon) + ts.sys.newLine;
+        var optsList = ts.filter(ts.optionDeclarations.slice(), function (v) { return !v.experimental; });
+        optsList.sort(function (a, b) { return ts.compareValues(a.name.toLowerCase(), b.name.toLowerCase()); });
+        var marginLength = 0;
+        var usageColumn = [];
+        var descriptionColumn = [];
+        for (var i = 0; i < optsList.length; i++) {
+            var option = optsList[i];
+            if (!option.description) {
+                continue;
+            }
+            var usageText = " ";
+            if (option.shortName) {
+                usageText += "-" + option.shortName;
+                usageText += getParamType(option);
+                usageText += ", ";
+            }
+            usageText += "--" + option.name;
+            usageText += getParamType(option);
+            usageColumn.push(usageText);
+            descriptionColumn.push(getDiagnosticText(option.description));
+            marginLength = Math.max(usageText.length, marginLength);
+        }
+        var usageText = " @<" + getDiagnosticText(ts.Diagnostics.file) + ">";
+        usageColumn.push(usageText);
+        descriptionColumn.push(getDiagnosticText(ts.Diagnostics.Insert_command_line_options_and_files_from_a_file));
+        marginLength = Math.max(usageText.length, marginLength);
+        for (var i = 0; i < usageColumn.length; i++) {
+            var usage = usageColumn[i];
+            var description = descriptionColumn[i];
+            output += usage + makePadding(marginLength - usage.length + 2) + description + ts.sys.newLine;
+        }
+        ts.sys.write(output);
+        return;
+        function getParamType(option) {
+            if (option.paramType !== undefined) {
+                return " " + getDiagnosticText(option.paramType);
+            }
+            return "";
+        }
+        function makePadding(paddingLength) {
+            return Array(paddingLength + 1).join(" ");
+        }
+    }
+})(ts || (ts = {}));
+ts.executeCommandLine(ts.sys.args);
diff --git a/dist/typescript/compiler/types.js b/dist/typescript/compiler/types.js
new file mode 100644
index 000000000..dbcc11b11
--- /dev/null
+++ b/dist/typescript/compiler/types.js
@@ -0,0 +1,596 @@
+var ts;
+(function (ts) {
+    (function (SyntaxKind) {
+        SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown";
+        SyntaxKind[SyntaxKind["EndOfFileToken"] = 1] = "EndOfFileToken";
+        SyntaxKind[SyntaxKind["SingleLineCommentTrivia"] = 2] = "SingleLineCommentTrivia";
+        SyntaxKind[SyntaxKind["MultiLineCommentTrivia"] = 3] = "MultiLineCommentTrivia";
+        SyntaxKind[SyntaxKind["NewLineTrivia"] = 4] = "NewLineTrivia";
+        SyntaxKind[SyntaxKind["WhitespaceTrivia"] = 5] = "WhitespaceTrivia";
+        SyntaxKind[SyntaxKind["ConflictMarkerTrivia"] = 6] = "ConflictMarkerTrivia";
+        SyntaxKind[SyntaxKind["NumericLiteral"] = 7] = "NumericLiteral";
+        SyntaxKind[SyntaxKind["StringLiteral"] = 8] = "StringLiteral";
+        SyntaxKind[SyntaxKind["RegularExpressionLiteral"] = 9] = "RegularExpressionLiteral";
+        SyntaxKind[SyntaxKind["NoSubstitutionTemplateLiteral"] = 10] = "NoSubstitutionTemplateLiteral";
+        SyntaxKind[SyntaxKind["TemplateHead"] = 11] = "TemplateHead";
+        SyntaxKind[SyntaxKind["TemplateMiddle"] = 12] = "TemplateMiddle";
+        SyntaxKind[SyntaxKind["TemplateTail"] = 13] = "TemplateTail";
+        SyntaxKind[SyntaxKind["OpenBraceToken"] = 14] = "OpenBraceToken";
+        SyntaxKind[SyntaxKind["CloseBraceToken"] = 15] = "CloseBraceToken";
+        SyntaxKind[SyntaxKind["OpenParenToken"] = 16] = "OpenParenToken";
+        SyntaxKind[SyntaxKind["CloseParenToken"] = 17] = "CloseParenToken";
+        SyntaxKind[SyntaxKind["OpenBracketToken"] = 18] = "OpenBracketToken";
+        SyntaxKind[SyntaxKind["CloseBracketToken"] = 19] = "CloseBracketToken";
+        SyntaxKind[SyntaxKind["DotToken"] = 20] = "DotToken";
+        SyntaxKind[SyntaxKind["DotDotDotToken"] = 21] = "DotDotDotToken";
+        SyntaxKind[SyntaxKind["SemicolonToken"] = 22] = "SemicolonToken";
+        SyntaxKind[SyntaxKind["CommaToken"] = 23] = "CommaToken";
+        SyntaxKind[SyntaxKind["LessThanToken"] = 24] = "LessThanToken";
+        SyntaxKind[SyntaxKind["GreaterThanToken"] = 25] = "GreaterThanToken";
+        SyntaxKind[SyntaxKind["LessThanEqualsToken"] = 26] = "LessThanEqualsToken";
+        SyntaxKind[SyntaxKind["GreaterThanEqualsToken"] = 27] = "GreaterThanEqualsToken";
+        SyntaxKind[SyntaxKind["EqualsEqualsToken"] = 28] = "EqualsEqualsToken";
+        SyntaxKind[SyntaxKind["ExclamationEqualsToken"] = 29] = "ExclamationEqualsToken";
+        SyntaxKind[SyntaxKind["EqualsEqualsEqualsToken"] = 30] = "EqualsEqualsEqualsToken";
+        SyntaxKind[SyntaxKind["ExclamationEqualsEqualsToken"] = 31] = "ExclamationEqualsEqualsToken";
+        SyntaxKind[SyntaxKind["EqualsGreaterThanToken"] = 32] = "EqualsGreaterThanToken";
+        SyntaxKind[SyntaxKind["PlusToken"] = 33] = "PlusToken";
+        SyntaxKind[SyntaxKind["MinusToken"] = 34] = "MinusToken";
+        SyntaxKind[SyntaxKind["AsteriskToken"] = 35] = "AsteriskToken";
+        SyntaxKind[SyntaxKind["SlashToken"] = 36] = "SlashToken";
+        SyntaxKind[SyntaxKind["PercentToken"] = 37] = "PercentToken";
+        SyntaxKind[SyntaxKind["PlusPlusToken"] = 38] = "PlusPlusToken";
+        SyntaxKind[SyntaxKind["MinusMinusToken"] = 39] = "MinusMinusToken";
+        SyntaxKind[SyntaxKind["LessThanLessThanToken"] = 40] = "LessThanLessThanToken";
+        SyntaxKind[SyntaxKind["GreaterThanGreaterThanToken"] = 41] = "GreaterThanGreaterThanToken";
+        SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanToken"] = 42] = "GreaterThanGreaterThanGreaterThanToken";
+        SyntaxKind[SyntaxKind["AmpersandToken"] = 43] = "AmpersandToken";
+        SyntaxKind[SyntaxKind["BarToken"] = 44] = "BarToken";
+        SyntaxKind[SyntaxKind["CaretToken"] = 45] = "CaretToken";
+        SyntaxKind[SyntaxKind["ExclamationToken"] = 46] = "ExclamationToken";
+        SyntaxKind[SyntaxKind["TildeToken"] = 47] = "TildeToken";
+        SyntaxKind[SyntaxKind["AmpersandAmpersandToken"] = 48] = "AmpersandAmpersandToken";
+        SyntaxKind[SyntaxKind["BarBarToken"] = 49] = "BarBarToken";
+        SyntaxKind[SyntaxKind["QuestionToken"] = 50] = "QuestionToken";
+        SyntaxKind[SyntaxKind["ColonToken"] = 51] = "ColonToken";
+        SyntaxKind[SyntaxKind["AtToken"] = 52] = "AtToken";
+        SyntaxKind[SyntaxKind["EqualsToken"] = 53] = "EqualsToken";
+        SyntaxKind[SyntaxKind["PlusEqualsToken"] = 54] = "PlusEqualsToken";
+        SyntaxKind[SyntaxKind["MinusEqualsToken"] = 55] = "MinusEqualsToken";
+        SyntaxKind[SyntaxKind["AsteriskEqualsToken"] = 56] = "AsteriskEqualsToken";
+        SyntaxKind[SyntaxKind["SlashEqualsToken"] = 57] = "SlashEqualsToken";
+        SyntaxKind[SyntaxKind["PercentEqualsToken"] = 58] = "PercentEqualsToken";
+        SyntaxKind[SyntaxKind["LessThanLessThanEqualsToken"] = 59] = "LessThanLessThanEqualsToken";
+        SyntaxKind[SyntaxKind["GreaterThanGreaterThanEqualsToken"] = 60] = "GreaterThanGreaterThanEqualsToken";
+        SyntaxKind[SyntaxKind["GreaterThanGreaterThanGreaterThanEqualsToken"] = 61] = "GreaterThanGreaterThanGreaterThanEqualsToken";
+        SyntaxKind[SyntaxKind["AmpersandEqualsToken"] = 62] = "AmpersandEqualsToken";
+        SyntaxKind[SyntaxKind["BarEqualsToken"] = 63] = "BarEqualsToken";
+        SyntaxKind[SyntaxKind["CaretEqualsToken"] = 64] = "CaretEqualsToken";
+        SyntaxKind[SyntaxKind["Identifier"] = 65] = "Identifier";
+        SyntaxKind[SyntaxKind["BreakKeyword"] = 66] = "BreakKeyword";
+        SyntaxKind[SyntaxKind["CaseKeyword"] = 67] = "CaseKeyword";
+        SyntaxKind[SyntaxKind["CatchKeyword"] = 68] = "CatchKeyword";
+        SyntaxKind[SyntaxKind["ClassKeyword"] = 69] = "ClassKeyword";
+        SyntaxKind[SyntaxKind["ConstKeyword"] = 70] = "ConstKeyword";
+        SyntaxKind[SyntaxKind["ContinueKeyword"] = 71] = "ContinueKeyword";
+        SyntaxKind[SyntaxKind["DebuggerKeyword"] = 72] = "DebuggerKeyword";
+        SyntaxKind[SyntaxKind["DefaultKeyword"] = 73] = "DefaultKeyword";
+        SyntaxKind[SyntaxKind["DeleteKeyword"] = 74] = "DeleteKeyword";
+        SyntaxKind[SyntaxKind["DoKeyword"] = 75] = "DoKeyword";
+        SyntaxKind[SyntaxKind["ElseKeyword"] = 76] = "ElseKeyword";
+        SyntaxKind[SyntaxKind["EnumKeyword"] = 77] = "EnumKeyword";
+        SyntaxKind[SyntaxKind["ExportKeyword"] = 78] = "ExportKeyword";
+        SyntaxKind[SyntaxKind["ExtendsKeyword"] = 79] = "ExtendsKeyword";
+        SyntaxKind[SyntaxKind["FalseKeyword"] = 80] = "FalseKeyword";
+        SyntaxKind[SyntaxKind["FinallyKeyword"] = 81] = "FinallyKeyword";
+        SyntaxKind[SyntaxKind["ForKeyword"] = 82] = "ForKeyword";
+        SyntaxKind[SyntaxKind["FunctionKeyword"] = 83] = "FunctionKeyword";
+        SyntaxKind[SyntaxKind["IfKeyword"] = 84] = "IfKeyword";
+        SyntaxKind[SyntaxKind["ImportKeyword"] = 85] = "ImportKeyword";
+        SyntaxKind[SyntaxKind["InKeyword"] = 86] = "InKeyword";
+        SyntaxKind[SyntaxKind["InstanceOfKeyword"] = 87] = "InstanceOfKeyword";
+        SyntaxKind[SyntaxKind["NewKeyword"] = 88] = "NewKeyword";
+        SyntaxKind[SyntaxKind["NullKeyword"] = 89] = "NullKeyword";
+        SyntaxKind[SyntaxKind["ReturnKeyword"] = 90] = "ReturnKeyword";
+        SyntaxKind[SyntaxKind["SuperKeyword"] = 91] = "SuperKeyword";
+        SyntaxKind[SyntaxKind["SwitchKeyword"] = 92] = "SwitchKeyword";
+        SyntaxKind[SyntaxKind["ThisKeyword"] = 93] = "ThisKeyword";
+        SyntaxKind[SyntaxKind["ThrowKeyword"] = 94] = "ThrowKeyword";
+        SyntaxKind[SyntaxKind["TrueKeyword"] = 95] = "TrueKeyword";
+        SyntaxKind[SyntaxKind["TryKeyword"] = 96] = "TryKeyword";
+        SyntaxKind[SyntaxKind["TypeOfKeyword"] = 97] = "TypeOfKeyword";
+        SyntaxKind[SyntaxKind["VarKeyword"] = 98] = "VarKeyword";
+        SyntaxKind[SyntaxKind["VoidKeyword"] = 99] = "VoidKeyword";
+        SyntaxKind[SyntaxKind["WhileKeyword"] = 100] = "WhileKeyword";
+        SyntaxKind[SyntaxKind["WithKeyword"] = 101] = "WithKeyword";
+        SyntaxKind[SyntaxKind["ImplementsKeyword"] = 102] = "ImplementsKeyword";
+        SyntaxKind[SyntaxKind["InterfaceKeyword"] = 103] = "InterfaceKeyword";
+        SyntaxKind[SyntaxKind["LetKeyword"] = 104] = "LetKeyword";
+        SyntaxKind[SyntaxKind["PackageKeyword"] = 105] = "PackageKeyword";
+        SyntaxKind[SyntaxKind["PrivateKeyword"] = 106] = "PrivateKeyword";
+        SyntaxKind[SyntaxKind["ProtectedKeyword"] = 107] = "ProtectedKeyword";
+        SyntaxKind[SyntaxKind["PublicKeyword"] = 108] = "PublicKeyword";
+        SyntaxKind[SyntaxKind["StaticKeyword"] = 109] = "StaticKeyword";
+        SyntaxKind[SyntaxKind["YieldKeyword"] = 110] = "YieldKeyword";
+        SyntaxKind[SyntaxKind["AsKeyword"] = 111] = "AsKeyword";
+        SyntaxKind[SyntaxKind["AnyKeyword"] = 112] = "AnyKeyword";
+        SyntaxKind[SyntaxKind["BooleanKeyword"] = 113] = "BooleanKeyword";
+        SyntaxKind[SyntaxKind["ConstructorKeyword"] = 114] = "ConstructorKeyword";
+        SyntaxKind[SyntaxKind["DeclareKeyword"] = 115] = "DeclareKeyword";
+        SyntaxKind[SyntaxKind["GetKeyword"] = 116] = "GetKeyword";
+        SyntaxKind[SyntaxKind["ModuleKeyword"] = 117] = "ModuleKeyword";
+        SyntaxKind[SyntaxKind["RequireKeyword"] = 118] = "RequireKeyword";
+        SyntaxKind[SyntaxKind["NumberKeyword"] = 119] = "NumberKeyword";
+        SyntaxKind[SyntaxKind["SetKeyword"] = 120] = "SetKeyword";
+        SyntaxKind[SyntaxKind["StringKeyword"] = 121] = "StringKeyword";
+        SyntaxKind[SyntaxKind["SymbolKeyword"] = 122] = "SymbolKeyword";
+        SyntaxKind[SyntaxKind["TypeKeyword"] = 123] = "TypeKeyword";
+        SyntaxKind[SyntaxKind["FromKeyword"] = 124] = "FromKeyword";
+        SyntaxKind[SyntaxKind["OfKeyword"] = 125] = "OfKeyword";
+        SyntaxKind[SyntaxKind["QualifiedName"] = 126] = "QualifiedName";
+        SyntaxKind[SyntaxKind["ComputedPropertyName"] = 127] = "ComputedPropertyName";
+        SyntaxKind[SyntaxKind["TypeParameter"] = 128] = "TypeParameter";
+        SyntaxKind[SyntaxKind["Parameter"] = 129] = "Parameter";
+        SyntaxKind[SyntaxKind["Decorator"] = 130] = "Decorator";
+        SyntaxKind[SyntaxKind["PropertySignature"] = 131] = "PropertySignature";
+        SyntaxKind[SyntaxKind["PropertyDeclaration"] = 132] = "PropertyDeclaration";
+        SyntaxKind[SyntaxKind["MethodSignature"] = 133] = "MethodSignature";
+        SyntaxKind[SyntaxKind["MethodDeclaration"] = 134] = "MethodDeclaration";
+        SyntaxKind[SyntaxKind["Constructor"] = 135] = "Constructor";
+        SyntaxKind[SyntaxKind["GetAccessor"] = 136] = "GetAccessor";
+        SyntaxKind[SyntaxKind["SetAccessor"] = 137] = "SetAccessor";
+        SyntaxKind[SyntaxKind["CallSignature"] = 138] = "CallSignature";
+        SyntaxKind[SyntaxKind["ConstructSignature"] = 139] = "ConstructSignature";
+        SyntaxKind[SyntaxKind["IndexSignature"] = 140] = "IndexSignature";
+        SyntaxKind[SyntaxKind["TypeReference"] = 141] = "TypeReference";
+        SyntaxKind[SyntaxKind["FunctionType"] = 142] = "FunctionType";
+        SyntaxKind[SyntaxKind["ConstructorType"] = 143] = "ConstructorType";
+        SyntaxKind[SyntaxKind["TypeQuery"] = 144] = "TypeQuery";
+        SyntaxKind[SyntaxKind["TypeLiteral"] = 145] = "TypeLiteral";
+        SyntaxKind[SyntaxKind["ArrayType"] = 146] = "ArrayType";
+        SyntaxKind[SyntaxKind["TupleType"] = 147] = "TupleType";
+        SyntaxKind[SyntaxKind["UnionType"] = 148] = "UnionType";
+        SyntaxKind[SyntaxKind["ParenthesizedType"] = 149] = "ParenthesizedType";
+        SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 150] = "ObjectBindingPattern";
+        SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 151] = "ArrayBindingPattern";
+        SyntaxKind[SyntaxKind["BindingElement"] = 152] = "BindingElement";
+        SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 153] = "ArrayLiteralExpression";
+        SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 154] = "ObjectLiteralExpression";
+        SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 155] = "PropertyAccessExpression";
+        SyntaxKind[SyntaxKind["ElementAccessExpression"] = 156] = "ElementAccessExpression";
+        SyntaxKind[SyntaxKind["CallExpression"] = 157] = "CallExpression";
+        SyntaxKind[SyntaxKind["NewExpression"] = 158] = "NewExpression";
+        SyntaxKind[SyntaxKind["TaggedTemplateExpression"] = 159] = "TaggedTemplateExpression";
+        SyntaxKind[SyntaxKind["TypeAssertionExpression"] = 160] = "TypeAssertionExpression";
+        SyntaxKind[SyntaxKind["ParenthesizedExpression"] = 161] = "ParenthesizedExpression";
+        SyntaxKind[SyntaxKind["FunctionExpression"] = 162] = "FunctionExpression";
+        SyntaxKind[SyntaxKind["ArrowFunction"] = 163] = "ArrowFunction";
+        SyntaxKind[SyntaxKind["DeleteExpression"] = 164] = "DeleteExpression";
+        SyntaxKind[SyntaxKind["TypeOfExpression"] = 165] = "TypeOfExpression";
+        SyntaxKind[SyntaxKind["VoidExpression"] = 166] = "VoidExpression";
+        SyntaxKind[SyntaxKind["PrefixUnaryExpression"] = 167] = "PrefixUnaryExpression";
+        SyntaxKind[SyntaxKind["PostfixUnaryExpression"] = 168] = "PostfixUnaryExpression";
+        SyntaxKind[SyntaxKind["BinaryExpression"] = 169] = "BinaryExpression";
+        SyntaxKind[SyntaxKind["ConditionalExpression"] = 170] = "ConditionalExpression";
+        SyntaxKind[SyntaxKind["TemplateExpression"] = 171] = "TemplateExpression";
+        SyntaxKind[SyntaxKind["YieldExpression"] = 172] = "YieldExpression";
+        SyntaxKind[SyntaxKind["SpreadElementExpression"] = 173] = "SpreadElementExpression";
+        SyntaxKind[SyntaxKind["ClassExpression"] = 174] = "ClassExpression";
+        SyntaxKind[SyntaxKind["OmittedExpression"] = 175] = "OmittedExpression";
+        SyntaxKind[SyntaxKind["TemplateSpan"] = 176] = "TemplateSpan";
+        SyntaxKind[SyntaxKind["HeritageClauseElement"] = 177] = "HeritageClauseElement";
+        SyntaxKind[SyntaxKind["SemicolonClassElement"] = 178] = "SemicolonClassElement";
+        SyntaxKind[SyntaxKind["Block"] = 179] = "Block";
+        SyntaxKind[SyntaxKind["VariableStatement"] = 180] = "VariableStatement";
+        SyntaxKind[SyntaxKind["EmptyStatement"] = 181] = "EmptyStatement";
+        SyntaxKind[SyntaxKind["ExpressionStatement"] = 182] = "ExpressionStatement";
+        SyntaxKind[SyntaxKind["IfStatement"] = 183] = "IfStatement";
+        SyntaxKind[SyntaxKind["DoStatement"] = 184] = "DoStatement";
+        SyntaxKind[SyntaxKind["WhileStatement"] = 185] = "WhileStatement";
+        SyntaxKind[SyntaxKind["ForStatement"] = 186] = "ForStatement";
+        SyntaxKind[SyntaxKind["ForInStatement"] = 187] = "ForInStatement";
+        SyntaxKind[SyntaxKind["ForOfStatement"] = 188] = "ForOfStatement";
+        SyntaxKind[SyntaxKind["ContinueStatement"] = 189] = "ContinueStatement";
+        SyntaxKind[SyntaxKind["BreakStatement"] = 190] = "BreakStatement";
+        SyntaxKind[SyntaxKind["ReturnStatement"] = 191] = "ReturnStatement";
+        SyntaxKind[SyntaxKind["WithStatement"] = 192] = "WithStatement";
+        SyntaxKind[SyntaxKind["SwitchStatement"] = 193] = "SwitchStatement";
+        SyntaxKind[SyntaxKind["LabeledStatement"] = 194] = "LabeledStatement";
+        SyntaxKind[SyntaxKind["ThrowStatement"] = 195] = "ThrowStatement";
+        SyntaxKind[SyntaxKind["TryStatement"] = 196] = "TryStatement";
+        SyntaxKind[SyntaxKind["DebuggerStatement"] = 197] = "DebuggerStatement";
+        SyntaxKind[SyntaxKind["VariableDeclaration"] = 198] = "VariableDeclaration";
+        SyntaxKind[SyntaxKind["VariableDeclarationList"] = 199] = "VariableDeclarationList";
+        SyntaxKind[SyntaxKind["FunctionDeclaration"] = 200] = "FunctionDeclaration";
+        SyntaxKind[SyntaxKind["ClassDeclaration"] = 201] = "ClassDeclaration";
+        SyntaxKind[SyntaxKind["InterfaceDeclaration"] = 202] = "InterfaceDeclaration";
+        SyntaxKind[SyntaxKind["TypeAliasDeclaration"] = 203] = "TypeAliasDeclaration";
+        SyntaxKind[SyntaxKind["EnumDeclaration"] = 204] = "EnumDeclaration";
+        SyntaxKind[SyntaxKind["ModuleDeclaration"] = 205] = "ModuleDeclaration";
+        SyntaxKind[SyntaxKind["ModuleBlock"] = 206] = "ModuleBlock";
+        SyntaxKind[SyntaxKind["CaseBlock"] = 207] = "CaseBlock";
+        SyntaxKind[SyntaxKind["ImportEqualsDeclaration"] = 208] = "ImportEqualsDeclaration";
+        SyntaxKind[SyntaxKind["ImportDeclaration"] = 209] = "ImportDeclaration";
+        SyntaxKind[SyntaxKind["ImportClause"] = 210] = "ImportClause";
+        SyntaxKind[SyntaxKind["NamespaceImport"] = 211] = "NamespaceImport";
+        SyntaxKind[SyntaxKind["NamedImports"] = 212] = "NamedImports";
+        SyntaxKind[SyntaxKind["ImportSpecifier"] = 213] = "ImportSpecifier";
+        SyntaxKind[SyntaxKind["ExportAssignment"] = 214] = "ExportAssignment";
+        SyntaxKind[SyntaxKind["ExportDeclaration"] = 215] = "ExportDeclaration";
+        SyntaxKind[SyntaxKind["NamedExports"] = 216] = "NamedExports";
+        SyntaxKind[SyntaxKind["ExportSpecifier"] = 217] = "ExportSpecifier";
+        SyntaxKind[SyntaxKind["MissingDeclaration"] = 218] = "MissingDeclaration";
+        SyntaxKind[SyntaxKind["ExternalModuleReference"] = 219] = "ExternalModuleReference";
+        SyntaxKind[SyntaxKind["CaseClause"] = 220] = "CaseClause";
+        SyntaxKind[SyntaxKind["DefaultClause"] = 221] = "DefaultClause";
+        SyntaxKind[SyntaxKind["HeritageClause"] = 222] = "HeritageClause";
+        SyntaxKind[SyntaxKind["CatchClause"] = 223] = "CatchClause";
+        SyntaxKind[SyntaxKind["PropertyAssignment"] = 224] = "PropertyAssignment";
+        SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 225] = "ShorthandPropertyAssignment";
+        SyntaxKind[SyntaxKind["EnumMember"] = 226] = "EnumMember";
+        SyntaxKind[SyntaxKind["SourceFile"] = 227] = "SourceFile";
+        SyntaxKind[SyntaxKind["SyntaxList"] = 228] = "SyntaxList";
+        SyntaxKind[SyntaxKind["Count"] = 229] = "Count";
+        SyntaxKind[SyntaxKind["FirstAssignment"] = 53] = "FirstAssignment";
+        SyntaxKind[SyntaxKind["LastAssignment"] = 64] = "LastAssignment";
+        SyntaxKind[SyntaxKind["FirstReservedWord"] = 66] = "FirstReservedWord";
+        SyntaxKind[SyntaxKind["LastReservedWord"] = 101] = "LastReservedWord";
+        SyntaxKind[SyntaxKind["FirstKeyword"] = 66] = "FirstKeyword";
+        SyntaxKind[SyntaxKind["LastKeyword"] = 125] = "LastKeyword";
+        SyntaxKind[SyntaxKind["FirstFutureReservedWord"] = 102] = "FirstFutureReservedWord";
+        SyntaxKind[SyntaxKind["LastFutureReservedWord"] = 110] = "LastFutureReservedWord";
+        SyntaxKind[SyntaxKind["FirstTypeNode"] = 141] = "FirstTypeNode";
+        SyntaxKind[SyntaxKind["LastTypeNode"] = 149] = "LastTypeNode";
+        SyntaxKind[SyntaxKind["FirstPunctuation"] = 14] = "FirstPunctuation";
+        SyntaxKind[SyntaxKind["LastPunctuation"] = 64] = "LastPunctuation";
+        SyntaxKind[SyntaxKind["FirstToken"] = 0] = "FirstToken";
+        SyntaxKind[SyntaxKind["LastToken"] = 125] = "LastToken";
+        SyntaxKind[SyntaxKind["FirstTriviaToken"] = 2] = "FirstTriviaToken";
+        SyntaxKind[SyntaxKind["LastTriviaToken"] = 6] = "LastTriviaToken";
+        SyntaxKind[SyntaxKind["FirstLiteralToken"] = 7] = "FirstLiteralToken";
+        SyntaxKind[SyntaxKind["LastLiteralToken"] = 10] = "LastLiteralToken";
+        SyntaxKind[SyntaxKind["FirstTemplateToken"] = 10] = "FirstTemplateToken";
+        SyntaxKind[SyntaxKind["LastTemplateToken"] = 13] = "LastTemplateToken";
+        SyntaxKind[SyntaxKind["FirstBinaryOperator"] = 24] = "FirstBinaryOperator";
+        SyntaxKind[SyntaxKind["LastBinaryOperator"] = 64] = "LastBinaryOperator";
+        SyntaxKind[SyntaxKind["FirstNode"] = 126] = "FirstNode";
+    })(ts.SyntaxKind || (ts.SyntaxKind = {}));
+    var SyntaxKind = ts.SyntaxKind;
+    (function (NodeFlags) {
+        NodeFlags[NodeFlags["Export"] = 1] = "Export";
+        NodeFlags[NodeFlags["Ambient"] = 2] = "Ambient";
+        NodeFlags[NodeFlags["Public"] = 16] = "Public";
+        NodeFlags[NodeFlags["Private"] = 32] = "Private";
+        NodeFlags[NodeFlags["Protected"] = 64] = "Protected";
+        NodeFlags[NodeFlags["Static"] = 128] = "Static";
+        NodeFlags[NodeFlags["Default"] = 256] = "Default";
+        NodeFlags[NodeFlags["MultiLine"] = 512] = "MultiLine";
+        NodeFlags[NodeFlags["Synthetic"] = 1024] = "Synthetic";
+        NodeFlags[NodeFlags["DeclarationFile"] = 2048] = "DeclarationFile";
+        NodeFlags[NodeFlags["Let"] = 4096] = "Let";
+        NodeFlags[NodeFlags["Const"] = 8192] = "Const";
+        NodeFlags[NodeFlags["OctalLiteral"] = 16384] = "OctalLiteral";
+        NodeFlags[NodeFlags["ExportContext"] = 32768] = "ExportContext";
+        NodeFlags[NodeFlags["Modifier"] = 499] = "Modifier";
+        NodeFlags[NodeFlags["AccessibilityModifier"] = 112] = "AccessibilityModifier";
+        NodeFlags[NodeFlags["BlockScoped"] = 12288] = "BlockScoped";
+    })(ts.NodeFlags || (ts.NodeFlags = {}));
+    var NodeFlags = ts.NodeFlags;
+    (function (ParserContextFlags) {
+        ParserContextFlags[ParserContextFlags["StrictMode"] = 1] = "StrictMode";
+        ParserContextFlags[ParserContextFlags["DisallowIn"] = 2] = "DisallowIn";
+        ParserContextFlags[ParserContextFlags["Yield"] = 4] = "Yield";
+        ParserContextFlags[ParserContextFlags["GeneratorParameter"] = 8] = "GeneratorParameter";
+        ParserContextFlags[ParserContextFlags["Decorator"] = 16] = "Decorator";
+        ParserContextFlags[ParserContextFlags["ThisNodeHasError"] = 32] = "ThisNodeHasError";
+        ParserContextFlags[ParserContextFlags["ParserGeneratedFlags"] = 63] = "ParserGeneratedFlags";
+        ParserContextFlags[ParserContextFlags["ThisNodeOrAnySubNodesHasError"] = 64] = "ThisNodeOrAnySubNodesHasError";
+        ParserContextFlags[ParserContextFlags["HasAggregatedChildData"] = 128] = "HasAggregatedChildData";
+    })(ts.ParserContextFlags || (ts.ParserContextFlags = {}));
+    var ParserContextFlags = ts.ParserContextFlags;
+    (function (RelationComparisonResult) {
+        RelationComparisonResult[RelationComparisonResult["Succeeded"] = 1] = "Succeeded";
+        RelationComparisonResult[RelationComparisonResult["Failed"] = 2] = "Failed";
+        RelationComparisonResult[RelationComparisonResult["FailedAndReported"] = 3] = "FailedAndReported";
+    })(ts.RelationComparisonResult || (ts.RelationComparisonResult = {}));
+    var RelationComparisonResult = ts.RelationComparisonResult;
+    (function (ExitStatus) {
+        ExitStatus[ExitStatus["Success"] = 0] = "Success";
+        ExitStatus[ExitStatus["DiagnosticsPresent_OutputsSkipped"] = 1] = "DiagnosticsPresent_OutputsSkipped";
+        ExitStatus[ExitStatus["DiagnosticsPresent_OutputsGenerated"] = 2] = "DiagnosticsPresent_OutputsGenerated";
+    })(ts.ExitStatus || (ts.ExitStatus = {}));
+    var ExitStatus = ts.ExitStatus;
+    (function (TypeFormatFlags) {
+        TypeFormatFlags[TypeFormatFlags["None"] = 0] = "None";
+        TypeFormatFlags[TypeFormatFlags["WriteArrayAsGenericType"] = 1] = "WriteArrayAsGenericType";
+        TypeFormatFlags[TypeFormatFlags["UseTypeOfFunction"] = 2] = "UseTypeOfFunction";
+        TypeFormatFlags[TypeFormatFlags["NoTruncation"] = 4] = "NoTruncation";
+        TypeFormatFlags[TypeFormatFlags["WriteArrowStyleSignature"] = 8] = "WriteArrowStyleSignature";
+        TypeFormatFlags[TypeFormatFlags["WriteOwnNameForAnyLike"] = 16] = "WriteOwnNameForAnyLike";
+        TypeFormatFlags[TypeFormatFlags["WriteTypeArgumentsOfSignature"] = 32] = "WriteTypeArgumentsOfSignature";
+        TypeFormatFlags[TypeFormatFlags["InElementType"] = 64] = "InElementType";
+        TypeFormatFlags[TypeFormatFlags["UseFullyQualifiedType"] = 128] = "UseFullyQualifiedType";
+    })(ts.TypeFormatFlags || (ts.TypeFormatFlags = {}));
+    var TypeFormatFlags = ts.TypeFormatFlags;
+    (function (SymbolFormatFlags) {
+        SymbolFormatFlags[SymbolFormatFlags["None"] = 0] = "None";
+        SymbolFormatFlags[SymbolFormatFlags["WriteTypeParametersOrArguments"] = 1] = "WriteTypeParametersOrArguments";
+        SymbolFormatFlags[SymbolFormatFlags["UseOnlyExternalAliasing"] = 2] = "UseOnlyExternalAliasing";
+    })(ts.SymbolFormatFlags || (ts.SymbolFormatFlags = {}));
+    var SymbolFormatFlags = ts.SymbolFormatFlags;
+    (function (SymbolAccessibility) {
+        SymbolAccessibility[SymbolAccessibility["Accessible"] = 0] = "Accessible";
+        SymbolAccessibility[SymbolAccessibility["NotAccessible"] = 1] = "NotAccessible";
+        SymbolAccessibility[SymbolAccessibility["CannotBeNamed"] = 2] = "CannotBeNamed";
+    })(ts.SymbolAccessibility || (ts.SymbolAccessibility = {}));
+    var SymbolAccessibility = ts.SymbolAccessibility;
+    (function (SymbolFlags) {
+        SymbolFlags[SymbolFlags["FunctionScopedVariable"] = 1] = "FunctionScopedVariable";
+        SymbolFlags[SymbolFlags["BlockScopedVariable"] = 2] = "BlockScopedVariable";
+        SymbolFlags[SymbolFlags["Property"] = 4] = "Property";
+        SymbolFlags[SymbolFlags["EnumMember"] = 8] = "EnumMember";
+        SymbolFlags[SymbolFlags["Function"] = 16] = "Function";
+        SymbolFlags[SymbolFlags["Class"] = 32] = "Class";
+        SymbolFlags[SymbolFlags["Interface"] = 64] = "Interface";
+        SymbolFlags[SymbolFlags["ConstEnum"] = 128] = "ConstEnum";
+        SymbolFlags[SymbolFlags["RegularEnum"] = 256] = "RegularEnum";
+        SymbolFlags[SymbolFlags["ValueModule"] = 512] = "ValueModule";
+        SymbolFlags[SymbolFlags["NamespaceModule"] = 1024] = "NamespaceModule";
+        SymbolFlags[SymbolFlags["TypeLiteral"] = 2048] = "TypeLiteral";
+        SymbolFlags[SymbolFlags["ObjectLiteral"] = 4096] = "ObjectLiteral";
+        SymbolFlags[SymbolFlags["Method"] = 8192] = "Method";
+        SymbolFlags[SymbolFlags["Constructor"] = 16384] = "Constructor";
+        SymbolFlags[SymbolFlags["GetAccessor"] = 32768] = "GetAccessor";
+        SymbolFlags[SymbolFlags["SetAccessor"] = 65536] = "SetAccessor";
+        SymbolFlags[SymbolFlags["Signature"] = 131072] = "Signature";
+        SymbolFlags[SymbolFlags["TypeParameter"] = 262144] = "TypeParameter";
+        SymbolFlags[SymbolFlags["TypeAlias"] = 524288] = "TypeAlias";
+        SymbolFlags[SymbolFlags["ExportValue"] = 1048576] = "ExportValue";
+        SymbolFlags[SymbolFlags["ExportType"] = 2097152] = "ExportType";
+        SymbolFlags[SymbolFlags["ExportNamespace"] = 4194304] = "ExportNamespace";
+        SymbolFlags[SymbolFlags["Alias"] = 8388608] = "Alias";
+        SymbolFlags[SymbolFlags["Instantiated"] = 16777216] = "Instantiated";
+        SymbolFlags[SymbolFlags["Merged"] = 33554432] = "Merged";
+        SymbolFlags[SymbolFlags["Transient"] = 67108864] = "Transient";
+        SymbolFlags[SymbolFlags["Prototype"] = 134217728] = "Prototype";
+        SymbolFlags[SymbolFlags["UnionProperty"] = 268435456] = "UnionProperty";
+        SymbolFlags[SymbolFlags["Optional"] = 536870912] = "Optional";
+        SymbolFlags[SymbolFlags["ExportStar"] = 1073741824] = "ExportStar";
+        SymbolFlags[SymbolFlags["Enum"] = 384] = "Enum";
+        SymbolFlags[SymbolFlags["Variable"] = 3] = "Variable";
+        SymbolFlags[SymbolFlags["Value"] = 107455] = "Value";
+        SymbolFlags[SymbolFlags["Type"] = 793056] = "Type";
+        SymbolFlags[SymbolFlags["Namespace"] = 1536] = "Namespace";
+        SymbolFlags[SymbolFlags["Module"] = 1536] = "Module";
+        SymbolFlags[SymbolFlags["Accessor"] = 98304] = "Accessor";
+        SymbolFlags[SymbolFlags["FunctionScopedVariableExcludes"] = 107454] = "FunctionScopedVariableExcludes";
+        SymbolFlags[SymbolFlags["BlockScopedVariableExcludes"] = 107455] = "BlockScopedVariableExcludes";
+        SymbolFlags[SymbolFlags["ParameterExcludes"] = 107455] = "ParameterExcludes";
+        SymbolFlags[SymbolFlags["PropertyExcludes"] = 107455] = "PropertyExcludes";
+        SymbolFlags[SymbolFlags["EnumMemberExcludes"] = 107455] = "EnumMemberExcludes";
+        SymbolFlags[SymbolFlags["FunctionExcludes"] = 106927] = "FunctionExcludes";
+        SymbolFlags[SymbolFlags["ClassExcludes"] = 899583] = "ClassExcludes";
+        SymbolFlags[SymbolFlags["InterfaceExcludes"] = 792992] = "InterfaceExcludes";
+        SymbolFlags[SymbolFlags["RegularEnumExcludes"] = 899327] = "RegularEnumExcludes";
+        SymbolFlags[SymbolFlags["ConstEnumExcludes"] = 899967] = "ConstEnumExcludes";
+        SymbolFlags[SymbolFlags["ValueModuleExcludes"] = 106639] = "ValueModuleExcludes";
+        SymbolFlags[SymbolFlags["NamespaceModuleExcludes"] = 0] = "NamespaceModuleExcludes";
+        SymbolFlags[SymbolFlags["MethodExcludes"] = 99263] = "MethodExcludes";
+        SymbolFlags[SymbolFlags["GetAccessorExcludes"] = 41919] = "GetAccessorExcludes";
+        SymbolFlags[SymbolFlags["SetAccessorExcludes"] = 74687] = "SetAccessorExcludes";
+        SymbolFlags[SymbolFlags["TypeParameterExcludes"] = 530912] = "TypeParameterExcludes";
+        SymbolFlags[SymbolFlags["TypeAliasExcludes"] = 793056] = "TypeAliasExcludes";
+        SymbolFlags[SymbolFlags["AliasExcludes"] = 8388608] = "AliasExcludes";
+        SymbolFlags[SymbolFlags["ModuleMember"] = 8914931] = "ModuleMember";
+        SymbolFlags[SymbolFlags["ExportHasLocal"] = 944] = "ExportHasLocal";
+        SymbolFlags[SymbolFlags["HasLocals"] = 255504] = "HasLocals";
+        SymbolFlags[SymbolFlags["HasExports"] = 1952] = "HasExports";
+        SymbolFlags[SymbolFlags["HasMembers"] = 6240] = "HasMembers";
+        SymbolFlags[SymbolFlags["IsContainer"] = 262128] = "IsContainer";
+        SymbolFlags[SymbolFlags["PropertyOrAccessor"] = 98308] = "PropertyOrAccessor";
+        SymbolFlags[SymbolFlags["Export"] = 7340032] = "Export";
+    })(ts.SymbolFlags || (ts.SymbolFlags = {}));
+    var SymbolFlags = ts.SymbolFlags;
+    (function (NodeCheckFlags) {
+        NodeCheckFlags[NodeCheckFlags["TypeChecked"] = 1] = "TypeChecked";
+        NodeCheckFlags[NodeCheckFlags["LexicalThis"] = 2] = "LexicalThis";
+        NodeCheckFlags[NodeCheckFlags["CaptureThis"] = 4] = "CaptureThis";
+        NodeCheckFlags[NodeCheckFlags["EmitExtends"] = 8] = "EmitExtends";
+        NodeCheckFlags[NodeCheckFlags["SuperInstance"] = 16] = "SuperInstance";
+        NodeCheckFlags[NodeCheckFlags["SuperStatic"] = 32] = "SuperStatic";
+        NodeCheckFlags[NodeCheckFlags["ContextChecked"] = 64] = "ContextChecked";
+        NodeCheckFlags[NodeCheckFlags["EnumValuesComputed"] = 128] = "EnumValuesComputed";
+        NodeCheckFlags[NodeCheckFlags["BlockScopedBindingInLoop"] = 256] = "BlockScopedBindingInLoop";
+        NodeCheckFlags[NodeCheckFlags["EmitDecorate"] = 512] = "EmitDecorate";
+        NodeCheckFlags[NodeCheckFlags["EmitParam"] = 1024] = "EmitParam";
+        NodeCheckFlags[NodeCheckFlags["LexicalModuleMergesWithClass"] = 2048] = "LexicalModuleMergesWithClass";
+    })(ts.NodeCheckFlags || (ts.NodeCheckFlags = {}));
+    var NodeCheckFlags = ts.NodeCheckFlags;
+    (function (TypeFlags) {
+        TypeFlags[TypeFlags["Any"] = 1] = "Any";
+        TypeFlags[TypeFlags["String"] = 2] = "String";
+        TypeFlags[TypeFlags["Number"] = 4] = "Number";
+        TypeFlags[TypeFlags["Boolean"] = 8] = "Boolean";
+        TypeFlags[TypeFlags["Void"] = 16] = "Void";
+        TypeFlags[TypeFlags["Undefined"] = 32] = "Undefined";
+        TypeFlags[TypeFlags["Null"] = 64] = "Null";
+        TypeFlags[TypeFlags["Enum"] = 128] = "Enum";
+        TypeFlags[TypeFlags["StringLiteral"] = 256] = "StringLiteral";
+        TypeFlags[TypeFlags["TypeParameter"] = 512] = "TypeParameter";
+        TypeFlags[TypeFlags["Class"] = 1024] = "Class";
+        TypeFlags[TypeFlags["Interface"] = 2048] = "Interface";
+        TypeFlags[TypeFlags["Reference"] = 4096] = "Reference";
+        TypeFlags[TypeFlags["Tuple"] = 8192] = "Tuple";
+        TypeFlags[TypeFlags["Union"] = 16384] = "Union";
+        TypeFlags[TypeFlags["Anonymous"] = 32768] = "Anonymous";
+        TypeFlags[TypeFlags["FromSignature"] = 65536] = "FromSignature";
+        TypeFlags[TypeFlags["ObjectLiteral"] = 131072] = "ObjectLiteral";
+        TypeFlags[TypeFlags["ContainsUndefinedOrNull"] = 262144] = "ContainsUndefinedOrNull";
+        TypeFlags[TypeFlags["ContainsObjectLiteral"] = 524288] = "ContainsObjectLiteral";
+        TypeFlags[TypeFlags["ESSymbol"] = 1048576] = "ESSymbol";
+        TypeFlags[TypeFlags["Intrinsic"] = 1048703] = "Intrinsic";
+        TypeFlags[TypeFlags["Primitive"] = 1049086] = "Primitive";
+        TypeFlags[TypeFlags["StringLike"] = 258] = "StringLike";
+        TypeFlags[TypeFlags["NumberLike"] = 132] = "NumberLike";
+        TypeFlags[TypeFlags["ObjectType"] = 48128] = "ObjectType";
+        TypeFlags[TypeFlags["RequiresWidening"] = 786432] = "RequiresWidening";
+    })(ts.TypeFlags || (ts.TypeFlags = {}));
+    var TypeFlags = ts.TypeFlags;
+    (function (SignatureKind) {
+        SignatureKind[SignatureKind["Call"] = 0] = "Call";
+        SignatureKind[SignatureKind["Construct"] = 1] = "Construct";
+    })(ts.SignatureKind || (ts.SignatureKind = {}));
+    var SignatureKind = ts.SignatureKind;
+    (function (IndexKind) {
+        IndexKind[IndexKind["String"] = 0] = "String";
+        IndexKind[IndexKind["Number"] = 1] = "Number";
+    })(ts.IndexKind || (ts.IndexKind = {}));
+    var IndexKind = ts.IndexKind;
+    (function (DiagnosticCategory) {
+        DiagnosticCategory[DiagnosticCategory["Warning"] = 0] = "Warning";
+        DiagnosticCategory[DiagnosticCategory["Error"] = 1] = "Error";
+        DiagnosticCategory[DiagnosticCategory["Message"] = 2] = "Message";
+    })(ts.DiagnosticCategory || (ts.DiagnosticCategory = {}));
+    var DiagnosticCategory = ts.DiagnosticCategory;
+    (function (ModuleKind) {
+        ModuleKind[ModuleKind["None"] = 0] = "None";
+        ModuleKind[ModuleKind["CommonJS"] = 1] = "CommonJS";
+        ModuleKind[ModuleKind["AMD"] = 2] = "AMD";
+        ModuleKind[ModuleKind["UMD"] = 3] = "UMD";
+    })(ts.ModuleKind || (ts.ModuleKind = {}));
+    var ModuleKind = ts.ModuleKind;
+    (function (ScriptTarget) {
+        ScriptTarget[ScriptTarget["ES3"] = 0] = "ES3";
+        ScriptTarget[ScriptTarget["ES5"] = 1] = "ES5";
+        ScriptTarget[ScriptTarget["ES6"] = 2] = "ES6";
+        ScriptTarget[ScriptTarget["Latest"] = 2] = "Latest";
+    })(ts.ScriptTarget || (ts.ScriptTarget = {}));
+    var ScriptTarget = ts.ScriptTarget;
+    (function (CharacterCodes) {
+        CharacterCodes[CharacterCodes["nullCharacter"] = 0] = "nullCharacter";
+        CharacterCodes[CharacterCodes["maxAsciiCharacter"] = 127] = "maxAsciiCharacter";
+        CharacterCodes[CharacterCodes["lineFeed"] = 10] = "lineFeed";
+        CharacterCodes[CharacterCodes["carriageReturn"] = 13] = "carriageReturn";
+        CharacterCodes[CharacterCodes["lineSeparator"] = 8232] = "lineSeparator";
+        CharacterCodes[CharacterCodes["paragraphSeparator"] = 8233] = "paragraphSeparator";
+        CharacterCodes[CharacterCodes["nextLine"] = 133] = "nextLine";
+        CharacterCodes[CharacterCodes["space"] = 32] = "space";
+        CharacterCodes[CharacterCodes["nonBreakingSpace"] = 160] = "nonBreakingSpace";
+        CharacterCodes[CharacterCodes["enQuad"] = 8192] = "enQuad";
+        CharacterCodes[CharacterCodes["emQuad"] = 8193] = "emQuad";
+        CharacterCodes[CharacterCodes["enSpace"] = 8194] = "enSpace";
+        CharacterCodes[CharacterCodes["emSpace"] = 8195] = "emSpace";
+        CharacterCodes[CharacterCodes["threePerEmSpace"] = 8196] = "threePerEmSpace";
+        CharacterCodes[CharacterCodes["fourPerEmSpace"] = 8197] = "fourPerEmSpace";
+        CharacterCodes[CharacterCodes["sixPerEmSpace"] = 8198] = "sixPerEmSpace";
+        CharacterCodes[CharacterCodes["figureSpace"] = 8199] = "figureSpace";
+        CharacterCodes[CharacterCodes["punctuationSpace"] = 8200] = "punctuationSpace";
+        CharacterCodes[CharacterCodes["thinSpace"] = 8201] = "thinSpace";
+        CharacterCodes[CharacterCodes["hairSpace"] = 8202] = "hairSpace";
+        CharacterCodes[CharacterCodes["zeroWidthSpace"] = 8203] = "zeroWidthSpace";
+        CharacterCodes[CharacterCodes["narrowNoBreakSpace"] = 8239] = "narrowNoBreakSpace";
+        CharacterCodes[CharacterCodes["ideographicSpace"] = 12288] = "ideographicSpace";
+        CharacterCodes[CharacterCodes["mathematicalSpace"] = 8287] = "mathematicalSpace";
+        CharacterCodes[CharacterCodes["ogham"] = 5760] = "ogham";
+        CharacterCodes[CharacterCodes["_"] = 95] = "_";
+        CharacterCodes[CharacterCodes["$"] = 36] = "$";
+        CharacterCodes[CharacterCodes["_0"] = 48] = "_0";
+        CharacterCodes[CharacterCodes["_1"] = 49] = "_1";
+        CharacterCodes[CharacterCodes["_2"] = 50] = "_2";
+        CharacterCodes[CharacterCodes["_3"] = 51] = "_3";
+        CharacterCodes[CharacterCodes["_4"] = 52] = "_4";
+        CharacterCodes[CharacterCodes["_5"] = 53] = "_5";
+        CharacterCodes[CharacterCodes["_6"] = 54] = "_6";
+        CharacterCodes[CharacterCodes["_7"] = 55] = "_7";
+        CharacterCodes[CharacterCodes["_8"] = 56] = "_8";
+        CharacterCodes[CharacterCodes["_9"] = 57] = "_9";
+        CharacterCodes[CharacterCodes["a"] = 97] = "a";
+        CharacterCodes[CharacterCodes["b"] = 98] = "b";
+        CharacterCodes[CharacterCodes["c"] = 99] = "c";
+        CharacterCodes[CharacterCodes["d"] = 100] = "d";
+        CharacterCodes[CharacterCodes["e"] = 101] = "e";
+        CharacterCodes[CharacterCodes["f"] = 102] = "f";
+        CharacterCodes[CharacterCodes["g"] = 103] = "g";
+        CharacterCodes[CharacterCodes["h"] = 104] = "h";
+        CharacterCodes[CharacterCodes["i"] = 105] = "i";
+        CharacterCodes[CharacterCodes["j"] = 106] = "j";
+        CharacterCodes[CharacterCodes["k"] = 107] = "k";
+        CharacterCodes[CharacterCodes["l"] = 108] = "l";
+        CharacterCodes[CharacterCodes["m"] = 109] = "m";
+        CharacterCodes[CharacterCodes["n"] = 110] = "n";
+        CharacterCodes[CharacterCodes["o"] = 111] = "o";
+        CharacterCodes[CharacterCodes["p"] = 112] = "p";
+        CharacterCodes[CharacterCodes["q"] = 113] = "q";
+        CharacterCodes[CharacterCodes["r"] = 114] = "r";
+        CharacterCodes[CharacterCodes["s"] = 115] = "s";
+        CharacterCodes[CharacterCodes["t"] = 116] = "t";
+        CharacterCodes[CharacterCodes["u"] = 117] = "u";
+        CharacterCodes[CharacterCodes["v"] = 118] = "v";
+        CharacterCodes[CharacterCodes["w"] = 119] = "w";
+        CharacterCodes[CharacterCodes["x"] = 120] = "x";
+        CharacterCodes[CharacterCodes["y"] = 121] = "y";
+        CharacterCodes[CharacterCodes["z"] = 122] = "z";
+        CharacterCodes[CharacterCodes["A"] = 65] = "A";
+        CharacterCodes[CharacterCodes["B"] = 66] = "B";
+        CharacterCodes[CharacterCodes["C"] = 67] = "C";
+        CharacterCodes[CharacterCodes["D"] = 68] = "D";
+        CharacterCodes[CharacterCodes["E"] = 69] = "E";
+        CharacterCodes[CharacterCodes["F"] = 70] = "F";
+        CharacterCodes[CharacterCodes["G"] = 71] = "G";
+        CharacterCodes[CharacterCodes["H"] = 72] = "H";
+        CharacterCodes[CharacterCodes["I"] = 73] = "I";
+        CharacterCodes[CharacterCodes["J"] = 74] = "J";
+        CharacterCodes[CharacterCodes["K"] = 75] = "K";
+        CharacterCodes[CharacterCodes["L"] = 76] = "L";
+        CharacterCodes[CharacterCodes["M"] = 77] = "M";
+        CharacterCodes[CharacterCodes["N"] = 78] = "N";
+        CharacterCodes[CharacterCodes["O"] = 79] = "O";
+        CharacterCodes[CharacterCodes["P"] = 80] = "P";
+        CharacterCodes[CharacterCodes["Q"] = 81] = "Q";
+        CharacterCodes[CharacterCodes["R"] = 82] = "R";
+        CharacterCodes[CharacterCodes["S"] = 83] = "S";
+        CharacterCodes[CharacterCodes["T"] = 84] = "T";
+        CharacterCodes[CharacterCodes["U"] = 85] = "U";
+        CharacterCodes[CharacterCodes["V"] = 86] = "V";
+        CharacterCodes[CharacterCodes["W"] = 87] = "W";
+        CharacterCodes[CharacterCodes["X"] = 88] = "X";
+        CharacterCodes[CharacterCodes["Y"] = 89] = "Y";
+        CharacterCodes[CharacterCodes["Z"] = 90] = "Z";
+        CharacterCodes[CharacterCodes["ampersand"] = 38] = "ampersand";
+        CharacterCodes[CharacterCodes["asterisk"] = 42] = "asterisk";
+        CharacterCodes[CharacterCodes["at"] = 64] = "at";
+        CharacterCodes[CharacterCodes["backslash"] = 92] = "backslash";
+        CharacterCodes[CharacterCodes["backtick"] = 96] = "backtick";
+        CharacterCodes[CharacterCodes["bar"] = 124] = "bar";
+        CharacterCodes[CharacterCodes["caret"] = 94] = "caret";
+        CharacterCodes[CharacterCodes["closeBrace"] = 125] = "closeBrace";
+        CharacterCodes[CharacterCodes["closeBracket"] = 93] = "closeBracket";
+        CharacterCodes[CharacterCodes["closeParen"] = 41] = "closeParen";
+        CharacterCodes[CharacterCodes["colon"] = 58] = "colon";
+        CharacterCodes[CharacterCodes["comma"] = 44] = "comma";
+        CharacterCodes[CharacterCodes["dot"] = 46] = "dot";
+        CharacterCodes[CharacterCodes["doubleQuote"] = 34] = "doubleQuote";
+        CharacterCodes[CharacterCodes["equals"] = 61] = "equals";
+        CharacterCodes[CharacterCodes["exclamation"] = 33] = "exclamation";
+        CharacterCodes[CharacterCodes["greaterThan"] = 62] = "greaterThan";
+        CharacterCodes[CharacterCodes["hash"] = 35] = "hash";
+        CharacterCodes[CharacterCodes["lessThan"] = 60] = "lessThan";
+        CharacterCodes[CharacterCodes["minus"] = 45] = "minus";
+        CharacterCodes[CharacterCodes["openBrace"] = 123] = "openBrace";
+        CharacterCodes[CharacterCodes["openBracket"] = 91] = "openBracket";
+        CharacterCodes[CharacterCodes["openParen"] = 40] = "openParen";
+        CharacterCodes[CharacterCodes["percent"] = 37] = "percent";
+        CharacterCodes[CharacterCodes["plus"] = 43] = "plus";
+        CharacterCodes[CharacterCodes["question"] = 63] = "question";
+        CharacterCodes[CharacterCodes["semicolon"] = 59] = "semicolon";
+        CharacterCodes[CharacterCodes["singleQuote"] = 39] = "singleQuote";
+        CharacterCodes[CharacterCodes["slash"] = 47] = "slash";
+        CharacterCodes[CharacterCodes["tilde"] = 126] = "tilde";
+        CharacterCodes[CharacterCodes["backspace"] = 8] = "backspace";
+        CharacterCodes[CharacterCodes["formFeed"] = 12] = "formFeed";
+        CharacterCodes[CharacterCodes["byteOrderMark"] = 65279] = "byteOrderMark";
+        CharacterCodes[CharacterCodes["tab"] = 9] = "tab";
+        CharacterCodes[CharacterCodes["verticalTab"] = 11] = "verticalTab";
+    })(ts.CharacterCodes || (ts.CharacterCodes = {}));
+    var CharacterCodes = ts.CharacterCodes;
+})(ts || (ts = {}));
diff --git a/dist/typescript/compiler/utilities.js b/dist/typescript/compiler/utilities.js
new file mode 100644
index 000000000..e532c25a3
--- /dev/null
+++ b/dist/typescript/compiler/utilities.js
@@ -0,0 +1,1523 @@
+/// <reference path="binder.ts" />
+var ts;
+(function (ts) {
+    function getDeclarationOfKind(symbol, kind) {
+        var declarations = symbol.declarations;
+        for (var _i = 0; _i < declarations.length; _i++) {
+            var declaration = declarations[_i];
+            if (declaration.kind === kind) {
+                return declaration;
+            }
+        }
+        return undefined;
+    }
+    ts.getDeclarationOfKind = getDeclarationOfKind;
+    var stringWriters = [];
+    function getSingleLineStringWriter() {
+        if (stringWriters.length == 0) {
+            var str = "";
+            var writeText = function (text) { return str += text; };
+            return {
+                string: function () { return str; },
+                writeKeyword: writeText,
+                writeOperator: writeText,
+                writePunctuation: writeText,
+                writeSpace: writeText,
+                writeStringLiteral: writeText,
+                writeParameter: writeText,
+                writeSymbol: writeText,
+                writeLine: function () { return str += " "; },
+                increaseIndent: function () { },
+                decreaseIndent: function () { },
+                clear: function () { return str = ""; },
+                trackSymbol: function () { }
+            };
+        }
+        return stringWriters.pop();
+    }
+    ts.getSingleLineStringWriter = getSingleLineStringWriter;
+    function releaseStringWriter(writer) {
+        writer.clear();
+        stringWriters.push(writer);
+    }
+    ts.releaseStringWriter = releaseStringWriter;
+    function getFullWidth(node) {
+        return node.end - node.pos;
+    }
+    ts.getFullWidth = getFullWidth;
+    function containsParseError(node) {
+        aggregateChildData(node);
+        return (node.parserContextFlags & 64) !== 0;
+    }
+    ts.containsParseError = containsParseError;
+    function aggregateChildData(node) {
+        if (!(node.parserContextFlags & 128)) {
+            var thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & 32) !== 0) ||
+                ts.forEachChild(node, containsParseError);
+            if (thisNodeOrAnySubNodesHasError) {
+                node.parserContextFlags |= 64;
+            }
+            node.parserContextFlags |= 128;
+        }
+    }
+    function getSourceFileOfNode(node) {
+        while (node && node.kind !== 227) {
+            node = node.parent;
+        }
+        return node;
+    }
+    ts.getSourceFileOfNode = getSourceFileOfNode;
+    function getStartPositionOfLine(line, sourceFile) {
+        ts.Debug.assert(line >= 0);
+        return ts.getLineStarts(sourceFile)[line];
+    }
+    ts.getStartPositionOfLine = getStartPositionOfLine;
+    function nodePosToString(node) {
+        var file = getSourceFileOfNode(node);
+        var loc = ts.getLineAndCharacterOfPosition(file, node.pos);
+        return file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + ")";
+    }
+    ts.nodePosToString = nodePosToString;
+    function getStartPosOfNode(node) {
+        return node.pos;
+    }
+    ts.getStartPosOfNode = getStartPosOfNode;
+    function nodeIsMissing(node) {
+        if (!node) {
+            return true;
+        }
+        return node.pos === node.end && node.kind !== 1;
+    }
+    ts.nodeIsMissing = nodeIsMissing;
+    function nodeIsPresent(node) {
+        return !nodeIsMissing(node);
+    }
+    ts.nodeIsPresent = nodeIsPresent;
+    function getTokenPosOfNode(node, sourceFile) {
+        if (nodeIsMissing(node)) {
+            return node.pos;
+        }
+        return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
+    }
+    ts.getTokenPosOfNode = getTokenPosOfNode;
+    function getNonDecoratorTokenPosOfNode(node, sourceFile) {
+        if (nodeIsMissing(node) || !node.decorators) {
+            return getTokenPosOfNode(node, sourceFile);
+        }
+        return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.decorators.end);
+    }
+    ts.getNonDecoratorTokenPosOfNode = getNonDecoratorTokenPosOfNode;
+    function getSourceTextOfNodeFromSourceFile(sourceFile, node) {
+        if (nodeIsMissing(node)) {
+            return "";
+        }
+        var text = sourceFile.text;
+        return text.substring(ts.skipTrivia(text, node.pos), node.end);
+    }
+    ts.getSourceTextOfNodeFromSourceFile = getSourceTextOfNodeFromSourceFile;
+    function getTextOfNodeFromSourceText(sourceText, node) {
+        if (nodeIsMissing(node)) {
+            return "";
+        }
+        return sourceText.substring(ts.skipTrivia(sourceText, node.pos), node.end);
+    }
+    ts.getTextOfNodeFromSourceText = getTextOfNodeFromSourceText;
+    function getTextOfNode(node) {
+        return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node);
+    }
+    ts.getTextOfNode = getTextOfNode;
+    function escapeIdentifier(identifier) {
+        return identifier.length >= 2 && identifier.charCodeAt(0) === 95 && identifier.charCodeAt(1) === 95 ? "_" + identifier : identifier;
+    }
+    ts.escapeIdentifier = escapeIdentifier;
+    function unescapeIdentifier(identifier) {
+        return identifier.length >= 3 && identifier.charCodeAt(0) === 95 && identifier.charCodeAt(1) === 95 && identifier.charCodeAt(2) === 95 ? identifier.substr(1) : identifier;
+    }
+    ts.unescapeIdentifier = unescapeIdentifier;
+    function makeIdentifierFromModuleName(moduleName) {
+        return ts.getBaseFileName(moduleName).replace(/\W/g, "_");
+    }
+    ts.makeIdentifierFromModuleName = makeIdentifierFromModuleName;
+    function isBlockOrCatchScoped(declaration) {
+        return (getCombinedNodeFlags(declaration) & 12288) !== 0 ||
+            isCatchClauseVariableDeclaration(declaration);
+    }
+    ts.isBlockOrCatchScoped = isBlockOrCatchScoped;
+    function getEnclosingBlockScopeContainer(node) {
+        var current = node.parent;
+        while (current) {
+            if (isFunctionLike(current)) {
+                return current;
+            }
+            switch (current.kind) {
+                case 227:
+                case 207:
+                case 223:
+                case 205:
+                case 186:
+                case 187:
+                case 188:
+                    return current;
+                case 179:
+                    if (!isFunctionLike(current.parent)) {
+                        return current;
+                    }
+            }
+            current = current.parent;
+        }
+    }
+    ts.getEnclosingBlockScopeContainer = getEnclosingBlockScopeContainer;
+    function isCatchClauseVariableDeclaration(declaration) {
+        return declaration &&
+            declaration.kind === 198 &&
+            declaration.parent &&
+            declaration.parent.kind === 223;
+    }
+    ts.isCatchClauseVariableDeclaration = isCatchClauseVariableDeclaration;
+    function declarationNameToString(name) {
+        return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
+    }
+    ts.declarationNameToString = declarationNameToString;
+    function createDiagnosticForNode(node, message, arg0, arg1, arg2) {
+        var sourceFile = getSourceFileOfNode(node);
+        var span = getErrorSpanForNode(sourceFile, node);
+        return ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2);
+    }
+    ts.createDiagnosticForNode = createDiagnosticForNode;
+    function createDiagnosticForNodeFromMessageChain(node, messageChain) {
+        var sourceFile = getSourceFileOfNode(node);
+        var span = getErrorSpanForNode(sourceFile, node);
+        return {
+            file: sourceFile,
+            start: span.start,
+            length: span.length,
+            code: messageChain.code,
+            category: messageChain.category,
+            messageText: messageChain.next ? messageChain : messageChain.messageText
+        };
+    }
+    ts.createDiagnosticForNodeFromMessageChain = createDiagnosticForNodeFromMessageChain;
+    function getSpanOfTokenAtPosition(sourceFile, pos) {
+        var scanner = ts.createScanner(sourceFile.languageVersion, true, sourceFile.text, undefined, pos);
+        scanner.scan();
+        var start = scanner.getTokenPos();
+        return ts.createTextSpanFromBounds(start, scanner.getTextPos());
+    }
+    ts.getSpanOfTokenAtPosition = getSpanOfTokenAtPosition;
+    function getErrorSpanForNode(sourceFile, node) {
+        var errorNode = node;
+        switch (node.kind) {
+            case 227:
+                var pos_1 = ts.skipTrivia(sourceFile.text, 0, false);
+                if (pos_1 === sourceFile.text.length) {
+                    return ts.createTextSpan(0, 0);
+                }
+                return getSpanOfTokenAtPosition(sourceFile, pos_1);
+            case 198:
+            case 152:
+            case 201:
+            case 174:
+            case 202:
+            case 205:
+            case 204:
+            case 226:
+            case 200:
+            case 162:
+                errorNode = node.name;
+                break;
+        }
+        if (errorNode === undefined) {
+            return getSpanOfTokenAtPosition(sourceFile, node.pos);
+        }
+        var pos = nodeIsMissing(errorNode)
+            ? errorNode.pos
+            : ts.skipTrivia(sourceFile.text, errorNode.pos);
+        return ts.createTextSpanFromBounds(pos, errorNode.end);
+    }
+    ts.getErrorSpanForNode = getErrorSpanForNode;
+    function isExternalModule(file) {
+        return file.externalModuleIndicator !== undefined;
+    }
+    ts.isExternalModule = isExternalModule;
+    function isDeclarationFile(file) {
+        return (file.flags & 2048) !== 0;
+    }
+    ts.isDeclarationFile = isDeclarationFile;
+    function isConstEnumDeclaration(node) {
+        return node.kind === 204 && isConst(node);
+    }
+    ts.isConstEnumDeclaration = isConstEnumDeclaration;
+    function walkUpBindingElementsAndPatterns(node) {
+        while (node && (node.kind === 152 || isBindingPattern(node))) {
+            node = node.parent;
+        }
+        return node;
+    }
+    function getCombinedNodeFlags(node) {
+        node = walkUpBindingElementsAndPatterns(node);
+        var flags = node.flags;
+        if (node.kind === 198) {
+            node = node.parent;
+        }
+        if (node && node.kind === 199) {
+            flags |= node.flags;
+            node = node.parent;
+        }
+        if (node && node.kind === 180) {
+            flags |= node.flags;
+        }
+        return flags;
+    }
+    ts.getCombinedNodeFlags = getCombinedNodeFlags;
+    function isConst(node) {
+        return !!(getCombinedNodeFlags(node) & 8192);
+    }
+    ts.isConst = isConst;
+    function isLet(node) {
+        return !!(getCombinedNodeFlags(node) & 4096);
+    }
+    ts.isLet = isLet;
+    function isPrologueDirective(node) {
+        return node.kind === 182 && node.expression.kind === 8;
+    }
+    ts.isPrologueDirective = isPrologueDirective;
+    function getLeadingCommentRangesOfNode(node, sourceFileOfNode) {
+        if (node.kind === 129 || node.kind === 128) {
+            return ts.concatenate(ts.getTrailingCommentRanges(sourceFileOfNode.text, node.pos), ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos));
+        }
+        else {
+            return ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
+        }
+    }
+    ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode;
+    function getJsDocComments(node, sourceFileOfNode) {
+        return ts.filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment);
+        function isJsDocComment(comment) {
+            return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === 42 &&
+                sourceFileOfNode.text.charCodeAt(comment.pos + 2) === 42 &&
+                sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== 47;
+        }
+    }
+    ts.getJsDocComments = getJsDocComments;
+    ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/;
+    function forEachReturnStatement(body, visitor) {
+        return traverse(body);
+        function traverse(node) {
+            switch (node.kind) {
+                case 191:
+                    return visitor(node);
+                case 207:
+                case 179:
+                case 183:
+                case 184:
+                case 185:
+                case 186:
+                case 187:
+                case 188:
+                case 192:
+                case 193:
+                case 220:
+                case 221:
+                case 194:
+                case 196:
+                case 223:
+                    return ts.forEachChild(node, traverse);
+            }
+        }
+    }
+    ts.forEachReturnStatement = forEachReturnStatement;
+    function isVariableLike(node) {
+        if (node) {
+            switch (node.kind) {
+                case 152:
+                case 226:
+                case 129:
+                case 224:
+                case 132:
+                case 131:
+                case 225:
+                case 198:
+                    return true;
+            }
+        }
+        return false;
+    }
+    ts.isVariableLike = isVariableLike;
+    function isAccessor(node) {
+        if (node) {
+            switch (node.kind) {
+                case 136:
+                case 137:
+                    return true;
+            }
+        }
+        return false;
+    }
+    ts.isAccessor = isAccessor;
+    function isFunctionLike(node) {
+        if (node) {
+            switch (node.kind) {
+                case 135:
+                case 162:
+                case 200:
+                case 163:
+                case 134:
+                case 133:
+                case 136:
+                case 137:
+                case 138:
+                case 139:
+                case 140:
+                case 142:
+                case 143:
+                case 162:
+                case 163:
+                case 200:
+                    return true;
+            }
+        }
+        return false;
+    }
+    ts.isFunctionLike = isFunctionLike;
+    function isFunctionBlock(node) {
+        return node && node.kind === 179 && isFunctionLike(node.parent);
+    }
+    ts.isFunctionBlock = isFunctionBlock;
+    function isObjectLiteralMethod(node) {
+        return node && node.kind === 134 && node.parent.kind === 154;
+    }
+    ts.isObjectLiteralMethod = isObjectLiteralMethod;
+    function getContainingFunction(node) {
+        while (true) {
+            node = node.parent;
+            if (!node || isFunctionLike(node)) {
+                return node;
+            }
+        }
+    }
+    ts.getContainingFunction = getContainingFunction;
+    function getThisContainer(node, includeArrowFunctions) {
+        while (true) {
+            node = node.parent;
+            if (!node) {
+                return undefined;
+            }
+            switch (node.kind) {
+                case 127:
+                    if (node.parent.parent.kind === 201) {
+                        return node;
+                    }
+                    node = node.parent;
+                    break;
+                case 130:
+                    if (node.parent.kind === 129 && isClassElement(node.parent.parent)) {
+                        node = node.parent.parent;
+                    }
+                    else if (isClassElement(node.parent)) {
+                        node = node.parent;
+                    }
+                    break;
+                case 163:
+                    if (!includeArrowFunctions) {
+                        continue;
+                    }
+                case 200:
+                case 162:
+                case 205:
+                case 132:
+                case 131:
+                case 134:
+                case 133:
+                case 135:
+                case 136:
+                case 137:
+                case 204:
+                case 227:
+                    return node;
+            }
+        }
+    }
+    ts.getThisContainer = getThisContainer;
+    function getSuperContainer(node, includeFunctions) {
+        while (true) {
+            node = node.parent;
+            if (!node)
+                return node;
+            switch (node.kind) {
+                case 127:
+                    if (node.parent.parent.kind === 201) {
+                        return node;
+                    }
+                    node = node.parent;
+                    break;
+                case 130:
+                    if (node.parent.kind === 129 && isClassElement(node.parent.parent)) {
+                        node = node.parent.parent;
+                    }
+                    else if (isClassElement(node.parent)) {
+                        node = node.parent;
+                    }
+                    break;
+                case 200:
+                case 162:
+                case 163:
+                    if (!includeFunctions) {
+                        continue;
+                    }
+                case 132:
+                case 131:
+                case 134:
+                case 133:
+                case 135:
+                case 136:
+                case 137:
+                    return node;
+            }
+        }
+    }
+    ts.getSuperContainer = getSuperContainer;
+    function getInvokedExpression(node) {
+        if (node.kind === 159) {
+            return node.tag;
+        }
+        return node.expression;
+    }
+    ts.getInvokedExpression = getInvokedExpression;
+    function nodeCanBeDecorated(node) {
+        switch (node.kind) {
+            case 201:
+                return true;
+            case 132:
+                return node.parent.kind === 201;
+            case 129:
+                return node.parent.body && node.parent.parent.kind === 201;
+            case 136:
+            case 137:
+            case 134:
+                return node.body && node.parent.kind === 201;
+        }
+        return false;
+    }
+    ts.nodeCanBeDecorated = nodeCanBeDecorated;
+    function nodeIsDecorated(node) {
+        switch (node.kind) {
+            case 201:
+                if (node.decorators) {
+                    return true;
+                }
+                return false;
+            case 132:
+            case 129:
+                if (node.decorators) {
+                    return true;
+                }
+                return false;
+            case 136:
+                if (node.body && node.decorators) {
+                    return true;
+                }
+                return false;
+            case 134:
+            case 137:
+                if (node.body && node.decorators) {
+                    return true;
+                }
+                return false;
+        }
+        return false;
+    }
+    ts.nodeIsDecorated = nodeIsDecorated;
+    function childIsDecorated(node) {
+        switch (node.kind) {
+            case 201:
+                return ts.forEach(node.members, nodeOrChildIsDecorated);
+            case 134:
+            case 137:
+                return ts.forEach(node.parameters, nodeIsDecorated);
+        }
+        return false;
+    }
+    ts.childIsDecorated = childIsDecorated;
+    function nodeOrChildIsDecorated(node) {
+        return nodeIsDecorated(node) || childIsDecorated(node);
+    }
+    ts.nodeOrChildIsDecorated = nodeOrChildIsDecorated;
+    function isExpression(node) {
+        switch (node.kind) {
+            case 93:
+            case 91:
+            case 89:
+            case 95:
+            case 80:
+            case 9:
+            case 153:
+            case 154:
+            case 155:
+            case 156:
+            case 157:
+            case 158:
+            case 159:
+            case 160:
+            case 161:
+            case 162:
+            case 174:
+            case 163:
+            case 166:
+            case 164:
+            case 165:
+            case 167:
+            case 168:
+            case 169:
+            case 170:
+            case 173:
+            case 171:
+            case 10:
+            case 175:
+                return true;
+            case 126:
+                while (node.parent.kind === 126) {
+                    node = node.parent;
+                }
+                return node.parent.kind === 144;
+            case 65:
+                if (node.parent.kind === 144) {
+                    return true;
+                }
+            case 7:
+            case 8:
+                var parent_1 = node.parent;
+                switch (parent_1.kind) {
+                    case 198:
+                    case 129:
+                    case 132:
+                    case 131:
+                    case 226:
+                    case 224:
+                    case 152:
+                        return parent_1.initializer === node;
+                    case 182:
+                    case 183:
+                    case 184:
+                    case 185:
+                    case 191:
+                    case 192:
+                    case 193:
+                    case 220:
+                    case 195:
+                    case 193:
+                        return parent_1.expression === node;
+                    case 186:
+                        var forStatement = parent_1;
+                        return (forStatement.initializer === node && forStatement.initializer.kind !== 199) ||
+                            forStatement.condition === node ||
+                            forStatement.incrementor === node;
+                    case 187:
+                    case 188:
+                        var forInStatement = parent_1;
+                        return (forInStatement.initializer === node && forInStatement.initializer.kind !== 199) ||
+                            forInStatement.expression === node;
+                    case 160:
+                        return node === parent_1.expression;
+                    case 176:
+                        return node === parent_1.expression;
+                    case 127:
+                        return node === parent_1.expression;
+                    case 130:
+                        return true;
+                    default:
+                        if (isExpression(parent_1)) {
+                            return true;
+                        }
+                }
+        }
+        return false;
+    }
+    ts.isExpression = isExpression;
+    function isInstantiatedModule(node, preserveConstEnums) {
+        var moduleState = ts.getModuleInstanceState(node);
+        return moduleState === 1 ||
+            (preserveConstEnums && moduleState === 2);
+    }
+    ts.isInstantiatedModule = isInstantiatedModule;
+    function isExternalModuleImportEqualsDeclaration(node) {
+        return node.kind === 208 && node.moduleReference.kind === 219;
+    }
+    ts.isExternalModuleImportEqualsDeclaration = isExternalModuleImportEqualsDeclaration;
+    function getExternalModuleImportEqualsDeclarationExpression(node) {
+        ts.Debug.assert(isExternalModuleImportEqualsDeclaration(node));
+        return node.moduleReference.expression;
+    }
+    ts.getExternalModuleImportEqualsDeclarationExpression = getExternalModuleImportEqualsDeclarationExpression;
+    function isInternalModuleImportEqualsDeclaration(node) {
+        return node.kind === 208 && node.moduleReference.kind !== 219;
+    }
+    ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration;
+    function getExternalModuleName(node) {
+        if (node.kind === 209) {
+            return node.moduleSpecifier;
+        }
+        if (node.kind === 208) {
+            var reference = node.moduleReference;
+            if (reference.kind === 219) {
+                return reference.expression;
+            }
+        }
+        if (node.kind === 215) {
+            return node.moduleSpecifier;
+        }
+    }
+    ts.getExternalModuleName = getExternalModuleName;
+    function hasDotDotDotToken(node) {
+        return node && node.kind === 129 && node.dotDotDotToken !== undefined;
+    }
+    ts.hasDotDotDotToken = hasDotDotDotToken;
+    function hasQuestionToken(node) {
+        if (node) {
+            switch (node.kind) {
+                case 129:
+                    return node.questionToken !== undefined;
+                case 134:
+                case 133:
+                    return node.questionToken !== undefined;
+                case 225:
+                case 224:
+                case 132:
+                case 131:
+                    return node.questionToken !== undefined;
+            }
+        }
+        return false;
+    }
+    ts.hasQuestionToken = hasQuestionToken;
+    function hasRestParameters(s) {
+        return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined;
+    }
+    ts.hasRestParameters = hasRestParameters;
+    function isLiteralKind(kind) {
+        return 7 <= kind && kind <= 10;
+    }
+    ts.isLiteralKind = isLiteralKind;
+    function isTextualLiteralKind(kind) {
+        return kind === 8 || kind === 10;
+    }
+    ts.isTextualLiteralKind = isTextualLiteralKind;
+    function isTemplateLiteralKind(kind) {
+        return 10 <= kind && kind <= 13;
+    }
+    ts.isTemplateLiteralKind = isTemplateLiteralKind;
+    function isBindingPattern(node) {
+        return !!node && (node.kind === 151 || node.kind === 150);
+    }
+    ts.isBindingPattern = isBindingPattern;
+    function isInAmbientContext(node) {
+        while (node) {
+            if (node.flags & (2 | 2048)) {
+                return true;
+            }
+            node = node.parent;
+        }
+        return false;
+    }
+    ts.isInAmbientContext = isInAmbientContext;
+    function isDeclaration(node) {
+        switch (node.kind) {
+            case 163:
+            case 152:
+            case 201:
+            case 135:
+            case 204:
+            case 226:
+            case 217:
+            case 200:
+            case 162:
+            case 136:
+            case 210:
+            case 208:
+            case 213:
+            case 202:
+            case 134:
+            case 133:
+            case 205:
+            case 211:
+            case 129:
+            case 224:
+            case 132:
+            case 131:
+            case 137:
+            case 225:
+            case 203:
+            case 128:
+            case 198:
+                return true;
+        }
+        return false;
+    }
+    ts.isDeclaration = isDeclaration;
+    function isStatement(n) {
+        switch (n.kind) {
+            case 190:
+            case 189:
+            case 197:
+            case 184:
+            case 182:
+            case 181:
+            case 187:
+            case 188:
+            case 186:
+            case 183:
+            case 194:
+            case 191:
+            case 193:
+            case 94:
+            case 196:
+            case 180:
+            case 185:
+            case 192:
+            case 214:
+                return true;
+            default:
+                return false;
+        }
+    }
+    ts.isStatement = isStatement;
+    function isClassElement(n) {
+        switch (n.kind) {
+            case 135:
+            case 132:
+            case 134:
+            case 136:
+            case 137:
+            case 133:
+            case 140:
+                return true;
+            default:
+                return false;
+        }
+    }
+    ts.isClassElement = isClassElement;
+    function isDeclarationName(name) {
+        if (name.kind !== 65 && name.kind !== 8 && name.kind !== 7) {
+            return false;
+        }
+        var parent = name.parent;
+        if (parent.kind === 213 || parent.kind === 217) {
+            if (parent.propertyName) {
+                return true;
+            }
+        }
+        if (isDeclaration(parent)) {
+            return parent.name === name;
+        }
+        return false;
+    }
+    ts.isDeclarationName = isDeclarationName;
+    function isAliasSymbolDeclaration(node) {
+        return node.kind === 208 ||
+            node.kind === 210 && !!node.name ||
+            node.kind === 211 ||
+            node.kind === 213 ||
+            node.kind === 217 ||
+            node.kind === 214 && node.expression.kind === 65;
+    }
+    ts.isAliasSymbolDeclaration = isAliasSymbolDeclaration;
+    function getClassExtendsHeritageClauseElement(node) {
+        var heritageClause = getHeritageClause(node.heritageClauses, 79);
+        return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
+    }
+    ts.getClassExtendsHeritageClauseElement = getClassExtendsHeritageClauseElement;
+    function getClassImplementsHeritageClauseElements(node) {
+        var heritageClause = getHeritageClause(node.heritageClauses, 102);
+        return heritageClause ? heritageClause.types : undefined;
+    }
+    ts.getClassImplementsHeritageClauseElements = getClassImplementsHeritageClauseElements;
+    function getInterfaceBaseTypeNodes(node) {
+        var heritageClause = getHeritageClause(node.heritageClauses, 79);
+        return heritageClause ? heritageClause.types : undefined;
+    }
+    ts.getInterfaceBaseTypeNodes = getInterfaceBaseTypeNodes;
+    function getHeritageClause(clauses, kind) {
+        if (clauses) {
+            for (var _i = 0; _i < clauses.length; _i++) {
+                var clause = clauses[_i];
+                if (clause.token === kind) {
+                    return clause;
+                }
+            }
+        }
+        return undefined;
+    }
+    ts.getHeritageClause = getHeritageClause;
+    function tryResolveScriptReference(host, sourceFile, reference) {
+        if (!host.getCompilerOptions().noResolve) {
+            var referenceFileName = ts.isRootedDiskPath(reference.fileName) ? reference.fileName : ts.combinePaths(ts.getDirectoryPath(sourceFile.fileName), reference.fileName);
+            referenceFileName = ts.getNormalizedAbsolutePath(referenceFileName, host.getCurrentDirectory());
+            return host.getSourceFile(referenceFileName);
+        }
+    }
+    ts.tryResolveScriptReference = tryResolveScriptReference;
+    function getAncestor(node, kind) {
+        while (node) {
+            if (node.kind === kind) {
+                return node;
+            }
+            node = node.parent;
+        }
+        return undefined;
+    }
+    ts.getAncestor = getAncestor;
+    function getFileReferenceFromReferencePath(comment, commentRange) {
+        var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
+        var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
+        if (simpleReferenceRegEx.exec(comment)) {
+            if (isNoDefaultLibRegEx.exec(comment)) {
+                return {
+                    isNoDefaultLib: true
+                };
+            }
+            else {
+                var matchResult = ts.fullTripleSlashReferencePathRegEx.exec(comment);
+                if (matchResult) {
+                    var start = commentRange.pos;
+                    var end = commentRange.end;
+                    return {
+                        fileReference: {
+                            pos: start,
+                            end: end,
+                            fileName: matchResult[3]
+                        },
+                        isNoDefaultLib: false
+                    };
+                }
+                else {
+                    return {
+                        diagnosticMessage: ts.Diagnostics.Invalid_reference_directive_syntax,
+                        isNoDefaultLib: false
+                    };
+                }
+            }
+        }
+        return undefined;
+    }
+    ts.getFileReferenceFromReferencePath = getFileReferenceFromReferencePath;
+    function isKeyword(token) {
+        return 66 <= token && token <= 125;
+    }
+    ts.isKeyword = isKeyword;
+    function isTrivia(token) {
+        return 2 <= token && token <= 6;
+    }
+    ts.isTrivia = isTrivia;
+    function hasDynamicName(declaration) {
+        return declaration.name &&
+            declaration.name.kind === 127 &&
+            !isWellKnownSymbolSyntactically(declaration.name.expression);
+    }
+    ts.hasDynamicName = hasDynamicName;
+    function isWellKnownSymbolSyntactically(node) {
+        return node.kind === 155 && isESSymbolIdentifier(node.expression);
+    }
+    ts.isWellKnownSymbolSyntactically = isWellKnownSymbolSyntactically;
+    function getPropertyNameForPropertyNameNode(name) {
+        if (name.kind === 65 || name.kind === 8 || name.kind === 7) {
+            return name.text;
+        }
+        if (name.kind === 127) {
+            var nameExpression = name.expression;
+            if (isWellKnownSymbolSyntactically(nameExpression)) {
+                var rightHandSideName = nameExpression.name.text;
+                return getPropertyNameForKnownSymbolName(rightHandSideName);
+            }
+        }
+        return undefined;
+    }
+    ts.getPropertyNameForPropertyNameNode = getPropertyNameForPropertyNameNode;
+    function getPropertyNameForKnownSymbolName(symbolName) {
+        return "__@" + symbolName;
+    }
+    ts.getPropertyNameForKnownSymbolName = getPropertyNameForKnownSymbolName;
+    function isESSymbolIdentifier(node) {
+        return node.kind === 65 && node.text === "Symbol";
+    }
+    ts.isESSymbolIdentifier = isESSymbolIdentifier;
+    function isModifier(token) {
+        switch (token) {
+            case 108:
+            case 106:
+            case 107:
+            case 109:
+            case 78:
+            case 115:
+            case 70:
+            case 73:
+                return true;
+        }
+        return false;
+    }
+    ts.isModifier = isModifier;
+    function nodeStartsNewLexicalEnvironment(n) {
+        return isFunctionLike(n) || n.kind === 205 || n.kind === 227;
+    }
+    ts.nodeStartsNewLexicalEnvironment = nodeStartsNewLexicalEnvironment;
+    function nodeIsSynthesized(node) {
+        return node.pos === -1;
+    }
+    ts.nodeIsSynthesized = nodeIsSynthesized;
+    function createSynthesizedNode(kind, startsOnNewLine) {
+        var node = ts.createNode(kind);
+        node.pos = -1;
+        node.end = -1;
+        node.startsOnNewLine = startsOnNewLine;
+        return node;
+    }
+    ts.createSynthesizedNode = createSynthesizedNode;
+    function createSynthesizedNodeArray() {
+        var array = [];
+        array.pos = -1;
+        array.end = -1;
+        return array;
+    }
+    ts.createSynthesizedNodeArray = createSynthesizedNodeArray;
+    function createDiagnosticCollection() {
+        var nonFileDiagnostics = [];
+        var fileDiagnostics = {};
+        var diagnosticsModified = false;
+        var modificationCount = 0;
+        return {
+            add: add,
+            getGlobalDiagnostics: getGlobalDiagnostics,
+            getDiagnostics: getDiagnostics,
+            getModificationCount: getModificationCount
+        };
+        function getModificationCount() {
+            return modificationCount;
+        }
+        function add(diagnostic) {
+            var diagnostics;
+            if (diagnostic.file) {
+                diagnostics = fileDiagnostics[diagnostic.file.fileName];
+                if (!diagnostics) {
+                    diagnostics = [];
+                    fileDiagnostics[diagnostic.file.fileName] = diagnostics;
+                }
+            }
+            else {
+                diagnostics = nonFileDiagnostics;
+            }
+            diagnostics.push(diagnostic);
+            diagnosticsModified = true;
+            modificationCount++;
+        }
+        function getGlobalDiagnostics() {
+            sortAndDeduplicate();
+            return nonFileDiagnostics;
+        }
+        function getDiagnostics(fileName) {
+            sortAndDeduplicate();
+            if (fileName) {
+                return fileDiagnostics[fileName] || [];
+            }
+            var allDiagnostics = [];
+            function pushDiagnostic(d) {
+                allDiagnostics.push(d);
+            }
+            ts.forEach(nonFileDiagnostics, pushDiagnostic);
+            for (var key in fileDiagnostics) {
+                if (ts.hasProperty(fileDiagnostics, key)) {
+                    ts.forEach(fileDiagnostics[key], pushDiagnostic);
+                }
+            }
+            return ts.sortAndDeduplicateDiagnostics(allDiagnostics);
+        }
+        function sortAndDeduplicate() {
+            if (!diagnosticsModified) {
+                return;
+            }
+            diagnosticsModified = false;
+            nonFileDiagnostics = ts.sortAndDeduplicateDiagnostics(nonFileDiagnostics);
+            for (var key in fileDiagnostics) {
+                if (ts.hasProperty(fileDiagnostics, key)) {
+                    fileDiagnostics[key] = ts.sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
+                }
+            }
+        }
+    }
+    ts.createDiagnosticCollection = createDiagnosticCollection;
+    var escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
+    var escapedCharsMap = {
+        "\0": "\\0",
+        "\t": "\\t",
+        "\v": "\\v",
+        "\f": "\\f",
+        "\b": "\\b",
+        "\r": "\\r",
+        "\n": "\\n",
+        "\\": "\\\\",
+        "\"": "\\\"",
+        "\u2028": "\\u2028",
+        "\u2029": "\\u2029",
+        "\u0085": "\\u0085"
+    };
+    function escapeString(s) {
+        s = escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, getReplacement) : s;
+        return s;
+        function getReplacement(c) {
+            return escapedCharsMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
+        }
+    }
+    ts.escapeString = escapeString;
+    function get16BitUnicodeEscapeSequence(charCode) {
+        var hexCharCode = charCode.toString(16).toUpperCase();
+        var paddedHexCode = ("0000" + hexCharCode).slice(-4);
+        return "\\u" + paddedHexCode;
+    }
+    var nonAsciiCharacters = /[^\u0000-\u007F]/g;
+    function escapeNonAsciiCharacters(s) {
+        return nonAsciiCharacters.test(s) ?
+            s.replace(nonAsciiCharacters, function (c) { return get16BitUnicodeEscapeSequence(c.charCodeAt(0)); }) :
+            s;
+    }
+    ts.escapeNonAsciiCharacters = escapeNonAsciiCharacters;
+    var indentStrings = ["", "    "];
+    function getIndentString(level) {
+        if (indentStrings[level] === undefined) {
+            indentStrings[level] = getIndentString(level - 1) + indentStrings[1];
+        }
+        return indentStrings[level];
+    }
+    ts.getIndentString = getIndentString;
+    function getIndentSize() {
+        return indentStrings[1].length;
+    }
+    ts.getIndentSize = getIndentSize;
+    function createTextWriter(newLine) {
+        var output = "";
+        var indent = 0;
+        var lineStart = true;
+        var lineCount = 0;
+        var linePos = 0;
+        function write(s) {
+            if (s && s.length) {
+                if (lineStart) {
+                    output += getIndentString(indent);
+                    lineStart = false;
+                }
+                output += s;
+            }
+        }
+        function rawWrite(s) {
+            if (s !== undefined) {
+                if (lineStart) {
+                    lineStart = false;
+                }
+                output += s;
+            }
+        }
+        function writeLiteral(s) {
+            if (s && s.length) {
+                write(s);
+                var lineStartsOfS = ts.computeLineStarts(s);
+                if (lineStartsOfS.length > 1) {
+                    lineCount = lineCount + lineStartsOfS.length - 1;
+                    linePos = output.length - s.length + lineStartsOfS[lineStartsOfS.length - 1];
+                }
+            }
+        }
+        function writeLine() {
+            if (!lineStart) {
+                output += newLine;
+                lineCount++;
+                linePos = output.length;
+                lineStart = true;
+            }
+        }
+        function writeTextOfNode(sourceFile, node) {
+            write(getSourceTextOfNodeFromSourceFile(sourceFile, node));
+        }
+        return {
+            write: write,
+            rawWrite: rawWrite,
+            writeTextOfNode: writeTextOfNode,
+            writeLiteral: writeLiteral,
+            writeLine: writeLine,
+            increaseIndent: function () { return indent++; },
+            decreaseIndent: function () { return indent--; },
+            getIndent: function () { return indent; },
+            getTextPos: function () { return output.length; },
+            getLine: function () { return lineCount + 1; },
+            getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; },
+            getText: function () { return output; },
+        };
+    }
+    ts.createTextWriter = createTextWriter;
+    function getOwnEmitOutputFilePath(sourceFile, host, extension) {
+        var compilerOptions = host.getCompilerOptions();
+        var emitOutputFilePathWithoutExtension;
+        if (compilerOptions.outDir) {
+            emitOutputFilePathWithoutExtension = ts.removeFileExtension(getSourceFilePathInNewDir(sourceFile, host, compilerOptions.outDir));
+        }
+        else {
+            emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName);
+        }
+        return emitOutputFilePathWithoutExtension + extension;
+    }
+    ts.getOwnEmitOutputFilePath = getOwnEmitOutputFilePath;
+    function getSourceFilePathInNewDir(sourceFile, host, newDirPath) {
+        var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, host.getCurrentDirectory());
+        sourceFilePath = sourceFilePath.replace(host.getCommonSourceDirectory(), "");
+        return ts.combinePaths(newDirPath, sourceFilePath);
+    }
+    ts.getSourceFilePathInNewDir = getSourceFilePathInNewDir;
+    function writeFile(host, diagnostics, fileName, data, writeByteOrderMark) {
+        host.writeFile(fileName, data, writeByteOrderMark, function (hostErrorMessage) {
+            diagnostics.push(ts.createCompilerDiagnostic(ts.Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage));
+        });
+    }
+    ts.writeFile = writeFile;
+    function getLineOfLocalPosition(currentSourceFile, pos) {
+        return ts.getLineAndCharacterOfPosition(currentSourceFile, pos).line;
+    }
+    ts.getLineOfLocalPosition = getLineOfLocalPosition;
+    function getFirstConstructorWithBody(node) {
+        return ts.forEach(node.members, function (member) {
+            if (member.kind === 135 && nodeIsPresent(member.body)) {
+                return member;
+            }
+        });
+    }
+    ts.getFirstConstructorWithBody = getFirstConstructorWithBody;
+    function shouldEmitToOwnFile(sourceFile, compilerOptions) {
+        if (!isDeclarationFile(sourceFile)) {
+            if ((isExternalModule(sourceFile) || !compilerOptions.out) && !ts.fileExtensionIs(sourceFile.fileName, ".js")) {
+                return true;
+            }
+            return false;
+        }
+        return false;
+    }
+    ts.shouldEmitToOwnFile = shouldEmitToOwnFile;
+    function getAllAccessorDeclarations(declarations, accessor) {
+        var firstAccessor;
+        var secondAccessor;
+        var getAccessor;
+        var setAccessor;
+        if (hasDynamicName(accessor)) {
+            firstAccessor = accessor;
+            if (accessor.kind === 136) {
+                getAccessor = accessor;
+            }
+            else if (accessor.kind === 137) {
+                setAccessor = accessor;
+            }
+            else {
+                ts.Debug.fail("Accessor has wrong kind");
+            }
+        }
+        else {
+            ts.forEach(declarations, function (member) {
+                if ((member.kind === 136 || member.kind === 137)
+                    && (member.flags & 128) === (accessor.flags & 128)) {
+                    var memberName = getPropertyNameForPropertyNameNode(member.name);
+                    var accessorName = getPropertyNameForPropertyNameNode(accessor.name);
+                    if (memberName === accessorName) {
+                        if (!firstAccessor) {
+                            firstAccessor = member;
+                        }
+                        else if (!secondAccessor) {
+                            secondAccessor = member;
+                        }
+                        if (member.kind === 136 && !getAccessor) {
+                            getAccessor = member;
+                        }
+                        if (member.kind === 137 && !setAccessor) {
+                            setAccessor = member;
+                        }
+                    }
+                }
+            });
+        }
+        return {
+            firstAccessor: firstAccessor,
+            secondAccessor: secondAccessor,
+            getAccessor: getAccessor,
+            setAccessor: setAccessor
+        };
+    }
+    ts.getAllAccessorDeclarations = getAllAccessorDeclarations;
+    function emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments) {
+        if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
+            getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) {
+            writer.writeLine();
+        }
+    }
+    ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments;
+    function emitComments(currentSourceFile, writer, comments, trailingSeparator, newLine, writeComment) {
+        var emitLeadingSpace = !trailingSeparator;
+        ts.forEach(comments, function (comment) {
+            if (emitLeadingSpace) {
+                writer.write(" ");
+                emitLeadingSpace = false;
+            }
+            writeComment(currentSourceFile, writer, comment, newLine);
+            if (comment.hasTrailingNewLine) {
+                writer.writeLine();
+            }
+            else if (trailingSeparator) {
+                writer.write(" ");
+            }
+            else {
+                emitLeadingSpace = true;
+            }
+        });
+    }
+    ts.emitComments = emitComments;
+    function writeCommentRange(currentSourceFile, writer, comment, newLine) {
+        if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42) {
+            var firstCommentLineAndCharacter = ts.getLineAndCharacterOfPosition(currentSourceFile, comment.pos);
+            var lineCount = ts.getLineStarts(currentSourceFile).length;
+            var firstCommentLineIndent;
+            for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) {
+                var nextLineStart = (currentLine + 1) === lineCount
+                    ? currentSourceFile.text.length + 1
+                    : getStartPositionOfLine(currentLine + 1, currentSourceFile);
+                if (pos !== comment.pos) {
+                    if (firstCommentLineIndent === undefined) {
+                        firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos);
+                    }
+                    var currentWriterIndentSpacing = writer.getIndent() * getIndentSize();
+                    var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart);
+                    if (spacesToEmit > 0) {
+                        var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize();
+                        var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize());
+                        writer.rawWrite(indentSizeSpaceString);
+                        while (numberOfSingleSpacesToEmit) {
+                            writer.rawWrite(" ");
+                            numberOfSingleSpacesToEmit--;
+                        }
+                    }
+                    else {
+                        writer.rawWrite("");
+                    }
+                }
+                writeTrimmedCurrentLine(pos, nextLineStart);
+                pos = nextLineStart;
+            }
+        }
+        else {
+            writer.write(currentSourceFile.text.substring(comment.pos, comment.end));
+        }
+        function writeTrimmedCurrentLine(pos, nextLineStart) {
+            var end = Math.min(comment.end, nextLineStart - 1);
+            var currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, '');
+            if (currentLineText) {
+                writer.write(currentLineText);
+                if (end !== comment.end) {
+                    writer.writeLine();
+                }
+            }
+            else {
+                writer.writeLiteral(newLine);
+            }
+        }
+        function calculateIndent(pos, end) {
+            var currentLineIndent = 0;
+            for (; pos < end && ts.isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) {
+                if (currentSourceFile.text.charCodeAt(pos) === 9) {
+                    currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
+                }
+                else {
+                    currentLineIndent++;
+                }
+            }
+            return currentLineIndent;
+        }
+    }
+    ts.writeCommentRange = writeCommentRange;
+    function modifierToFlag(token) {
+        switch (token) {
+            case 109: return 128;
+            case 108: return 16;
+            case 107: return 64;
+            case 106: return 32;
+            case 78: return 1;
+            case 115: return 2;
+            case 70: return 8192;
+            case 73: return 256;
+        }
+        return 0;
+    }
+    ts.modifierToFlag = modifierToFlag;
+    function isLeftHandSideExpression(expr) {
+        if (expr) {
+            switch (expr.kind) {
+                case 155:
+                case 156:
+                case 158:
+                case 157:
+                case 159:
+                case 153:
+                case 161:
+                case 154:
+                case 174:
+                case 162:
+                case 65:
+                case 9:
+                case 7:
+                case 8:
+                case 10:
+                case 171:
+                case 80:
+                case 89:
+                case 93:
+                case 95:
+                case 91:
+                    return true;
+            }
+        }
+        return false;
+    }
+    ts.isLeftHandSideExpression = isLeftHandSideExpression;
+    function isAssignmentOperator(token) {
+        return token >= 53 && token <= 64;
+    }
+    ts.isAssignmentOperator = isAssignmentOperator;
+    function isSupportedHeritageClauseElement(node) {
+        return isSupportedHeritageClauseElementExpression(node.expression);
+    }
+    ts.isSupportedHeritageClauseElement = isSupportedHeritageClauseElement;
+    function isSupportedHeritageClauseElementExpression(node) {
+        if (node.kind === 65) {
+            return true;
+        }
+        else if (node.kind === 155) {
+            return isSupportedHeritageClauseElementExpression(node.expression);
+        }
+        else {
+            return false;
+        }
+    }
+    function isRightSideOfQualifiedNameOrPropertyAccess(node) {
+        return (node.parent.kind === 126 && node.parent.right === node) ||
+            (node.parent.kind === 155 && node.parent.name === node);
+    }
+    ts.isRightSideOfQualifiedNameOrPropertyAccess = isRightSideOfQualifiedNameOrPropertyAccess;
+    function getLocalSymbolForExportDefault(symbol) {
+        return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 256) ? symbol.valueDeclaration.localSymbol : undefined;
+    }
+    ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault;
+})(ts || (ts = {}));
+var ts;
+(function (ts) {
+    function getDefaultLibFileName(options) {
+        return options.target === 2 ? "lib.es6.d.ts" : "lib.d.ts";
+    }
+    ts.getDefaultLibFileName = getDefaultLibFileName;
+    function textSpanEnd(span) {
+        return span.start + span.length;
+    }
+    ts.textSpanEnd = textSpanEnd;
+    function textSpanIsEmpty(span) {
+        return span.length === 0;
+    }
+    ts.textSpanIsEmpty = textSpanIsEmpty;
+    function textSpanContainsPosition(span, position) {
+        return position >= span.start && position < textSpanEnd(span);
+    }
+    ts.textSpanContainsPosition = textSpanContainsPosition;
+    function textSpanContainsTextSpan(span, other) {
+        return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span);
+    }
+    ts.textSpanContainsTextSpan = textSpanContainsTextSpan;
+    function textSpanOverlapsWith(span, other) {
+        var overlapStart = Math.max(span.start, other.start);
+        var overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
+        return overlapStart < overlapEnd;
+    }
+    ts.textSpanOverlapsWith = textSpanOverlapsWith;
+    function textSpanOverlap(span1, span2) {
+        var overlapStart = Math.max(span1.start, span2.start);
+        var overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
+        if (overlapStart < overlapEnd) {
+            return createTextSpanFromBounds(overlapStart, overlapEnd);
+        }
+        return undefined;
+    }
+    ts.textSpanOverlap = textSpanOverlap;
+    function textSpanIntersectsWithTextSpan(span, other) {
+        return other.start <= textSpanEnd(span) && textSpanEnd(other) >= span.start;
+    }
+    ts.textSpanIntersectsWithTextSpan = textSpanIntersectsWithTextSpan;
+    function textSpanIntersectsWith(span, start, length) {
+        var end = start + length;
+        return start <= textSpanEnd(span) && end >= span.start;
+    }
+    ts.textSpanIntersectsWith = textSpanIntersectsWith;
+    function textSpanIntersectsWithPosition(span, position) {
+        return position <= textSpanEnd(span) && position >= span.start;
+    }
+    ts.textSpanIntersectsWithPosition = textSpanIntersectsWithPosition;
+    function textSpanIntersection(span1, span2) {
+        var intersectStart = Math.max(span1.start, span2.start);
+        var intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
+        if (intersectStart <= intersectEnd) {
+            return createTextSpanFromBounds(intersectStart, intersectEnd);
+        }
+        return undefined;
+    }
+    ts.textSpanIntersection = textSpanIntersection;
+    function createTextSpan(start, length) {
+        if (start < 0) {
+            throw new Error("start < 0");
+        }
+        if (length < 0) {
+            throw new Error("length < 0");
+        }
+        return { start: start, length: length };
+    }
+    ts.createTextSpan = createTextSpan;
+    function createTextSpanFromBounds(start, end) {
+        return createTextSpan(start, end - start);
+    }
+    ts.createTextSpanFromBounds = createTextSpanFromBounds;
+    function textChangeRangeNewSpan(range) {
+        return createTextSpan(range.span.start, range.newLength);
+    }
+    ts.textChangeRangeNewSpan = textChangeRangeNewSpan;
+    function textChangeRangeIsUnchanged(range) {
+        return textSpanIsEmpty(range.span) && range.newLength === 0;
+    }
+    ts.textChangeRangeIsUnchanged = textChangeRangeIsUnchanged;
+    function createTextChangeRange(span, newLength) {
+        if (newLength < 0) {
+            throw new Error("newLength < 0");
+        }
+        return { span: span, newLength: newLength };
+    }
+    ts.createTextChangeRange = createTextChangeRange;
+    ts.unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0);
+    function collapseTextChangeRangesAcrossMultipleVersions(changes) {
+        if (changes.length === 0) {
+            return ts.unchangedTextChangeRange;
+        }
+        if (changes.length === 1) {
+            return changes[0];
+        }
+        var change0 = changes[0];
+        var oldStartN = change0.span.start;
+        var oldEndN = textSpanEnd(change0.span);
+        var newEndN = oldStartN + change0.newLength;
+        for (var i = 1; i < changes.length; i++) {
+            var nextChange = changes[i];
+            var oldStart1 = oldStartN;
+            var oldEnd1 = oldEndN;
+            var newEnd1 = newEndN;
+            var oldStart2 = nextChange.span.start;
+            var oldEnd2 = textSpanEnd(nextChange.span);
+            var newEnd2 = oldStart2 + nextChange.newLength;
+            oldStartN = Math.min(oldStart1, oldStart2);
+            oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
+            newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
+        }
+        return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), newEndN - oldStartN);
+    }
+    ts.collapseTextChangeRangesAcrossMultipleVersions = collapseTextChangeRangesAcrossMultipleVersions;
+})(ts || (ts = {}));
diff --git a/dist/typescript/makeTypeScriptGlobal.js b/dist/typescript/makeTypeScriptGlobal.js
new file mode 100644
index 000000000..d7f70695d
--- /dev/null
+++ b/dist/typescript/makeTypeScriptGlobal.js
@@ -0,0 +1,50 @@
+var servicesFiles = [
+    "../compiler/core.ts",
+    "../compiler/sys.ts",
+    "../compiler/types.ts",
+    "../compiler/scanner.ts",
+    "../compiler/parser.ts",
+    "../compiler/utilities.ts",
+    "../compiler/binder.ts",
+    "../compiler/checker.ts",
+    "../compiler/emitter.ts",
+    "../compiler/program.ts",
+    "../compiler/diagnosticInformationMap.generated.ts",
+    "../compiler/commandLineParser.ts",
+    "breakpoints.ts",
+    "navigationBar.ts",
+    "outliningElementsCollector.ts",
+    "services.ts",
+    "shims.ts",
+    "signatureHelp.ts",
+    "utilities.ts",
+    "formatting/formatting.ts",
+    "formatting/formattingContext.ts",
+    "formatting/formattingRequestKind.ts",
+    "formatting/formattingScanner.ts",
+    "formatting/references.ts",
+    "formatting/rule.ts",
+    "formatting/ruleAction.ts",
+    "formatting/ruleDescriptor.ts",
+    "formatting/ruleFlag.ts",
+    "formatting/ruleOperation.ts",
+    "formatting/ruleOperationContext.ts",
+    "formatting/rules.ts",
+    "formatting/rulesMap.ts",
+    "formatting/rulesProvider.ts",
+    "formatting/smartIndenter.ts",
+    "formatting/tokenRange.ts"
+];
+var files = servicesFiles.map(function (f) { return ("./services/" + f.replace('.ts', '.js')); });
+var vm = require('vm');
+var fs = require('fs');
+var path = require('path');
+function makeTsGlobal() {
+    var sandbox = { ts: {} };
+    vm.createContext(sandbox);
+    files.forEach(function (f) {
+        vm.runInContext(fs.readFileSync(path.resolve(__dirname, f)).toString(), sandbox);
+    });
+    global.ts = sandbox.ts;
+}
+exports.makeTsGlobal = makeTsGlobal;
diff --git a/dist/typescript/readme.js b/dist/typescript/readme.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/dist/typescript/services/breakpoints.js b/dist/typescript/services/breakpoints.js
new file mode 100644
index 000000000..e21105b83
--- /dev/null
+++ b/dist/typescript/services/breakpoints.js
@@ -0,0 +1,364 @@
+// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. 
+// See LICENSE.txt in the project root for complete license information.
+/// <reference path='services.ts' />
+var ts;
+(function (ts) {
+    var BreakpointResolver;
+    (function (BreakpointResolver) {
+        function spanInSourceFileAtLocation(sourceFile, position) {
+            if (sourceFile.flags & 2048) {
+                return undefined;
+            }
+            var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position);
+            var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
+            if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
+                tokenAtLocation = ts.findPrecedingToken(tokenAtLocation.pos, sourceFile);
+                if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) {
+                    return undefined;
+                }
+            }
+            if (ts.isInAmbientContext(tokenAtLocation)) {
+                return undefined;
+            }
+            return spanInNode(tokenAtLocation);
+            function textSpan(startNode, endNode) {
+                return ts.createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
+            }
+            function spanInNodeIfStartsOnSameLine(node, otherwiseOnNode) {
+                if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
+                    return spanInNode(node);
+                }
+                return spanInNode(otherwiseOnNode);
+            }
+            function spanInPreviousNode(node) {
+                return spanInNode(ts.findPrecedingToken(node.pos, sourceFile));
+            }
+            function spanInNextNode(node) {
+                return spanInNode(ts.findNextToken(node, node.parent));
+            }
+            function spanInNode(node) {
+                if (node) {
+                    if (ts.isExpression(node)) {
+                        if (node.parent.kind === 184) {
+                            return spanInPreviousNode(node);
+                        }
+                        if (node.parent.kind === 186) {
+                            return textSpan(node);
+                        }
+                        if (node.parent.kind === 169 && node.parent.operatorToken.kind === 23) {
+                            return textSpan(node);
+                        }
+                        if (node.parent.kind == 163 && node.parent.body == node) {
+                            return textSpan(node);
+                        }
+                    }
+                    switch (node.kind) {
+                        case 180:
+                            return spanInVariableDeclaration(node.declarationList.declarations[0]);
+                        case 198:
+                        case 132:
+                        case 131:
+                            return spanInVariableDeclaration(node);
+                        case 129:
+                            return spanInParameterDeclaration(node);
+                        case 200:
+                        case 134:
+                        case 133:
+                        case 136:
+                        case 137:
+                        case 135:
+                        case 162:
+                        case 163:
+                            return spanInFunctionDeclaration(node);
+                        case 179:
+                            if (ts.isFunctionBlock(node)) {
+                                return spanInFunctionBlock(node);
+                            }
+                        case 206:
+                            return spanInBlock(node);
+                        case 223:
+                            return spanInBlock(node.block);
+                        case 182:
+                            return textSpan(node.expression);
+                        case 191:
+                            return textSpan(node.getChildAt(0), node.expression);
+                        case 185:
+                            return textSpan(node, ts.findNextToken(node.expression, node));
+                        case 184:
+                            return spanInNode(node.statement);
+                        case 197:
+                            return textSpan(node.getChildAt(0));
+                        case 183:
+                            return textSpan(node, ts.findNextToken(node.expression, node));
+                        case 194:
+                            return spanInNode(node.statement);
+                        case 190:
+                        case 189:
+                            return textSpan(node.getChildAt(0), node.label);
+                        case 186:
+                            return spanInForStatement(node);
+                        case 187:
+                        case 188:
+                            return textSpan(node, ts.findNextToken(node.expression, node));
+                        case 193:
+                            return textSpan(node, ts.findNextToken(node.expression, node));
+                        case 220:
+                        case 221:
+                            return spanInNode(node.statements[0]);
+                        case 196:
+                            return spanInBlock(node.tryBlock);
+                        case 195:
+                            return textSpan(node, node.expression);
+                        case 214:
+                            return textSpan(node, node.expression);
+                        case 208:
+                            return textSpan(node, node.moduleReference);
+                        case 209:
+                            return textSpan(node, node.moduleSpecifier);
+                        case 215:
+                            return textSpan(node, node.moduleSpecifier);
+                        case 205:
+                            if (ts.getModuleInstanceState(node) !== 1) {
+                                return undefined;
+                            }
+                        case 201:
+                        case 204:
+                        case 226:
+                        case 157:
+                        case 158:
+                            return textSpan(node);
+                        case 192:
+                            return spanInNode(node.statement);
+                        case 202:
+                        case 203:
+                            return undefined;
+                        case 22:
+                        case 1:
+                            return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile));
+                        case 23:
+                            return spanInPreviousNode(node);
+                        case 14:
+                            return spanInOpenBraceToken(node);
+                        case 15:
+                            return spanInCloseBraceToken(node);
+                        case 16:
+                            return spanInOpenParenToken(node);
+                        case 17:
+                            return spanInCloseParenToken(node);
+                        case 51:
+                            return spanInColonToken(node);
+                        case 25:
+                        case 24:
+                            return spanInGreaterThanOrLessThanToken(node);
+                        case 100:
+                            return spanInWhileKeyword(node);
+                        case 76:
+                        case 68:
+                        case 81:
+                            return spanInNextNode(node);
+                        default:
+                            if (node.parent.kind === 224 && node.parent.name === node) {
+                                return spanInNode(node.parent.initializer);
+                            }
+                            if (node.parent.kind === 160 && node.parent.type === node) {
+                                return spanInNode(node.parent.expression);
+                            }
+                            if (ts.isFunctionLike(node.parent) && node.parent.type === node) {
+                                return spanInPreviousNode(node);
+                            }
+                            return spanInNode(node.parent);
+                    }
+                }
+                function spanInVariableDeclaration(variableDeclaration) {
+                    if (variableDeclaration.parent.parent.kind === 187 ||
+                        variableDeclaration.parent.parent.kind === 188) {
+                        return spanInNode(variableDeclaration.parent.parent);
+                    }
+                    var isParentVariableStatement = variableDeclaration.parent.parent.kind === 180;
+                    var isDeclarationOfForStatement = variableDeclaration.parent.parent.kind === 186 && ts.contains(variableDeclaration.parent.parent.initializer.declarations, variableDeclaration);
+                    var declarations = isParentVariableStatement
+                        ? variableDeclaration.parent.parent.declarationList.declarations
+                        : isDeclarationOfForStatement
+                            ? variableDeclaration.parent.parent.initializer.declarations
+                            : undefined;
+                    if (variableDeclaration.initializer || (variableDeclaration.flags & 1)) {
+                        if (declarations && declarations[0] === variableDeclaration) {
+                            if (isParentVariableStatement) {
+                                return textSpan(variableDeclaration.parent, variableDeclaration);
+                            }
+                            else {
+                                ts.Debug.assert(isDeclarationOfForStatement);
+                                return textSpan(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
+                            }
+                        }
+                        else {
+                            return textSpan(variableDeclaration);
+                        }
+                    }
+                    else if (declarations && declarations[0] !== variableDeclaration) {
+                        var indexOfCurrentDeclaration = ts.indexOf(declarations, variableDeclaration);
+                        return spanInVariableDeclaration(declarations[indexOfCurrentDeclaration - 1]);
+                    }
+                }
+                function canHaveSpanInParameterDeclaration(parameter) {
+                    return !!parameter.initializer || parameter.dotDotDotToken !== undefined ||
+                        !!(parameter.flags & 16) || !!(parameter.flags & 32);
+                }
+                function spanInParameterDeclaration(parameter) {
+                    if (canHaveSpanInParameterDeclaration(parameter)) {
+                        return textSpan(parameter);
+                    }
+                    else {
+                        var functionDeclaration = parameter.parent;
+                        var indexOfParameter = ts.indexOf(functionDeclaration.parameters, parameter);
+                        if (indexOfParameter) {
+                            return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
+                        }
+                        else {
+                            return spanInNode(functionDeclaration.body);
+                        }
+                    }
+                }
+                function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) {
+                    return !!(functionDeclaration.flags & 1) ||
+                        (functionDeclaration.parent.kind === 201 && functionDeclaration.kind !== 135);
+                }
+                function spanInFunctionDeclaration(functionDeclaration) {
+                    if (!functionDeclaration.body) {
+                        return undefined;
+                    }
+                    if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) {
+                        return textSpan(functionDeclaration);
+                    }
+                    return spanInNode(functionDeclaration.body);
+                }
+                function spanInFunctionBlock(block) {
+                    var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
+                    if (canFunctionHaveSpanInWholeDeclaration(block.parent)) {
+                        return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
+                    }
+                    return spanInNode(nodeForSpanInBlock);
+                }
+                function spanInBlock(block) {
+                    switch (block.parent.kind) {
+                        case 205:
+                            if (ts.getModuleInstanceState(block.parent) !== 1) {
+                                return undefined;
+                            }
+                        case 185:
+                        case 183:
+                        case 187:
+                        case 188:
+                            return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]);
+                        case 186:
+                            return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]);
+                    }
+                    return spanInNode(block.statements[0]);
+                }
+                function spanInForStatement(forStatement) {
+                    if (forStatement.initializer) {
+                        if (forStatement.initializer.kind === 199) {
+                            var variableDeclarationList = forStatement.initializer;
+                            if (variableDeclarationList.declarations.length > 0) {
+                                return spanInNode(variableDeclarationList.declarations[0]);
+                            }
+                        }
+                        else {
+                            return spanInNode(forStatement.initializer);
+                        }
+                    }
+                    if (forStatement.condition) {
+                        return textSpan(forStatement.condition);
+                    }
+                    if (forStatement.incrementor) {
+                        return textSpan(forStatement.incrementor);
+                    }
+                }
+                function spanInOpenBraceToken(node) {
+                    switch (node.parent.kind) {
+                        case 204:
+                            var enumDeclaration = node.parent;
+                            return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile));
+                        case 201:
+                            var classDeclaration = node.parent;
+                            return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile));
+                        case 207:
+                            return spanInNodeIfStartsOnSameLine(node.parent.parent, node.parent.clauses[0]);
+                    }
+                    return spanInNode(node.parent);
+                }
+                function spanInCloseBraceToken(node) {
+                    switch (node.parent.kind) {
+                        case 206:
+                            if (ts.getModuleInstanceState(node.parent.parent) !== 1) {
+                                return undefined;
+                            }
+                        case 204:
+                        case 201:
+                            return textSpan(node);
+                        case 179:
+                            if (ts.isFunctionBlock(node.parent)) {
+                                return textSpan(node);
+                            }
+                        case 223:
+                            return spanInNode(node.parent.statements[node.parent.statements.length - 1]);
+                            ;
+                        case 207:
+                            var caseBlock = node.parent;
+                            var lastClause = caseBlock.clauses[caseBlock.clauses.length - 1];
+                            if (lastClause) {
+                                return spanInNode(lastClause.statements[lastClause.statements.length - 1]);
+                            }
+                            return undefined;
+                        default:
+                            return spanInNode(node.parent);
+                    }
+                }
+                function spanInOpenParenToken(node) {
+                    if (node.parent.kind === 184) {
+                        return spanInPreviousNode(node);
+                    }
+                    return spanInNode(node.parent);
+                }
+                function spanInCloseParenToken(node) {
+                    switch (node.parent.kind) {
+                        case 162:
+                        case 200:
+                        case 163:
+                        case 134:
+                        case 133:
+                        case 136:
+                        case 137:
+                        case 135:
+                        case 185:
+                        case 184:
+                        case 186:
+                            return spanInPreviousNode(node);
+                        default:
+                            return spanInNode(node.parent);
+                    }
+                    return spanInNode(node.parent);
+                }
+                function spanInColonToken(node) {
+                    if (ts.isFunctionLike(node.parent) || node.parent.kind === 224) {
+                        return spanInPreviousNode(node);
+                    }
+                    return spanInNode(node.parent);
+                }
+                function spanInGreaterThanOrLessThanToken(node) {
+                    if (node.parent.kind === 160) {
+                        return spanInNode(node.parent.expression);
+                    }
+                    return spanInNode(node.parent);
+                }
+                function spanInWhileKeyword(node) {
+                    if (node.parent.kind === 184) {
+                        return textSpan(node, ts.findNextToken(node.parent.expression, node.parent));
+                    }
+                    return spanInNode(node.parent);
+                }
+            }
+        }
+        BreakpointResolver.spanInSourceFileAtLocation = spanInSourceFileAtLocation;
+    })(BreakpointResolver = ts.BreakpointResolver || (ts.BreakpointResolver = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/formatting.js b/dist/typescript/services/formatting/formatting.js
new file mode 100644
index 000000000..bb8fb661c
--- /dev/null
+++ b/dist/typescript/services/formatting/formatting.js
@@ -0,0 +1,747 @@
+///<reference path='..\services.ts' />
+///<reference path='formattingScanner.ts' />
+///<reference path='rulesProvider.ts' />
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var Constants;
+        (function (Constants) {
+            Constants[Constants["Unknown"] = -1] = "Unknown";
+        })(Constants || (Constants = {}));
+        function formatOnEnter(position, sourceFile, rulesProvider, options) {
+            var line = sourceFile.getLineAndCharacterOfPosition(position).line;
+            if (line === 0) {
+                return [];
+            }
+            var span = {
+                pos: ts.getStartPositionOfLine(line - 1, sourceFile),
+                end: ts.getEndLinePosition(line, sourceFile) + 1
+            };
+            return formatSpan(span, sourceFile, options, rulesProvider, 2);
+        }
+        formatting.formatOnEnter = formatOnEnter;
+        function formatOnSemicolon(position, sourceFile, rulesProvider, options) {
+            return formatOutermostParent(position, 22, sourceFile, options, rulesProvider, 3);
+        }
+        formatting.formatOnSemicolon = formatOnSemicolon;
+        function formatOnClosingCurly(position, sourceFile, rulesProvider, options) {
+            return formatOutermostParent(position, 15, sourceFile, options, rulesProvider, 4);
+        }
+        formatting.formatOnClosingCurly = formatOnClosingCurly;
+        function formatDocument(sourceFile, rulesProvider, options) {
+            var span = {
+                pos: 0,
+                end: sourceFile.text.length
+            };
+            return formatSpan(span, sourceFile, options, rulesProvider, 0);
+        }
+        formatting.formatDocument = formatDocument;
+        function formatSelection(start, end, sourceFile, rulesProvider, options) {
+            var span = {
+                pos: ts.getLineStartPositionForPosition(start, sourceFile),
+                end: end
+            };
+            return formatSpan(span, sourceFile, options, rulesProvider, 1);
+        }
+        formatting.formatSelection = formatSelection;
+        function formatOutermostParent(position, expectedLastToken, sourceFile, options, rulesProvider, requestKind) {
+            var parent = findOutermostParent(position, expectedLastToken, sourceFile);
+            if (!parent) {
+                return [];
+            }
+            var span = {
+                pos: ts.getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile),
+                end: parent.end
+            };
+            return formatSpan(span, sourceFile, options, rulesProvider, requestKind);
+        }
+        function findOutermostParent(position, expectedTokenKind, sourceFile) {
+            var precedingToken = ts.findPrecedingToken(position, sourceFile);
+            if (!precedingToken ||
+                precedingToken.kind !== expectedTokenKind ||
+                position !== precedingToken.getEnd()) {
+                return undefined;
+            }
+            var current = precedingToken;
+            while (current &&
+                current.parent &&
+                current.parent.end === precedingToken.end &&
+                !isListElement(current.parent, current)) {
+                current = current.parent;
+            }
+            return current;
+        }
+        function isListElement(parent, node) {
+            switch (parent.kind) {
+                case 201:
+                case 202:
+                    return ts.rangeContainsRange(parent.members, node);
+                case 205:
+                    var body = parent.body;
+                    return body && body.kind === 179 && ts.rangeContainsRange(body.statements, node);
+                case 227:
+                case 179:
+                case 206:
+                    return ts.rangeContainsRange(parent.statements, node);
+                case 223:
+                    return ts.rangeContainsRange(parent.block.statements, node);
+            }
+            return false;
+        }
+        function findEnclosingNode(range, sourceFile) {
+            return find(sourceFile);
+            function find(n) {
+                var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; });
+                if (candidate) {
+                    var result = find(candidate);
+                    if (result) {
+                        return result;
+                    }
+                }
+                return n;
+            }
+        }
+        function prepareRangeContainsErrorFunction(errors, originalRange) {
+            if (!errors.length) {
+                return rangeHasNoErrors;
+            }
+            var sorted = errors
+                .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); })
+                .sort(function (e1, e2) { return e1.start - e2.start; });
+            if (!sorted.length) {
+                return rangeHasNoErrors;
+            }
+            var index = 0;
+            return function (r) {
+                while (true) {
+                    if (index >= sorted.length) {
+                        return false;
+                    }
+                    var error = sorted[index];
+                    if (r.end <= error.start) {
+                        return false;
+                    }
+                    if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) {
+                        return true;
+                    }
+                    index++;
+                }
+            };
+            function rangeHasNoErrors(r) {
+                return false;
+            }
+        }
+        function getScanStartPosition(enclosingNode, originalRange, sourceFile) {
+            var start = enclosingNode.getStart(sourceFile);
+            if (start === originalRange.pos && enclosingNode.end === originalRange.end) {
+                return start;
+            }
+            var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile);
+            if (!precedingToken) {
+                return enclosingNode.pos;
+            }
+            if (precedingToken.end >= originalRange.pos) {
+                return enclosingNode.pos;
+            }
+            return precedingToken.end;
+        }
+        function getOwnOrInheritedDelta(n, options, sourceFile) {
+            var previousLine = -1;
+            var childKind = 0;
+            while (n) {
+                var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
+                if (previousLine !== -1 && line !== previousLine) {
+                    break;
+                }
+                if (formatting.SmartIndenter.shouldIndentChildNode(n.kind, childKind)) {
+                    return options.IndentSize;
+                }
+                previousLine = line;
+                childKind = n.kind;
+                n = n.parent;
+            }
+            return 0;
+        }
+        function formatSpan(originalRange, sourceFile, options, rulesProvider, requestKind) {
+            var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
+            var formattingContext = new formatting.FormattingContext(sourceFile, requestKind);
+            var enclosingNode = findEnclosingNode(originalRange, sourceFile);
+            var formattingScanner = formatting.getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
+            var initialIndentation = formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
+            var previousRangeHasError;
+            var previousRange;
+            var previousParent;
+            var previousRangeStartLine;
+            var edits = [];
+            formattingScanner.advance();
+            if (formattingScanner.isOnToken()) {
+                var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
+                var undecoratedStartLine = startLine;
+                if (enclosingNode.decorators) {
+                    undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
+                }
+                var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
+                processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
+            }
+            formattingScanner.close();
+            return edits;
+            function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) {
+                if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos)) {
+                    if (inheritedIndentation !== -1) {
+                        return inheritedIndentation;
+                    }
+                }
+                else {
+                    var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
+                    var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile);
+                    var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
+                    if (startLine !== parentStartLine || startPos === column) {
+                        return column;
+                    }
+                }
+                return -1;
+            }
+            function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) {
+                var indentation = inheritedIndentation;
+                if (indentation === -1) {
+                    if (isSomeBlock(node.kind)) {
+                        if (isSomeBlock(parent.kind) ||
+                            parent.kind === 227 ||
+                            parent.kind === 220 ||
+                            parent.kind === 221) {
+                            indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
+                        }
+                        else {
+                            indentation = parentDynamicIndentation.getIndentation();
+                        }
+                    }
+                    else {
+                        if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
+                            indentation = parentDynamicIndentation.getIndentation();
+                        }
+                        else {
+                            indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
+                        }
+                    }
+                }
+                var delta = formatting.SmartIndenter.shouldIndentChildNode(node.kind, 0) ? options.IndentSize : 0;
+                if (effectiveParentStartLine === startLine) {
+                    indentation = parentDynamicIndentation.getIndentation();
+                    delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
+                }
+                return {
+                    indentation: indentation,
+                    delta: delta
+                };
+            }
+            function getFirstNonDecoratorTokenOfNode(node) {
+                if (node.modifiers && node.modifiers.length) {
+                    return node.modifiers[0].kind;
+                }
+                switch (node.kind) {
+                    case 201: return 69;
+                    case 202: return 103;
+                    case 200: return 83;
+                    case 204: return 204;
+                    case 136: return 116;
+                    case 137: return 120;
+                    case 134:
+                        if (node.asteriskToken) {
+                            return 35;
+                        }
+                    case 132:
+                    case 129:
+                        return node.name.kind;
+                }
+            }
+            function getDynamicIndentation(node, nodeStartLine, indentation, delta) {
+                return {
+                    getIndentationForComment: function (kind) {
+                        switch (kind) {
+                            case 15:
+                            case 19:
+                                return indentation + delta;
+                        }
+                        return indentation;
+                    },
+                    getIndentationForToken: function (line, kind) {
+                        if (nodeStartLine !== line && node.decorators) {
+                            if (kind === getFirstNonDecoratorTokenOfNode(node)) {
+                                return indentation;
+                            }
+                        }
+                        switch (kind) {
+                            case 14:
+                            case 15:
+                            case 18:
+                            case 19:
+                            case 76:
+                            case 100:
+                            case 52:
+                                return indentation;
+                            default:
+                                return nodeStartLine !== line ? indentation + delta : indentation;
+                        }
+                    },
+                    getIndentation: function () { return indentation; },
+                    getDelta: function () { return delta; },
+                    recomputeIndentation: function (lineAdded) {
+                        if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent.kind, node.kind)) {
+                            if (lineAdded) {
+                                indentation += options.IndentSize;
+                            }
+                            else {
+                                indentation -= options.IndentSize;
+                            }
+                            if (formatting.SmartIndenter.shouldIndentChildNode(node.kind, 0)) {
+                                delta = options.IndentSize;
+                            }
+                            else {
+                                delta = 0;
+                            }
+                        }
+                    },
+                };
+            }
+            function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) {
+                if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) {
+                    return;
+                }
+                var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
+                var childContextNode = contextNode;
+                ts.forEachChild(node, function (child) {
+                    processChildNode(child, -1, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, false);
+                }, function (nodes) {
+                    processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation);
+                });
+                while (formattingScanner.isOnToken()) {
+                    var tokenInfo = formattingScanner.readTokenInfo(node);
+                    if (tokenInfo.token.end > node.end) {
+                        break;
+                    }
+                    consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation);
+                }
+                function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem) {
+                    var childStartPos = child.getStart(sourceFile);
+                    var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line;
+                    var undecoratedChildStartLine = childStartLine;
+                    if (child.decorators) {
+                        undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line;
+                    }
+                    var childIndentationAmount = -1;
+                    if (isListItem) {
+                        childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
+                        if (childIndentationAmount !== -1) {
+                            inheritedIndentation = childIndentationAmount;
+                        }
+                    }
+                    if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
+                        return inheritedIndentation;
+                    }
+                    if (child.getFullWidth() === 0) {
+                        return inheritedIndentation;
+                    }
+                    while (formattingScanner.isOnToken()) {
+                        var tokenInfo = formattingScanner.readTokenInfo(node);
+                        if (tokenInfo.token.end > childStartPos) {
+                            break;
+                        }
+                        consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
+                    }
+                    if (!formattingScanner.isOnToken()) {
+                        return inheritedIndentation;
+                    }
+                    if (ts.isToken(child)) {
+                        var tokenInfo = formattingScanner.readTokenInfo(child);
+                        ts.Debug.assert(tokenInfo.token.end === child.end);
+                        consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
+                        return inheritedIndentation;
+                    }
+                    var effectiveParentStartLine = child.kind === 130 ? childStartLine : undecoratedParentStartLine;
+                    var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine);
+                    processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta);
+                    childContextNode = node;
+                    return inheritedIndentation;
+                }
+                function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) {
+                    var listStartToken = getOpenTokenForList(parent, nodes);
+                    var listEndToken = getCloseTokenForOpenToken(listStartToken);
+                    var listDynamicIndentation = parentDynamicIndentation;
+                    var startLine = parentStartLine;
+                    if (listStartToken !== 0) {
+                        while (formattingScanner.isOnToken()) {
+                            var tokenInfo = formattingScanner.readTokenInfo(parent);
+                            if (tokenInfo.token.end > nodes.pos) {
+                                break;
+                            }
+                            else if (tokenInfo.token.kind === listStartToken) {
+                                startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
+                                var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1, parent, parentDynamicIndentation, startLine);
+                                listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta);
+                                consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
+                            }
+                            else {
+                                consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation);
+                            }
+                        }
+                    }
+                    var inheritedIndentation = -1;
+                    for (var _i = 0; _i < nodes.length; _i++) {
+                        var child = nodes[_i];
+                        inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, true);
+                    }
+                    if (listEndToken !== 0) {
+                        if (formattingScanner.isOnToken()) {
+                            var tokenInfo = formattingScanner.readTokenInfo(parent);
+                            if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) {
+                                consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
+                            }
+                        }
+                    }
+                }
+                function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation) {
+                    ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token));
+                    var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
+                    var indentToken = false;
+                    if (currentTokenInfo.leadingTrivia) {
+                        processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation);
+                    }
+                    var lineAdded;
+                    var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token);
+                    var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
+                    if (isTokenInRange) {
+                        var rangeHasError = rangeContainsError(currentTokenInfo.token);
+                        var prevStartLine = previousRangeStartLine;
+                        lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
+                        if (rangeHasError) {
+                            indentToken = false;
+                        }
+                        else {
+                            if (lineAdded !== undefined) {
+                                indentToken = lineAdded;
+                            }
+                            else {
+                                indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine;
+                            }
+                        }
+                    }
+                    if (currentTokenInfo.trailingTrivia) {
+                        processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation);
+                    }
+                    if (indentToken) {
+                        var indentNextTokenOrTrivia = true;
+                        if (currentTokenInfo.leadingTrivia) {
+                            for (var _i = 0, _a = currentTokenInfo.leadingTrivia; _i < _a.length; _i++) {
+                                var triviaItem = _a[_i];
+                                if (!ts.rangeContainsRange(originalRange, triviaItem)) {
+                                    continue;
+                                }
+                                var triviaStartLine = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos).line;
+                                switch (triviaItem.kind) {
+                                    case 3:
+                                        var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
+                                        indentMultilineComment(triviaItem, commentIndentation, !indentNextTokenOrTrivia);
+                                        indentNextTokenOrTrivia = false;
+                                        break;
+                                    case 2:
+                                        if (indentNextTokenOrTrivia) {
+                                            var commentIndentation_1 = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
+                                            insertIndentation(triviaItem.pos, commentIndentation_1, false);
+                                            indentNextTokenOrTrivia = false;
+                                        }
+                                        break;
+                                    case 4:
+                                        indentNextTokenOrTrivia = true;
+                                        break;
+                                }
+                            }
+                        }
+                        if (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) {
+                            var tokenIndentation = dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind);
+                            insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
+                        }
+                    }
+                    formattingScanner.advance();
+                    childContextNode = parent;
+                }
+            }
+            function processTrivia(trivia, parent, contextNode, dynamicIndentation) {
+                for (var _i = 0; _i < trivia.length; _i++) {
+                    var triviaItem = trivia[_i];
+                    if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) {
+                        var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
+                        processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation);
+                    }
+                }
+            }
+            function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) {
+                var rangeHasError = rangeContainsError(range);
+                var lineAdded;
+                if (!rangeHasError && !previousRangeHasError) {
+                    if (!previousRange) {
+                        var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
+                        trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
+                    }
+                    else {
+                        lineAdded =
+                            processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation);
+                    }
+                }
+                previousRange = range;
+                previousParent = parent;
+                previousRangeStartLine = rangeStart.line;
+                previousRangeHasError = rangeHasError;
+                return lineAdded;
+            }
+            function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) {
+                formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
+                var rule = rulesProvider.getRulesMap().GetRule(formattingContext);
+                var trimTrailingWhitespaces;
+                var lineAdded;
+                if (rule) {
+                    applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
+                    if (rule.Operation.Action & (2 | 8) && currentStartLine !== previousStartLine) {
+                        lineAdded = false;
+                        if (currentParent.getStart(sourceFile) === currentItem.pos) {
+                            dynamicIndentation.recomputeIndentation(false);
+                        }
+                    }
+                    else if (rule.Operation.Action & 4 && currentStartLine === previousStartLine) {
+                        lineAdded = true;
+                        if (currentParent.getStart(sourceFile) === currentItem.pos) {
+                            dynamicIndentation.recomputeIndentation(true);
+                        }
+                    }
+                    trimTrailingWhitespaces =
+                        (rule.Operation.Action & (4 | 2)) &&
+                            rule.Flag !== 1;
+                }
+                else {
+                    trimTrailingWhitespaces = true;
+                }
+                if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) {
+                    trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem);
+                }
+                return lineAdded;
+            }
+            function insertIndentation(pos, indentation, lineAdded) {
+                var indentationString = getIndentationString(indentation, options);
+                if (lineAdded) {
+                    recordReplace(pos, 0, indentationString);
+                }
+                else {
+                    var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
+                    if (indentation !== tokenStart.character) {
+                        var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile);
+                        recordReplace(startLinePosition, tokenStart.character, indentationString);
+                    }
+                }
+            }
+            function indentMultilineComment(commentRange, indentation, firstLineIsIndented) {
+                var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
+                var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
+                var parts;
+                if (startLine === endLine) {
+                    if (!firstLineIsIndented) {
+                        insertIndentation(commentRange.pos, indentation, false);
+                    }
+                    return;
+                }
+                else {
+                    parts = [];
+                    var startPos = commentRange.pos;
+                    for (var line = startLine; line < endLine; ++line) {
+                        var endOfLine = ts.getEndLinePosition(line, sourceFile);
+                        parts.push({ pos: startPos, end: endOfLine });
+                        startPos = ts.getStartPositionOfLine(line + 1, sourceFile);
+                    }
+                    parts.push({ pos: startPos, end: commentRange.end });
+                }
+                var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile);
+                var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
+                if (indentation === nonWhitespaceColumnInFirstPart.column) {
+                    return;
+                }
+                var startIndex = 0;
+                if (firstLineIsIndented) {
+                    startIndex = 1;
+                    startLine++;
+                }
+                var delta = indentation - nonWhitespaceColumnInFirstPart.column;
+                for (var i = startIndex, len = parts.length; i < len; ++i, ++startLine) {
+                    var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile);
+                    var nonWhitespaceCharacterAndColumn = i === 0
+                        ? nonWhitespaceColumnInFirstPart
+                        : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
+                    var newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
+                    if (newIndentation > 0) {
+                        var indentationString = getIndentationString(newIndentation, options);
+                        recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString);
+                    }
+                    else {
+                        recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character);
+                    }
+                }
+            }
+            function trimTrailingWhitespacesForLines(line1, line2, range) {
+                for (var line = line1; line < line2; ++line) {
+                    var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile);
+                    var lineEndPosition = ts.getEndLinePosition(line, sourceFile);
+                    if (range && ts.isComment(range.kind) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
+                        continue;
+                    }
+                    var pos = lineEndPosition;
+                    while (pos >= lineStartPosition && ts.isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
+                        pos--;
+                    }
+                    if (pos !== lineEndPosition) {
+                        ts.Debug.assert(pos === lineStartPosition || !ts.isWhiteSpace(sourceFile.text.charCodeAt(pos)));
+                        recordDelete(pos + 1, lineEndPosition - pos);
+                    }
+                }
+            }
+            function newTextChange(start, len, newText) {
+                return { span: ts.createTextSpan(start, len), newText: newText };
+            }
+            function recordDelete(start, len) {
+                if (len) {
+                    edits.push(newTextChange(start, len, ""));
+                }
+            }
+            function recordReplace(start, len, newText) {
+                if (len || newText) {
+                    edits.push(newTextChange(start, len, newText));
+                }
+            }
+            function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) {
+                var between;
+                switch (rule.Operation.Action) {
+                    case 1:
+                        return;
+                    case 8:
+                        if (previousRange.end !== currentRange.pos) {
+                            recordDelete(previousRange.end, currentRange.pos - previousRange.end);
+                        }
+                        break;
+                    case 4:
+                        if (rule.Flag !== 1 && previousStartLine !== currentStartLine) {
+                            return;
+                        }
+                        var lineDelta = currentStartLine - previousStartLine;
+                        if (lineDelta !== 1) {
+                            recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter);
+                        }
+                        break;
+                    case 2:
+                        if (rule.Flag !== 1 && previousStartLine !== currentStartLine) {
+                            return;
+                        }
+                        var posDelta = currentRange.pos - previousRange.end;
+                        if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32) {
+                            recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
+                        }
+                        break;
+                }
+            }
+        }
+        function isSomeBlock(kind) {
+            switch (kind) {
+                case 179:
+                case 206:
+                    return true;
+            }
+            return false;
+        }
+        function getOpenTokenForList(node, list) {
+            switch (node.kind) {
+                case 135:
+                case 200:
+                case 162:
+                case 134:
+                case 133:
+                case 163:
+                    if (node.typeParameters === list) {
+                        return 24;
+                    }
+                    else if (node.parameters === list) {
+                        return 16;
+                    }
+                    break;
+                case 157:
+                case 158:
+                    if (node.typeArguments === list) {
+                        return 24;
+                    }
+                    else if (node.arguments === list) {
+                        return 16;
+                    }
+                    break;
+                case 141:
+                    if (node.typeArguments === list) {
+                        return 24;
+                    }
+            }
+            return 0;
+        }
+        function getCloseTokenForOpenToken(kind) {
+            switch (kind) {
+                case 16:
+                    return 17;
+                case 24:
+                    return 25;
+            }
+            return 0;
+        }
+        var internedSizes;
+        var internedTabsIndentation;
+        var internedSpacesIndentation;
+        function getIndentationString(indentation, options) {
+            var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize);
+            if (resetInternedStrings) {
+                internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize };
+                internedTabsIndentation = internedSpacesIndentation = undefined;
+            }
+            if (!options.ConvertTabsToSpaces) {
+                var tabs = Math.floor(indentation / options.TabSize);
+                var spaces = indentation - tabs * options.TabSize;
+                var tabString;
+                if (!internedTabsIndentation) {
+                    internedTabsIndentation = [];
+                }
+                if (internedTabsIndentation[tabs] === undefined) {
+                    internedTabsIndentation[tabs] = tabString = repeat('\t', tabs);
+                }
+                else {
+                    tabString = internedTabsIndentation[tabs];
+                }
+                return spaces ? tabString + repeat(" ", spaces) : tabString;
+            }
+            else {
+                var spacesString;
+                var quotient = Math.floor(indentation / options.IndentSize);
+                var remainder = indentation % options.IndentSize;
+                if (!internedSpacesIndentation) {
+                    internedSpacesIndentation = [];
+                }
+                if (internedSpacesIndentation[quotient] === undefined) {
+                    spacesString = repeat(" ", options.IndentSize * quotient);
+                    internedSpacesIndentation[quotient] = spacesString;
+                }
+                else {
+                    spacesString = internedSpacesIndentation[quotient];
+                }
+                return remainder ? spacesString + repeat(" ", remainder) : spacesString;
+            }
+            function repeat(value, count) {
+                var s = "";
+                for (var i = 0; i < count; ++i) {
+                    s += value;
+                }
+                return s;
+            }
+        }
+        formatting.getIndentationString = getIndentationString;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/formattingContext.js b/dist/typescript/services/formatting/formattingContext.js
new file mode 100644
index 000000000..bd40c24fa
--- /dev/null
+++ b/dist/typescript/services/formatting/formattingContext.js
@@ -0,0 +1,79 @@
+/// <reference path="references.ts"/>
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var FormattingContext = (function () {
+            function FormattingContext(sourceFile, formattingRequestKind) {
+                this.sourceFile = sourceFile;
+                this.formattingRequestKind = formattingRequestKind;
+            }
+            FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) {
+                ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null");
+                ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null");
+                ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null");
+                ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null");
+                ts.Debug.assert(commonParent !== undefined, "commonParent is null");
+                this.currentTokenSpan = currentRange;
+                this.currentTokenParent = currentTokenParent;
+                this.nextTokenSpan = nextRange;
+                this.nextTokenParent = nextTokenParent;
+                this.contextNode = commonParent;
+                this.contextNodeAllOnSameLine = undefined;
+                this.nextNodeAllOnSameLine = undefined;
+                this.tokensAreOnSameLine = undefined;
+                this.contextNodeBlockIsOnOneLine = undefined;
+                this.nextNodeBlockIsOnOneLine = undefined;
+            };
+            FormattingContext.prototype.ContextNodeAllOnSameLine = function () {
+                if (this.contextNodeAllOnSameLine === undefined) {
+                    this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
+                }
+                return this.contextNodeAllOnSameLine;
+            };
+            FormattingContext.prototype.NextNodeAllOnSameLine = function () {
+                if (this.nextNodeAllOnSameLine === undefined) {
+                    this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
+                }
+                return this.nextNodeAllOnSameLine;
+            };
+            FormattingContext.prototype.TokensAreOnSameLine = function () {
+                if (this.tokensAreOnSameLine === undefined) {
+                    var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
+                    var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
+                    this.tokensAreOnSameLine = (startLine == endLine);
+                }
+                return this.tokensAreOnSameLine;
+            };
+            FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () {
+                if (this.contextNodeBlockIsOnOneLine === undefined) {
+                    this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
+                }
+                return this.contextNodeBlockIsOnOneLine;
+            };
+            FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () {
+                if (this.nextNodeBlockIsOnOneLine === undefined) {
+                    this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
+                }
+                return this.nextNodeBlockIsOnOneLine;
+            };
+            FormattingContext.prototype.NodeIsOnOneLine = function (node) {
+                var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
+                var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
+                return startLine == endLine;
+            };
+            FormattingContext.prototype.BlockIsOnOneLine = function (node) {
+                var openBrace = ts.findChildOfKind(node, 14, this.sourceFile);
+                var closeBrace = ts.findChildOfKind(node, 15, this.sourceFile);
+                if (openBrace && closeBrace) {
+                    var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
+                    var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
+                    return startLine === endLine;
+                }
+                return false;
+            };
+            return FormattingContext;
+        })();
+        formatting.FormattingContext = FormattingContext;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/formattingRequestKind.js b/dist/typescript/services/formatting/formattingRequestKind.js
new file mode 100644
index 000000000..1b32c464d
--- /dev/null
+++ b/dist/typescript/services/formatting/formattingRequestKind.js
@@ -0,0 +1,15 @@
+/// <reference path="references.ts"/>
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        (function (FormattingRequestKind) {
+            FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument";
+            FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection";
+            FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter";
+            FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon";
+            FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace";
+        })(formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {}));
+        var FormattingRequestKind = formatting.FormattingRequestKind;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/formattingScanner.js b/dist/typescript/services/formatting/formattingScanner.js
new file mode 100644
index 000000000..0e3022521
--- /dev/null
+++ b/dist/typescript/services/formatting/formattingScanner.js
@@ -0,0 +1,184 @@
+/// <reference path="formatting.ts"/>
+/// <reference path="..\..\compiler\scanner.ts"/>
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var scanner = ts.createScanner(2, false);
+        var ScanAction;
+        (function (ScanAction) {
+            ScanAction[ScanAction["Scan"] = 0] = "Scan";
+            ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken";
+            ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken";
+            ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken";
+        })(ScanAction || (ScanAction = {}));
+        function getFormattingScanner(sourceFile, startPos, endPos) {
+            scanner.setText(sourceFile.text);
+            scanner.setTextPos(startPos);
+            var wasNewLine = true;
+            var leadingTrivia;
+            var trailingTrivia;
+            var savedPos;
+            var lastScanAction;
+            var lastTokenInfo;
+            return {
+                advance: advance,
+                readTokenInfo: readTokenInfo,
+                isOnToken: isOnToken,
+                lastTrailingTriviaWasNewLine: function () { return wasNewLine; },
+                close: function () {
+                    lastTokenInfo = undefined;
+                    scanner.setText(undefined);
+                }
+            };
+            function advance() {
+                lastTokenInfo = undefined;
+                var isStarted = scanner.getStartPos() !== startPos;
+                if (isStarted) {
+                    if (trailingTrivia) {
+                        ts.Debug.assert(trailingTrivia.length !== 0);
+                        wasNewLine = trailingTrivia[trailingTrivia.length - 1].kind === 4;
+                    }
+                    else {
+                        wasNewLine = false;
+                    }
+                }
+                leadingTrivia = undefined;
+                trailingTrivia = undefined;
+                if (!isStarted) {
+                    scanner.scan();
+                }
+                var t;
+                var pos = scanner.getStartPos();
+                while (pos < endPos) {
+                    var t_1 = scanner.getToken();
+                    if (!ts.isTrivia(t_1)) {
+                        break;
+                    }
+                    scanner.scan();
+                    var item_1 = {
+                        pos: pos,
+                        end: scanner.getStartPos(),
+                        kind: t_1
+                    };
+                    pos = scanner.getStartPos();
+                    if (!leadingTrivia) {
+                        leadingTrivia = [];
+                    }
+                    leadingTrivia.push(item_1);
+                }
+                savedPos = scanner.getStartPos();
+            }
+            function shouldRescanGreaterThanToken(node) {
+                if (node) {
+                    switch (node.kind) {
+                        case 27:
+                        case 60:
+                        case 61:
+                        case 42:
+                        case 41:
+                            return true;
+                    }
+                }
+                return false;
+            }
+            function shouldRescanSlashToken(container) {
+                return container.kind === 9;
+            }
+            function shouldRescanTemplateToken(container) {
+                return container.kind === 12 ||
+                    container.kind === 13;
+            }
+            function startsWithSlashToken(t) {
+                return t === 36 || t === 57;
+            }
+            function readTokenInfo(n) {
+                if (!isOnToken()) {
+                    return {
+                        leadingTrivia: leadingTrivia,
+                        trailingTrivia: undefined,
+                        token: undefined
+                    };
+                }
+                var expectedScanAction = shouldRescanGreaterThanToken(n)
+                    ? 1
+                    : shouldRescanSlashToken(n)
+                        ? 2
+                        : shouldRescanTemplateToken(n)
+                            ? 3
+                            : 0;
+                if (lastTokenInfo && expectedScanAction === lastScanAction) {
+                    return fixTokenKind(lastTokenInfo, n);
+                }
+                if (scanner.getStartPos() !== savedPos) {
+                    ts.Debug.assert(lastTokenInfo !== undefined);
+                    scanner.setTextPos(savedPos);
+                    scanner.scan();
+                }
+                var currentToken = scanner.getToken();
+                if (expectedScanAction === 1 && currentToken === 25) {
+                    currentToken = scanner.reScanGreaterToken();
+                    ts.Debug.assert(n.kind === currentToken);
+                    lastScanAction = 1;
+                }
+                else if (expectedScanAction === 2 && startsWithSlashToken(currentToken)) {
+                    currentToken = scanner.reScanSlashToken();
+                    ts.Debug.assert(n.kind === currentToken);
+                    lastScanAction = 2;
+                }
+                else if (expectedScanAction === 3 && currentToken === 15) {
+                    currentToken = scanner.reScanTemplateToken();
+                    lastScanAction = 3;
+                }
+                else {
+                    lastScanAction = 0;
+                }
+                var token = {
+                    pos: scanner.getStartPos(),
+                    end: scanner.getTextPos(),
+                    kind: currentToken
+                };
+                if (trailingTrivia) {
+                    trailingTrivia = undefined;
+                }
+                while (scanner.getStartPos() < endPos) {
+                    currentToken = scanner.scan();
+                    if (!ts.isTrivia(currentToken)) {
+                        break;
+                    }
+                    var trivia = {
+                        pos: scanner.getStartPos(),
+                        end: scanner.getTextPos(),
+                        kind: currentToken
+                    };
+                    if (!trailingTrivia) {
+                        trailingTrivia = [];
+                    }
+                    trailingTrivia.push(trivia);
+                    if (currentToken === 4) {
+                        scanner.scan();
+                        break;
+                    }
+                }
+                lastTokenInfo = {
+                    leadingTrivia: leadingTrivia,
+                    trailingTrivia: trailingTrivia,
+                    token: token
+                };
+                return fixTokenKind(lastTokenInfo, n);
+            }
+            function isOnToken() {
+                var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
+                var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
+                return startPos < endPos && current !== 1 && !ts.isTrivia(current);
+            }
+            function fixTokenKind(tokenInfo, container) {
+                if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) {
+                    tokenInfo.token.kind = container.kind;
+                }
+                return tokenInfo;
+            }
+        }
+        formatting.getFormattingScanner = getFormattingScanner;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/references.js b/dist/typescript/services/formatting/references.js
new file mode 100644
index 000000000..5a854c4e8
--- /dev/null
+++ b/dist/typescript/services/formatting/references.js
@@ -0,0 +1,12 @@
+///<reference path='..\services.ts' />
+///<reference path='formattingContext.ts' />
+///<reference path='formattingRequestKind.ts' />
+///<reference path='rule.ts' />
+///<reference path='ruleAction.ts' />
+///<reference path='ruleDescriptor.ts' />
+///<reference path='ruleFlag.ts' />
+///<reference path='ruleOperation.ts' />
+///<reference path='ruleOperationContext.ts' />
+///<reference path='rules.ts' />
+///<reference path='rulesMap.ts' />
+///<reference path='tokenRange.ts' /> 
diff --git a/dist/typescript/services/formatting/rule.js b/dist/typescript/services/formatting/rule.js
new file mode 100644
index 000000000..d96fb232e
--- /dev/null
+++ b/dist/typescript/services/formatting/rule.js
@@ -0,0 +1,22 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var Rule = (function () {
+            function Rule(Descriptor, Operation, Flag) {
+                if (Flag === void 0) { Flag = 0; }
+                this.Descriptor = Descriptor;
+                this.Operation = Operation;
+                this.Flag = Flag;
+            }
+            Rule.prototype.toString = function () {
+                return "[desc=" + this.Descriptor + "," +
+                    "operation=" + this.Operation + "," +
+                    "flag=" + this.Flag + "]";
+            };
+            return Rule;
+        })();
+        formatting.Rule = Rule;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/ruleAction.js b/dist/typescript/services/formatting/ruleAction.js
new file mode 100644
index 000000000..201e3c669
--- /dev/null
+++ b/dist/typescript/services/formatting/ruleAction.js
@@ -0,0 +1,14 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        (function (RuleAction) {
+            RuleAction[RuleAction["Ignore"] = 1] = "Ignore";
+            RuleAction[RuleAction["Space"] = 2] = "Space";
+            RuleAction[RuleAction["NewLine"] = 4] = "NewLine";
+            RuleAction[RuleAction["Delete"] = 8] = "Delete";
+        })(formatting.RuleAction || (formatting.RuleAction = {}));
+        var RuleAction = formatting.RuleAction;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/ruleDescriptor.js b/dist/typescript/services/formatting/ruleDescriptor.js
new file mode 100644
index 000000000..38e69aabe
--- /dev/null
+++ b/dist/typescript/services/formatting/ruleDescriptor.js
@@ -0,0 +1,31 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var RuleDescriptor = (function () {
+            function RuleDescriptor(LeftTokenRange, RightTokenRange) {
+                this.LeftTokenRange = LeftTokenRange;
+                this.RightTokenRange = RightTokenRange;
+            }
+            RuleDescriptor.prototype.toString = function () {
+                return "[leftRange=" + this.LeftTokenRange + "," +
+                    "rightRange=" + this.RightTokenRange + "]";
+            };
+            RuleDescriptor.create1 = function (left, right) {
+                return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), formatting.Shared.TokenRange.FromToken(right));
+            };
+            RuleDescriptor.create2 = function (left, right) {
+                return RuleDescriptor.create4(left, formatting.Shared.TokenRange.FromToken(right));
+            };
+            RuleDescriptor.create3 = function (left, right) {
+                return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), right);
+            };
+            RuleDescriptor.create4 = function (left, right) {
+                return new RuleDescriptor(left, right);
+            };
+            return RuleDescriptor;
+        })();
+        formatting.RuleDescriptor = RuleDescriptor;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/ruleFlag.js b/dist/typescript/services/formatting/ruleFlag.js
new file mode 100644
index 000000000..298f9a28d
--- /dev/null
+++ b/dist/typescript/services/formatting/ruleFlag.js
@@ -0,0 +1,12 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        (function (RuleFlags) {
+            RuleFlags[RuleFlags["None"] = 0] = "None";
+            RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines";
+        })(formatting.RuleFlags || (formatting.RuleFlags = {}));
+        var RuleFlags = formatting.RuleFlags;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/ruleOperation.js b/dist/typescript/services/formatting/ruleOperation.js
new file mode 100644
index 000000000..52558928e
--- /dev/null
+++ b/dist/typescript/services/formatting/ruleOperation.js
@@ -0,0 +1,28 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var RuleOperation = (function () {
+            function RuleOperation() {
+                this.Context = null;
+                this.Action = null;
+            }
+            RuleOperation.prototype.toString = function () {
+                return "[context=" + this.Context + "," +
+                    "action=" + this.Action + "]";
+            };
+            RuleOperation.create1 = function (action) {
+                return RuleOperation.create2(formatting.RuleOperationContext.Any, action);
+            };
+            RuleOperation.create2 = function (context, action) {
+                var result = new RuleOperation();
+                result.Context = context;
+                result.Action = action;
+                return result;
+            };
+            return RuleOperation;
+        })();
+        formatting.RuleOperation = RuleOperation;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/ruleOperationContext.js b/dist/typescript/services/formatting/ruleOperationContext.js
new file mode 100644
index 000000000..0fc174a3b
--- /dev/null
+++ b/dist/typescript/services/formatting/ruleOperationContext.js
@@ -0,0 +1,34 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var RuleOperationContext = (function () {
+            function RuleOperationContext() {
+                var funcs = [];
+                for (var _i = 0; _i < arguments.length; _i++) {
+                    funcs[_i - 0] = arguments[_i];
+                }
+                this.customContextChecks = funcs;
+            }
+            RuleOperationContext.prototype.IsAny = function () {
+                return this == RuleOperationContext.Any;
+            };
+            RuleOperationContext.prototype.InContext = function (context) {
+                if (this.IsAny()) {
+                    return true;
+                }
+                for (var _i = 0, _a = this.customContextChecks; _i < _a.length; _i++) {
+                    var check = _a[_i];
+                    if (!check(context)) {
+                        return false;
+                    }
+                }
+                return true;
+            };
+            RuleOperationContext.Any = new RuleOperationContext();
+            return RuleOperationContext;
+        })();
+        formatting.RuleOperationContext = RuleOperationContext;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/rules.js b/dist/typescript/services/formatting/rules.js
new file mode 100644
index 000000000..ecb95c7b1
--- /dev/null
+++ b/dist/typescript/services/formatting/rules.js
@@ -0,0 +1,378 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var Rules = (function () {
+            function Rules() {
+                ///
+                /// Common Rules
+                ///
+                this.IgnoreBeforeComment = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.Comments), formatting.RuleOperation.create1(1));
+                this.IgnoreAfterLineComment = new formatting.Rule(formatting.RuleDescriptor.create3(2, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create1(1));
+                this.NoSpaceBeforeSemicolon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 22), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceBeforeColon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 51), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
+                this.NoSpaceBeforeQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 50), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
+                this.SpaceAfterColon = new formatting.Rule(formatting.RuleDescriptor.create3(51, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 2));
+                this.SpaceAfterQuestionMarkInConditionalOperator = new formatting.Rule(formatting.RuleDescriptor.create3(50, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsConditionalOperatorContext), 2));
+                this.NoSpaceAfterQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create3(50, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceAfterSemicolon = new formatting.Rule(formatting.RuleDescriptor.create3(22, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.SpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsAfterCodeBlockContext), 2));
+                this.SpaceBetweenCloseBraceAndElse = new formatting.Rule(formatting.RuleDescriptor.create1(15, 76), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.SpaceBetweenCloseBraceAndWhile = new formatting.Rule(formatting.RuleDescriptor.create1(15, 100), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.NoSpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15, formatting.Shared.TokenRange.FromTokens([17, 19, 23, 22])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceBeforeDot = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceAfterDot = new formatting.Rule(formatting.RuleDescriptor.create3(20, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceBeforeOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(18, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 19), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceAfterCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.FunctionOpenBraceLeftTokenRange = formatting.Shared.TokenRange.AnyIncludingMultilineComments;
+                this.SpaceBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2), 1);
+                this.TypeScriptOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([65, 3]);
+                this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2), 1);
+                this.ControlOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([17, 3, 75, 96, 81, 76]);
+                this.SpaceBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2), 1);
+                this.SpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(14, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2));
+                this.SpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2));
+                this.NoSpaceBetweenEmptyBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(14, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectContext), 8));
+                this.NewLineAfterOpenBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create3(14, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4));
+                this.NewLineBeforeCloseBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.AnyIncludingMultilineComments, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4));
+                this.NoSpaceAfterUnaryPrefixOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.UnaryPrefixOperators, formatting.Shared.TokenRange.UnaryPrefixExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
+                this.NoSpaceAfterUnaryPreincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(38, formatting.Shared.TokenRange.UnaryPreincrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceAfterUnaryPredecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(39, formatting.Shared.TokenRange.UnaryPredecrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceBeforeUnaryPostincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostincrementExpressions, 38), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceBeforeUnaryPostdecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 39), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceAfterPostincrementWhenFollowedByAdd = new formatting.Rule(formatting.RuleDescriptor.create1(38, 33), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.SpaceAfterAddWhenFollowedByUnaryPlus = new formatting.Rule(formatting.RuleDescriptor.create1(33, 33), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.SpaceAfterAddWhenFollowedByPreincrement = new formatting.Rule(formatting.RuleDescriptor.create1(33, 38), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.SpaceAfterPostdecrementWhenFollowedBySubtract = new formatting.Rule(formatting.RuleDescriptor.create1(39, 34), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new formatting.Rule(formatting.RuleDescriptor.create1(34, 34), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.SpaceAfterSubtractWhenFollowedByPredecrement = new formatting.Rule(formatting.RuleDescriptor.create1(34, 39), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.NoSpaceBeforeComma = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 23), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceAfterCertainKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([98, 94, 88, 74, 90, 97]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.SpaceAfterLetConstInVariableDeclaration = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([104, 70]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), 2));
+                this.NoSpaceBeforeOpenParenInFuncCall = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), 8));
+                this.SpaceAfterFunctionInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create3(83, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2));
+                this.NoSpaceBeforeOpenParenInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionDeclContext), 8));
+                this.SpaceAfterVoidOperator = new formatting.Rule(formatting.RuleDescriptor.create3(99, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsVoidOpContext), 2));
+                this.NoSpaceBetweenReturnAndSemicolon = new formatting.Rule(formatting.RuleDescriptor.create1(90, 22), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceBetweenStatements = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([17, 75, 76, 67]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotForContext), 2));
+                this.SpaceAfterTryFinally = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([96, 81]), 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.SpaceAfterGetSetInMember = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([116, 120]), 65), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2));
+                this.SpaceBeforeBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryKeywordOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.SpaceAfterBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryKeywordOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.NoSpaceAfterConstructor = new formatting.Rule(formatting.RuleDescriptor.create1(114, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceAfterModuleImport = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([117, 118]), 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceAfterCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([69, 115, 77, 78, 79, 116, 102, 85, 103, 117, 106, 108, 120, 109]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.SpaceBeforeCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([79, 102])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.SpaceAfterModuleName = new formatting.Rule(formatting.RuleDescriptor.create1(8, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsModuleDeclContext), 2));
+                this.SpaceAfterArrow = new formatting.Rule(formatting.RuleDescriptor.create3(32, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.NoSpaceAfterEllipsis = new formatting.Rule(formatting.RuleDescriptor.create1(21, 65), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceAfterOptionalParameters = new formatting.Rule(formatting.RuleDescriptor.create3(50, formatting.Shared.TokenRange.FromTokens([17, 23])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), 8));
+                this.NoSpaceBeforeOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.TypeNames, 24), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
+                this.NoSpaceBetweenCloseParenAndAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create1(17, 24), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
+                this.NoSpaceAfterOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(24, formatting.Shared.TokenRange.TypeNames), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
+                this.NoSpaceBeforeCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 25), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
+                this.NoSpaceAfterCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(25, formatting.Shared.TokenRange.FromTokens([16, 18, 25, 23])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), 8));
+                this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(14, 15), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectTypeContext), 8));
+                this.SpaceBeforeAt = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 52), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.NoSpaceAfterAt = new formatting.Rule(formatting.RuleDescriptor.create3(52, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceAfterDecorator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([65, 78, 73, 69, 109, 108, 106, 107, 116, 120, 18, 35])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), 2));
+                this.HighPriorityCommonRules =
+                    [
+                        this.IgnoreBeforeComment, this.IgnoreAfterLineComment,
+                        this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator,
+                        this.NoSpaceAfterQuestionMark,
+                        this.NoSpaceBeforeDot, this.NoSpaceAfterDot,
+                        this.NoSpaceAfterUnaryPrefixOperator,
+                        this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator,
+                        this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator,
+                        this.SpaceAfterPostincrementWhenFollowedByAdd,
+                        this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement,
+                        this.SpaceAfterPostdecrementWhenFollowedBySubtract,
+                        this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement,
+                        this.NoSpaceAfterCloseBrace,
+                        this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NewLineBeforeCloseBraceInBlockContext,
+                        this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets,
+                        this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember,
+                        this.NoSpaceBetweenReturnAndSemicolon,
+                        this.SpaceAfterCertainKeywords,
+                        this.SpaceAfterLetConstInVariableDeclaration,
+                        this.NoSpaceBeforeOpenParenInFuncCall,
+                        this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator,
+                        this.SpaceAfterVoidOperator,
+                        this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
+                        this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords,
+                        this.SpaceAfterModuleName,
+                        this.SpaceAfterArrow,
+                        this.NoSpaceAfterEllipsis,
+                        this.NoSpaceAfterOptionalParameters,
+                        this.NoSpaceBetweenEmptyInterfaceBraceBrackets,
+                        this.NoSpaceBeforeOpenAngularBracket,
+                        this.NoSpaceBetweenCloseParenAndAngularBracket,
+                        this.NoSpaceAfterOpenAngularBracket,
+                        this.NoSpaceBeforeCloseAngularBracket,
+                        this.NoSpaceAfterCloseAngularBracket,
+                        this.SpaceBeforeAt,
+                        this.NoSpaceAfterAt,
+                        this.SpaceAfterDecorator,
+                    ];
+                this.LowPriorityCommonRules =
+                    [
+                        this.NoSpaceBeforeSemicolon,
+                        this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock,
+                        this.NoSpaceBeforeComma,
+                        this.NoSpaceBeforeOpenBracket, this.NoSpaceAfterOpenBracket,
+                        this.NoSpaceBeforeCloseBracket, this.NoSpaceAfterCloseBracket,
+                        this.SpaceAfterSemicolon,
+                        this.NoSpaceBeforeOpenParenInFuncDecl,
+                        this.SpaceBetweenStatements, this.SpaceAfterTryFinally
+                    ];
+                this.SpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(23, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.NoSpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(23, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.SpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 2));
+                this.NoSpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 8));
+                this.NoSpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), 8));
+                this.SpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 2));
+                this.NoSpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 8));
+                this.NewLineBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 4), 1);
+                this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 4), 1);
+                this.NewLineBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 14), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 4), 1);
+                this.SpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(22, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 2));
+                this.NoSpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(22, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), 8));
+                this.SpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(16, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.SpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 2));
+                this.NoSpaceBetweenParens = new formatting.Rule(formatting.RuleDescriptor.create1(16, 17), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(16, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.NoSpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSameLineTokenContext), 8));
+                this.SpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(83, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2));
+                this.NoSpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(83, 16), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 8));
+            }
+            Rules.prototype.getRuleName = function (rule) {
+                var o = this;
+                for (var name_1 in o) {
+                    if (o[name_1] === rule) {
+                        return name_1;
+                    }
+                }
+                throw new Error("Unknown rule");
+            };
+            Rules.IsForContext = function (context) {
+                return context.contextNode.kind === 186;
+            };
+            Rules.IsNotForContext = function (context) {
+                return !Rules.IsForContext(context);
+            };
+            Rules.IsBinaryOpContext = function (context) {
+                switch (context.contextNode.kind) {
+                    case 169:
+                    case 170:
+                        return true;
+                    case 152:
+                    case 203:
+                    case 208:
+                    case 198:
+                    case 129:
+                    case 226:
+                    case 132:
+                    case 131:
+                        return context.currentTokenSpan.kind === 53 || context.nextTokenSpan.kind === 53;
+                    case 187:
+                        return context.currentTokenSpan.kind === 86 || context.nextTokenSpan.kind === 86;
+                    case 188:
+                        return context.currentTokenSpan.kind === 125 || context.nextTokenSpan.kind === 125;
+                }
+                return false;
+            };
+            Rules.IsNotBinaryOpContext = function (context) {
+                return !Rules.IsBinaryOpContext(context);
+            };
+            Rules.IsConditionalOperatorContext = function (context) {
+                return context.contextNode.kind === 170;
+            };
+            Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) {
+                //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction.
+                ////
+                //// Ex: 
+                //// if (1)     { ....
+                ////      * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context
+                ////
+                //// Ex: 
+                //// if (1)
+                //// { ... }
+                ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we don't format.
+                ////
+                //// Ex:
+                //// if (1) 
+                //// { ...
+                //// }
+                ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we format.
+                return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context);
+            };
+            Rules.IsBeforeMultilineBlockContext = function (context) {
+                return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine());
+            };
+            Rules.IsMultilineBlockContext = function (context) {
+                return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
+            };
+            Rules.IsSingleLineBlockContext = function (context) {
+                return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
+            };
+            Rules.IsBlockContext = function (context) {
+                return Rules.NodeIsBlockContext(context.contextNode);
+            };
+            Rules.IsBeforeBlockContext = function (context) {
+                return Rules.NodeIsBlockContext(context.nextTokenParent);
+            };
+            Rules.NodeIsBlockContext = function (node) {
+                if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) {
+                    return true;
+                }
+                switch (node.kind) {
+                    case 179:
+                    case 207:
+                    case 154:
+                    case 206:
+                        return true;
+                }
+                return false;
+            };
+            Rules.IsFunctionDeclContext = function (context) {
+                switch (context.contextNode.kind) {
+                    case 200:
+                    case 134:
+                    case 133:
+                    case 136:
+                    case 137:
+                    case 138:
+                    case 162:
+                    case 135:
+                    case 163:
+                    case 202:
+                        return true;
+                }
+                return false;
+            };
+            Rules.IsTypeScriptDeclWithBlockContext = function (context) {
+                return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode);
+            };
+            Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) {
+                switch (node.kind) {
+                    case 201:
+                    case 202:
+                    case 204:
+                    case 145:
+                    case 205:
+                        return true;
+                }
+                return false;
+            };
+            Rules.IsAfterCodeBlockContext = function (context) {
+                switch (context.currentTokenParent.kind) {
+                    case 201:
+                    case 205:
+                    case 204:
+                    case 179:
+                    case 223:
+                    case 206:
+                    case 193:
+                        return true;
+                }
+                return false;
+            };
+            Rules.IsControlDeclContext = function (context) {
+                switch (context.contextNode.kind) {
+                    case 183:
+                    case 193:
+                    case 186:
+                    case 187:
+                    case 188:
+                    case 185:
+                    case 196:
+                    case 184:
+                    case 192:
+                    case 223:
+                        return true;
+                    default:
+                        return false;
+                }
+            };
+            Rules.IsObjectContext = function (context) {
+                return context.contextNode.kind === 154;
+            };
+            Rules.IsFunctionCallContext = function (context) {
+                return context.contextNode.kind === 157;
+            };
+            Rules.IsNewContext = function (context) {
+                return context.contextNode.kind === 158;
+            };
+            Rules.IsFunctionCallOrNewContext = function (context) {
+                return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context);
+            };
+            Rules.IsPreviousTokenNotComma = function (context) {
+                return context.currentTokenSpan.kind !== 23;
+            };
+            Rules.IsSameLineTokenContext = function (context) {
+                return context.TokensAreOnSameLine();
+            };
+            Rules.IsEndOfDecoratorContextOnSameLine = function (context) {
+                return context.TokensAreOnSameLine() &&
+                    context.contextNode.decorators &&
+                    Rules.NodeIsInDecoratorContext(context.currentTokenParent) &&
+                    !Rules.NodeIsInDecoratorContext(context.nextTokenParent);
+            };
+            Rules.NodeIsInDecoratorContext = function (node) {
+                while (ts.isExpression(node)) {
+                    node = node.parent;
+                }
+                return node.kind === 130;
+            };
+            Rules.IsStartOfVariableDeclarationList = function (context) {
+                return context.currentTokenParent.kind === 199 &&
+                    context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
+            };
+            Rules.IsNotFormatOnEnter = function (context) {
+                return context.formattingRequestKind != 2;
+            };
+            Rules.IsModuleDeclContext = function (context) {
+                return context.contextNode.kind === 205;
+            };
+            Rules.IsObjectTypeContext = function (context) {
+                return context.contextNode.kind === 145;
+            };
+            Rules.IsTypeArgumentOrParameter = function (token, parent) {
+                if (token.kind !== 24 && token.kind !== 25) {
+                    return false;
+                }
+                switch (parent.kind) {
+                    case 141:
+                    case 201:
+                    case 202:
+                    case 200:
+                    case 162:
+                    case 163:
+                    case 134:
+                    case 133:
+                    case 138:
+                    case 139:
+                    case 157:
+                    case 158:
+                        return true;
+                    default:
+                        return false;
+                }
+            };
+            Rules.IsTypeArgumentOrParameterContext = function (context) {
+                return Rules.IsTypeArgumentOrParameter(context.currentTokenSpan, context.currentTokenParent) ||
+                    Rules.IsTypeArgumentOrParameter(context.nextTokenSpan, context.nextTokenParent);
+            };
+            Rules.IsVoidOpContext = function (context) {
+                return context.currentTokenSpan.kind === 99 && context.currentTokenParent.kind === 166;
+            };
+            return Rules;
+        })();
+        formatting.Rules = Rules;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/rulesMap.js b/dist/typescript/services/formatting/rulesMap.js
new file mode 100644
index 000000000..ad474abf7
--- /dev/null
+++ b/dist/typescript/services/formatting/rulesMap.js
@@ -0,0 +1,137 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var RulesMap = (function () {
+            function RulesMap() {
+                this.map = [];
+                this.mapRowLength = 0;
+            }
+            RulesMap.create = function (rules) {
+                var result = new RulesMap();
+                result.Initialize(rules);
+                return result;
+            };
+            RulesMap.prototype.Initialize = function (rules) {
+                this.mapRowLength = 125 + 1;
+                this.map = new Array(this.mapRowLength * this.mapRowLength);
+                var rulesBucketConstructionStateList = new Array(this.map.length);
+                this.FillRules(rules, rulesBucketConstructionStateList);
+                return this.map;
+            };
+            RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) {
+                var _this = this;
+                rules.forEach(function (rule) {
+                    _this.FillRule(rule, rulesBucketConstructionStateList);
+                });
+            };
+            RulesMap.prototype.GetRuleBucketIndex = function (row, column) {
+                var rulesBucketIndex = (row * this.mapRowLength) + column;
+                return rulesBucketIndex;
+            };
+            RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) {
+                var _this = this;
+                var specificRule = rule.Descriptor.LeftTokenRange != formatting.Shared.TokenRange.Any &&
+                    rule.Descriptor.RightTokenRange != formatting.Shared.TokenRange.Any;
+                rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) {
+                    rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) {
+                        var rulesBucketIndex = _this.GetRuleBucketIndex(left, right);
+                        var rulesBucket = _this.map[rulesBucketIndex];
+                        if (rulesBucket == undefined) {
+                            rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket();
+                        }
+                        rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex);
+                    });
+                });
+            };
+            RulesMap.prototype.GetRule = function (context) {
+                var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind);
+                var bucket = this.map[bucketIndex];
+                if (bucket != null) {
+                    for (var _i = 0, _a = bucket.Rules(); _i < _a.length; _i++) {
+                        var rule = _a[_i];
+                        if (rule.Operation.Context.InContext(context)) {
+                            return rule;
+                        }
+                    }
+                }
+                return null;
+            };
+            return RulesMap;
+        })();
+        formatting.RulesMap = RulesMap;
+        var MaskBitSize = 5;
+        var Mask = 0x1f;
+        (function (RulesPosition) {
+            RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific";
+            RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny";
+            RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific";
+            RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny";
+            RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific";
+            RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny";
+        })(formatting.RulesPosition || (formatting.RulesPosition = {}));
+        var RulesPosition = formatting.RulesPosition;
+        var RulesBucketConstructionState = (function () {
+            function RulesBucketConstructionState() {
+                this.rulesInsertionIndexBitmap = 0;
+            }
+            RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) {
+                var index = 0;
+                var pos = 0;
+                var indexBitmap = this.rulesInsertionIndexBitmap;
+                while (pos <= maskPosition) {
+                    index += (indexBitmap & Mask);
+                    indexBitmap >>= MaskBitSize;
+                    pos += MaskBitSize;
+                }
+                return index;
+            };
+            RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) {
+                var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
+                value++;
+                ts.Debug.assert((value & Mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
+                var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
+                temp |= value << maskPosition;
+                this.rulesInsertionIndexBitmap = temp;
+            };
+            return RulesBucketConstructionState;
+        })();
+        formatting.RulesBucketConstructionState = RulesBucketConstructionState;
+        var RulesBucket = (function () {
+            function RulesBucket() {
+                this.rules = [];
+            }
+            RulesBucket.prototype.Rules = function () {
+                return this.rules;
+            };
+            RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) {
+                var position;
+                if (rule.Operation.Action == 1) {
+                    position = specificTokens ?
+                        RulesPosition.IgnoreRulesSpecific :
+                        RulesPosition.IgnoreRulesAny;
+                }
+                else if (!rule.Operation.Context.IsAny()) {
+                    position = specificTokens ?
+                        RulesPosition.ContextRulesSpecific :
+                        RulesPosition.ContextRulesAny;
+                }
+                else {
+                    position = specificTokens ?
+                        RulesPosition.NoContextRulesSpecific :
+                        RulesPosition.NoContextRulesAny;
+                }
+                var state = constructionState[rulesBucketIndex];
+                if (state === undefined) {
+                    state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState();
+                }
+                var index = state.GetInsertionIndex(position);
+                this.rules.splice(index, 0, rule);
+                state.IncreaseInsertionIndex(position);
+            };
+            return RulesBucket;
+        })();
+        formatting.RulesBucket = RulesBucket;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/rulesProvider.js b/dist/typescript/services/formatting/rulesProvider.js
new file mode 100644
index 000000000..5b9ad5b9b
--- /dev/null
+++ b/dist/typescript/services/formatting/rulesProvider.js
@@ -0,0 +1,86 @@
+/// <reference path="references.ts"/>
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var RulesProvider = (function () {
+            function RulesProvider() {
+                this.globalRules = new formatting.Rules();
+            }
+            RulesProvider.prototype.getRuleName = function (rule) {
+                return this.globalRules.getRuleName(rule);
+            };
+            RulesProvider.prototype.getRuleByName = function (name) {
+                return this.globalRules[name];
+            };
+            RulesProvider.prototype.getRulesMap = function () {
+                return this.rulesMap;
+            };
+            RulesProvider.prototype.ensureUpToDate = function (options) {
+                if (this.options == null || !ts.compareDataObjects(this.options, options)) {
+                    var activeRules = this.createActiveRules(options);
+                    var rulesMap = formatting.RulesMap.create(activeRules);
+                    this.activeRules = activeRules;
+                    this.rulesMap = rulesMap;
+                    this.options = ts.clone(options);
+                }
+            };
+            RulesProvider.prototype.createActiveRules = function (options) {
+                var rules = this.globalRules.HighPriorityCommonRules.slice(0);
+                if (options.InsertSpaceAfterCommaDelimiter) {
+                    rules.push(this.globalRules.SpaceAfterComma);
+                }
+                else {
+                    rules.push(this.globalRules.NoSpaceAfterComma);
+                }
+                if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) {
+                    rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword);
+                }
+                else {
+                    rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword);
+                }
+                if (options.InsertSpaceAfterKeywordsInControlFlowStatements) {
+                    rules.push(this.globalRules.SpaceAfterKeywordInControl);
+                }
+                else {
+                    rules.push(this.globalRules.NoSpaceAfterKeywordInControl);
+                }
+                if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
+                    rules.push(this.globalRules.SpaceAfterOpenParen);
+                    rules.push(this.globalRules.SpaceBeforeCloseParen);
+                    rules.push(this.globalRules.NoSpaceBetweenParens);
+                }
+                else {
+                    rules.push(this.globalRules.NoSpaceAfterOpenParen);
+                    rules.push(this.globalRules.NoSpaceBeforeCloseParen);
+                    rules.push(this.globalRules.NoSpaceBetweenParens);
+                }
+                if (options.InsertSpaceAfterSemicolonInForStatements) {
+                    rules.push(this.globalRules.SpaceAfterSemicolonInFor);
+                }
+                else {
+                    rules.push(this.globalRules.NoSpaceAfterSemicolonInFor);
+                }
+                if (options.InsertSpaceBeforeAndAfterBinaryOperators) {
+                    rules.push(this.globalRules.SpaceBeforeBinaryOperator);
+                    rules.push(this.globalRules.SpaceAfterBinaryOperator);
+                }
+                else {
+                    rules.push(this.globalRules.NoSpaceBeforeBinaryOperator);
+                    rules.push(this.globalRules.NoSpaceAfterBinaryOperator);
+                }
+                if (options.PlaceOpenBraceOnNewLineForControlBlocks) {
+                    rules.push(this.globalRules.NewLineBeforeOpenBraceInControl);
+                }
+                if (options.PlaceOpenBraceOnNewLineForFunctions) {
+                    rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction);
+                    rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock);
+                }
+                rules = rules.concat(this.globalRules.LowPriorityCommonRules);
+                return rules;
+            };
+            return RulesProvider;
+        })();
+        formatting.RulesProvider = RulesProvider;
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/smartIndenter.js b/dist/typescript/services/formatting/smartIndenter.js
new file mode 100644
index 000000000..efc161a3c
--- /dev/null
+++ b/dist/typescript/services/formatting/smartIndenter.js
@@ -0,0 +1,307 @@
+///<reference path='..\services.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var SmartIndenter;
+        (function (SmartIndenter) {
+            var Value;
+            (function (Value) {
+                Value[Value["Unknown"] = -1] = "Unknown";
+            })(Value || (Value = {}));
+            function getIndentation(position, sourceFile, options) {
+                if (position > sourceFile.text.length) {
+                    return 0;
+                }
+                var precedingToken = ts.findPrecedingToken(position, sourceFile);
+                if (!precedingToken) {
+                    return 0;
+                }
+                var precedingTokenIsLiteral = precedingToken.kind === 8 ||
+                    precedingToken.kind === 9 ||
+                    precedingToken.kind === 10 ||
+                    precedingToken.kind === 11 ||
+                    precedingToken.kind === 12 ||
+                    precedingToken.kind === 13;
+                if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) {
+                    return 0;
+                }
+                var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
+                if (precedingToken.kind === 23 && precedingToken.parent.kind !== 169) {
+                    var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
+                    if (actualIndentation !== -1) {
+                        return actualIndentation;
+                    }
+                }
+                var previous;
+                var current = precedingToken;
+                var currentStart;
+                var indentationDelta;
+                while (current) {
+                    if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current.kind, previous ? previous.kind : 0)) {
+                        currentStart = getStartLineAndCharacterForNode(current, sourceFile);
+                        if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
+                            indentationDelta = 0;
+                        }
+                        else {
+                            indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0;
+                        }
+                        break;
+                    }
+                    var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
+                    if (actualIndentation !== -1) {
+                        return actualIndentation;
+                    }
+                    previous = current;
+                    current = current.parent;
+                }
+                if (!current) {
+                    return 0;
+                }
+                return getIndentationForNodeWorker(current, currentStart, undefined, indentationDelta, sourceFile, options);
+            }
+            SmartIndenter.getIndentation = getIndentation;
+            function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) {
+                var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
+                return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, 0, sourceFile, options);
+            }
+            SmartIndenter.getIndentationForNode = getIndentationForNode;
+            function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, options) {
+                var parent = current.parent;
+                var parentStart;
+                while (parent) {
+                    var useActualIndentation = true;
+                    if (ignoreActualIndentationRange) {
+                        var start = current.getStart(sourceFile);
+                        useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end;
+                    }
+                    if (useActualIndentation) {
+                        var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
+                        if (actualIndentation !== -1) {
+                            return actualIndentation + indentationDelta;
+                        }
+                    }
+                    parentStart = getParentStart(parent, current, sourceFile);
+                    var parentAndChildShareLine = parentStart.line === currentStart.line ||
+                        childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
+                    if (useActualIndentation) {
+                        var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
+                        if (actualIndentation !== -1) {
+                            return actualIndentation + indentationDelta;
+                        }
+                    }
+                    if (shouldIndentChildNode(parent.kind, current.kind) && !parentAndChildShareLine) {
+                        indentationDelta += options.IndentSize;
+                    }
+                    current = parent;
+                    currentStart = parentStart;
+                    parent = current.parent;
+                }
+                return indentationDelta;
+            }
+            function getParentStart(parent, child, sourceFile) {
+                var containingList = getContainingList(child, sourceFile);
+                if (containingList) {
+                    return sourceFile.getLineAndCharacterOfPosition(containingList.pos);
+                }
+                return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile));
+            }
+            function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) {
+                var commaItemInfo = ts.findListItemInfo(commaToken);
+                if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
+                    return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
+                }
+                else {
+                    return -1;
+                }
+            }
+            function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) {
+                var useActualIndentation = (ts.isDeclaration(current) || ts.isStatement(current)) &&
+                    (parent.kind === 227 || !parentAndChildShareLine);
+                if (!useActualIndentation) {
+                    return -1;
+                }
+                return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
+            }
+            function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) {
+                var nextToken = ts.findNextToken(precedingToken, current);
+                if (!nextToken) {
+                    return false;
+                }
+                if (nextToken.kind === 14) {
+                    return true;
+                }
+                else if (nextToken.kind === 15) {
+                    var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
+                    return lineAtPosition === nextTokenStartLine;
+                }
+                return false;
+            }
+            function getStartLineAndCharacterForNode(n, sourceFile) {
+                return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
+            }
+            function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) {
+                if (parent.kind === 183 && parent.elseStatement === child) {
+                    var elseKeyword = ts.findChildOfKind(parent, 76, sourceFile);
+                    ts.Debug.assert(elseKeyword !== undefined);
+                    var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
+                    return elseKeywordStartLine === childStartLine;
+                }
+                return false;
+            }
+            SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement;
+            function getContainingList(node, sourceFile) {
+                if (node.parent) {
+                    switch (node.parent.kind) {
+                        case 141:
+                            if (node.parent.typeArguments &&
+                                ts.rangeContainsStartEnd(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd())) {
+                                return node.parent.typeArguments;
+                            }
+                            break;
+                        case 154:
+                            return node.parent.properties;
+                        case 153:
+                            return node.parent.elements;
+                        case 200:
+                        case 162:
+                        case 163:
+                        case 134:
+                        case 133:
+                        case 138:
+                        case 139: {
+                            var start = node.getStart(sourceFile);
+                            if (node.parent.typeParameters &&
+                                ts.rangeContainsStartEnd(node.parent.typeParameters, start, node.getEnd())) {
+                                return node.parent.typeParameters;
+                            }
+                            if (ts.rangeContainsStartEnd(node.parent.parameters, start, node.getEnd())) {
+                                return node.parent.parameters;
+                            }
+                            break;
+                        }
+                        case 158:
+                        case 157: {
+                            var start = node.getStart(sourceFile);
+                            if (node.parent.typeArguments &&
+                                ts.rangeContainsStartEnd(node.parent.typeArguments, start, node.getEnd())) {
+                                return node.parent.typeArguments;
+                            }
+                            if (node.parent.arguments &&
+                                ts.rangeContainsStartEnd(node.parent.arguments, start, node.getEnd())) {
+                                return node.parent.arguments;
+                            }
+                            break;
+                        }
+                    }
+                }
+                return undefined;
+            }
+            function getActualIndentationForListItem(node, sourceFile, options) {
+                var containingList = getContainingList(node, sourceFile);
+                return containingList ? getActualIndentationFromList(containingList) : -1;
+                function getActualIndentationFromList(list) {
+                    var index = ts.indexOf(list, node);
+                    return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1;
+                }
+            }
+            function deriveActualIndentationFromList(list, index, sourceFile, options) {
+                ts.Debug.assert(index >= 0 && index < list.length);
+                var node = list[index];
+                var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
+                for (var i = index - 1; i >= 0; --i) {
+                    if (list[i].kind === 23) {
+                        continue;
+                    }
+                    var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line;
+                    if (prevEndLine !== lineAndCharacter.line) {
+                        return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
+                    }
+                    lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile);
+                }
+                return -1;
+            }
+            function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) {
+                var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
+                return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
+            }
+            function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) {
+                var character = 0;
+                var column = 0;
+                for (var pos = startPos; pos < endPos; ++pos) {
+                    var ch = sourceFile.text.charCodeAt(pos);
+                    if (!ts.isWhiteSpace(ch)) {
+                        break;
+                    }
+                    if (ch === 9) {
+                        column += options.TabSize + (column % options.TabSize);
+                    }
+                    else {
+                        column++;
+                    }
+                    character++;
+                }
+                return { column: column, character: character };
+            }
+            SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn;
+            function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) {
+                return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
+            }
+            SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn;
+            function nodeContentIsAlwaysIndented(kind) {
+                switch (kind) {
+                    case 201:
+                    case 202:
+                    case 204:
+                    case 153:
+                    case 179:
+                    case 206:
+                    case 154:
+                    case 145:
+                    case 147:
+                    case 207:
+                    case 221:
+                    case 220:
+                    case 161:
+                    case 157:
+                    case 158:
+                    case 180:
+                    case 198:
+                    case 214:
+                    case 191:
+                    case 170:
+                    case 151:
+                    case 150:
+                        return true;
+                }
+                return false;
+            }
+            function shouldIndentChildNode(parent, child) {
+                if (nodeContentIsAlwaysIndented(parent)) {
+                    return true;
+                }
+                switch (parent) {
+                    case 184:
+                    case 185:
+                    case 187:
+                    case 188:
+                    case 186:
+                    case 183:
+                    case 200:
+                    case 162:
+                    case 134:
+                    case 133:
+                    case 138:
+                    case 163:
+                    case 135:
+                    case 136:
+                    case 137:
+                        return child !== 179;
+                    default:
+                        return false;
+                }
+            }
+            SmartIndenter.shouldIndentChildNode = shouldIndentChildNode;
+        })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {}));
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/formatting/tokenRange.js b/dist/typescript/services/formatting/tokenRange.js
new file mode 100644
index 000000000..7e7f9f4b0
--- /dev/null
+++ b/dist/typescript/services/formatting/tokenRange.js
@@ -0,0 +1,115 @@
+///<reference path='references.ts' />
+var ts;
+(function (ts) {
+    var formatting;
+    (function (formatting) {
+        var Shared;
+        (function (Shared) {
+            var TokenRangeAccess = (function () {
+                function TokenRangeAccess(from, to, except) {
+                    this.tokens = [];
+                    for (var token = from; token <= to; token++) {
+                        if (except.indexOf(token) < 0) {
+                            this.tokens.push(token);
+                        }
+                    }
+                }
+                TokenRangeAccess.prototype.GetTokens = function () {
+                    return this.tokens;
+                };
+                TokenRangeAccess.prototype.Contains = function (token) {
+                    return this.tokens.indexOf(token) >= 0;
+                };
+                return TokenRangeAccess;
+            })();
+            Shared.TokenRangeAccess = TokenRangeAccess;
+            var TokenValuesAccess = (function () {
+                function TokenValuesAccess(tks) {
+                    this.tokens = tks && tks.length ? tks : [];
+                }
+                TokenValuesAccess.prototype.GetTokens = function () {
+                    return this.tokens;
+                };
+                TokenValuesAccess.prototype.Contains = function (token) {
+                    return this.tokens.indexOf(token) >= 0;
+                };
+                return TokenValuesAccess;
+            })();
+            Shared.TokenValuesAccess = TokenValuesAccess;
+            var TokenSingleValueAccess = (function () {
+                function TokenSingleValueAccess(token) {
+                    this.token = token;
+                }
+                TokenSingleValueAccess.prototype.GetTokens = function () {
+                    return [this.token];
+                };
+                TokenSingleValueAccess.prototype.Contains = function (tokenValue) {
+                    return tokenValue == this.token;
+                };
+                return TokenSingleValueAccess;
+            })();
+            Shared.TokenSingleValueAccess = TokenSingleValueAccess;
+            var TokenAllAccess = (function () {
+                function TokenAllAccess() {
+                }
+                TokenAllAccess.prototype.GetTokens = function () {
+                    var result = [];
+                    for (var token = 0; token <= 125; token++) {
+                        result.push(token);
+                    }
+                    return result;
+                };
+                TokenAllAccess.prototype.Contains = function (tokenValue) {
+                    return true;
+                };
+                TokenAllAccess.prototype.toString = function () {
+                    return "[allTokens]";
+                };
+                return TokenAllAccess;
+            })();
+            Shared.TokenAllAccess = TokenAllAccess;
+            var TokenRange = (function () {
+                function TokenRange(tokenAccess) {
+                    this.tokenAccess = tokenAccess;
+                }
+                TokenRange.FromToken = function (token) {
+                    return new TokenRange(new TokenSingleValueAccess(token));
+                };
+                TokenRange.FromTokens = function (tokens) {
+                    return new TokenRange(new TokenValuesAccess(tokens));
+                };
+                TokenRange.FromRange = function (f, to, except) {
+                    if (except === void 0) { except = []; }
+                    return new TokenRange(new TokenRangeAccess(f, to, except));
+                };
+                TokenRange.AllTokens = function () {
+                    return new TokenRange(new TokenAllAccess());
+                };
+                TokenRange.prototype.GetTokens = function () {
+                    return this.tokenAccess.GetTokens();
+                };
+                TokenRange.prototype.Contains = function (token) {
+                    return this.tokenAccess.Contains(token);
+                };
+                TokenRange.prototype.toString = function () {
+                    return this.tokenAccess.toString();
+                };
+                TokenRange.Any = TokenRange.AllTokens();
+                TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([3]));
+                TokenRange.Keywords = TokenRange.FromRange(66, 125);
+                TokenRange.BinaryOperators = TokenRange.FromRange(24, 64);
+                TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([86, 87, 125]);
+                TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([38, 39, 47, 46]);
+                TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([7, 65, 16, 18, 14, 93, 88]);
+                TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([65, 16, 93, 88]);
+                TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([65, 17, 19, 88]);
+                TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([65, 16, 93, 88]);
+                TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([65, 17, 19, 88]);
+                TokenRange.Comments = TokenRange.FromTokens([2, 3]);
+                TokenRange.TypeNames = TokenRange.FromTokens([65, 119, 121, 113, 122, 99, 112]);
+                return TokenRange;
+            })();
+            Shared.TokenRange = TokenRange;
+        })(Shared = formatting.Shared || (formatting.Shared = {}));
+    })(formatting = ts.formatting || (ts.formatting = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/navigateTo.js b/dist/typescript/services/navigateTo.js
new file mode 100644
index 000000000..7856a6c9c
--- /dev/null
+++ b/dist/typescript/services/navigateTo.js
@@ -0,0 +1,147 @@
+var ts;
+(function (ts) {
+    var NavigateTo;
+    (function (NavigateTo) {
+        function getNavigateToItems(program, cancellationToken, searchValue, maxResultCount) {
+            var patternMatcher = ts.createPatternMatcher(searchValue);
+            var rawItems = [];
+            ts.forEach(program.getSourceFiles(), function (sourceFile) {
+                cancellationToken.throwIfCancellationRequested();
+                var nameToDeclarations = sourceFile.getNamedDeclarations();
+                for (var name_1 in nameToDeclarations) {
+                    var declarations = ts.getProperty(nameToDeclarations, name_1);
+                    if (declarations) {
+                        var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_1);
+                        if (!matches) {
+                            continue;
+                        }
+                        for (var _i = 0; _i < declarations.length; _i++) {
+                            var declaration = declarations[_i];
+                            if (patternMatcher.patternContainsDots) {
+                                var containers = getContainers(declaration);
+                                if (!containers) {
+                                    return undefined;
+                                }
+                                matches = patternMatcher.getMatches(containers, name_1);
+                                if (!matches) {
+                                    continue;
+                                }
+                            }
+                            var fileName = sourceFile.fileName;
+                            var matchKind = bestMatchKind(matches);
+                            rawItems.push({ name: name_1, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration });
+                        }
+                    }
+                }
+            });
+            rawItems.sort(compareNavigateToItems);
+            if (maxResultCount !== undefined) {
+                rawItems = rawItems.slice(0, maxResultCount);
+            }
+            var items = ts.map(rawItems, createNavigateToItem);
+            return items;
+            function allMatchesAreCaseSensitive(matches) {
+                ts.Debug.assert(matches.length > 0);
+                for (var _i = 0; _i < matches.length; _i++) {
+                    var match = matches[_i];
+                    if (!match.isCaseSensitive) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            function getTextOfIdentifierOrLiteral(node) {
+                if (node) {
+                    if (node.kind === 65 ||
+                        node.kind === 8 ||
+                        node.kind === 7) {
+                        return node.text;
+                    }
+                }
+                return undefined;
+            }
+            function tryAddSingleDeclarationName(declaration, containers) {
+                if (declaration && declaration.name) {
+                    var text = getTextOfIdentifierOrLiteral(declaration.name);
+                    if (text !== undefined) {
+                        containers.unshift(text);
+                    }
+                    else if (declaration.name.kind === 127) {
+                        return tryAddComputedPropertyName(declaration.name.expression, containers, true);
+                    }
+                    else {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            function tryAddComputedPropertyName(expression, containers, includeLastPortion) {
+                var text = getTextOfIdentifierOrLiteral(expression);
+                if (text !== undefined) {
+                    if (includeLastPortion) {
+                        containers.unshift(text);
+                    }
+                    return true;
+                }
+                if (expression.kind === 155) {
+                    var propertyAccess = expression;
+                    if (includeLastPortion) {
+                        containers.unshift(propertyAccess.name.text);
+                    }
+                    return tryAddComputedPropertyName(propertyAccess.expression, containers, true);
+                }
+                return false;
+            }
+            function getContainers(declaration) {
+                var containers = [];
+                if (declaration.name.kind === 127) {
+                    if (!tryAddComputedPropertyName(declaration.name.expression, containers, false)) {
+                        return undefined;
+                    }
+                }
+                declaration = ts.getContainerNode(declaration);
+                while (declaration) {
+                    if (!tryAddSingleDeclarationName(declaration, containers)) {
+                        return undefined;
+                    }
+                    declaration = ts.getContainerNode(declaration);
+                }
+                return containers;
+            }
+            function bestMatchKind(matches) {
+                ts.Debug.assert(matches.length > 0);
+                var bestMatchKind = ts.PatternMatchKind.camelCase;
+                for (var _i = 0; _i < matches.length; _i++) {
+                    var match = matches[_i];
+                    var kind = match.kind;
+                    if (kind < bestMatchKind) {
+                        bestMatchKind = kind;
+                    }
+                }
+                return bestMatchKind;
+            }
+            var baseSensitivity = { sensitivity: "base" };
+            function compareNavigateToItems(i1, i2) {
+                return i1.matchKind - i2.matchKind ||
+                    i1.name.localeCompare(i2.name, undefined, baseSensitivity) ||
+                    i1.name.localeCompare(i2.name);
+            }
+            function createNavigateToItem(rawItem) {
+                var declaration = rawItem.declaration;
+                var container = ts.getContainerNode(declaration);
+                return {
+                    name: rawItem.name,
+                    kind: ts.getNodeKind(declaration),
+                    kindModifiers: ts.getNodeModifiers(declaration),
+                    matchKind: ts.PatternMatchKind[rawItem.matchKind],
+                    isCaseSensitive: rawItem.isCaseSensitive,
+                    fileName: rawItem.fileName,
+                    textSpan: ts.createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()),
+                    containerName: container && container.name ? container.name.text : "",
+                    containerKind: container && container.name ? ts.getNodeKind(container) : ""
+                };
+            }
+        }
+        NavigateTo.getNavigateToItems = getNavigateToItems;
+    })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/navigationBar.js b/dist/typescript/services/navigationBar.js
new file mode 100644
index 000000000..6e53a1a9b
--- /dev/null
+++ b/dist/typescript/services/navigationBar.js
@@ -0,0 +1,370 @@
+/// <reference path='services.ts' />
+var ts;
+(function (ts) {
+    var NavigationBar;
+    (function (NavigationBar) {
+        function getNavigationBarItems(sourceFile) {
+            var hasGlobalNode = false;
+            return getItemsWorker(getTopLevelNodes(sourceFile), createTopLevelItem);
+            function getIndent(node) {
+                var indent = hasGlobalNode ? 1 : 0;
+                var current = node.parent;
+                while (current) {
+                    switch (current.kind) {
+                        case 205:
+                            do {
+                                current = current.parent;
+                            } while (current.kind === 205);
+                        case 201:
+                        case 204:
+                        case 202:
+                        case 200:
+                            indent++;
+                    }
+                    current = current.parent;
+                }
+                return indent;
+            }
+            function getChildNodes(nodes) {
+                var childNodes = [];
+                function visit(node) {
+                    switch (node.kind) {
+                        case 180:
+                            ts.forEach(node.declarationList.declarations, visit);
+                            break;
+                        case 150:
+                        case 151:
+                            ts.forEach(node.elements, visit);
+                            break;
+                        case 215:
+                            if (node.exportClause) {
+                                ts.forEach(node.exportClause.elements, visit);
+                            }
+                            break;
+                        case 209:
+                            var importClause = node.importClause;
+                            if (importClause) {
+                                if (importClause.name) {
+                                    childNodes.push(importClause);
+                                }
+                                if (importClause.namedBindings) {
+                                    if (importClause.namedBindings.kind === 211) {
+                                        childNodes.push(importClause.namedBindings);
+                                    }
+                                    else {
+                                        ts.forEach(importClause.namedBindings.elements, visit);
+                                    }
+                                }
+                            }
+                            break;
+                        case 152:
+                        case 198:
+                            if (ts.isBindingPattern(node.name)) {
+                                visit(node.name);
+                                break;
+                            }
+                        case 201:
+                        case 204:
+                        case 202:
+                        case 205:
+                        case 200:
+                        case 208:
+                        case 213:
+                        case 217:
+                            childNodes.push(node);
+                            break;
+                    }
+                }
+                ts.forEach(nodes, visit);
+                return sortNodes(childNodes);
+            }
+            function getTopLevelNodes(node) {
+                var topLevelNodes = [];
+                topLevelNodes.push(node);
+                addTopLevelNodes(node.statements, topLevelNodes);
+                return topLevelNodes;
+            }
+            function sortNodes(nodes) {
+                return nodes.slice(0).sort(function (n1, n2) {
+                    if (n1.name && n2.name) {
+                        return ts.getPropertyNameForPropertyNameNode(n1.name).localeCompare(ts.getPropertyNameForPropertyNameNode(n2.name));
+                    }
+                    else if (n1.name) {
+                        return 1;
+                    }
+                    else if (n2.name) {
+                        return -1;
+                    }
+                    else {
+                        return n1.kind - n2.kind;
+                    }
+                });
+            }
+            function addTopLevelNodes(nodes, topLevelNodes) {
+                nodes = sortNodes(nodes);
+                for (var _i = 0; _i < nodes.length; _i++) {
+                    var node = nodes[_i];
+                    switch (node.kind) {
+                        case 201:
+                        case 204:
+                        case 202:
+                            topLevelNodes.push(node);
+                            break;
+                        case 205:
+                            var moduleDeclaration = node;
+                            topLevelNodes.push(node);
+                            addTopLevelNodes(getInnermostModule(moduleDeclaration).body.statements, topLevelNodes);
+                            break;
+                        case 200:
+                            var functionDeclaration = node;
+                            if (isTopLevelFunctionDeclaration(functionDeclaration)) {
+                                topLevelNodes.push(node);
+                                addTopLevelNodes(functionDeclaration.body.statements, topLevelNodes);
+                            }
+                            break;
+                    }
+                }
+            }
+            function isTopLevelFunctionDeclaration(functionDeclaration) {
+                if (functionDeclaration.kind === 200) {
+                    if (functionDeclaration.body && functionDeclaration.body.kind === 179) {
+                        if (ts.forEach(functionDeclaration.body.statements, function (s) { return s.kind === 200 && !isEmpty(s.name.text); })) {
+                            return true;
+                        }
+                        if (!ts.isFunctionBlock(functionDeclaration.parent)) {
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            }
+            function getItemsWorker(nodes, createItem) {
+                var items = [];
+                var keyToItem = {};
+                for (var _i = 0; _i < nodes.length; _i++) {
+                    var child = nodes[_i];
+                    var item_1 = createItem(child);
+                    if (item_1 !== undefined) {
+                        if (item_1.text.length > 0) {
+                            var key = item_1.text + "-" + item_1.kind + "-" + item_1.indent;
+                            var itemWithSameName = keyToItem[key];
+                            if (itemWithSameName) {
+                                merge(itemWithSameName, item_1);
+                            }
+                            else {
+                                keyToItem[key] = item_1;
+                                items.push(item_1);
+                            }
+                        }
+                    }
+                }
+                return items;
+            }
+            function merge(target, source) {
+                target.spans.push.apply(target.spans, source.spans);
+                if (source.childItems) {
+                    if (!target.childItems) {
+                        target.childItems = [];
+                    }
+                    outer: for (var _i = 0, _a = source.childItems; _i < _a.length; _i++) {
+                        var sourceChild = _a[_i];
+                        for (var _b = 0, _c = target.childItems; _b < _c.length; _b++) {
+                            var targetChild = _c[_b];
+                            if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
+                                merge(targetChild, sourceChild);
+                                continue outer;
+                            }
+                        }
+                        target.childItems.push(sourceChild);
+                    }
+                }
+            }
+            function createChildItem(node) {
+                switch (node.kind) {
+                    case 129:
+                        if (ts.isBindingPattern(node.name)) {
+                            break;
+                        }
+                        if ((node.flags & 499) === 0) {
+                            return undefined;
+                        }
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
+                    case 134:
+                    case 133:
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberFunctionElement);
+                    case 136:
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberGetAccessorElement);
+                    case 137:
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberSetAccessorElement);
+                    case 140:
+                        return createItem(node, "[]", ts.ScriptElementKind.indexSignatureElement);
+                    case 226:
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
+                    case 138:
+                        return createItem(node, "()", ts.ScriptElementKind.callSignatureElement);
+                    case 139:
+                        return createItem(node, "new()", ts.ScriptElementKind.constructSignatureElement);
+                    case 132:
+                    case 131:
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.memberVariableElement);
+                    case 200:
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.functionElement);
+                    case 198:
+                    case 152:
+                        var variableDeclarationNode;
+                        var name_1;
+                        if (node.kind === 152) {
+                            name_1 = node.name;
+                            variableDeclarationNode = node;
+                            while (variableDeclarationNode && variableDeclarationNode.kind !== 198) {
+                                variableDeclarationNode = variableDeclarationNode.parent;
+                            }
+                            ts.Debug.assert(variableDeclarationNode !== undefined);
+                        }
+                        else {
+                            ts.Debug.assert(!ts.isBindingPattern(node.name));
+                            variableDeclarationNode = node;
+                            name_1 = node.name;
+                        }
+                        if (ts.isConst(variableDeclarationNode)) {
+                            return createItem(node, getTextOfNode(name_1), ts.ScriptElementKind.constElement);
+                        }
+                        else if (ts.isLet(variableDeclarationNode)) {
+                            return createItem(node, getTextOfNode(name_1), ts.ScriptElementKind.letElement);
+                        }
+                        else {
+                            return createItem(node, getTextOfNode(name_1), ts.ScriptElementKind.variableElement);
+                        }
+                    case 135:
+                        return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement);
+                    case 217:
+                    case 213:
+                    case 208:
+                    case 210:
+                    case 211:
+                        return createItem(node, getTextOfNode(node.name), ts.ScriptElementKind.alias);
+                }
+                return undefined;
+                function createItem(node, name, scriptElementKind) {
+                    return getNavigationBarItem(name, scriptElementKind, ts.getNodeModifiers(node), [getNodeSpan(node)]);
+                }
+            }
+            function isEmpty(text) {
+                return !text || text.trim() === "";
+            }
+            function getNavigationBarItem(text, kind, kindModifiers, spans, childItems, indent) {
+                if (childItems === void 0) { childItems = []; }
+                if (indent === void 0) { indent = 0; }
+                if (isEmpty(text)) {
+                    return undefined;
+                }
+                return {
+                    text: text,
+                    kind: kind,
+                    kindModifiers: kindModifiers,
+                    spans: spans,
+                    childItems: childItems,
+                    indent: indent,
+                    bolded: false,
+                    grayed: false
+                };
+            }
+            function createTopLevelItem(node) {
+                switch (node.kind) {
+                    case 227:
+                        return createSourceFileItem(node);
+                    case 201:
+                        return createClassItem(node);
+                    case 204:
+                        return createEnumItem(node);
+                    case 202:
+                        return createIterfaceItem(node);
+                    case 205:
+                        return createModuleItem(node);
+                    case 200:
+                        return createFunctionItem(node);
+                }
+                return undefined;
+                function getModuleName(moduleDeclaration) {
+                    if (moduleDeclaration.name.kind === 8) {
+                        return getTextOfNode(moduleDeclaration.name);
+                    }
+                    var result = [];
+                    result.push(moduleDeclaration.name.text);
+                    while (moduleDeclaration.body && moduleDeclaration.body.kind === 205) {
+                        moduleDeclaration = moduleDeclaration.body;
+                        result.push(moduleDeclaration.name.text);
+                    }
+                    return result.join(".");
+                }
+                function createModuleItem(node) {
+                    var moduleName = getModuleName(node);
+                    var childItems = getItemsWorker(getChildNodes(getInnermostModule(node).body.statements), createChildItem);
+                    return getNavigationBarItem(moduleName, ts.ScriptElementKind.moduleElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
+                }
+                function createFunctionItem(node) {
+                    if (node.body && node.body.kind === 179) {
+                        var childItems = getItemsWorker(sortNodes(node.body.statements), createChildItem);
+                        return getNavigationBarItem(!node.name ? "default" : node.name.text, ts.ScriptElementKind.functionElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
+                    }
+                    return undefined;
+                }
+                function createSourceFileItem(node) {
+                    var childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
+                    if (childItems === undefined || childItems.length === 0) {
+                        return undefined;
+                    }
+                    hasGlobalNode = true;
+                    var rootName = ts.isExternalModule(node)
+                        ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(node.fileName)))) + "\""
+                        : "<global>";
+                    return getNavigationBarItem(rootName, ts.ScriptElementKind.moduleElement, ts.ScriptElementKindModifier.none, [getNodeSpan(node)], childItems);
+                }
+                function createClassItem(node) {
+                    var childItems;
+                    if (node.members) {
+                        var constructor = ts.forEach(node.members, function (member) {
+                            return member.kind === 135 && member;
+                        });
+                        var nodes = removeDynamicallyNamedProperties(node);
+                        if (constructor) {
+                            nodes.push.apply(nodes, ts.filter(constructor.parameters, function (p) { return !ts.isBindingPattern(p.name); }));
+                        }
+                        childItems = getItemsWorker(sortNodes(nodes), createChildItem);
+                    }
+                    var nodeName = !node.name ? "default" : node.name.text;
+                    return getNavigationBarItem(nodeName, ts.ScriptElementKind.classElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
+                }
+                function createEnumItem(node) {
+                    var childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem);
+                    return getNavigationBarItem(node.name.text, ts.ScriptElementKind.enumElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
+                }
+                function createIterfaceItem(node) {
+                    var childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem);
+                    return getNavigationBarItem(node.name.text, ts.ScriptElementKind.interfaceElement, ts.getNodeModifiers(node), [getNodeSpan(node)], childItems, getIndent(node));
+                }
+            }
+            function removeComputedProperties(node) {
+                return ts.filter(node.members, function (member) { return member.name === undefined || member.name.kind !== 127; });
+            }
+            function removeDynamicallyNamedProperties(node) {
+                return ts.filter(node.members, function (member) { return !ts.hasDynamicName(member); });
+            }
+            function getInnermostModule(node) {
+                while (node.body.kind === 205) {
+                    node = node.body;
+                }
+                return node;
+            }
+            function getNodeSpan(node) {
+                return node.kind === 227
+                    ? ts.createTextSpanFromBounds(node.getFullStart(), node.getEnd())
+                    : ts.createTextSpanFromBounds(node.getStart(), node.getEnd());
+            }
+            function getTextOfNode(node) {
+                return ts.getTextOfNodeFromSourceText(sourceFile.text, node);
+            }
+        }
+        NavigationBar.getNavigationBarItems = getNavigationBarItems;
+    })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/outliningElementsCollector.js b/dist/typescript/services/outliningElementsCollector.js
new file mode 100644
index 000000000..ad0937543
--- /dev/null
+++ b/dist/typescript/services/outliningElementsCollector.js
@@ -0,0 +1,151 @@
+var ts;
+(function (ts) {
+    var OutliningElementsCollector;
+    (function (OutliningElementsCollector) {
+        function collectElements(sourceFile) {
+            var elements = [];
+            var collapseText = "...";
+            function addOutliningSpan(hintSpanNode, startElement, endElement, autoCollapse) {
+                if (hintSpanNode && startElement && endElement) {
+                    var span = {
+                        textSpan: ts.createTextSpanFromBounds(startElement.pos, endElement.end),
+                        hintSpan: ts.createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end),
+                        bannerText: collapseText,
+                        autoCollapse: autoCollapse
+                    };
+                    elements.push(span);
+                }
+            }
+            function addOutliningSpanComments(commentSpan, autoCollapse) {
+                if (commentSpan) {
+                    var span = {
+                        textSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end),
+                        hintSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end),
+                        bannerText: collapseText,
+                        autoCollapse: autoCollapse
+                    };
+                    elements.push(span);
+                }
+            }
+            function addOutliningForLeadingCommentsForNode(n) {
+                var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile);
+                if (comments) {
+                    var firstSingleLineCommentStart = -1;
+                    var lastSingleLineCommentEnd = -1;
+                    var isFirstSingleLineComment = true;
+                    var singleLineCommentCount = 0;
+                    for (var _i = 0; _i < comments.length; _i++) {
+                        var currentComment = comments[_i];
+                        if (currentComment.kind === 2) {
+                            if (isFirstSingleLineComment) {
+                                firstSingleLineCommentStart = currentComment.pos;
+                            }
+                            isFirstSingleLineComment = false;
+                            lastSingleLineCommentEnd = currentComment.end;
+                            singleLineCommentCount++;
+                        }
+                        else if (currentComment.kind === 3) {
+                            combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd);
+                            addOutliningSpanComments(currentComment, false);
+                            singleLineCommentCount = 0;
+                            lastSingleLineCommentEnd = -1;
+                            isFirstSingleLineComment = true;
+                        }
+                    }
+                    combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd);
+                }
+            }
+            function combineAndAddMultipleSingleLineComments(count, start, end) {
+                if (count > 1) {
+                    var multipleSingleLineComments = {
+                        pos: start,
+                        end: end,
+                        kind: 2
+                    };
+                    addOutliningSpanComments(multipleSingleLineComments, false);
+                }
+            }
+            function autoCollapse(node) {
+                return ts.isFunctionBlock(node) && node.parent.kind !== 163;
+            }
+            var depth = 0;
+            var maxDepth = 20;
+            function walk(n) {
+                if (depth > maxDepth) {
+                    return;
+                }
+                if (ts.isDeclaration(n)) {
+                    addOutliningForLeadingCommentsForNode(n);
+                }
+                switch (n.kind) {
+                    case 179:
+                        if (!ts.isFunctionBlock(n)) {
+                            var parent_1 = n.parent;
+                            var openBrace = ts.findChildOfKind(n, 14, sourceFile);
+                            var closeBrace = ts.findChildOfKind(n, 15, sourceFile);
+                            if (parent_1.kind === 184 ||
+                                parent_1.kind === 187 ||
+                                parent_1.kind === 188 ||
+                                parent_1.kind === 186 ||
+                                parent_1.kind === 183 ||
+                                parent_1.kind === 185 ||
+                                parent_1.kind === 192 ||
+                                parent_1.kind === 223) {
+                                addOutliningSpan(parent_1, openBrace, closeBrace, autoCollapse(n));
+                                break;
+                            }
+                            if (parent_1.kind === 196) {
+                                var tryStatement = parent_1;
+                                if (tryStatement.tryBlock === n) {
+                                    addOutliningSpan(parent_1, openBrace, closeBrace, autoCollapse(n));
+                                    break;
+                                }
+                                else if (tryStatement.finallyBlock === n) {
+                                    var finallyKeyword = ts.findChildOfKind(tryStatement, 81, sourceFile);
+                                    if (finallyKeyword) {
+                                        addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n));
+                                        break;
+                                    }
+                                }
+                            }
+                            var span = ts.createTextSpanFromBounds(n.getStart(), n.end);
+                            elements.push({
+                                textSpan: span,
+                                hintSpan: span,
+                                bannerText: collapseText,
+                                autoCollapse: autoCollapse(n)
+                            });
+                            break;
+                        }
+                    case 206: {
+                        var openBrace = ts.findChildOfKind(n, 14, sourceFile);
+                        var closeBrace = ts.findChildOfKind(n, 15, sourceFile);
+                        addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n));
+                        break;
+                    }
+                    case 201:
+                    case 202:
+                    case 204:
+                    case 154:
+                    case 207: {
+                        var openBrace = ts.findChildOfKind(n, 14, sourceFile);
+                        var closeBrace = ts.findChildOfKind(n, 15, sourceFile);
+                        addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n));
+                        break;
+                    }
+                    case 153:
+                        var openBracket = ts.findChildOfKind(n, 18, sourceFile);
+                        var closeBracket = ts.findChildOfKind(n, 19, sourceFile);
+                        addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n));
+                        break;
+                }
+                depth++;
+                ts.forEachChild(n, walk);
+                depth--;
+            }
+            walk(sourceFile);
+            return elements;
+        }
+        OutliningElementsCollector.collectElements = collectElements;
+    })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/patternMatcher.js b/dist/typescript/services/patternMatcher.js
new file mode 100644
index 000000000..90774f4ff
--- /dev/null
+++ b/dist/typescript/services/patternMatcher.js
@@ -0,0 +1,451 @@
+var ts;
+(function (ts) {
+    (function (PatternMatchKind) {
+        PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact";
+        PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix";
+        PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring";
+        PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase";
+    })(ts.PatternMatchKind || (ts.PatternMatchKind = {}));
+    var PatternMatchKind = ts.PatternMatchKind;
+    function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) {
+        return {
+            kind: kind,
+            punctuationStripped: punctuationStripped,
+            isCaseSensitive: isCaseSensitive,
+            camelCaseWeight: camelCaseWeight
+        };
+    }
+    function createPatternMatcher(pattern) {
+        var stringToWordSpans = {};
+        pattern = pattern.trim();
+        var fullPatternSegment = createSegment(pattern);
+        var dotSeparatedSegments = pattern.split(".").map(function (p) { return createSegment(p.trim()); });
+        var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid);
+        return {
+            getMatches: getMatches,
+            getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern,
+            patternContainsDots: dotSeparatedSegments.length > 1
+        };
+        function skipMatch(candidate) {
+            return invalidPattern || !candidate;
+        }
+        function getMatchesForLastSegmentOfPattern(candidate) {
+            if (skipMatch(candidate)) {
+                return undefined;
+            }
+            return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
+        }
+        function getMatches(candidateContainers, candidate) {
+            if (skipMatch(candidate)) {
+                return undefined;
+            }
+            var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
+            if (!candidateMatch) {
+                return undefined;
+            }
+            candidateContainers = candidateContainers || [];
+            if (dotSeparatedSegments.length - 1 > candidateContainers.length) {
+                return undefined;
+            }
+            var totalMatch = candidateMatch;
+            for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i--, j--) {
+                var segment = dotSeparatedSegments[i];
+                var containerName = candidateContainers[j];
+                var containerMatch = matchSegment(containerName, segment);
+                if (!containerMatch) {
+                    return undefined;
+                }
+                ts.addRange(totalMatch, containerMatch);
+            }
+            return totalMatch;
+        }
+        function getWordSpans(word) {
+            if (!ts.hasProperty(stringToWordSpans, word)) {
+                stringToWordSpans[word] = breakIntoWordSpans(word);
+            }
+            return stringToWordSpans[word];
+        }
+        function matchTextChunk(candidate, chunk, punctuationStripped) {
+            var index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
+            if (index === 0) {
+                if (chunk.text.length === candidate.length) {
+                    return createPatternMatch(PatternMatchKind.exact, punctuationStripped, candidate === chunk.text);
+                }
+                else {
+                    return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, startsWith(candidate, chunk.text));
+                }
+            }
+            var isLowercase = chunk.isLowerCase;
+            if (isLowercase) {
+                if (index > 0) {
+                    var wordSpans = getWordSpans(candidate);
+                    for (var _i = 0; _i < wordSpans.length; _i++) {
+                        var span = wordSpans[_i];
+                        if (partStartsWith(candidate, span, chunk.text, true)) {
+                            return createPatternMatch(PatternMatchKind.substring, punctuationStripped, partStartsWith(candidate, span, chunk.text, false));
+                        }
+                    }
+                }
+            }
+            else {
+                if (candidate.indexOf(chunk.text) > 0) {
+                    return createPatternMatch(PatternMatchKind.substring, punctuationStripped, true);
+                }
+            }
+            if (!isLowercase) {
+                if (chunk.characterSpans.length > 0) {
+                    var candidateParts = getWordSpans(candidate);
+                    var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, false);
+                    if (camelCaseWeight !== undefined) {
+                        return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, true, camelCaseWeight);
+                    }
+                    camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, true);
+                    if (camelCaseWeight !== undefined) {
+                        return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, false, camelCaseWeight);
+                    }
+                }
+            }
+            if (isLowercase) {
+                if (chunk.text.length < candidate.length) {
+                    if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) {
+                        return createPatternMatch(PatternMatchKind.substring, punctuationStripped, false);
+                    }
+                }
+            }
+            return undefined;
+        }
+        function containsSpaceOrAsterisk(text) {
+            for (var i = 0; i < text.length; i++) {
+                var ch = text.charCodeAt(i);
+                if (ch === 32 || ch === 42) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        function matchSegment(candidate, segment) {
+            if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) {
+                var match = matchTextChunk(candidate, segment.totalTextChunk, false);
+                if (match) {
+                    return [match];
+                }
+            }
+            var subWordTextChunks = segment.subWordTextChunks;
+            var matches = undefined;
+            for (var _i = 0; _i < subWordTextChunks.length; _i++) {
+                var subWordTextChunk = subWordTextChunks[_i];
+                var result = matchTextChunk(candidate, subWordTextChunk, true);
+                if (!result) {
+                    return undefined;
+                }
+                matches = matches || [];
+                matches.push(result);
+            }
+            return matches;
+        }
+        function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) {
+            var patternPartStart = patternSpan ? patternSpan.start : 0;
+            var patternPartLength = patternSpan ? patternSpan.length : pattern.length;
+            if (patternPartLength > candidateSpan.length) {
+                return false;
+            }
+            if (ignoreCase) {
+                for (var i = 0; i < patternPartLength; i++) {
+                    var ch1 = pattern.charCodeAt(patternPartStart + i);
+                    var ch2 = candidate.charCodeAt(candidateSpan.start + i);
+                    if (toLowerCase(ch1) !== toLowerCase(ch2)) {
+                        return false;
+                    }
+                }
+            }
+            else {
+                for (var i = 0; i < patternPartLength; i++) {
+                    var ch1 = pattern.charCodeAt(patternPartStart + i);
+                    var ch2 = candidate.charCodeAt(candidateSpan.start + i);
+                    if (ch1 !== ch2) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) {
+            var chunkCharacterSpans = chunk.characterSpans;
+            var currentCandidate = 0;
+            var currentChunkSpan = 0;
+            var firstMatch = undefined;
+            var contiguous = undefined;
+            while (true) {
+                if (currentChunkSpan === chunkCharacterSpans.length) {
+                    var weight = 0;
+                    if (contiguous) {
+                        weight += 1;
+                    }
+                    if (firstMatch === 0) {
+                        weight += 2;
+                    }
+                    return weight;
+                }
+                else if (currentCandidate === candidateParts.length) {
+                    return undefined;
+                }
+                var candidatePart = candidateParts[currentCandidate];
+                var gotOneMatchThisCandidate = false;
+                for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) {
+                    var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
+                    if (gotOneMatchThisCandidate) {
+                        if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) ||
+                            !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) {
+                            break;
+                        }
+                    }
+                    if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) {
+                        break;
+                    }
+                    gotOneMatchThisCandidate = true;
+                    firstMatch = firstMatch === undefined ? currentCandidate : firstMatch;
+                    contiguous = contiguous === undefined ? true : contiguous;
+                    candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length);
+                }
+                if (!gotOneMatchThisCandidate && contiguous !== undefined) {
+                    contiguous = false;
+                }
+                currentCandidate++;
+            }
+        }
+    }
+    ts.createPatternMatcher = createPatternMatcher;
+    function patternMatchCompareTo(match1, match2) {
+        return compareType(match1, match2) ||
+            compareCamelCase(match1, match2) ||
+            compareCase(match1, match2) ||
+            comparePunctuation(match1, match2);
+    }
+    function comparePunctuation(result1, result2) {
+        if (result1.punctuationStripped !== result2.punctuationStripped) {
+            return result1.punctuationStripped ? 1 : -1;
+        }
+        return 0;
+    }
+    function compareCase(result1, result2) {
+        if (result1.isCaseSensitive !== result2.isCaseSensitive) {
+            return result1.isCaseSensitive ? -1 : 1;
+        }
+        return 0;
+    }
+    function compareType(result1, result2) {
+        return result1.kind - result2.kind;
+    }
+    function compareCamelCase(result1, result2) {
+        if (result1.kind === PatternMatchKind.camelCase && result2.kind === PatternMatchKind.camelCase) {
+            return result2.camelCaseWeight - result1.camelCaseWeight;
+        }
+        return 0;
+    }
+    function createSegment(text) {
+        return {
+            totalTextChunk: createTextChunk(text),
+            subWordTextChunks: breakPatternIntoTextChunks(text)
+        };
+    }
+    function segmentIsInvalid(segment) {
+        return segment.subWordTextChunks.length === 0;
+    }
+    function isUpperCaseLetter(ch) {
+        if (ch >= 65 && ch <= 90) {
+            return true;
+        }
+        if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 2)) {
+            return false;
+        }
+        var str = String.fromCharCode(ch);
+        return str === str.toUpperCase();
+    }
+    function isLowerCaseLetter(ch) {
+        if (ch >= 97 && ch <= 122) {
+            return true;
+        }
+        if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 2)) {
+            return false;
+        }
+        var str = String.fromCharCode(ch);
+        return str === str.toLowerCase();
+    }
+    function containsUpperCaseLetter(string) {
+        for (var i = 0, n = string.length; i < n; i++) {
+            if (isUpperCaseLetter(string.charCodeAt(i))) {
+                return true;
+            }
+        }
+        return false;
+    }
+    function startsWith(string, search) {
+        for (var i = 0, n = search.length; i < n; i++) {
+            if (string.charCodeAt(i) !== search.charCodeAt(i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    function indexOfIgnoringCase(string, value) {
+        for (var i = 0, n = string.length - value.length; i <= n; i++) {
+            if (startsWithIgnoringCase(string, value, i)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+    function startsWithIgnoringCase(string, value, start) {
+        for (var i = 0, n = value.length; i < n; i++) {
+            var ch1 = toLowerCase(string.charCodeAt(i + start));
+            var ch2 = value.charCodeAt(i);
+            if (ch1 !== ch2) {
+                return false;
+            }
+        }
+        return true;
+    }
+    function toLowerCase(ch) {
+        if (ch >= 65 && ch <= 90) {
+            return 97 + (ch - 65);
+        }
+        if (ch < 127) {
+            return ch;
+        }
+        return String.fromCharCode(ch).toLowerCase().charCodeAt(0);
+    }
+    function isDigit(ch) {
+        return ch >= 48 && ch <= 57;
+    }
+    function isWordChar(ch) {
+        return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 || ch === 36;
+    }
+    function breakPatternIntoTextChunks(pattern) {
+        var result = [];
+        var wordStart = 0;
+        var wordLength = 0;
+        for (var i = 0; i < pattern.length; i++) {
+            var ch = pattern.charCodeAt(i);
+            if (isWordChar(ch)) {
+                if (wordLength++ === 0) {
+                    wordStart = i;
+                }
+            }
+            else {
+                if (wordLength > 0) {
+                    result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
+                    wordLength = 0;
+                }
+            }
+        }
+        if (wordLength > 0) {
+            result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
+        }
+        return result;
+    }
+    function createTextChunk(text) {
+        var textLowerCase = text.toLowerCase();
+        return {
+            text: text,
+            textLowerCase: textLowerCase,
+            isLowerCase: text === textLowerCase,
+            characterSpans: breakIntoCharacterSpans(text)
+        };
+    }
+    function breakIntoCharacterSpans(identifier) {
+        return breakIntoSpans(identifier, false);
+    }
+    ts.breakIntoCharacterSpans = breakIntoCharacterSpans;
+    function breakIntoWordSpans(identifier) {
+        return breakIntoSpans(identifier, true);
+    }
+    ts.breakIntoWordSpans = breakIntoWordSpans;
+    function breakIntoSpans(identifier, word) {
+        var result = [];
+        var wordStart = 0;
+        for (var i = 1, n = identifier.length; i < n; i++) {
+            var lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
+            var currentIsDigit = isDigit(identifier.charCodeAt(i));
+            var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
+            var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart);
+            if (charIsPunctuation(identifier.charCodeAt(i - 1)) ||
+                charIsPunctuation(identifier.charCodeAt(i)) ||
+                lastIsDigit != currentIsDigit ||
+                hasTransitionFromLowerToUpper ||
+                hasTransitionFromUpperToLower) {
+                if (!isAllPunctuation(identifier, wordStart, i)) {
+                    result.push(ts.createTextSpan(wordStart, i - wordStart));
+                }
+                wordStart = i;
+            }
+        }
+        if (!isAllPunctuation(identifier, wordStart, identifier.length)) {
+            result.push(ts.createTextSpan(wordStart, identifier.length - wordStart));
+        }
+        return result;
+    }
+    function charIsPunctuation(ch) {
+        switch (ch) {
+            case 33:
+            case 34:
+            case 35:
+            case 37:
+            case 38:
+            case 39:
+            case 40:
+            case 41:
+            case 42:
+            case 44:
+            case 45:
+            case 46:
+            case 47:
+            case 58:
+            case 59:
+            case 63:
+            case 64:
+            case 91:
+            case 92:
+            case 93:
+            case 95:
+            case 123:
+            case 125:
+                return true;
+        }
+        return false;
+    }
+    function isAllPunctuation(identifier, start, end) {
+        for (var i = start; i < end; i++) {
+            var ch = identifier.charCodeAt(i);
+            if (!charIsPunctuation(ch) || ch === 95 || ch === 36) {
+                return false;
+            }
+        }
+        return true;
+    }
+    function transitionFromUpperToLower(identifier, word, index, wordStart) {
+        if (word) {
+            if (index != wordStart &&
+                index + 1 < identifier.length) {
+                var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
+                var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
+                if (currentIsUpper && nextIsLower) {
+                    for (var i = wordStart; i < index; i++) {
+                        if (!isUpperCaseLetter(identifier.charCodeAt(i))) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    function transitionFromLowerToUpper(identifier, word, index) {
+        var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
+        var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
+        var transition = word
+            ? (currentIsUpper && !lastIsUpper)
+            : currentIsUpper;
+        return transition;
+    }
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/services.js b/dist/typescript/services/services.js
new file mode 100644
index 000000000..df6112b53
--- /dev/null
+++ b/dist/typescript/services/services.js
@@ -0,0 +1,4804 @@
+/// <reference path="..\compiler\program.ts"/>
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+/// <reference path='breakpoints.ts' />
+/// <reference path='outliningElementsCollector.ts' />
+/// <reference path='navigateTo.ts' />
+/// <reference path='navigationBar.ts' />
+/// <reference path='patternMatcher.ts' />
+/// <reference path='signatureHelp.ts' />
+/// <reference path='utilities.ts' />
+/// <reference path='formatting\formatting.ts' />
+/// <reference path='formatting\smartIndenter.ts' />
+var ts;
+(function (ts) {
+    ts.servicesVersion = "0.4";
+    var ScriptSnapshot;
+    (function (ScriptSnapshot) {
+        var StringScriptSnapshot = (function () {
+            function StringScriptSnapshot(text) {
+                this.text = text;
+                this._lineStartPositions = undefined;
+            }
+            StringScriptSnapshot.prototype.getText = function (start, end) {
+                return this.text.substring(start, end);
+            };
+            StringScriptSnapshot.prototype.getLength = function () {
+                return this.text.length;
+            };
+            StringScriptSnapshot.prototype.getChangeRange = function (oldSnapshot) {
+                return undefined;
+            };
+            return StringScriptSnapshot;
+        })();
+        function fromString(text) {
+            return new StringScriptSnapshot(text);
+        }
+        ScriptSnapshot.fromString = fromString;
+    })(ScriptSnapshot = ts.ScriptSnapshot || (ts.ScriptSnapshot = {}));
+    var scanner = ts.createScanner(2, true);
+    var emptyArray = [];
+    function createNode(kind, pos, end, flags, parent) {
+        var node = new (ts.getNodeConstructor(kind))();
+        node.pos = pos;
+        node.end = end;
+        node.flags = flags;
+        node.parent = parent;
+        return node;
+    }
+    var NodeObject = (function () {
+        function NodeObject() {
+        }
+        NodeObject.prototype.getSourceFile = function () {
+            return ts.getSourceFileOfNode(this);
+        };
+        NodeObject.prototype.getStart = function (sourceFile) {
+            return ts.getTokenPosOfNode(this, sourceFile);
+        };
+        NodeObject.prototype.getFullStart = function () {
+            return this.pos;
+        };
+        NodeObject.prototype.getEnd = function () {
+            return this.end;
+        };
+        NodeObject.prototype.getWidth = function (sourceFile) {
+            return this.getEnd() - this.getStart(sourceFile);
+        };
+        NodeObject.prototype.getFullWidth = function () {
+            return this.end - this.getFullStart();
+        };
+        NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) {
+            return this.getStart(sourceFile) - this.pos;
+        };
+        NodeObject.prototype.getFullText = function (sourceFile) {
+            return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
+        };
+        NodeObject.prototype.getText = function (sourceFile) {
+            return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
+        };
+        NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end) {
+            scanner.setTextPos(pos);
+            while (pos < end) {
+                var token = scanner.scan();
+                var textPos = scanner.getTextPos();
+                nodes.push(createNode(token, pos, textPos, 1024, this));
+                pos = textPos;
+            }
+            return pos;
+        };
+        NodeObject.prototype.createSyntaxList = function (nodes) {
+            var list = createNode(228, nodes.pos, nodes.end, 1024, this);
+            list._children = [];
+            var pos = nodes.pos;
+            for (var _i = 0; _i < nodes.length; _i++) {
+                var node = nodes[_i];
+                if (pos < node.pos) {
+                    pos = this.addSyntheticNodes(list._children, pos, node.pos);
+                }
+                list._children.push(node);
+                pos = node.end;
+            }
+            if (pos < nodes.end) {
+                this.addSyntheticNodes(list._children, pos, nodes.end);
+            }
+            return list;
+        };
+        NodeObject.prototype.createChildren = function (sourceFile) {
+            var _this = this;
+            var children;
+            if (this.kind >= 126) {
+                scanner.setText((sourceFile || this.getSourceFile()).text);
+                children = [];
+                var pos = this.pos;
+                var processNode = function (node) {
+                    if (pos < node.pos) {
+                        pos = _this.addSyntheticNodes(children, pos, node.pos);
+                    }
+                    children.push(node);
+                    pos = node.end;
+                };
+                var processNodes = function (nodes) {
+                    if (pos < nodes.pos) {
+                        pos = _this.addSyntheticNodes(children, pos, nodes.pos);
+                    }
+                    children.push(_this.createSyntaxList(nodes));
+                    pos = nodes.end;
+                };
+                ts.forEachChild(this, processNode, processNodes);
+                if (pos < this.end) {
+                    this.addSyntheticNodes(children, pos, this.end);
+                }
+                scanner.setText(undefined);
+            }
+            this._children = children || emptyArray;
+        };
+        NodeObject.prototype.getChildCount = function (sourceFile) {
+            if (!this._children)
+                this.createChildren(sourceFile);
+            return this._children.length;
+        };
+        NodeObject.prototype.getChildAt = function (index, sourceFile) {
+            if (!this._children)
+                this.createChildren(sourceFile);
+            return this._children[index];
+        };
+        NodeObject.prototype.getChildren = function (sourceFile) {
+            if (!this._children)
+                this.createChildren(sourceFile);
+            return this._children;
+        };
+        NodeObject.prototype.getFirstToken = function (sourceFile) {
+            var children = this.getChildren();
+            for (var _i = 0; _i < children.length; _i++) {
+                var child = children[_i];
+                if (child.kind < 126) {
+                    return child;
+                }
+                return child.getFirstToken(sourceFile);
+            }
+        };
+        NodeObject.prototype.getLastToken = function (sourceFile) {
+            var children = this.getChildren(sourceFile);
+            for (var i = children.length - 1; i >= 0; i--) {
+                var child = children[i];
+                if (child.kind < 126) {
+                    return child;
+                }
+                return child.getLastToken(sourceFile);
+            }
+        };
+        return NodeObject;
+    })();
+    var SymbolObject = (function () {
+        function SymbolObject(flags, name) {
+            this.flags = flags;
+            this.name = name;
+        }
+        SymbolObject.prototype.getFlags = function () {
+            return this.flags;
+        };
+        SymbolObject.prototype.getName = function () {
+            return this.name;
+        };
+        SymbolObject.prototype.getDeclarations = function () {
+            return this.declarations;
+        };
+        SymbolObject.prototype.getDocumentationComment = function () {
+            if (this.documentationComment === undefined) {
+                this.documentationComment = getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & 4));
+            }
+            return this.documentationComment;
+        };
+        return SymbolObject;
+    })();
+    function getJsDocCommentsFromDeclarations(declarations, name, canUseParsedParamTagComments) {
+        var documentationComment = [];
+        var docComments = getJsDocCommentsSeparatedByNewLines();
+        ts.forEach(docComments, function (docComment) {
+            if (documentationComment.length) {
+                documentationComment.push(ts.lineBreakPart());
+            }
+            documentationComment.push(docComment);
+        });
+        return documentationComment;
+        function getJsDocCommentsSeparatedByNewLines() {
+            var paramTag = "@param";
+            var jsDocCommentParts = [];
+            ts.forEach(declarations, function (declaration, indexOfDeclaration) {
+                if (ts.indexOf(declarations, declaration) === indexOfDeclaration) {
+                    var sourceFileOfDeclaration = ts.getSourceFileOfNode(declaration);
+                    if (canUseParsedParamTagComments && declaration.kind === 129) {
+                        ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), function (jsDocCommentTextRange) {
+                            var cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
+                            if (cleanedParamJsDocComment) {
+                                jsDocCommentParts.push.apply(jsDocCommentParts, cleanedParamJsDocComment);
+                            }
+                        });
+                    }
+                    if (declaration.kind === 205 && declaration.body.kind === 205) {
+                        return;
+                    }
+                    while (declaration.kind === 205 && declaration.parent.kind === 205) {
+                        declaration = declaration.parent;
+                    }
+                    ts.forEach(getJsDocCommentTextRange(declaration.kind === 198 ? declaration.parent.parent : declaration, sourceFileOfDeclaration), function (jsDocCommentTextRange) {
+                        var cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
+                        if (cleanedJsDocComment) {
+                            jsDocCommentParts.push.apply(jsDocCommentParts, cleanedJsDocComment);
+                        }
+                    });
+                }
+            });
+            return jsDocCommentParts;
+            function getJsDocCommentTextRange(node, sourceFile) {
+                return ts.map(ts.getJsDocComments(node, sourceFile), function (jsDocComment) {
+                    return {
+                        pos: jsDocComment.pos + "/*".length,
+                        end: jsDocComment.end - "*/".length
+                    };
+                });
+            }
+            function consumeWhiteSpacesOnTheLine(pos, end, sourceFile, maxSpacesToRemove) {
+                if (maxSpacesToRemove !== undefined) {
+                    end = Math.min(end, pos + maxSpacesToRemove);
+                }
+                for (; pos < end; pos++) {
+                    var ch = sourceFile.text.charCodeAt(pos);
+                    if (!ts.isWhiteSpace(ch) || ts.isLineBreak(ch)) {
+                        return pos;
+                    }
+                }
+                return end;
+            }
+            function consumeLineBreaks(pos, end, sourceFile) {
+                while (pos < end && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                    pos++;
+                }
+                return pos;
+            }
+            function isName(pos, end, sourceFile, name) {
+                return pos + name.length < end &&
+                    sourceFile.text.substr(pos, name.length) === name &&
+                    (ts.isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)) ||
+                        ts.isLineBreak(sourceFile.text.charCodeAt(pos + name.length)));
+            }
+            function isParamTag(pos, end, sourceFile) {
+                return isName(pos, end, sourceFile, paramTag);
+            }
+            function pushDocCommentLineText(docComments, text, blankLineCount) {
+                while (blankLineCount--) {
+                    docComments.push(ts.textPart(""));
+                }
+                docComments.push(ts.textPart(text));
+            }
+            function getCleanedJsDocComment(pos, end, sourceFile) {
+                var spacesToRemoveAfterAsterisk;
+                var docComments = [];
+                var blankLineCount = 0;
+                var isInParamTag = false;
+                while (pos < end) {
+                    var docCommentTextOfLine = "";
+                    pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile);
+                    if (pos < end && sourceFile.text.charCodeAt(pos) === 42) {
+                        var lineStartPos = pos + 1;
+                        pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk);
+                        if (spacesToRemoveAfterAsterisk === undefined && pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                            spacesToRemoveAfterAsterisk = pos - lineStartPos;
+                        }
+                    }
+                    else if (spacesToRemoveAfterAsterisk === undefined) {
+                        spacesToRemoveAfterAsterisk = 0;
+                    }
+                    while (pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                        var ch = sourceFile.text.charAt(pos);
+                        if (ch === "@") {
+                            if (isParamTag(pos, end, sourceFile)) {
+                                isInParamTag = true;
+                                pos += paramTag.length;
+                                continue;
+                            }
+                            else {
+                                isInParamTag = false;
+                            }
+                        }
+                        if (!isInParamTag) {
+                            docCommentTextOfLine += ch;
+                        }
+                        pos++;
+                    }
+                    pos = consumeLineBreaks(pos, end, sourceFile);
+                    if (docCommentTextOfLine) {
+                        pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount);
+                        blankLineCount = 0;
+                    }
+                    else if (!isInParamTag && docComments.length) {
+                        blankLineCount++;
+                    }
+                }
+                return docComments;
+            }
+            function getCleanedParamJsDocComment(pos, end, sourceFile) {
+                var paramHelpStringMargin;
+                var paramDocComments = [];
+                while (pos < end) {
+                    if (isParamTag(pos, end, sourceFile)) {
+                        var blankLineCount = 0;
+                        var recordedParamTag = false;
+                        pos = consumeWhiteSpaces(pos + paramTag.length);
+                        if (pos >= end) {
+                            break;
+                        }
+                        if (sourceFile.text.charCodeAt(pos) === 123) {
+                            pos++;
+                            for (var curlies = 1; pos < end; pos++) {
+                                var charCode = sourceFile.text.charCodeAt(pos);
+                                if (charCode === 123) {
+                                    curlies++;
+                                    continue;
+                                }
+                                if (charCode === 125) {
+                                    curlies--;
+                                    if (curlies === 0) {
+                                        pos++;
+                                        break;
+                                    }
+                                    else {
+                                        continue;
+                                    }
+                                }
+                                if (charCode === 64) {
+                                    break;
+                                }
+                            }
+                            pos = consumeWhiteSpaces(pos);
+                            if (pos >= end) {
+                                break;
+                            }
+                        }
+                        if (isName(pos, end, sourceFile, name)) {
+                            pos = consumeWhiteSpaces(pos + name.length);
+                            if (pos >= end) {
+                                break;
+                            }
+                            var paramHelpString = "";
+                            var firstLineParamHelpStringPos = pos;
+                            while (pos < end) {
+                                var ch = sourceFile.text.charCodeAt(pos);
+                                if (ts.isLineBreak(ch)) {
+                                    if (paramHelpString) {
+                                        pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
+                                        paramHelpString = "";
+                                        blankLineCount = 0;
+                                        recordedParamTag = true;
+                                    }
+                                    else if (recordedParamTag) {
+                                        blankLineCount++;
+                                    }
+                                    setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos);
+                                    continue;
+                                }
+                                if (ch === 64) {
+                                    break;
+                                }
+                                paramHelpString += sourceFile.text.charAt(pos);
+                                pos++;
+                            }
+                            if (paramHelpString) {
+                                pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
+                            }
+                            paramHelpStringMargin = undefined;
+                        }
+                        if (sourceFile.text.charCodeAt(pos) === 64) {
+                            continue;
+                        }
+                    }
+                    pos++;
+                }
+                return paramDocComments;
+                function consumeWhiteSpaces(pos) {
+                    while (pos < end && ts.isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
+                        pos++;
+                    }
+                    return pos;
+                }
+                function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos) {
+                    pos = consumeLineBreaks(pos, end, sourceFile);
+                    if (pos >= end) {
+                        return;
+                    }
+                    if (paramHelpStringMargin === undefined) {
+                        paramHelpStringMargin = sourceFile.getLineAndCharacterOfPosition(firstLineParamHelpStringPos).character;
+                    }
+                    var startOfLinePos = pos;
+                    pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin);
+                    if (pos >= end) {
+                        return;
+                    }
+                    var consumedSpaces = pos - startOfLinePos;
+                    if (consumedSpaces < paramHelpStringMargin) {
+                        var ch = sourceFile.text.charCodeAt(pos);
+                        if (ch === 42) {
+                            pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    var TypeObject = (function () {
+        function TypeObject(checker, flags) {
+            this.checker = checker;
+            this.flags = flags;
+        }
+        TypeObject.prototype.getFlags = function () {
+            return this.flags;
+        };
+        TypeObject.prototype.getSymbol = function () {
+            return this.symbol;
+        };
+        TypeObject.prototype.getProperties = function () {
+            return this.checker.getPropertiesOfType(this);
+        };
+        TypeObject.prototype.getProperty = function (propertyName) {
+            return this.checker.getPropertyOfType(this, propertyName);
+        };
+        TypeObject.prototype.getApparentProperties = function () {
+            return this.checker.getAugmentedPropertiesOfType(this);
+        };
+        TypeObject.prototype.getCallSignatures = function () {
+            return this.checker.getSignaturesOfType(this, 0);
+        };
+        TypeObject.prototype.getConstructSignatures = function () {
+            return this.checker.getSignaturesOfType(this, 1);
+        };
+        TypeObject.prototype.getStringIndexType = function () {
+            return this.checker.getIndexTypeOfType(this, 0);
+        };
+        TypeObject.prototype.getNumberIndexType = function () {
+            return this.checker.getIndexTypeOfType(this, 1);
+        };
+        return TypeObject;
+    })();
+    var SignatureObject = (function () {
+        function SignatureObject(checker) {
+            this.checker = checker;
+        }
+        SignatureObject.prototype.getDeclaration = function () {
+            return this.declaration;
+        };
+        SignatureObject.prototype.getTypeParameters = function () {
+            return this.typeParameters;
+        };
+        SignatureObject.prototype.getParameters = function () {
+            return this.parameters;
+        };
+        SignatureObject.prototype.getReturnType = function () {
+            return this.checker.getReturnTypeOfSignature(this);
+        };
+        SignatureObject.prototype.getDocumentationComment = function () {
+            if (this.documentationComment === undefined) {
+                this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations([this.declaration], undefined, false) : [];
+            }
+            return this.documentationComment;
+        };
+        return SignatureObject;
+    })();
+    var SourceFileObject = (function (_super) {
+        __extends(SourceFileObject, _super);
+        function SourceFileObject() {
+            _super.apply(this, arguments);
+        }
+        SourceFileObject.prototype.update = function (newText, textChangeRange) {
+            return ts.updateSourceFile(this, newText, textChangeRange);
+        };
+        SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) {
+            return ts.getLineAndCharacterOfPosition(this, position);
+        };
+        SourceFileObject.prototype.getLineStarts = function () {
+            return ts.getLineStarts(this);
+        };
+        SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) {
+            return ts.getPositionOfLineAndCharacter(this, line, character);
+        };
+        SourceFileObject.prototype.getNamedDeclarations = function () {
+            if (!this.namedDeclarations) {
+                this.namedDeclarations = this.computeNamedDeclarations();
+            }
+            return this.namedDeclarations;
+        };
+        SourceFileObject.prototype.computeNamedDeclarations = function () {
+            var result = {};
+            ts.forEachChild(this, visit);
+            return result;
+            function addDeclaration(declaration) {
+                var name = getDeclarationName(declaration);
+                if (name) {
+                    var declarations = getDeclarations(name);
+                    declarations.push(declaration);
+                }
+            }
+            function getDeclarations(name) {
+                return ts.getProperty(result, name) || (result[name] = []);
+            }
+            function getDeclarationName(declaration) {
+                if (declaration.name) {
+                    var result_1 = getTextOfIdentifierOrLiteral(declaration.name);
+                    if (result_1 !== undefined) {
+                        return result_1;
+                    }
+                    if (declaration.name.kind === 127) {
+                        var expr = declaration.name.expression;
+                        if (expr.kind === 155) {
+                            return expr.name.text;
+                        }
+                        return getTextOfIdentifierOrLiteral(expr);
+                    }
+                }
+                return undefined;
+            }
+            function getTextOfIdentifierOrLiteral(node) {
+                if (node) {
+                    if (node.kind === 65 ||
+                        node.kind === 8 ||
+                        node.kind === 7) {
+                        return node.text;
+                    }
+                }
+                return undefined;
+            }
+            function visit(node) {
+                switch (node.kind) {
+                    case 200:
+                    case 134:
+                    case 133:
+                        var functionDeclaration = node;
+                        var declarationName = getDeclarationName(functionDeclaration);
+                        if (declarationName) {
+                            var declarations = getDeclarations(declarationName);
+                            var lastDeclaration = ts.lastOrUndefined(declarations);
+                            if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) {
+                                if (functionDeclaration.body && !lastDeclaration.body) {
+                                    declarations[declarations.length - 1] = functionDeclaration;
+                                }
+                            }
+                            else {
+                                declarations.push(functionDeclaration);
+                            }
+                            ts.forEachChild(node, visit);
+                        }
+                        break;
+                    case 201:
+                    case 202:
+                    case 203:
+                    case 204:
+                    case 205:
+                    case 208:
+                    case 217:
+                    case 213:
+                    case 208:
+                    case 210:
+                    case 211:
+                    case 136:
+                    case 137:
+                    case 145:
+                        addDeclaration(node);
+                    case 135:
+                    case 180:
+                    case 199:
+                    case 150:
+                    case 151:
+                    case 206:
+                        ts.forEachChild(node, visit);
+                        break;
+                    case 179:
+                        if (ts.isFunctionBlock(node)) {
+                            ts.forEachChild(node, visit);
+                        }
+                        break;
+                    case 129:
+                        if (!(node.flags & 112)) {
+                            break;
+                        }
+                    case 198:
+                    case 152:
+                        if (ts.isBindingPattern(node.name)) {
+                            ts.forEachChild(node.name, visit);
+                            break;
+                        }
+                    case 226:
+                    case 132:
+                    case 131:
+                        addDeclaration(node);
+                        break;
+                    case 215:
+                        if (node.exportClause) {
+                            ts.forEach(node.exportClause.elements, visit);
+                        }
+                        break;
+                    case 209:
+                        var importClause = node.importClause;
+                        if (importClause) {
+                            if (importClause.name) {
+                                addDeclaration(importClause);
+                            }
+                            if (importClause.namedBindings) {
+                                if (importClause.namedBindings.kind === 211) {
+                                    addDeclaration(importClause.namedBindings);
+                                }
+                                else {
+                                    ts.forEach(importClause.namedBindings.elements, visit);
+                                }
+                            }
+                        }
+                        break;
+                }
+            }
+        };
+        return SourceFileObject;
+    })(NodeObject);
+    var TextChange = (function () {
+        function TextChange() {
+        }
+        return TextChange;
+    })();
+    ts.TextChange = TextChange;
+    var HighlightSpanKind;
+    (function (HighlightSpanKind) {
+        HighlightSpanKind.none = "none";
+        HighlightSpanKind.definition = "definition";
+        HighlightSpanKind.reference = "reference";
+        HighlightSpanKind.writtenReference = "writtenReference";
+    })(HighlightSpanKind = ts.HighlightSpanKind || (ts.HighlightSpanKind = {}));
+    (function (SymbolDisplayPartKind) {
+        SymbolDisplayPartKind[SymbolDisplayPartKind["aliasName"] = 0] = "aliasName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["className"] = 1] = "className";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["enumName"] = 2] = "enumName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["fieldName"] = 3] = "fieldName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["interfaceName"] = 4] = "interfaceName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["keyword"] = 5] = "keyword";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["lineBreak"] = 6] = "lineBreak";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["numericLiteral"] = 7] = "numericLiteral";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["stringLiteral"] = 8] = "stringLiteral";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["localName"] = 9] = "localName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["methodName"] = 10] = "methodName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["moduleName"] = 11] = "moduleName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["operator"] = 12] = "operator";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["parameterName"] = 13] = "parameterName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["propertyName"] = 14] = "propertyName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["punctuation"] = 15] = "punctuation";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["space"] = 16] = "space";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["text"] = 17] = "text";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["typeParameterName"] = 18] = "typeParameterName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["enumMemberName"] = 19] = "enumMemberName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["functionName"] = 20] = "functionName";
+        SymbolDisplayPartKind[SymbolDisplayPartKind["regularExpressionLiteral"] = 21] = "regularExpressionLiteral";
+    })(ts.SymbolDisplayPartKind || (ts.SymbolDisplayPartKind = {}));
+    var SymbolDisplayPartKind = ts.SymbolDisplayPartKind;
+    (function (OutputFileType) {
+        OutputFileType[OutputFileType["JavaScript"] = 0] = "JavaScript";
+        OutputFileType[OutputFileType["SourceMap"] = 1] = "SourceMap";
+        OutputFileType[OutputFileType["Declaration"] = 2] = "Declaration";
+    })(ts.OutputFileType || (ts.OutputFileType = {}));
+    var OutputFileType = ts.OutputFileType;
+    (function (EndOfLineState) {
+        EndOfLineState[EndOfLineState["Start"] = 0] = "Start";
+        EndOfLineState[EndOfLineState["InMultiLineCommentTrivia"] = 1] = "InMultiLineCommentTrivia";
+        EndOfLineState[EndOfLineState["InSingleQuoteStringLiteral"] = 2] = "InSingleQuoteStringLiteral";
+        EndOfLineState[EndOfLineState["InDoubleQuoteStringLiteral"] = 3] = "InDoubleQuoteStringLiteral";
+        EndOfLineState[EndOfLineState["InTemplateHeadOrNoSubstitutionTemplate"] = 4] = "InTemplateHeadOrNoSubstitutionTemplate";
+        EndOfLineState[EndOfLineState["InTemplateMiddleOrTail"] = 5] = "InTemplateMiddleOrTail";
+        EndOfLineState[EndOfLineState["InTemplateSubstitutionPosition"] = 6] = "InTemplateSubstitutionPosition";
+    })(ts.EndOfLineState || (ts.EndOfLineState = {}));
+    var EndOfLineState = ts.EndOfLineState;
+    (function (TokenClass) {
+        TokenClass[TokenClass["Punctuation"] = 0] = "Punctuation";
+        TokenClass[TokenClass["Keyword"] = 1] = "Keyword";
+        TokenClass[TokenClass["Operator"] = 2] = "Operator";
+        TokenClass[TokenClass["Comment"] = 3] = "Comment";
+        TokenClass[TokenClass["Whitespace"] = 4] = "Whitespace";
+        TokenClass[TokenClass["Identifier"] = 5] = "Identifier";
+        TokenClass[TokenClass["NumberLiteral"] = 6] = "NumberLiteral";
+        TokenClass[TokenClass["StringLiteral"] = 7] = "StringLiteral";
+        TokenClass[TokenClass["RegExpLiteral"] = 8] = "RegExpLiteral";
+    })(ts.TokenClass || (ts.TokenClass = {}));
+    var TokenClass = ts.TokenClass;
+    var ScriptElementKind;
+    (function (ScriptElementKind) {
+        ScriptElementKind.unknown = "";
+        ScriptElementKind.warning = "warning";
+        ScriptElementKind.keyword = "keyword";
+        ScriptElementKind.scriptElement = "script";
+        ScriptElementKind.moduleElement = "module";
+        ScriptElementKind.classElement = "class";
+        ScriptElementKind.interfaceElement = "interface";
+        ScriptElementKind.typeElement = "type";
+        ScriptElementKind.enumElement = "enum";
+        ScriptElementKind.variableElement = "var";
+        ScriptElementKind.localVariableElement = "local var";
+        ScriptElementKind.functionElement = "function";
+        ScriptElementKind.localFunctionElement = "local function";
+        ScriptElementKind.memberFunctionElement = "method";
+        ScriptElementKind.memberGetAccessorElement = "getter";
+        ScriptElementKind.memberSetAccessorElement = "setter";
+        ScriptElementKind.memberVariableElement = "property";
+        ScriptElementKind.constructorImplementationElement = "constructor";
+        ScriptElementKind.callSignatureElement = "call";
+        ScriptElementKind.indexSignatureElement = "index";
+        ScriptElementKind.constructSignatureElement = "construct";
+        ScriptElementKind.parameterElement = "parameter";
+        ScriptElementKind.typeParameterElement = "type parameter";
+        ScriptElementKind.primitiveType = "primitive type";
+        ScriptElementKind.label = "label";
+        ScriptElementKind.alias = "alias";
+        ScriptElementKind.constElement = "const";
+        ScriptElementKind.letElement = "let";
+    })(ScriptElementKind = ts.ScriptElementKind || (ts.ScriptElementKind = {}));
+    var ScriptElementKindModifier;
+    (function (ScriptElementKindModifier) {
+        ScriptElementKindModifier.none = "";
+        ScriptElementKindModifier.publicMemberModifier = "public";
+        ScriptElementKindModifier.privateMemberModifier = "private";
+        ScriptElementKindModifier.protectedMemberModifier = "protected";
+        ScriptElementKindModifier.exportedModifier = "export";
+        ScriptElementKindModifier.ambientModifier = "declare";
+        ScriptElementKindModifier.staticModifier = "static";
+    })(ScriptElementKindModifier = ts.ScriptElementKindModifier || (ts.ScriptElementKindModifier = {}));
+    var ClassificationTypeNames = (function () {
+        function ClassificationTypeNames() {
+        }
+        ClassificationTypeNames.comment = "comment";
+        ClassificationTypeNames.identifier = "identifier";
+        ClassificationTypeNames.keyword = "keyword";
+        ClassificationTypeNames.numericLiteral = "number";
+        ClassificationTypeNames.operator = "operator";
+        ClassificationTypeNames.stringLiteral = "string";
+        ClassificationTypeNames.whiteSpace = "whitespace";
+        ClassificationTypeNames.text = "text";
+        ClassificationTypeNames.punctuation = "punctuation";
+        ClassificationTypeNames.className = "class name";
+        ClassificationTypeNames.enumName = "enum name";
+        ClassificationTypeNames.interfaceName = "interface name";
+        ClassificationTypeNames.moduleName = "module name";
+        ClassificationTypeNames.typeParameterName = "type parameter name";
+        ClassificationTypeNames.typeAlias = "type alias name";
+        return ClassificationTypeNames;
+    })();
+    ts.ClassificationTypeNames = ClassificationTypeNames;
+    function displayPartsToString(displayParts) {
+        if (displayParts) {
+            return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join("");
+        }
+        return "";
+    }
+    ts.displayPartsToString = displayPartsToString;
+    function isLocalVariableOrFunction(symbol) {
+        if (symbol.parent) {
+            return false;
+        }
+        return ts.forEach(symbol.declarations, function (declaration) {
+            if (declaration.kind === 162) {
+                return true;
+            }
+            if (declaration.kind !== 198 && declaration.kind !== 200) {
+                return false;
+            }
+            for (var parent_1 = declaration.parent; !ts.isFunctionBlock(parent_1); parent_1 = parent_1.parent) {
+                if (parent_1.kind === 227 || parent_1.kind === 206) {
+                    return false;
+                }
+            }
+            return true;
+        });
+    }
+    function getDefaultCompilerOptions() {
+        return {
+            target: 1,
+            module: 0,
+        };
+    }
+    ts.getDefaultCompilerOptions = getDefaultCompilerOptions;
+    var OperationCanceledException = (function () {
+        function OperationCanceledException() {
+        }
+        return OperationCanceledException;
+    })();
+    ts.OperationCanceledException = OperationCanceledException;
+    var CancellationTokenObject = (function () {
+        function CancellationTokenObject(cancellationToken) {
+            this.cancellationToken = cancellationToken;
+        }
+        CancellationTokenObject.prototype.isCancellationRequested = function () {
+            return this.cancellationToken && this.cancellationToken.isCancellationRequested();
+        };
+        CancellationTokenObject.prototype.throwIfCancellationRequested = function () {
+            if (this.isCancellationRequested()) {
+                throw new OperationCanceledException();
+            }
+        };
+        CancellationTokenObject.None = new CancellationTokenObject(null);
+        return CancellationTokenObject;
+    })();
+    ts.CancellationTokenObject = CancellationTokenObject;
+    var HostCache = (function () {
+        function HostCache(host) {
+            this.host = host;
+            this.fileNameToEntry = {};
+            var rootFileNames = host.getScriptFileNames();
+            for (var _i = 0; _i < rootFileNames.length; _i++) {
+                var fileName = rootFileNames[_i];
+                this.createEntry(fileName);
+            }
+            this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
+        }
+        HostCache.prototype.compilationSettings = function () {
+            return this._compilationSettings;
+        };
+        HostCache.prototype.createEntry = function (fileName) {
+            var entry;
+            var scriptSnapshot = this.host.getScriptSnapshot(fileName);
+            if (scriptSnapshot) {
+                entry = {
+                    hostFileName: fileName,
+                    version: this.host.getScriptVersion(fileName),
+                    scriptSnapshot: scriptSnapshot
+                };
+            }
+            return this.fileNameToEntry[ts.normalizeSlashes(fileName)] = entry;
+        };
+        HostCache.prototype.getEntry = function (fileName) {
+            return ts.lookUp(this.fileNameToEntry, ts.normalizeSlashes(fileName));
+        };
+        HostCache.prototype.contains = function (fileName) {
+            return ts.hasProperty(this.fileNameToEntry, ts.normalizeSlashes(fileName));
+        };
+        HostCache.prototype.getOrCreateEntry = function (fileName) {
+            if (this.contains(fileName)) {
+                return this.getEntry(fileName);
+            }
+            return this.createEntry(fileName);
+        };
+        HostCache.prototype.getRootFileNames = function () {
+            var _this = this;
+            var fileNames = [];
+            ts.forEachKey(this.fileNameToEntry, function (key) {
+                if (ts.hasProperty(_this.fileNameToEntry, key) && _this.fileNameToEntry[key])
+                    fileNames.push(key);
+            });
+            return fileNames;
+        };
+        HostCache.prototype.getVersion = function (fileName) {
+            var file = this.getEntry(fileName);
+            return file && file.version;
+        };
+        HostCache.prototype.getScriptSnapshot = function (fileName) {
+            var file = this.getEntry(fileName);
+            return file && file.scriptSnapshot;
+        };
+        return HostCache;
+    })();
+    var SyntaxTreeCache = (function () {
+        function SyntaxTreeCache(host) {
+            this.host = host;
+        }
+        SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) {
+            var scriptSnapshot = this.host.getScriptSnapshot(fileName);
+            if (!scriptSnapshot) {
+                throw new Error("Could not find file: '" + fileName + "'.");
+            }
+            var version = this.host.getScriptVersion(fileName);
+            var sourceFile;
+            if (this.currentFileName !== fileName) {
+                sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2, version, true);
+            }
+            else if (this.currentFileVersion !== version) {
+                var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
+                sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
+            }
+            if (sourceFile) {
+                this.currentFileVersion = version;
+                this.currentFileName = fileName;
+                this.currentFileScriptSnapshot = scriptSnapshot;
+                this.currentSourceFile = sourceFile;
+            }
+            return this.currentSourceFile;
+        };
+        return SyntaxTreeCache;
+    })();
+    function setSourceFileFields(sourceFile, scriptSnapshot, version) {
+        sourceFile.version = version;
+        sourceFile.scriptSnapshot = scriptSnapshot;
+    }
+    function transpile(input, compilerOptions, fileName, diagnostics) {
+        var options = compilerOptions ? ts.clone(compilerOptions) : getDefaultCompilerOptions();
+        options.separateCompilation = true;
+        options.allowNonTsExtensions = true;
+        var inputFileName = fileName || "module.ts";
+        var sourceFile = ts.createSourceFile(inputFileName, input, options.target);
+        if (diagnostics && sourceFile.parseDiagnostics) {
+            diagnostics.push.apply(diagnostics, sourceFile.parseDiagnostics);
+        }
+        var outputText;
+        var compilerHost = {
+            getSourceFile: function (fileName, target) { return fileName === inputFileName ? sourceFile : undefined; },
+            writeFile: function (name, text, writeByteOrderMark) {
+                ts.Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: " + name);
+                outputText = text;
+            },
+            getDefaultLibFileName: function () { return "lib.d.ts"; },
+            useCaseSensitiveFileNames: function () { return false; },
+            getCanonicalFileName: function (fileName) { return fileName; },
+            getCurrentDirectory: function () { return ""; },
+            getNewLine: function () { return (ts.sys && ts.sys.newLine) || "\r\n"; }
+        };
+        var program = ts.createProgram([inputFileName], options, compilerHost);
+        if (diagnostics) {
+            diagnostics.push.apply(diagnostics, program.getGlobalDiagnostics());
+        }
+        program.emit();
+        ts.Debug.assert(outputText !== undefined, "Output generation failed");
+        return outputText;
+    }
+    ts.transpile = transpile;
+    function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents) {
+        var sourceFile = ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), scriptTarget, setNodeParents);
+        setSourceFileFields(sourceFile, scriptSnapshot, version);
+        sourceFile.nameTable = sourceFile.identifiers;
+        return sourceFile;
+    }
+    ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile;
+    ts.disableIncrementalParsing = false;
+    function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) {
+        if (textChangeRange) {
+            if (version !== sourceFile.version) {
+                if (!ts.disableIncrementalParsing) {
+                    var newSourceFile = ts.updateSourceFile(sourceFile, scriptSnapshot.getText(0, scriptSnapshot.getLength()), textChangeRange, aggressiveChecks);
+                    setSourceFileFields(newSourceFile, scriptSnapshot, version);
+                    newSourceFile.nameTable = undefined;
+                    return newSourceFile;
+                }
+            }
+        }
+        return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, true);
+    }
+    ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile;
+    function createDocumentRegistry() {
+        var buckets = {};
+        function getKeyFromCompilationSettings(settings) {
+            return "_" + settings.target;
+        }
+        function getBucketForCompilationSettings(settings, createIfMissing) {
+            var key = getKeyFromCompilationSettings(settings);
+            var bucket = ts.lookUp(buckets, key);
+            if (!bucket && createIfMissing) {
+                buckets[key] = bucket = {};
+            }
+            return bucket;
+        }
+        function reportStats() {
+            var bucketInfoArray = Object.keys(buckets).filter(function (name) { return name && name.charAt(0) === '_'; }).map(function (name) {
+                var entries = ts.lookUp(buckets, name);
+                var sourceFiles = [];
+                for (var i in entries) {
+                    var entry = entries[i];
+                    sourceFiles.push({
+                        name: i,
+                        refCount: entry.languageServiceRefCount,
+                        references: entry.owners.slice(0)
+                    });
+                }
+                sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; });
+                return {
+                    bucket: name,
+                    sourceFiles: sourceFiles
+                };
+            });
+            return JSON.stringify(bucketInfoArray, null, 2);
+        }
+        function acquireDocument(fileName, compilationSettings, scriptSnapshot, version) {
+            return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, true);
+        }
+        function updateDocument(fileName, compilationSettings, scriptSnapshot, version) {
+            return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, false);
+        }
+        function acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, acquiring) {
+            var bucket = getBucketForCompilationSettings(compilationSettings, true);
+            var entry = ts.lookUp(bucket, fileName);
+            if (!entry) {
+                ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
+                var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, false);
+                bucket[fileName] = entry = {
+                    sourceFile: sourceFile,
+                    languageServiceRefCount: 0,
+                    owners: []
+                };
+            }
+            else {
+                if (entry.sourceFile.version !== version) {
+                    entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
+                }
+            }
+            if (acquiring) {
+                entry.languageServiceRefCount++;
+            }
+            return entry.sourceFile;
+        }
+        function releaseDocument(fileName, compilationSettings) {
+            var bucket = getBucketForCompilationSettings(compilationSettings, false);
+            ts.Debug.assert(bucket !== undefined);
+            var entry = ts.lookUp(bucket, fileName);
+            entry.languageServiceRefCount--;
+            ts.Debug.assert(entry.languageServiceRefCount >= 0);
+            if (entry.languageServiceRefCount === 0) {
+                delete bucket[fileName];
+            }
+        }
+        return {
+            acquireDocument: acquireDocument,
+            updateDocument: updateDocument,
+            releaseDocument: releaseDocument,
+            reportStats: reportStats
+        };
+    }
+    ts.createDocumentRegistry = createDocumentRegistry;
+    function preProcessFile(sourceText, readImportFiles) {
+        if (readImportFiles === void 0) { readImportFiles = true; }
+        var referencedFiles = [];
+        var importedFiles = [];
+        var isNoDefaultLib = false;
+        function processTripleSlashDirectives() {
+            var commentRanges = ts.getLeadingCommentRanges(sourceText, 0);
+            ts.forEach(commentRanges, function (commentRange) {
+                var comment = sourceText.substring(commentRange.pos, commentRange.end);
+                var referencePathMatchResult = ts.getFileReferenceFromReferencePath(comment, commentRange);
+                if (referencePathMatchResult) {
+                    isNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
+                    var fileReference = referencePathMatchResult.fileReference;
+                    if (fileReference) {
+                        referencedFiles.push(fileReference);
+                    }
+                }
+            });
+        }
+        function recordModuleName() {
+            var importPath = scanner.getTokenValue();
+            var pos = scanner.getTokenPos();
+            importedFiles.push({
+                fileName: importPath,
+                pos: pos,
+                end: pos + importPath.length
+            });
+        }
+        function processImport() {
+            scanner.setText(sourceText);
+            var token = scanner.scan();
+            while (token !== 1) {
+                if (token === 85) {
+                    token = scanner.scan();
+                    if (token === 8) {
+                        recordModuleName();
+                        continue;
+                    }
+                    else {
+                        if (token === 65) {
+                            token = scanner.scan();
+                            if (token === 124) {
+                                token = scanner.scan();
+                                if (token === 8) {
+                                    recordModuleName();
+                                    continue;
+                                }
+                            }
+                            else if (token === 53) {
+                                token = scanner.scan();
+                                if (token === 118) {
+                                    token = scanner.scan();
+                                    if (token === 16) {
+                                        token = scanner.scan();
+                                        if (token === 8) {
+                                            recordModuleName();
+                                            continue;
+                                        }
+                                    }
+                                }
+                            }
+                            else if (token === 23) {
+                                token = scanner.scan();
+                            }
+                            else {
+                                continue;
+                            }
+                        }
+                        if (token === 14) {
+                            token = scanner.scan();
+                            while (token !== 15) {
+                                token = scanner.scan();
+                            }
+                            if (token === 15) {
+                                token = scanner.scan();
+                                if (token === 124) {
+                                    token = scanner.scan();
+                                    if (token === 8) {
+                                        recordModuleName();
+                                    }
+                                }
+                            }
+                        }
+                        else if (token === 35) {
+                            token = scanner.scan();
+                            if (token === 111) {
+                                token = scanner.scan();
+                                if (token === 65) {
+                                    token = scanner.scan();
+                                    if (token === 124) {
+                                        token = scanner.scan();
+                                        if (token === 8) {
+                                            recordModuleName();
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                else if (token === 78) {
+                    token = scanner.scan();
+                    if (token === 14) {
+                        token = scanner.scan();
+                        while (token !== 15) {
+                            token = scanner.scan();
+                        }
+                        if (token === 15) {
+                            token = scanner.scan();
+                            if (token === 124) {
+                                token = scanner.scan();
+                                if (token === 8) {
+                                    recordModuleName();
+                                }
+                            }
+                        }
+                    }
+                    else if (token === 35) {
+                        token = scanner.scan();
+                        if (token === 124) {
+                            token = scanner.scan();
+                            if (token === 8) {
+                                recordModuleName();
+                            }
+                        }
+                    }
+                }
+                token = scanner.scan();
+            }
+            scanner.setText(undefined);
+        }
+        if (readImportFiles) {
+            processImport();
+        }
+        processTripleSlashDirectives();
+        return { referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isNoDefaultLib };
+    }
+    ts.preProcessFile = preProcessFile;
+    function getTargetLabel(referenceNode, labelName) {
+        while (referenceNode) {
+            if (referenceNode.kind === 194 && referenceNode.label.text === labelName) {
+                return referenceNode.label;
+            }
+            referenceNode = referenceNode.parent;
+        }
+        return undefined;
+    }
+    function isJumpStatementTarget(node) {
+        return node.kind === 65 &&
+            (node.parent.kind === 190 || node.parent.kind === 189) &&
+            node.parent.label === node;
+    }
+    function isLabelOfLabeledStatement(node) {
+        return node.kind === 65 &&
+            node.parent.kind === 194 &&
+            node.parent.label === node;
+    }
+    function isLabeledBy(node, labelName) {
+        for (var owner = node.parent; owner.kind === 194; owner = owner.parent) {
+            if (owner.label.text === labelName) {
+                return true;
+            }
+        }
+        return false;
+    }
+    function isLabelName(node) {
+        return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node);
+    }
+    function isRightSideOfQualifiedName(node) {
+        return node.parent.kind === 126 && node.parent.right === node;
+    }
+    function isRightSideOfPropertyAccess(node) {
+        return node && node.parent && node.parent.kind === 155 && node.parent.name === node;
+    }
+    function isCallExpressionTarget(node) {
+        if (isRightSideOfPropertyAccess(node)) {
+            node = node.parent;
+        }
+        return node && node.parent && node.parent.kind === 157 && node.parent.expression === node;
+    }
+    function isNewExpressionTarget(node) {
+        if (isRightSideOfPropertyAccess(node)) {
+            node = node.parent;
+        }
+        return node && node.parent && node.parent.kind === 158 && node.parent.expression === node;
+    }
+    function isNameOfModuleDeclaration(node) {
+        return node.parent.kind === 205 && node.parent.name === node;
+    }
+    function isNameOfFunctionDeclaration(node) {
+        return node.kind === 65 &&
+            ts.isFunctionLike(node.parent) && node.parent.name === node;
+    }
+    function isNameOfPropertyAssignment(node) {
+        return (node.kind === 65 || node.kind === 8 || node.kind === 7) &&
+            (node.parent.kind === 224 || node.parent.kind === 225) && node.parent.name === node;
+    }
+    function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) {
+        if (node.kind === 8 || node.kind === 7) {
+            switch (node.parent.kind) {
+                case 132:
+                case 131:
+                case 224:
+                case 226:
+                case 134:
+                case 133:
+                case 136:
+                case 137:
+                case 205:
+                    return node.parent.name === node;
+                case 156:
+                    return node.parent.argumentExpression === node;
+            }
+        }
+        return false;
+    }
+    function isNameOfExternalModuleImportOrDeclaration(node) {
+        if (node.kind === 8) {
+            return isNameOfModuleDeclaration(node) ||
+                (ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node);
+        }
+        return false;
+    }
+    function isInsideComment(sourceFile, token, position) {
+        return position <= token.getStart(sourceFile) &&
+            (isInsideCommentRange(ts.getTrailingCommentRanges(sourceFile.text, token.getFullStart())) ||
+                isInsideCommentRange(ts.getLeadingCommentRanges(sourceFile.text, token.getFullStart())));
+        function isInsideCommentRange(comments) {
+            return ts.forEach(comments, function (comment) {
+                if (comment.pos < position && position < comment.end) {
+                    return true;
+                }
+                else if (position === comment.end) {
+                    var text = sourceFile.text;
+                    var width = comment.end - comment.pos;
+                    if (width <= 2 || text.charCodeAt(comment.pos + 1) === 47) {
+                        return true;
+                    }
+                    else {
+                        return !(text.charCodeAt(comment.end - 1) === 47 &&
+                            text.charCodeAt(comment.end - 2) === 42);
+                    }
+                }
+                return false;
+            });
+        }
+    }
+    var SemanticMeaning;
+    (function (SemanticMeaning) {
+        SemanticMeaning[SemanticMeaning["None"] = 0] = "None";
+        SemanticMeaning[SemanticMeaning["Value"] = 1] = "Value";
+        SemanticMeaning[SemanticMeaning["Type"] = 2] = "Type";
+        SemanticMeaning[SemanticMeaning["Namespace"] = 4] = "Namespace";
+        SemanticMeaning[SemanticMeaning["All"] = 7] = "All";
+    })(SemanticMeaning || (SemanticMeaning = {}));
+    var BreakContinueSearchType;
+    (function (BreakContinueSearchType) {
+        BreakContinueSearchType[BreakContinueSearchType["None"] = 0] = "None";
+        BreakContinueSearchType[BreakContinueSearchType["Unlabeled"] = 1] = "Unlabeled";
+        BreakContinueSearchType[BreakContinueSearchType["Labeled"] = 2] = "Labeled";
+        BreakContinueSearchType[BreakContinueSearchType["All"] = 3] = "All";
+    })(BreakContinueSearchType || (BreakContinueSearchType = {}));
+    var keywordCompletions = [];
+    for (var i = 66; i <= 125; i++) {
+        keywordCompletions.push({
+            name: ts.tokenToString(i),
+            kind: ScriptElementKind.keyword,
+            kindModifiers: ScriptElementKindModifier.none,
+            sortText: "0"
+        });
+    }
+    function getContainerNode(node) {
+        while (true) {
+            node = node.parent;
+            if (!node) {
+                return undefined;
+            }
+            switch (node.kind) {
+                case 227:
+                case 134:
+                case 133:
+                case 200:
+                case 162:
+                case 136:
+                case 137:
+                case 201:
+                case 202:
+                case 204:
+                case 205:
+                    return node;
+            }
+        }
+    }
+    ts.getContainerNode = getContainerNode;
+    function getNodeKind(node) {
+        switch (node.kind) {
+            case 205: return ScriptElementKind.moduleElement;
+            case 201: return ScriptElementKind.classElement;
+            case 202: return ScriptElementKind.interfaceElement;
+            case 203: return ScriptElementKind.typeElement;
+            case 204: return ScriptElementKind.enumElement;
+            case 198:
+                return ts.isConst(node)
+                    ? ScriptElementKind.constElement
+                    : ts.isLet(node)
+                        ? ScriptElementKind.letElement
+                        : ScriptElementKind.variableElement;
+            case 200: return ScriptElementKind.functionElement;
+            case 136: return ScriptElementKind.memberGetAccessorElement;
+            case 137: return ScriptElementKind.memberSetAccessorElement;
+            case 134:
+            case 133:
+                return ScriptElementKind.memberFunctionElement;
+            case 132:
+            case 131:
+                return ScriptElementKind.memberVariableElement;
+            case 140: return ScriptElementKind.indexSignatureElement;
+            case 139: return ScriptElementKind.constructSignatureElement;
+            case 138: return ScriptElementKind.callSignatureElement;
+            case 135: return ScriptElementKind.constructorImplementationElement;
+            case 128: return ScriptElementKind.typeParameterElement;
+            case 226: return ScriptElementKind.variableElement;
+            case 129: return (node.flags & 112) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
+            case 208:
+            case 213:
+            case 210:
+            case 217:
+            case 211:
+                return ScriptElementKind.alias;
+        }
+        return ScriptElementKind.unknown;
+    }
+    ts.getNodeKind = getNodeKind;
+    function createLanguageService(host, documentRegistry) {
+        if (documentRegistry === void 0) { documentRegistry = createDocumentRegistry(); }
+        var syntaxTreeCache = new SyntaxTreeCache(host);
+        var ruleProvider;
+        var program;
+        var useCaseSensitivefileNames = false;
+        var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
+        if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
+            ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
+        }
+        function log(message) {
+            if (host.log) {
+                host.log(message);
+            }
+        }
+        function getCanonicalFileName(fileName) {
+            return useCaseSensitivefileNames ? fileName : fileName.toLowerCase();
+        }
+        function getValidSourceFile(fileName) {
+            fileName = ts.normalizeSlashes(fileName);
+            var sourceFile = program.getSourceFile(getCanonicalFileName(fileName));
+            if (!sourceFile) {
+                throw new Error("Could not find file: '" + fileName + "'.");
+            }
+            return sourceFile;
+        }
+        function getRuleProvider(options) {
+            if (!ruleProvider) {
+                ruleProvider = new ts.formatting.RulesProvider();
+            }
+            ruleProvider.ensureUpToDate(options);
+            return ruleProvider;
+        }
+        function synchronizeHostData() {
+            var hostCache = new HostCache(host);
+            if (programUpToDate()) {
+                return;
+            }
+            var oldSettings = program && program.getCompilerOptions();
+            var newSettings = hostCache.compilationSettings();
+            var changesInCompilationSettingsAffectSyntax = oldSettings && oldSettings.target !== newSettings.target;
+            var newProgram = ts.createProgram(hostCache.getRootFileNames(), newSettings, {
+                getSourceFile: getOrCreateSourceFile,
+                getCancellationToken: function () { return cancellationToken; },
+                getCanonicalFileName: function (fileName) { return useCaseSensitivefileNames ? fileName : fileName.toLowerCase(); },
+                useCaseSensitiveFileNames: function () { return useCaseSensitivefileNames; },
+                getNewLine: function () { return host.getNewLine ? host.getNewLine() : "\r\n"; },
+                getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); },
+                writeFile: function (fileName, data, writeByteOrderMark) { },
+                getCurrentDirectory: function () { return host.getCurrentDirectory(); }
+            });
+            if (program) {
+                var oldSourceFiles = program.getSourceFiles();
+                for (var _i = 0; _i < oldSourceFiles.length; _i++) {
+                    var oldSourceFile = oldSourceFiles[_i];
+                    var fileName = oldSourceFile.fileName;
+                    if (!newProgram.getSourceFile(fileName) || changesInCompilationSettingsAffectSyntax) {
+                        documentRegistry.releaseDocument(fileName, oldSettings);
+                    }
+                }
+            }
+            program = newProgram;
+            program.getTypeChecker();
+            return;
+            function getOrCreateSourceFile(fileName) {
+                var hostFileInformation = hostCache.getOrCreateEntry(fileName);
+                if (!hostFileInformation) {
+                    return undefined;
+                }
+                if (!changesInCompilationSettingsAffectSyntax) {
+                    var oldSourceFile = program && program.getSourceFile(fileName);
+                    if (oldSourceFile) {
+                        return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
+                    }
+                }
+                return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
+            }
+            function sourceFileUpToDate(sourceFile) {
+                return sourceFile && sourceFile.version === hostCache.getVersion(sourceFile.fileName);
+            }
+            function programUpToDate() {
+                if (!program) {
+                    return false;
+                }
+                var rootFileNames = hostCache.getRootFileNames();
+                if (program.getSourceFiles().length !== rootFileNames.length) {
+                    return false;
+                }
+                for (var _i = 0; _i < rootFileNames.length; _i++) {
+                    var fileName = rootFileNames[_i];
+                    if (!sourceFileUpToDate(program.getSourceFile(fileName))) {
+                        return false;
+                    }
+                }
+                return ts.compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings());
+            }
+        }
+        function getProgram() {
+            synchronizeHostData();
+            return program;
+        }
+        function cleanupSemanticCache() {
+        }
+        function dispose() {
+            if (program) {
+                ts.forEach(program.getSourceFiles(), function (f) {
+                    return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions());
+                });
+            }
+        }
+        function getSyntacticDiagnostics(fileName) {
+            synchronizeHostData();
+            return program.getSyntacticDiagnostics(getValidSourceFile(fileName));
+        }
+        function getSemanticDiagnostics(fileName) {
+            synchronizeHostData();
+            var targetSourceFile = getValidSourceFile(fileName);
+            if (ts.isJavaScript(fileName)) {
+                return getJavaScriptSemanticDiagnostics(targetSourceFile);
+            }
+            var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile);
+            if (!program.getCompilerOptions().declaration) {
+                return semanticDiagnostics;
+            }
+            var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile);
+            return ts.concatenate(semanticDiagnostics, declarationDiagnostics);
+        }
+        function getJavaScriptSemanticDiagnostics(sourceFile) {
+            var diagnostics = [];
+            walk(sourceFile);
+            return diagnostics;
+            function walk(node) {
+                if (!node) {
+                    return false;
+                }
+                switch (node.kind) {
+                    case 208:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 214:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 201:
+                        var classDeclaration = node;
+                        if (checkModifiers(classDeclaration.modifiers) ||
+                            checkTypeParameters(classDeclaration.typeParameters)) {
+                            return true;
+                        }
+                        break;
+                    case 222:
+                        var heritageClause = node;
+                        if (heritageClause.token === 102) {
+                            diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        break;
+                    case 202:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 205:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 203:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 134:
+                    case 133:
+                    case 135:
+                    case 136:
+                    case 137:
+                    case 162:
+                    case 200:
+                    case 163:
+                    case 200:
+                        var functionDeclaration = node;
+                        if (checkModifiers(functionDeclaration.modifiers) ||
+                            checkTypeParameters(functionDeclaration.typeParameters) ||
+                            checkTypeAnnotation(functionDeclaration.type)) {
+                            return true;
+                        }
+                        break;
+                    case 180:
+                        var variableStatement = node;
+                        if (checkModifiers(variableStatement.modifiers)) {
+                            return true;
+                        }
+                        break;
+                    case 198:
+                        var variableDeclaration = node;
+                        if (checkTypeAnnotation(variableDeclaration.type)) {
+                            return true;
+                        }
+                        break;
+                    case 157:
+                    case 158:
+                        var expression = node;
+                        if (expression.typeArguments && expression.typeArguments.length > 0) {
+                            var start = expression.typeArguments.pos;
+                            diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        break;
+                    case 129:
+                        var parameter = node;
+                        if (parameter.modifiers) {
+                            var start = parameter.modifiers.pos;
+                            diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        if (parameter.questionToken) {
+                            diagnostics.push(ts.createDiagnosticForNode(parameter.questionToken, ts.Diagnostics.can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        if (parameter.type) {
+                            diagnostics.push(ts.createDiagnosticForNode(parameter.type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        break;
+                    case 132:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.property_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 204:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 160:
+                        var typeAssertionExpression = node;
+                        diagnostics.push(ts.createDiagnosticForNode(typeAssertionExpression.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case 130:
+                        diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.decorators_can_only_be_used_in_a_ts_file));
+                        return true;
+                }
+                return ts.forEachChild(node, walk);
+            }
+            function checkTypeParameters(typeParameters) {
+                if (typeParameters) {
+                    var start = typeParameters.pos;
+                    diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file));
+                    return true;
+                }
+                return false;
+            }
+            function checkTypeAnnotation(type) {
+                if (type) {
+                    diagnostics.push(ts.createDiagnosticForNode(type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file));
+                    return true;
+                }
+                return false;
+            }
+            function checkModifiers(modifiers) {
+                if (modifiers) {
+                    for (var _i = 0; _i < modifiers.length; _i++) {
+                        var modifier = modifiers[_i];
+                        switch (modifier.kind) {
+                            case 108:
+                            case 106:
+                            case 107:
+                            case 115:
+                                diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind)));
+                                return true;
+                            case 109:
+                            case 78:
+                            case 70:
+                            case 73:
+                        }
+                    }
+                }
+                return false;
+            }
+        }
+        function getCompilerOptionsDiagnostics() {
+            synchronizeHostData();
+            return program.getGlobalDiagnostics();
+        }
+        function getCompletionEntryDisplayNameForSymbol(symbol, target, performCharacterChecks) {
+            var displayName = symbol.getName();
+            if (displayName) {
+                if (displayName === "default") {
+                    var localSymbol = ts.getLocalSymbolForExportDefault(symbol);
+                    if (localSymbol && localSymbol.name) {
+                        displayName = symbol.valueDeclaration.localSymbol.name;
+                    }
+                }
+                var firstCharCode = displayName.charCodeAt(0);
+                if ((symbol.flags & 1536) && (firstCharCode === 39 || firstCharCode === 34)) {
+                    return undefined;
+                }
+            }
+            return getCompletionEntryDisplayName(displayName, target, performCharacterChecks);
+        }
+        function getCompletionEntryDisplayName(displayName, target, performCharacterChecks) {
+            if (!displayName) {
+                return undefined;
+            }
+            var firstCharCode = displayName.charCodeAt(0);
+            if (displayName.length >= 2 &&
+                firstCharCode === displayName.charCodeAt(displayName.length - 1) &&
+                (firstCharCode === 39 || firstCharCode === 34)) {
+                displayName = displayName.substring(1, displayName.length - 1);
+            }
+            if (!displayName) {
+                return undefined;
+            }
+            if (performCharacterChecks) {
+                if (!ts.isIdentifierStart(displayName.charCodeAt(0), target)) {
+                    return undefined;
+                }
+                for (var i = 1, n = displayName.length; i < n; i++) {
+                    if (!ts.isIdentifierPart(displayName.charCodeAt(i), target)) {
+                        return undefined;
+                    }
+                }
+            }
+            return ts.unescapeIdentifier(displayName);
+        }
+        function getCompletionData(fileName, position) {
+            var typeChecker = program.getTypeChecker();
+            var syntacticStart = new Date().getTime();
+            var sourceFile = getValidSourceFile(fileName);
+            var start = new Date().getTime();
+            var currentToken = ts.getTokenAtPosition(sourceFile, position);
+            log("getCompletionData: Get current token: " + (new Date().getTime() - start));
+            start = new Date().getTime();
+            var insideComment = isInsideComment(sourceFile, currentToken, position);
+            log("getCompletionData: Is inside comment: " + (new Date().getTime() - start));
+            if (insideComment) {
+                log("Returning an empty list because completion was inside a comment.");
+                return undefined;
+            }
+            start = new Date().getTime();
+            var previousToken = ts.findPrecedingToken(position, sourceFile);
+            log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start));
+            var contextToken = previousToken;
+            if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) {
+                var start_1 = new Date().getTime();
+                contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile);
+                log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start_1));
+            }
+            if (contextToken && isCompletionListBlocker(contextToken)) {
+                log("Returning an empty list because completion was requested in an invalid position.");
+                return undefined;
+            }
+            var node = currentToken;
+            var isRightOfDot = false;
+            if (contextToken && contextToken.kind === 20 && contextToken.parent.kind === 155) {
+                node = contextToken.parent.expression;
+                isRightOfDot = true;
+            }
+            else if (contextToken && contextToken.kind === 20 && contextToken.parent.kind === 126) {
+                node = contextToken.parent.left;
+                isRightOfDot = true;
+            }
+            var location = ts.getTouchingPropertyName(sourceFile, position);
+            var target = program.getCompilerOptions().target;
+            var semanticStart = new Date().getTime();
+            var isMemberCompletion;
+            var isNewIdentifierLocation;
+            var symbols = [];
+            if (isRightOfDot) {
+                getTypeScriptMemberSymbols();
+            }
+            else {
+                if (!tryGetGlobalSymbols()) {
+                    return undefined;
+                }
+            }
+            log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
+            return { symbols: symbols, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, location: location, isRightOfDot: isRightOfDot };
+            function getTypeScriptMemberSymbols() {
+                isMemberCompletion = true;
+                isNewIdentifierLocation = false;
+                if (node.kind === 65 || node.kind === 126 || node.kind === 155) {
+                    var symbol = typeChecker.getSymbolAtLocation(node);
+                    if (symbol && symbol.flags & 8388608) {
+                        symbol = typeChecker.getAliasedSymbol(symbol);
+                    }
+                    if (symbol && symbol.flags & 1952) {
+                        var exportedSymbols = typeChecker.getExportsOfModule(symbol);
+                        ts.forEach(exportedSymbols, function (symbol) {
+                            if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) {
+                                symbols.push(symbol);
+                            }
+                        });
+                    }
+                }
+                var type = typeChecker.getTypeAtLocation(node);
+                if (type) {
+                    ts.forEach(type.getApparentProperties(), function (symbol) {
+                        if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) {
+                            symbols.push(symbol);
+                        }
+                    });
+                }
+            }
+            function tryGetGlobalSymbols() {
+                var containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(contextToken);
+                if (containingObjectLiteral) {
+                    isMemberCompletion = true;
+                    isNewIdentifierLocation = true;
+                    var contextualType = typeChecker.getContextualType(containingObjectLiteral);
+                    if (!contextualType) {
+                        return false;
+                    }
+                    var contextualTypeMembers = typeChecker.getPropertiesOfType(contextualType);
+                    if (contextualTypeMembers && contextualTypeMembers.length > 0) {
+                        symbols = filterContextualMembersList(contextualTypeMembers, containingObjectLiteral.properties);
+                    }
+                }
+                else if (ts.getAncestor(contextToken, 210)) {
+                    isMemberCompletion = true;
+                    isNewIdentifierLocation = true;
+                    if (showCompletionsInImportsClause(contextToken)) {
+                        var importDeclaration = ts.getAncestor(contextToken, 209);
+                        ts.Debug.assert(importDeclaration !== undefined);
+                        var exports_1;
+                        if (importDeclaration.moduleSpecifier) {
+                            var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier);
+                            if (moduleSpecifierSymbol) {
+                                exports_1 = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
+                            }
+                        }
+                        symbols = exports_1 ? filterModuleExports(exports_1, importDeclaration) : emptyArray;
+                    }
+                }
+                else {
+                    isMemberCompletion = false;
+                    isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
+                    if (previousToken !== contextToken) {
+                        ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'.");
+                    }
+                    var adjustedPosition = previousToken !== contextToken ?
+                        previousToken.getStart() :
+                        position;
+                    var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
+                    var symbolMeanings = 793056 | 107455 | 1536 | 8388608;
+                    symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
+                }
+                return true;
+            }
+            function getScopeNode(initialToken, position, sourceFile) {
+                var scope = initialToken;
+                while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) {
+                    scope = scope.parent;
+                }
+                return scope;
+            }
+            function isCompletionListBlocker(previousToken) {
+                var start = new Date().getTime();
+                var result = isInStringOrRegularExpressionOrTemplateLiteral(previousToken) ||
+                    isIdentifierDefinitionLocation(previousToken) ||
+                    isRightOfIllegalDot(previousToken);
+                log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
+                return result;
+            }
+            function showCompletionsInImportsClause(node) {
+                if (node) {
+                    if (node.kind === 14 || node.kind === 23) {
+                        return node.parent.kind === 212;
+                    }
+                }
+                return false;
+            }
+            function isNewIdentifierDefinitionLocation(previousToken) {
+                if (previousToken) {
+                    var containingNodeKind = previousToken.parent.kind;
+                    switch (previousToken.kind) {
+                        case 23:
+                            return containingNodeKind === 157
+                                || containingNodeKind === 135
+                                || containingNodeKind === 158
+                                || containingNodeKind === 153
+                                || containingNodeKind === 169;
+                        case 16:
+                            return containingNodeKind === 157
+                                || containingNodeKind === 135
+                                || containingNodeKind === 158
+                                || containingNodeKind === 161;
+                        case 18:
+                            return containingNodeKind === 153;
+                        case 117:
+                            return true;
+                        case 20:
+                            return containingNodeKind === 205;
+                        case 14:
+                            return containingNodeKind === 201;
+                        case 53:
+                            return containingNodeKind === 198
+                                || containingNodeKind === 169;
+                        case 11:
+                            return containingNodeKind === 171;
+                        case 12:
+                            return containingNodeKind === 176;
+                        case 108:
+                        case 106:
+                        case 107:
+                            return containingNodeKind === 132;
+                    }
+                    switch (previousToken.getText()) {
+                        case "public":
+                        case "protected":
+                        case "private":
+                            return true;
+                    }
+                }
+                return false;
+            }
+            function isInStringOrRegularExpressionOrTemplateLiteral(previousToken) {
+                if (previousToken.kind === 8
+                    || previousToken.kind === 9
+                    || ts.isTemplateLiteralKind(previousToken.kind)) {
+                    var start_2 = previousToken.getStart();
+                    var end = previousToken.getEnd();
+                    if (start_2 < position && position < end) {
+                        return true;
+                    }
+                    else if (position === end) {
+                        return !!previousToken.isUnterminated;
+                    }
+                }
+                return false;
+            }
+            function getContainingObjectLiteralApplicableForCompletion(previousToken) {
+                // The locations in an object literal expression that are applicable for completion are property name definition locations.
+                if (previousToken) {
+                    var parent_2 = previousToken.parent;
+                    switch (previousToken.kind) {
+                        case 14:
+                        case 23:
+                            if (parent_2 && parent_2.kind === 154) {
+                                return parent_2;
+                            }
+                            break;
+                    }
+                }
+                return undefined;
+            }
+            function isFunction(kind) {
+                switch (kind) {
+                    case 162:
+                    case 163:
+                    case 200:
+                    case 134:
+                    case 133:
+                    case 136:
+                    case 137:
+                    case 138:
+                    case 139:
+                    case 140:
+                        return true;
+                }
+                return false;
+            }
+            function isIdentifierDefinitionLocation(previousToken) {
+                if (previousToken) {
+                    var containingNodeKind = previousToken.parent.kind;
+                    switch (previousToken.kind) {
+                        case 23:
+                            return containingNodeKind === 198 ||
+                                containingNodeKind === 199 ||
+                                containingNodeKind === 180 ||
+                                containingNodeKind === 204 ||
+                                isFunction(containingNodeKind) ||
+                                containingNodeKind === 201 ||
+                                containingNodeKind === 200 ||
+                                containingNodeKind === 202 ||
+                                containingNodeKind === 151 ||
+                                containingNodeKind === 150;
+                        case 20:
+                            return containingNodeKind === 151;
+                        case 18:
+                            return containingNodeKind === 151;
+                        case 16:
+                            return containingNodeKind === 223 ||
+                                isFunction(containingNodeKind);
+                        case 14:
+                            return containingNodeKind === 204 ||
+                                containingNodeKind === 202 ||
+                                containingNodeKind === 145 ||
+                                containingNodeKind === 150;
+                        case 22:
+                            return containingNodeKind === 131 &&
+                                previousToken.parent && previousToken.parent.parent &&
+                                (previousToken.parent.parent.kind === 202 ||
+                                    previousToken.parent.parent.kind === 145);
+                        case 24:
+                            return containingNodeKind === 201 ||
+                                containingNodeKind === 200 ||
+                                containingNodeKind === 202 ||
+                                isFunction(containingNodeKind);
+                        case 109:
+                            return containingNodeKind === 132;
+                        case 21:
+                            return containingNodeKind === 129 ||
+                                containingNodeKind === 135 ||
+                                (previousToken.parent && previousToken.parent.parent &&
+                                    previousToken.parent.parent.kind === 151);
+                        case 108:
+                        case 106:
+                        case 107:
+                            return containingNodeKind === 129;
+                        case 69:
+                        case 77:
+                        case 103:
+                        case 83:
+                        case 98:
+                        case 116:
+                        case 120:
+                        case 85:
+                        case 104:
+                        case 70:
+                        case 110:
+                            return true;
+                    }
+                    switch (previousToken.getText()) {
+                        case "class":
+                        case "interface":
+                        case "enum":
+                        case "function":
+                        case "var":
+                        case "static":
+                        case "let":
+                        case "const":
+                        case "yield":
+                            return true;
+                    }
+                }
+                return false;
+            }
+            function isRightOfIllegalDot(previousToken) {
+                if (previousToken && previousToken.kind === 7) {
+                    var text = previousToken.getFullText();
+                    return text.charAt(text.length - 1) === ".";
+                }
+                return false;
+            }
+            function filterModuleExports(exports, importDeclaration) {
+                var exisingImports = {};
+                if (!importDeclaration.importClause) {
+                    return exports;
+                }
+                if (importDeclaration.importClause.namedBindings &&
+                    importDeclaration.importClause.namedBindings.kind === 212) {
+                    ts.forEach(importDeclaration.importClause.namedBindings.elements, function (el) {
+                        var name = el.propertyName || el.name;
+                        exisingImports[name.text] = true;
+                    });
+                }
+                if (ts.isEmpty(exisingImports)) {
+                    return exports;
+                }
+                return ts.filter(exports, function (e) { return !ts.lookUp(exisingImports, e.name); });
+            }
+            function filterContextualMembersList(contextualMemberSymbols, existingMembers) {
+                if (!existingMembers || existingMembers.length === 0) {
+                    return contextualMemberSymbols;
+                }
+                var existingMemberNames = {};
+                ts.forEach(existingMembers, function (m) {
+                    if (m.kind !== 224 && m.kind !== 225) {
+                        return;
+                    }
+                    if (m.getStart() <= position && position <= m.getEnd()) {
+                        return;
+                    }
+                    existingMemberNames[m.name.text] = true;
+                });
+                var filteredMembers = [];
+                ts.forEach(contextualMemberSymbols, function (s) {
+                    if (!existingMemberNames[s.name]) {
+                        filteredMembers.push(s);
+                    }
+                });
+                return filteredMembers;
+            }
+        }
+        function getCompletionsAtPosition(fileName, position) {
+            synchronizeHostData();
+            var completionData = getCompletionData(fileName, position);
+            if (!completionData) {
+                return undefined;
+            }
+            var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isRightOfDot = completionData.isRightOfDot;
+            var entries;
+            if (isRightOfDot && ts.isJavaScript(fileName)) {
+                entries = getCompletionEntriesFromSymbols(symbols);
+                ts.addRange(entries, getJavaScriptCompletionEntries());
+            }
+            else {
+                if (!symbols || symbols.length === 0) {
+                    return undefined;
+                }
+                entries = getCompletionEntriesFromSymbols(symbols);
+            }
+            if (!isMemberCompletion) {
+                ts.addRange(entries, keywordCompletions);
+            }
+            return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries };
+            function getJavaScriptCompletionEntries() {
+                var entries = [];
+                var allNames = {};
+                var target = program.getCompilerOptions().target;
+                for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
+                    var sourceFile = _a[_i];
+                    var nameTable = getNameTable(sourceFile);
+                    for (var name_1 in nameTable) {
+                        if (!allNames[name_1]) {
+                            allNames[name_1] = name_1;
+                            var displayName = getCompletionEntryDisplayName(name_1, target, true);
+                            if (displayName) {
+                                var entry = {
+                                    name: displayName,
+                                    kind: ScriptElementKind.warning,
+                                    kindModifiers: "",
+                                    sortText: "1"
+                                };
+                                entries.push(entry);
+                            }
+                        }
+                    }
+                }
+                return entries;
+            }
+            function createCompletionEntry(symbol, location) {
+                var displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, true);
+                if (!displayName) {
+                    return undefined;
+                }
+                return {
+                    name: displayName,
+                    kind: getSymbolKind(symbol, location),
+                    kindModifiers: getSymbolModifiers(symbol),
+                    sortText: "0",
+                };
+            }
+            function getCompletionEntriesFromSymbols(symbols) {
+                var start = new Date().getTime();
+                var entries = [];
+                if (symbols) {
+                    var nameToSymbol = {};
+                    for (var _i = 0; _i < symbols.length; _i++) {
+                        var symbol = symbols[_i];
+                        var entry = createCompletionEntry(symbol, location);
+                        if (entry) {
+                            var id = ts.escapeIdentifier(entry.name);
+                            if (!ts.lookUp(nameToSymbol, id)) {
+                                entries.push(entry);
+                                nameToSymbol[id] = symbol;
+                            }
+                        }
+                    }
+                }
+                log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
+                return entries;
+            }
+        }
+        function getCompletionEntryDetails(fileName, position, entryName) {
+            synchronizeHostData();
+            var completionData = getCompletionData(fileName, position);
+            if (completionData) {
+                var symbols = completionData.symbols, location_1 = completionData.location;
+                var target = program.getCompilerOptions().target;
+                var symbol = ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(s, target, false) === entryName ? s : undefined; });
+                if (symbol) {
+                    var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location_1, location_1, 7);
+                    return {
+                        name: entryName,
+                        kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
+                        kindModifiers: getSymbolModifiers(symbol),
+                        displayParts: displayPartsDocumentationsAndSymbolKind.displayParts,
+                        documentation: displayPartsDocumentationsAndSymbolKind.documentation
+                    };
+                }
+            }
+            var keywordCompletion = ts.forEach(keywordCompletions, function (c) { return c.name === entryName; });
+            if (keywordCompletion) {
+                return {
+                    name: entryName,
+                    kind: ScriptElementKind.keyword,
+                    kindModifiers: ScriptElementKindModifier.none,
+                    displayParts: [ts.displayPart(entryName, SymbolDisplayPartKind.keyword)],
+                    documentation: undefined
+                };
+            }
+            return undefined;
+        }
+        function getSymbolKind(symbol, location) {
+            var flags = symbol.getFlags();
+            if (flags & 32)
+                return ScriptElementKind.classElement;
+            if (flags & 384)
+                return ScriptElementKind.enumElement;
+            if (flags & 524288)
+                return ScriptElementKind.typeElement;
+            if (flags & 64)
+                return ScriptElementKind.interfaceElement;
+            if (flags & 262144)
+                return ScriptElementKind.typeParameterElement;
+            var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location);
+            if (result === ScriptElementKind.unknown) {
+                if (flags & 262144)
+                    return ScriptElementKind.typeParameterElement;
+                if (flags & 8)
+                    return ScriptElementKind.variableElement;
+                if (flags & 8388608)
+                    return ScriptElementKind.alias;
+                if (flags & 1536)
+                    return ScriptElementKind.moduleElement;
+            }
+            return result;
+        }
+        function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location) {
+            var typeChecker = program.getTypeChecker();
+            if (typeChecker.isUndefinedSymbol(symbol)) {
+                return ScriptElementKind.variableElement;
+            }
+            if (typeChecker.isArgumentsSymbol(symbol)) {
+                return ScriptElementKind.localVariableElement;
+            }
+            if (flags & 3) {
+                if (ts.isFirstDeclarationOfSymbolParameter(symbol)) {
+                    return ScriptElementKind.parameterElement;
+                }
+                else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) {
+                    return ScriptElementKind.constElement;
+                }
+                else if (ts.forEach(symbol.declarations, ts.isLet)) {
+                    return ScriptElementKind.letElement;
+                }
+                return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement;
+            }
+            if (flags & 16)
+                return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement;
+            if (flags & 32768)
+                return ScriptElementKind.memberGetAccessorElement;
+            if (flags & 65536)
+                return ScriptElementKind.memberSetAccessorElement;
+            if (flags & 8192)
+                return ScriptElementKind.memberFunctionElement;
+            if (flags & 16384)
+                return ScriptElementKind.constructorImplementationElement;
+            if (flags & 4) {
+                if (flags & 268435456) {
+                    var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) {
+                        var rootSymbolFlags = rootSymbol.getFlags();
+                        if (rootSymbolFlags & (98308 | 3)) {
+                            return ScriptElementKind.memberVariableElement;
+                        }
+                        ts.Debug.assert(!!(rootSymbolFlags & 8192));
+                    });
+                    if (!unionPropertyKind) {
+                        var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
+                        if (typeOfUnionProperty.getCallSignatures().length) {
+                            return ScriptElementKind.memberFunctionElement;
+                        }
+                        return ScriptElementKind.memberVariableElement;
+                    }
+                    return unionPropertyKind;
+                }
+                return ScriptElementKind.memberVariableElement;
+            }
+            return ScriptElementKind.unknown;
+        }
+        function getTypeKind(type) {
+            var flags = type.getFlags();
+            if (flags & 128)
+                return ScriptElementKind.enumElement;
+            if (flags & 1024)
+                return ScriptElementKind.classElement;
+            if (flags & 2048)
+                return ScriptElementKind.interfaceElement;
+            if (flags & 512)
+                return ScriptElementKind.typeParameterElement;
+            if (flags & 1048703)
+                return ScriptElementKind.primitiveType;
+            if (flags & 256)
+                return ScriptElementKind.primitiveType;
+            return ScriptElementKind.unknown;
+        }
+        function getSymbolModifiers(symbol) {
+            return symbol && symbol.declarations && symbol.declarations.length > 0
+                ? ts.getNodeModifiers(symbol.declarations[0])
+                : ScriptElementKindModifier.none;
+        }
+        function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, enclosingDeclaration, location, semanticMeaning) {
+            if (semanticMeaning === void 0) { semanticMeaning = getMeaningFromLocation(location); }
+            var typeChecker = program.getTypeChecker();
+            var displayParts = [];
+            var documentation;
+            var symbolFlags = symbol.flags;
+            var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location);
+            var hasAddedSymbolInfo;
+            var type;
+            if (symbolKind !== ScriptElementKind.unknown || symbolFlags & 32 || symbolFlags & 8388608) {
+                if (symbolKind === ScriptElementKind.memberGetAccessorElement || symbolKind === ScriptElementKind.memberSetAccessorElement) {
+                    symbolKind = ScriptElementKind.memberVariableElement;
+                }
+                var signature;
+                type = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
+                if (type) {
+                    if (location.parent && location.parent.kind === 155) {
+                        var right = location.parent.name;
+                        if (right === location || (right && right.getFullWidth() === 0)) {
+                            location = location.parent;
+                        }
+                    }
+                    var callExpression;
+                    if (location.kind === 157 || location.kind === 158) {
+                        callExpression = location;
+                    }
+                    else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
+                        callExpression = location.parent;
+                    }
+                    if (callExpression) {
+                        var candidateSignatures = [];
+                        signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures);
+                        if (!signature && candidateSignatures.length) {
+                            signature = candidateSignatures[0];
+                        }
+                        var useConstructSignatures = callExpression.kind === 158 || callExpression.expression.kind === 91;
+                        var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();
+                        if (!ts.contains(allSignatures, signature.target || signature)) {
+                            signature = allSignatures.length ? allSignatures[0] : undefined;
+                        }
+                        if (signature) {
+                            if (useConstructSignatures && (symbolFlags & 32)) {
+                                symbolKind = ScriptElementKind.constructorImplementationElement;
+                                addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
+                            }
+                            else if (symbolFlags & 8388608) {
+                                symbolKind = ScriptElementKind.alias;
+                                pushTypePart(symbolKind);
+                                displayParts.push(ts.spacePart());
+                                if (useConstructSignatures) {
+                                    displayParts.push(ts.keywordPart(88));
+                                    displayParts.push(ts.spacePart());
+                                }
+                                addFullSymbolName(symbol);
+                            }
+                            else {
+                                addPrefixForAnyFunctionOrVar(symbol, symbolKind);
+                            }
+                            switch (symbolKind) {
+                                case ScriptElementKind.memberVariableElement:
+                                case ScriptElementKind.variableElement:
+                                case ScriptElementKind.constElement:
+                                case ScriptElementKind.letElement:
+                                case ScriptElementKind.parameterElement:
+                                case ScriptElementKind.localVariableElement:
+                                    displayParts.push(ts.punctuationPart(51));
+                                    displayParts.push(ts.spacePart());
+                                    if (useConstructSignatures) {
+                                        displayParts.push(ts.keywordPart(88));
+                                        displayParts.push(ts.spacePart());
+                                    }
+                                    if (!(type.flags & 32768)) {
+                                        displayParts.push.apply(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, undefined, 1));
+                                    }
+                                    addSignatureDisplayParts(signature, allSignatures, 8);
+                                    break;
+                                default:
+                                    addSignatureDisplayParts(signature, allSignatures);
+                            }
+                            hasAddedSymbolInfo = true;
+                        }
+                    }
+                    else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & 98304)) ||
+                        (location.kind === 114 && location.parent.kind === 135)) {
+                        var functionDeclaration = location.parent;
+                        var allSignatures = functionDeclaration.kind === 135 ? type.getConstructSignatures() : type.getCallSignatures();
+                        if (!typeChecker.isImplementationOfOverload(functionDeclaration)) {
+                            signature = typeChecker.getSignatureFromDeclaration(functionDeclaration);
+                        }
+                        else {
+                            signature = allSignatures[0];
+                        }
+                        if (functionDeclaration.kind === 135) {
+                            symbolKind = ScriptElementKind.constructorImplementationElement;
+                            addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
+                        }
+                        else {
+                            addPrefixForAnyFunctionOrVar(functionDeclaration.kind === 138 &&
+                                !(type.symbol.flags & 2048 || type.symbol.flags & 4096) ? type.symbol : symbol, symbolKind);
+                        }
+                        addSignatureDisplayParts(signature, allSignatures);
+                        hasAddedSymbolInfo = true;
+                    }
+                }
+            }
+            if (symbolFlags & 32 && !hasAddedSymbolInfo) {
+                displayParts.push(ts.keywordPart(69));
+                displayParts.push(ts.spacePart());
+                addFullSymbolName(symbol);
+                writeTypeParametersOfSymbol(symbol, sourceFile);
+            }
+            if ((symbolFlags & 64) && (semanticMeaning & 2)) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(ts.keywordPart(103));
+                displayParts.push(ts.spacePart());
+                addFullSymbolName(symbol);
+                writeTypeParametersOfSymbol(symbol, sourceFile);
+            }
+            if (symbolFlags & 524288) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(ts.keywordPart(123));
+                displayParts.push(ts.spacePart());
+                addFullSymbolName(symbol);
+                displayParts.push(ts.spacePart());
+                displayParts.push(ts.operatorPart(53));
+                displayParts.push(ts.spacePart());
+                displayParts.push.apply(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration));
+            }
+            if (symbolFlags & 384) {
+                addNewLineIfDisplayPartsExist();
+                if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) {
+                    displayParts.push(ts.keywordPart(70));
+                    displayParts.push(ts.spacePart());
+                }
+                displayParts.push(ts.keywordPart(77));
+                displayParts.push(ts.spacePart());
+                addFullSymbolName(symbol);
+            }
+            if (symbolFlags & 1536) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(ts.keywordPart(117));
+                displayParts.push(ts.spacePart());
+                addFullSymbolName(symbol);
+            }
+            if ((symbolFlags & 262144) && (semanticMeaning & 2)) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(ts.punctuationPart(16));
+                displayParts.push(ts.textPart("type parameter"));
+                displayParts.push(ts.punctuationPart(17));
+                displayParts.push(ts.spacePart());
+                addFullSymbolName(symbol);
+                displayParts.push(ts.spacePart());
+                displayParts.push(ts.keywordPart(86));
+                displayParts.push(ts.spacePart());
+                if (symbol.parent) {
+                    addFullSymbolName(symbol.parent, enclosingDeclaration);
+                    writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration);
+                }
+                else {
+                    var signatureDeclaration = ts.getDeclarationOfKind(symbol, 128).parent;
+                    var signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration);
+                    if (signatureDeclaration.kind === 139) {
+                        displayParts.push(ts.keywordPart(88));
+                        displayParts.push(ts.spacePart());
+                    }
+                    else if (signatureDeclaration.kind !== 138 && signatureDeclaration.name) {
+                        addFullSymbolName(signatureDeclaration.symbol);
+                    }
+                    displayParts.push.apply(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32));
+                }
+            }
+            if (symbolFlags & 8) {
+                addPrefixForAnyFunctionOrVar(symbol, "enum member");
+                var declaration = symbol.declarations[0];
+                if (declaration.kind === 226) {
+                    var constantValue = typeChecker.getConstantValue(declaration);
+                    if (constantValue !== undefined) {
+                        displayParts.push(ts.spacePart());
+                        displayParts.push(ts.operatorPart(53));
+                        displayParts.push(ts.spacePart());
+                        displayParts.push(ts.displayPart(constantValue.toString(), SymbolDisplayPartKind.numericLiteral));
+                    }
+                }
+            }
+            if (symbolFlags & 8388608) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(ts.keywordPart(85));
+                displayParts.push(ts.spacePart());
+                addFullSymbolName(symbol);
+                ts.forEach(symbol.declarations, function (declaration) {
+                    if (declaration.kind === 208) {
+                        var importEqualsDeclaration = declaration;
+                        if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) {
+                            displayParts.push(ts.spacePart());
+                            displayParts.push(ts.operatorPart(53));
+                            displayParts.push(ts.spacePart());
+                            displayParts.push(ts.keywordPart(118));
+                            displayParts.push(ts.punctuationPart(16));
+                            displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), SymbolDisplayPartKind.stringLiteral));
+                            displayParts.push(ts.punctuationPart(17));
+                        }
+                        else {
+                            var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference);
+                            if (internalAliasSymbol) {
+                                displayParts.push(ts.spacePart());
+                                displayParts.push(ts.operatorPart(53));
+                                displayParts.push(ts.spacePart());
+                                addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
+                            }
+                        }
+                        return true;
+                    }
+                });
+            }
+            if (!hasAddedSymbolInfo) {
+                if (symbolKind !== ScriptElementKind.unknown) {
+                    if (type) {
+                        addPrefixForAnyFunctionOrVar(symbol, symbolKind);
+                        if (symbolKind === ScriptElementKind.memberVariableElement ||
+                            symbolFlags & 3 ||
+                            symbolKind === ScriptElementKind.localVariableElement) {
+                            displayParts.push(ts.punctuationPart(51));
+                            displayParts.push(ts.spacePart());
+                            if (type.symbol && type.symbol.flags & 262144) {
+                                var typeParameterParts = ts.mapToDisplayParts(function (writer) {
+                                    typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration);
+                                });
+                                displayParts.push.apply(displayParts, typeParameterParts);
+                            }
+                            else {
+                                displayParts.push.apply(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration));
+                            }
+                        }
+                        else if (symbolFlags & 16 ||
+                            symbolFlags & 8192 ||
+                            symbolFlags & 16384 ||
+                            symbolFlags & 131072 ||
+                            symbolFlags & 98304 ||
+                            symbolKind === ScriptElementKind.memberFunctionElement) {
+                            var allSignatures = type.getCallSignatures();
+                            addSignatureDisplayParts(allSignatures[0], allSignatures);
+                        }
+                    }
+                }
+                else {
+                    symbolKind = getSymbolKind(symbol, location);
+                }
+            }
+            if (!documentation) {
+                documentation = symbol.getDocumentationComment();
+            }
+            return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind };
+            function addNewLineIfDisplayPartsExist() {
+                if (displayParts.length) {
+                    displayParts.push(ts.lineBreakPart());
+                }
+            }
+            function addFullSymbolName(symbol, enclosingDeclaration) {
+                var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, undefined, 1 | 2);
+                displayParts.push.apply(displayParts, fullSymbolDisplayParts);
+            }
+            function addPrefixForAnyFunctionOrVar(symbol, symbolKind) {
+                addNewLineIfDisplayPartsExist();
+                if (symbolKind) {
+                    pushTypePart(symbolKind);
+                    displayParts.push(ts.spacePart());
+                    addFullSymbolName(symbol);
+                }
+            }
+            function pushTypePart(symbolKind) {
+                switch (symbolKind) {
+                    case ScriptElementKind.variableElement:
+                    case ScriptElementKind.functionElement:
+                    case ScriptElementKind.letElement:
+                    case ScriptElementKind.constElement:
+                    case ScriptElementKind.constructorImplementationElement:
+                        displayParts.push(ts.textOrKeywordPart(symbolKind));
+                        return;
+                    default:
+                        displayParts.push(ts.punctuationPart(16));
+                        displayParts.push(ts.textOrKeywordPart(symbolKind));
+                        displayParts.push(ts.punctuationPart(17));
+                        return;
+                }
+            }
+            function addSignatureDisplayParts(signature, allSignatures, flags) {
+                displayParts.push.apply(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32));
+                if (allSignatures.length > 1) {
+                    displayParts.push(ts.spacePart());
+                    displayParts.push(ts.punctuationPart(16));
+                    displayParts.push(ts.operatorPart(33));
+                    displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), SymbolDisplayPartKind.numericLiteral));
+                    displayParts.push(ts.spacePart());
+                    displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads"));
+                    displayParts.push(ts.punctuationPart(17));
+                }
+                documentation = signature.getDocumentationComment();
+            }
+            function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) {
+                var typeParameterParts = ts.mapToDisplayParts(function (writer) {
+                    typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration);
+                });
+                displayParts.push.apply(displayParts, typeParameterParts);
+            }
+        }
+        function getQuickInfoAtPosition(fileName, position) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            var node = ts.getTouchingPropertyName(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+            if (isLabelName(node)) {
+                return undefined;
+            }
+            var typeChecker = program.getTypeChecker();
+            var symbol = typeChecker.getSymbolAtLocation(node);
+            if (!symbol) {
+                switch (node.kind) {
+                    case 65:
+                    case 155:
+                    case 126:
+                    case 93:
+                    case 91:
+                        var type = typeChecker.getTypeAtLocation(node);
+                        if (type) {
+                            return {
+                                kind: ScriptElementKind.unknown,
+                                kindModifiers: ScriptElementKindModifier.none,
+                                textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
+                                displayParts: ts.typeToDisplayParts(typeChecker, type, getContainerNode(node)),
+                                documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined
+                            };
+                        }
+                }
+                return undefined;
+            }
+            var displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node);
+            return {
+                kind: displayPartsDocumentationsAndKind.symbolKind,
+                kindModifiers: getSymbolModifiers(symbol),
+                textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
+                displayParts: displayPartsDocumentationsAndKind.displayParts,
+                documentation: displayPartsDocumentationsAndKind.documentation
+            };
+        }
+        function createDefinitionInfo(node, symbolKind, symbolName, containerName) {
+            return {
+                fileName: node.getSourceFile().fileName,
+                textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()),
+                kind: symbolKind,
+                name: symbolName,
+                containerKind: undefined,
+                containerName: containerName
+            };
+        }
+        function getDefinitionAtPosition(fileName, position) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            var node = ts.getTouchingPropertyName(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+            if (isJumpStatementTarget(node)) {
+                var labelName = node.text;
+                var label = getTargetLabel(node.parent, node.text);
+                return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, undefined)] : undefined;
+            }
+            var comment = ts.forEach(sourceFile.referencedFiles, function (r) { return (r.pos <= position && position < r.end) ? r : undefined; });
+            if (comment) {
+                var referenceFile = ts.tryResolveScriptReference(program, sourceFile, comment);
+                if (referenceFile) {
+                    return [{
+                            fileName: referenceFile.fileName,
+                            textSpan: ts.createTextSpanFromBounds(0, 0),
+                            kind: ScriptElementKind.scriptElement,
+                            name: comment.fileName,
+                            containerName: undefined,
+                            containerKind: undefined
+                        }];
+                }
+                return undefined;
+            }
+            var typeChecker = program.getTypeChecker();
+            var symbol = typeChecker.getSymbolAtLocation(node);
+            if (!symbol) {
+                return undefined;
+            }
+            if (symbol.flags & 8388608) {
+                var declaration = symbol.declarations[0];
+                if (node.kind === 65 && node.parent === declaration) {
+                    symbol = typeChecker.getAliasedSymbol(symbol);
+                }
+            }
+            if (node.parent.kind === 225) {
+                var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
+                if (!shorthandSymbol) {
+                    return [];
+                }
+                var shorthandDeclarations = shorthandSymbol.getDeclarations();
+                var shorthandSymbolKind = getSymbolKind(shorthandSymbol, node);
+                var shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol);
+                var shorthandContainerName = typeChecker.symbolToString(symbol.parent, node);
+                return ts.map(shorthandDeclarations, function (declaration) { return createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName); });
+            }
+            var result = [];
+            var declarations = symbol.getDeclarations();
+            var symbolName = typeChecker.symbolToString(symbol);
+            var symbolKind = getSymbolKind(symbol, node);
+            var containerSymbol = symbol.parent;
+            var containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : "";
+            if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
+                !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
+                ts.forEach(declarations, function (declaration) {
+                    result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName));
+                });
+            }
+            return result;
+            function tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) {
+                if (isNewExpressionTarget(location) || location.kind === 114) {
+                    if (symbol.flags & 32) {
+                        var classDeclaration = symbol.getDeclarations()[0];
+                        ts.Debug.assert(classDeclaration && classDeclaration.kind === 201);
+                        return tryAddSignature(classDeclaration.members, true, symbolKind, symbolName, containerName, result);
+                    }
+                }
+                return false;
+            }
+            function tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result) {
+                if (isCallExpressionTarget(location) || isNewExpressionTarget(location) || isNameOfFunctionDeclaration(location)) {
+                    return tryAddSignature(symbol.declarations, false, symbolKind, symbolName, containerName, result);
+                }
+                return false;
+            }
+            function tryAddSignature(signatureDeclarations, selectConstructors, symbolKind, symbolName, containerName, result) {
+                var declarations = [];
+                var definition;
+                ts.forEach(signatureDeclarations, function (d) {
+                    if ((selectConstructors && d.kind === 135) ||
+                        (!selectConstructors && (d.kind === 200 || d.kind === 134 || d.kind === 133))) {
+                        declarations.push(d);
+                        if (d.body)
+                            definition = d;
+                    }
+                });
+                if (definition) {
+                    result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName));
+                    return true;
+                }
+                else if (declarations.length) {
+                    result.push(createDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName));
+                    return true;
+                }
+                return false;
+            }
+        }
+        function getOccurrencesAtPosition(fileName, position) {
+            var results = getOccurrencesAtPositionCore(fileName, position);
+            if (results) {
+                var sourceFile = getCanonicalFileName(ts.normalizeSlashes(fileName));
+                results = ts.filter(results, function (r) { return getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile; });
+            }
+            return results;
+        }
+        function getDocumentHighlights(fileName, position, filesToSearch) {
+            synchronizeHostData();
+            filesToSearch = ts.map(filesToSearch, ts.normalizeSlashes);
+            var sourceFilesToSearch = ts.filter(program.getSourceFiles(), function (f) { return ts.contains(filesToSearch, f.fileName); });
+            var sourceFile = getValidSourceFile(fileName);
+            var node = ts.getTouchingWord(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+            return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node);
+            function getHighlightSpanForNode(node) {
+                var start = node.getStart();
+                var end = node.getEnd();
+                return {
+                    fileName: sourceFile.fileName,
+                    textSpan: ts.createTextSpanFromBounds(start, end),
+                    kind: HighlightSpanKind.none
+                };
+            }
+            function getSemanticDocumentHighlights(node) {
+                if (node.kind === 65 ||
+                    node.kind === 93 ||
+                    node.kind === 91 ||
+                    isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
+                    isNameOfExternalModuleImportOrDeclaration(node)) {
+                    var referencedSymbols = getReferencedSymbolsForNodes(node, sourceFilesToSearch, false, false);
+                    return convertReferencedSymbols(referencedSymbols);
+                }
+                return undefined;
+                function convertReferencedSymbols(referencedSymbols) {
+                    if (!referencedSymbols) {
+                        return undefined;
+                    }
+                    var fileNameToDocumentHighlights = {};
+                    var result = [];
+                    for (var _i = 0; _i < referencedSymbols.length; _i++) {
+                        var referencedSymbol = referencedSymbols[_i];
+                        for (var _a = 0, _b = referencedSymbol.references; _a < _b.length; _a++) {
+                            var referenceEntry = _b[_a];
+                            var fileName_1 = referenceEntry.fileName;
+                            var documentHighlights = ts.getProperty(fileNameToDocumentHighlights, fileName_1);
+                            if (!documentHighlights) {
+                                documentHighlights = { fileName: fileName_1, highlightSpans: [] };
+                                fileNameToDocumentHighlights[fileName_1] = documentHighlights;
+                                result.push(documentHighlights);
+                            }
+                            documentHighlights.highlightSpans.push({
+                                textSpan: referenceEntry.textSpan,
+                                kind: referenceEntry.isWriteAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference
+                            });
+                        }
+                    }
+                    return result;
+                }
+            }
+            function getSyntacticDocumentHighlights(node) {
+                var fileName = sourceFile.fileName;
+                var highlightSpans = getHighlightSpans(node);
+                if (!highlightSpans || highlightSpans.length === 0) {
+                    return undefined;
+                }
+                return [{ fileName: fileName, highlightSpans: highlightSpans }];
+                function hasKind(node, kind) {
+                    return node !== undefined && node.kind === kind;
+                }
+                function parent(node) {
+                    return node && node.parent;
+                }
+                function getHighlightSpans(node) {
+                    if (node) {
+                        switch (node.kind) {
+                            case 84:
+                            case 76:
+                                if (hasKind(node.parent, 183)) {
+                                    return getIfElseOccurrences(node.parent);
+                                }
+                                break;
+                            case 90:
+                                if (hasKind(node.parent, 191)) {
+                                    return getReturnOccurrences(node.parent);
+                                }
+                                break;
+                            case 94:
+                                if (hasKind(node.parent, 195)) {
+                                    return getThrowOccurrences(node.parent);
+                                }
+                                break;
+                            case 68:
+                                if (hasKind(parent(parent(node)), 196)) {
+                                    return getTryCatchFinallyOccurrences(node.parent.parent);
+                                }
+                                break;
+                            case 96:
+                            case 81:
+                                if (hasKind(parent(node), 196)) {
+                                    return getTryCatchFinallyOccurrences(node.parent);
+                                }
+                                break;
+                            case 92:
+                                if (hasKind(node.parent, 193)) {
+                                    return getSwitchCaseDefaultOccurrences(node.parent);
+                                }
+                                break;
+                            case 67:
+                            case 73:
+                                if (hasKind(parent(parent(parent(node))), 193)) {
+                                    return getSwitchCaseDefaultOccurrences(node.parent.parent.parent);
+                                }
+                                break;
+                            case 66:
+                            case 71:
+                                if (hasKind(node.parent, 190) || hasKind(node.parent, 189)) {
+                                    return getBreakOrContinueStatementOccurences(node.parent);
+                                }
+                                break;
+                            case 82:
+                                if (hasKind(node.parent, 186) ||
+                                    hasKind(node.parent, 187) ||
+                                    hasKind(node.parent, 188)) {
+                                    return getLoopBreakContinueOccurrences(node.parent);
+                                }
+                                break;
+                            case 100:
+                            case 75:
+                                if (hasKind(node.parent, 185) || hasKind(node.parent, 184)) {
+                                    return getLoopBreakContinueOccurrences(node.parent);
+                                }
+                                break;
+                            case 114:
+                                if (hasKind(node.parent, 135)) {
+                                    return getConstructorOccurrences(node.parent);
+                                }
+                                break;
+                            case 116:
+                            case 120:
+                                if (hasKind(node.parent, 136) || hasKind(node.parent, 137)) {
+                                    return getGetAndSetOccurrences(node.parent);
+                                }
+                            default:
+                                if (ts.isModifier(node.kind) && node.parent &&
+                                    (ts.isDeclaration(node.parent) || node.parent.kind === 180)) {
+                                    return getModifierOccurrences(node.kind, node.parent);
+                                }
+                        }
+                    }
+                    return undefined;
+                }
+                function aggregateOwnedThrowStatements(node) {
+                    var statementAccumulator = [];
+                    aggregate(node);
+                    return statementAccumulator;
+                    function aggregate(node) {
+                        if (node.kind === 195) {
+                            statementAccumulator.push(node);
+                        }
+                        else if (node.kind === 196) {
+                            var tryStatement = node;
+                            if (tryStatement.catchClause) {
+                                aggregate(tryStatement.catchClause);
+                            }
+                            else {
+                                aggregate(tryStatement.tryBlock);
+                            }
+                            if (tryStatement.finallyBlock) {
+                                aggregate(tryStatement.finallyBlock);
+                            }
+                        }
+                        else if (!ts.isFunctionLike(node)) {
+                            ts.forEachChild(node, aggregate);
+                        }
+                    }
+                    ;
+                }
+                function getThrowStatementOwner(throwStatement) {
+                    var child = throwStatement;
+                    while (child.parent) {
+                        var parent_3 = child.parent;
+                        if (ts.isFunctionBlock(parent_3) || parent_3.kind === 227) {
+                            return parent_3;
+                        }
+                        if (parent_3.kind === 196) {
+                            var tryStatement = parent_3;
+                            if (tryStatement.tryBlock === child && tryStatement.catchClause) {
+                                return child;
+                            }
+                        }
+                        child = parent_3;
+                    }
+                    return undefined;
+                }
+                function aggregateAllBreakAndContinueStatements(node) {
+                    var statementAccumulator = [];
+                    aggregate(node);
+                    return statementAccumulator;
+                    function aggregate(node) {
+                        if (node.kind === 190 || node.kind === 189) {
+                            statementAccumulator.push(node);
+                        }
+                        else if (!ts.isFunctionLike(node)) {
+                            ts.forEachChild(node, aggregate);
+                        }
+                    }
+                    ;
+                }
+                function ownsBreakOrContinueStatement(owner, statement) {
+                    var actualOwner = getBreakOrContinueOwner(statement);
+                    return actualOwner && actualOwner === owner;
+                }
+                function getBreakOrContinueOwner(statement) {
+                    for (var node_1 = statement.parent; node_1; node_1 = node_1.parent) {
+                        switch (node_1.kind) {
+                            case 193:
+                                if (statement.kind === 189) {
+                                    continue;
+                                }
+                            case 186:
+                            case 187:
+                            case 188:
+                            case 185:
+                            case 184:
+                                if (!statement.label || isLabeledBy(node_1, statement.label.text)) {
+                                    return node_1;
+                                }
+                                break;
+                            default:
+                                if (ts.isFunctionLike(node_1)) {
+                                    return undefined;
+                                }
+                                break;
+                        }
+                    }
+                    return undefined;
+                }
+                function getModifierOccurrences(modifier, declaration) {
+                    var container = declaration.parent;
+                    if (ts.isAccessibilityModifier(modifier)) {
+                        if (!(container.kind === 201 ||
+                            (declaration.kind === 129 && hasKind(container, 135)))) {
+                            return undefined;
+                        }
+                    }
+                    else if (modifier === 109) {
+                        if (container.kind !== 201) {
+                            return undefined;
+                        }
+                    }
+                    else if (modifier === 78 || modifier === 115) {
+                        if (!(container.kind === 206 || container.kind === 227)) {
+                            return undefined;
+                        }
+                    }
+                    else {
+                        return undefined;
+                    }
+                    var keywords = [];
+                    var modifierFlag = getFlagFromModifier(modifier);
+                    var nodes;
+                    switch (container.kind) {
+                        case 206:
+                        case 227:
+                            nodes = container.statements;
+                            break;
+                        case 135:
+                            nodes = container.parameters.concat(container.parent.members);
+                            break;
+                        case 201:
+                            nodes = container.members;
+                            if (modifierFlag & 112) {
+                                var constructor = ts.forEach(container.members, function (member) {
+                                    return member.kind === 135 && member;
+                                });
+                                if (constructor) {
+                                    nodes = nodes.concat(constructor.parameters);
+                                }
+                            }
+                            break;
+                        default:
+                            ts.Debug.fail("Invalid container kind.");
+                    }
+                    ts.forEach(nodes, function (node) {
+                        if (node.modifiers && node.flags & modifierFlag) {
+                            ts.forEach(node.modifiers, function (child) { return pushKeywordIf(keywords, child, modifier); });
+                        }
+                    });
+                    return ts.map(keywords, getHighlightSpanForNode);
+                    function getFlagFromModifier(modifier) {
+                        switch (modifier) {
+                            case 108:
+                                return 16;
+                            case 106:
+                                return 32;
+                            case 107:
+                                return 64;
+                            case 109:
+                                return 128;
+                            case 78:
+                                return 1;
+                            case 115:
+                                return 2;
+                            default:
+                                ts.Debug.fail();
+                        }
+                    }
+                }
+                function pushKeywordIf(keywordList, token) {
+                    var expected = [];
+                    for (var _i = 2; _i < arguments.length; _i++) {
+                        expected[_i - 2] = arguments[_i];
+                    }
+                    if (token && ts.contains(expected, token.kind)) {
+                        keywordList.push(token);
+                        return true;
+                    }
+                    return false;
+                }
+                function getGetAndSetOccurrences(accessorDeclaration) {
+                    var keywords = [];
+                    tryPushAccessorKeyword(accessorDeclaration.symbol, 136);
+                    tryPushAccessorKeyword(accessorDeclaration.symbol, 137);
+                    return ts.map(keywords, getHighlightSpanForNode);
+                    function tryPushAccessorKeyword(accessorSymbol, accessorKind) {
+                        var accessor = ts.getDeclarationOfKind(accessorSymbol, accessorKind);
+                        if (accessor) {
+                            ts.forEach(accessor.getChildren(), function (child) { return pushKeywordIf(keywords, child, 116, 120); });
+                        }
+                    }
+                }
+                function getConstructorOccurrences(constructorDeclaration) {
+                    var declarations = constructorDeclaration.symbol.getDeclarations();
+                    var keywords = [];
+                    ts.forEach(declarations, function (declaration) {
+                        ts.forEach(declaration.getChildren(), function (token) {
+                            return pushKeywordIf(keywords, token, 114);
+                        });
+                    });
+                    return ts.map(keywords, getHighlightSpanForNode);
+                }
+                function getLoopBreakContinueOccurrences(loopNode) {
+                    var keywords = [];
+                    if (pushKeywordIf(keywords, loopNode.getFirstToken(), 82, 100, 75)) {
+                        if (loopNode.kind === 184) {
+                            var loopTokens = loopNode.getChildren();
+                            for (var i = loopTokens.length - 1; i >= 0; i--) {
+                                if (pushKeywordIf(keywords, loopTokens[i], 100)) {
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement);
+                    ts.forEach(breaksAndContinues, function (statement) {
+                        if (ownsBreakOrContinueStatement(loopNode, statement)) {
+                            pushKeywordIf(keywords, statement.getFirstToken(), 66, 71);
+                        }
+                    });
+                    return ts.map(keywords, getHighlightSpanForNode);
+                }
+                function getBreakOrContinueStatementOccurences(breakOrContinueStatement) {
+                    var owner = getBreakOrContinueOwner(breakOrContinueStatement);
+                    if (owner) {
+                        switch (owner.kind) {
+                            case 186:
+                            case 187:
+                            case 188:
+                            case 184:
+                            case 185:
+                                return getLoopBreakContinueOccurrences(owner);
+                            case 193:
+                                return getSwitchCaseDefaultOccurrences(owner);
+                        }
+                    }
+                    return undefined;
+                }
+                function getSwitchCaseDefaultOccurrences(switchStatement) {
+                    var keywords = [];
+                    pushKeywordIf(keywords, switchStatement.getFirstToken(), 92);
+                    ts.forEach(switchStatement.caseBlock.clauses, function (clause) {
+                        pushKeywordIf(keywords, clause.getFirstToken(), 67, 73);
+                        var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause);
+                        ts.forEach(breaksAndContinues, function (statement) {
+                            if (ownsBreakOrContinueStatement(switchStatement, statement)) {
+                                pushKeywordIf(keywords, statement.getFirstToken(), 66);
+                            }
+                        });
+                    });
+                    return ts.map(keywords, getHighlightSpanForNode);
+                }
+                function getTryCatchFinallyOccurrences(tryStatement) {
+                    var keywords = [];
+                    pushKeywordIf(keywords, tryStatement.getFirstToken(), 96);
+                    if (tryStatement.catchClause) {
+                        pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 68);
+                    }
+                    if (tryStatement.finallyBlock) {
+                        var finallyKeyword = ts.findChildOfKind(tryStatement, 81, sourceFile);
+                        pushKeywordIf(keywords, finallyKeyword, 81);
+                    }
+                    return ts.map(keywords, getHighlightSpanForNode);
+                }
+                function getThrowOccurrences(throwStatement) {
+                    var owner = getThrowStatementOwner(throwStatement);
+                    if (!owner) {
+                        return undefined;
+                    }
+                    var keywords = [];
+                    ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) {
+                        pushKeywordIf(keywords, throwStatement.getFirstToken(), 94);
+                    });
+                    if (ts.isFunctionBlock(owner)) {
+                        ts.forEachReturnStatement(owner, function (returnStatement) {
+                            pushKeywordIf(keywords, returnStatement.getFirstToken(), 90);
+                        });
+                    }
+                    return ts.map(keywords, getHighlightSpanForNode);
+                }
+                function getReturnOccurrences(returnStatement) {
+                    var func = ts.getContainingFunction(returnStatement);
+                    if (!(func && hasKind(func.body, 179))) {
+                        return undefined;
+                    }
+                    var keywords = [];
+                    ts.forEachReturnStatement(func.body, function (returnStatement) {
+                        pushKeywordIf(keywords, returnStatement.getFirstToken(), 90);
+                    });
+                    ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) {
+                        pushKeywordIf(keywords, throwStatement.getFirstToken(), 94);
+                    });
+                    return ts.map(keywords, getHighlightSpanForNode);
+                }
+                function getIfElseOccurrences(ifStatement) {
+                    var keywords = [];
+                    while (hasKind(ifStatement.parent, 183) && ifStatement.parent.elseStatement === ifStatement) {
+                        ifStatement = ifStatement.parent;
+                    }
+                    while (ifStatement) {
+                        var children = ifStatement.getChildren();
+                        pushKeywordIf(keywords, children[0], 84);
+                        for (var i = children.length - 1; i >= 0; i--) {
+                            if (pushKeywordIf(keywords, children[i], 76)) {
+                                break;
+                            }
+                        }
+                        if (!hasKind(ifStatement.elseStatement, 183)) {
+                            break;
+                        }
+                        ifStatement = ifStatement.elseStatement;
+                    }
+                    var result = [];
+                    for (var i = 0; i < keywords.length; i++) {
+                        if (keywords[i].kind === 76 && i < keywords.length - 1) {
+                            var elseKeyword = keywords[i];
+                            var ifKeyword = keywords[i + 1];
+                            var shouldCombindElseAndIf = true;
+                            for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
+                                if (!ts.isWhiteSpace(sourceFile.text.charCodeAt(j))) {
+                                    shouldCombindElseAndIf = false;
+                                    break;
+                                }
+                            }
+                            if (shouldCombindElseAndIf) {
+                                result.push({
+                                    fileName: fileName,
+                                    textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
+                                    kind: HighlightSpanKind.reference
+                                });
+                                i++;
+                                continue;
+                            }
+                        }
+                        result.push(getHighlightSpanForNode(keywords[i]));
+                    }
+                    return result;
+                }
+            }
+        }
+        function getOccurrencesAtPositionCore(fileName, position) {
+            synchronizeHostData();
+            return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName]));
+            function convertDocumentHighlights(documentHighlights) {
+                if (!documentHighlights) {
+                    return undefined;
+                }
+                var result = [];
+                for (var _i = 0; _i < documentHighlights.length; _i++) {
+                    var entry = documentHighlights[_i];
+                    for (var _a = 0, _b = entry.highlightSpans; _a < _b.length; _a++) {
+                        var highlightSpan = _b[_a];
+                        result.push({
+                            fileName: entry.fileName,
+                            textSpan: highlightSpan.textSpan,
+                            isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference
+                        });
+                    }
+                }
+                return result;
+            }
+        }
+        function convertReferences(referenceSymbols) {
+            if (!referenceSymbols) {
+                return undefined;
+            }
+            var referenceEntries = [];
+            for (var _i = 0; _i < referenceSymbols.length; _i++) {
+                var referenceSymbol = referenceSymbols[_i];
+                ts.addRange(referenceEntries, referenceSymbol.references);
+            }
+            return referenceEntries;
+        }
+        function findRenameLocations(fileName, position, findInStrings, findInComments) {
+            var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments);
+            return convertReferences(referencedSymbols);
+        }
+        function getReferencesAtPosition(fileName, position) {
+            var referencedSymbols = findReferencedSymbols(fileName, position, false, false);
+            return convertReferences(referencedSymbols);
+        }
+        function findReferences(fileName, position) {
+            var referencedSymbols = findReferencedSymbols(fileName, position, false, false);
+            return ts.filter(referencedSymbols, function (rs) { return !!rs.definition; });
+        }
+        function findReferencedSymbols(fileName, position, findInStrings, findInComments) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            var node = ts.getTouchingPropertyName(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+            if (node.kind !== 65 &&
+                !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) &&
+                !isNameOfExternalModuleImportOrDeclaration(node)) {
+                return undefined;
+            }
+            ts.Debug.assert(node.kind === 65 || node.kind === 7 || node.kind === 8);
+            return getReferencedSymbolsForNodes(node, program.getSourceFiles(), findInStrings, findInComments);
+        }
+        function getReferencedSymbolsForNodes(node, sourceFiles, findInStrings, findInComments) {
+            var typeChecker = program.getTypeChecker();
+            if (isLabelName(node)) {
+                if (isJumpStatementTarget(node)) {
+                    var labelDefinition = getTargetLabel(node.parent, node.text);
+                    return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined;
+                }
+                else {
+                    return getLabelReferencesInNode(node.parent, node);
+                }
+            }
+            if (node.kind === 93) {
+                return getReferencesForThisKeyword(node, sourceFiles);
+            }
+            if (node.kind === 91) {
+                return getReferencesForSuperKeyword(node);
+            }
+            var symbol = typeChecker.getSymbolAtLocation(node);
+            if (!symbol) {
+                return undefined;
+            }
+            var declarations = symbol.declarations;
+            if (!declarations || !declarations.length) {
+                return undefined;
+            }
+            var result;
+            var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
+            var declaredName = getDeclaredName(symbol, node);
+            var scope = getSymbolScope(symbol);
+            var symbolToIndex = [];
+            if (scope) {
+                result = [];
+                getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
+            }
+            else {
+                var internedName = getInternedName(symbol, node, declarations);
+                for (var _i = 0; _i < sourceFiles.length; _i++) {
+                    var sourceFile = sourceFiles[_i];
+                    cancellationToken.throwIfCancellationRequested();
+                    var nameTable = getNameTable(sourceFile);
+                    if (ts.lookUp(nameTable, internedName)) {
+                        result = result || [];
+                        getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
+                    }
+                }
+            }
+            return result;
+            function getDefinition(symbol) {
+                var info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node);
+                var name = ts.map(info.displayParts, function (p) { return p.text; }).join("");
+                var declarations = symbol.declarations;
+                if (!declarations || declarations.length === 0) {
+                    return undefined;
+                }
+                return {
+                    containerKind: "",
+                    containerName: "",
+                    name: name,
+                    kind: info.symbolKind,
+                    fileName: declarations[0].getSourceFile().fileName,
+                    textSpan: ts.createTextSpan(declarations[0].getStart(), 0)
+                };
+            }
+            function isImportOrExportSpecifierName(location) {
+                return location.parent &&
+                    (location.parent.kind === 213 || location.parent.kind === 217) &&
+                    location.parent.propertyName === location;
+            }
+            function isImportOrExportSpecifierImportSymbol(symbol) {
+                return (symbol.flags & 8388608) && ts.forEach(symbol.declarations, function (declaration) {
+                    return declaration.kind === 213 || declaration.kind === 217;
+                });
+            }
+            function getDeclaredName(symbol, location) {
+                var functionExpression = ts.forEach(symbol.declarations, function (d) { return d.kind === 162 ? d : undefined; });
+                var name;
+                if (functionExpression && functionExpression.name) {
+                    name = functionExpression.name.text;
+                }
+                if (isImportOrExportSpecifierName(location)) {
+                    return location.getText();
+                }
+                name = typeChecker.symbolToString(symbol);
+                return stripQuotes(name);
+            }
+            function getInternedName(symbol, location, declarations) {
+                if (isImportOrExportSpecifierName(location)) {
+                    return location.getText();
+                }
+                var functionExpression = ts.forEach(declarations, function (d) { return d.kind === 162 ? d : undefined; });
+                var name = functionExpression && functionExpression.name
+                    ? functionExpression.name.text
+                    : symbol.name;
+                return stripQuotes(name);
+            }
+            function stripQuotes(name) {
+                var length = name.length;
+                if (length >= 2 && name.charCodeAt(0) === 34 && name.charCodeAt(length - 1) === 34) {
+                    return name.substring(1, length - 1);
+                }
+                ;
+                return name;
+            }
+            function getSymbolScope(symbol) {
+                if (symbol.flags & (4 | 8192)) {
+                    var privateDeclaration = ts.forEach(symbol.getDeclarations(), function (d) { return (d.flags & 32) ? d : undefined; });
+                    if (privateDeclaration) {
+                        return ts.getAncestor(privateDeclaration, 201);
+                    }
+                }
+                if (symbol.flags & 8388608) {
+                    return undefined;
+                }
+                if (symbol.parent || (symbol.flags & 268435456)) {
+                    return undefined;
+                }
+                var scope = undefined;
+                var declarations = symbol.getDeclarations();
+                if (declarations) {
+                    for (var _i = 0; _i < declarations.length; _i++) {
+                        var declaration = declarations[_i];
+                        var container = getContainerNode(declaration);
+                        if (!container) {
+                            return undefined;
+                        }
+                        if (scope && scope !== container) {
+                            return undefined;
+                        }
+                        if (container.kind === 227 && !ts.isExternalModule(container)) {
+                            return undefined;
+                        }
+                        scope = container;
+                    }
+                }
+                return scope;
+            }
+            function getPossibleSymbolReferencePositions(sourceFile, symbolName, start, end) {
+                var positions = [];
+                if (!symbolName || !symbolName.length) {
+                    return positions;
+                }
+                var text = sourceFile.text;
+                var sourceLength = text.length;
+                var symbolNameLength = symbolName.length;
+                var position = text.indexOf(symbolName, start);
+                while (position >= 0) {
+                    cancellationToken.throwIfCancellationRequested();
+                    if (position > end)
+                        break;
+                    var endPosition = position + symbolNameLength;
+                    if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 2)) &&
+                        (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 2))) {
+                        positions.push(position);
+                    }
+                    position = text.indexOf(symbolName, position + symbolNameLength + 1);
+                }
+                return positions;
+            }
+            function getLabelReferencesInNode(container, targetLabel) {
+                var references = [];
+                var sourceFile = container.getSourceFile();
+                var labelName = targetLabel.text;
+                var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd());
+                ts.forEach(possiblePositions, function (position) {
+                    cancellationToken.throwIfCancellationRequested();
+                    var node = ts.getTouchingWord(sourceFile, position);
+                    if (!node || node.getWidth() !== labelName.length) {
+                        return;
+                    }
+                    if (node === targetLabel ||
+                        (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) {
+                        references.push(getReferenceEntryFromNode(node));
+                    }
+                });
+                var definition = {
+                    containerKind: "",
+                    containerName: "",
+                    fileName: targetLabel.getSourceFile().fileName,
+                    kind: ScriptElementKind.label,
+                    name: labelName,
+                    textSpan: ts.createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd())
+                };
+                return [{ definition: definition, references: references }];
+            }
+            function isValidReferencePosition(node, searchSymbolName) {
+                if (node) {
+                    switch (node.kind) {
+                        case 65:
+                            return node.getWidth() === searchSymbolName.length;
+                        case 8:
+                            if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
+                                isNameOfExternalModuleImportOrDeclaration(node)) {
+                                return node.getWidth() === searchSymbolName.length + 2;
+                            }
+                            break;
+                        case 7:
+                            if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
+                                return node.getWidth() === searchSymbolName.length;
+                            }
+                            break;
+                    }
+                }
+                return false;
+            }
+            function getReferencesInNode(container, searchSymbol, searchText, searchLocation, searchMeaning, findInStrings, findInComments, result, symbolToIndex) {
+                var sourceFile = container.getSourceFile();
+                var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</;
+                var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
+                if (possiblePositions.length) {
+                    var searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation);
+                    ts.forEach(possiblePositions, function (position) {
+                        cancellationToken.throwIfCancellationRequested();
+                        var referenceLocation = ts.getTouchingPropertyName(sourceFile, position);
+                        if (!isValidReferencePosition(referenceLocation, searchText)) {
+                            if ((findInStrings && isInString(position)) ||
+                                (findInComments && isInComment(position))) {
+                                result.push({
+                                    definition: undefined,
+                                    references: [{
+                                            fileName: sourceFile.fileName,
+                                            textSpan: ts.createTextSpan(position, searchText.length),
+                                            isWriteAccess: false
+                                        }]
+                                });
+                            }
+                            return;
+                        }
+                        if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
+                            return;
+                        }
+                        var referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
+                        if (referenceSymbol) {
+                            var referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
+                            var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
+                            var relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation);
+                            if (relatedSymbol) {
+                                var referencedSymbol = getReferencedSymbol(relatedSymbol);
+                                referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation));
+                            }
+                            else if (!(referenceSymbol.flags & 67108864) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
+                                var referencedSymbol = getReferencedSymbol(shorthandValueSymbol);
+                                referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name));
+                            }
+                        }
+                    });
+                }
+                return;
+                function getReferencedSymbol(symbol) {
+                    var symbolId = ts.getSymbolId(symbol);
+                    var index = symbolToIndex[symbolId];
+                    if (index === undefined) {
+                        index = result.length;
+                        symbolToIndex[symbolId] = index;
+                        result.push({
+                            definition: getDefinition(symbol),
+                            references: []
+                        });
+                    }
+                    return result[index];
+                }
+                function isInString(position) {
+                    var token = ts.getTokenAtPosition(sourceFile, position);
+                    return token && token.kind === 8 && position > token.getStart();
+                }
+                function isInComment(position) {
+                    var token = ts.getTokenAtPosition(sourceFile, position);
+                    if (token && position < token.getStart()) {
+                        var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos);
+                        return ts.forEach(commentRanges, function (c) {
+                            if (c.pos < position && position < c.end) {
+                                var commentText = sourceFile.text.substring(c.pos, c.end);
+                                if (!tripleSlashDirectivePrefixRegex.test(commentText)) {
+                                    return true;
+                                }
+                            }
+                        });
+                    }
+                    return false;
+                }
+            }
+            function getReferencesForSuperKeyword(superKeyword) {
+                var searchSpaceNode = ts.getSuperContainer(superKeyword, false);
+                if (!searchSpaceNode) {
+                    return undefined;
+                }
+                var staticFlag = 128;
+                switch (searchSpaceNode.kind) {
+                    case 132:
+                    case 131:
+                    case 134:
+                    case 133:
+                    case 135:
+                    case 136:
+                    case 137:
+                        staticFlag &= searchSpaceNode.flags;
+                        searchSpaceNode = searchSpaceNode.parent;
+                        break;
+                    default:
+                        return undefined;
+                }
+                var references = [];
+                var sourceFile = searchSpaceNode.getSourceFile();
+                var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
+                ts.forEach(possiblePositions, function (position) {
+                    cancellationToken.throwIfCancellationRequested();
+                    var node = ts.getTouchingWord(sourceFile, position);
+                    if (!node || node.kind !== 91) {
+                        return;
+                    }
+                    var container = ts.getSuperContainer(node, false);
+                    if (container && (128 & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
+                        references.push(getReferenceEntryFromNode(node));
+                    }
+                });
+                var definition = getDefinition(searchSpaceNode.symbol);
+                return [{ definition: definition, references: references }];
+            }
+            function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles) {
+                var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, false);
+                var staticFlag = 128;
+                switch (searchSpaceNode.kind) {
+                    case 134:
+                    case 133:
+                        if (ts.isObjectLiteralMethod(searchSpaceNode)) {
+                            break;
+                        }
+                    case 132:
+                    case 131:
+                    case 135:
+                    case 136:
+                    case 137:
+                        staticFlag &= searchSpaceNode.flags;
+                        searchSpaceNode = searchSpaceNode.parent;
+                        break;
+                    case 227:
+                        if (ts.isExternalModule(searchSpaceNode)) {
+                            return undefined;
+                        }
+                    case 200:
+                    case 162:
+                        break;
+                    default:
+                        return undefined;
+                }
+                var references = [];
+                var possiblePositions;
+                if (searchSpaceNode.kind === 227) {
+                    ts.forEach(sourceFiles, function (sourceFile) {
+                        possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd());
+                        getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references);
+                    });
+                }
+                else {
+                    var sourceFile = searchSpaceNode.getSourceFile();
+                    possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
+                    getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references);
+                }
+                return [{
+                        definition: {
+                            containerKind: "",
+                            containerName: "",
+                            fileName: node.getSourceFile().fileName,
+                            kind: ScriptElementKind.variableElement,
+                            name: "this",
+                            textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd())
+                        },
+                        references: references
+                    }];
+                function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result) {
+                    ts.forEach(possiblePositions, function (position) {
+                        cancellationToken.throwIfCancellationRequested();
+                        var node = ts.getTouchingWord(sourceFile, position);
+                        if (!node || node.kind !== 93) {
+                            return;
+                        }
+                        var container = ts.getThisContainer(node, false);
+                        switch (searchSpaceNode.kind) {
+                            case 162:
+                            case 200:
+                                if (searchSpaceNode.symbol === container.symbol) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                            case 134:
+                            case 133:
+                                if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                            case 201:
+                                if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & 128) === staticFlag) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                            case 227:
+                                if (container.kind === 227 && !ts.isExternalModule(container)) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                        }
+                    });
+                }
+            }
+            function populateSearchSymbolSet(symbol, location) {
+                var result = [symbol];
+                if (isImportOrExportSpecifierImportSymbol(symbol)) {
+                    result.push(typeChecker.getAliasedSymbol(symbol));
+                }
+                if (isNameOfPropertyAssignment(location)) {
+                    ts.forEach(getPropertySymbolsFromContextualType(location), function (contextualSymbol) {
+                        result.push.apply(result, typeChecker.getRootSymbols(contextualSymbol));
+                    });
+                    var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent);
+                    if (shorthandValueSymbol) {
+                        result.push(shorthandValueSymbol);
+                    }
+                }
+                ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) {
+                    if (rootSymbol !== symbol) {
+                        result.push(rootSymbol);
+                    }
+                    if (rootSymbol.parent && rootSymbol.parent.flags & (32 | 64)) {
+                        getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
+                    }
+                });
+                return result;
+            }
+            function getPropertySymbolsFromBaseTypes(symbol, propertyName, result) {
+                if (symbol && symbol.flags & (32 | 64)) {
+                    ts.forEach(symbol.getDeclarations(), function (declaration) {
+                        if (declaration.kind === 201) {
+                            getPropertySymbolFromTypeReference(ts.getClassExtendsHeritageClauseElement(declaration));
+                            ts.forEach(ts.getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference);
+                        }
+                        else if (declaration.kind === 202) {
+                            ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference);
+                        }
+                    });
+                }
+                return;
+                function getPropertySymbolFromTypeReference(typeReference) {
+                    if (typeReference) {
+                        var type = typeChecker.getTypeAtLocation(typeReference);
+                        if (type) {
+                            var propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
+                            if (propertySymbol) {
+                                result.push(propertySymbol);
+                            }
+                            getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result);
+                        }
+                    }
+                }
+            }
+            function getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation) {
+                if (searchSymbols.indexOf(referenceSymbol) >= 0) {
+                    return referenceSymbol;
+                }
+                if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) {
+                    var aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol);
+                    if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
+                        return aliasedSymbol;
+                    }
+                }
+                if (isNameOfPropertyAssignment(referenceLocation)) {
+                    return ts.forEach(getPropertySymbolsFromContextualType(referenceLocation), function (contextualSymbol) {
+                        return ts.forEach(typeChecker.getRootSymbols(contextualSymbol), function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; });
+                    });
+                }
+                return ts.forEach(typeChecker.getRootSymbols(referenceSymbol), function (rootSymbol) {
+                    if (searchSymbols.indexOf(rootSymbol) >= 0) {
+                        return rootSymbol;
+                    }
+                    if (rootSymbol.parent && rootSymbol.parent.flags & (32 | 64)) {
+                        var result_2 = [];
+                        getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result_2);
+                        return ts.forEach(result_2, function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; });
+                    }
+                    return undefined;
+                });
+            }
+            function getPropertySymbolsFromContextualType(node) {
+                if (isNameOfPropertyAssignment(node)) {
+                    var objectLiteral = node.parent.parent;
+                    var contextualType = typeChecker.getContextualType(objectLiteral);
+                    var name_2 = node.text;
+                    if (contextualType) {
+                        if (contextualType.flags & 16384) {
+                            var unionProperty = contextualType.getProperty(name_2);
+                            if (unionProperty) {
+                                return [unionProperty];
+                            }
+                            else {
+                                var result_3 = [];
+                                ts.forEach(contextualType.types, function (t) {
+                                    var symbol = t.getProperty(name_2);
+                                    if (symbol) {
+                                        result_3.push(symbol);
+                                    }
+                                });
+                                return result_3;
+                            }
+                        }
+                        else {
+                            var symbol_1 = contextualType.getProperty(name_2);
+                            if (symbol_1) {
+                                return [symbol_1];
+                            }
+                        }
+                    }
+                }
+                return undefined;
+            }
+            function getIntersectingMeaningFromDeclarations(meaning, declarations) {
+                if (declarations) {
+                    var lastIterationMeaning;
+                    do {
+                        lastIterationMeaning = meaning;
+                        for (var _i = 0; _i < declarations.length; _i++) {
+                            var declaration = declarations[_i];
+                            var declarationMeaning = getMeaningFromDeclaration(declaration);
+                            if (declarationMeaning & meaning) {
+                                meaning |= declarationMeaning;
+                            }
+                        }
+                    } while (meaning !== lastIterationMeaning);
+                }
+                return meaning;
+            }
+        }
+        function getReferenceEntryFromNode(node) {
+            var start = node.getStart();
+            var end = node.getEnd();
+            if (node.kind === 8) {
+                start += 1;
+                end -= 1;
+            }
+            return {
+                fileName: node.getSourceFile().fileName,
+                textSpan: ts.createTextSpanFromBounds(start, end),
+                isWriteAccess: isWriteAccess(node)
+            };
+        }
+        function isWriteAccess(node) {
+            if (node.kind === 65 && ts.isDeclarationName(node)) {
+                return true;
+            }
+            var parent = node.parent;
+            if (parent) {
+                if (parent.kind === 168 || parent.kind === 167) {
+                    return true;
+                }
+                else if (parent.kind === 169 && parent.left === node) {
+                    var operator = parent.operatorToken.kind;
+                    return 53 <= operator && operator <= 64;
+                }
+            }
+            return false;
+        }
+        function getNavigateToItems(searchValue, maxResultCount) {
+            synchronizeHostData();
+            return ts.NavigateTo.getNavigateToItems(program, cancellationToken, searchValue, maxResultCount);
+        }
+        function containErrors(diagnostics) {
+            return ts.forEach(diagnostics, function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; });
+        }
+        function getEmitOutput(fileName) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            var outputFiles = [];
+            function writeFile(fileName, data, writeByteOrderMark) {
+                outputFiles.push({
+                    name: fileName,
+                    writeByteOrderMark: writeByteOrderMark,
+                    text: data
+                });
+            }
+            var emitOutput = program.emit(sourceFile, writeFile);
+            return {
+                outputFiles: outputFiles,
+                emitSkipped: emitOutput.emitSkipped
+            };
+        }
+        function getMeaningFromDeclaration(node) {
+            switch (node.kind) {
+                case 129:
+                case 198:
+                case 152:
+                case 132:
+                case 131:
+                case 224:
+                case 225:
+                case 226:
+                case 134:
+                case 133:
+                case 135:
+                case 136:
+                case 137:
+                case 200:
+                case 162:
+                case 163:
+                case 223:
+                    return 1;
+                case 128:
+                case 202:
+                case 203:
+                case 145:
+                    return 2;
+                case 201:
+                case 204:
+                    return 1 | 2;
+                case 205:
+                    if (node.name.kind === 8) {
+                        return 4 | 1;
+                    }
+                    else if (ts.getModuleInstanceState(node) === 1) {
+                        return 4 | 1;
+                    }
+                    else {
+                        return 4;
+                    }
+                case 212:
+                case 213:
+                case 208:
+                case 209:
+                case 214:
+                case 215:
+                    return 1 | 2 | 4;
+                case 227:
+                    return 4 | 1;
+            }
+            return 1 | 2 | 4;
+            ts.Debug.fail("Unknown declaration type");
+        }
+        function isTypeReference(node) {
+            if (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) {
+                node = node.parent;
+            }
+            return node.parent.kind === 141 || node.parent.kind === 177;
+        }
+        function isNamespaceReference(node) {
+            return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node);
+        }
+        function isPropertyAccessNamespaceReference(node) {
+            var root = node;
+            var isLastClause = true;
+            if (root.parent.kind === 155) {
+                while (root.parent && root.parent.kind === 155) {
+                    root = root.parent;
+                }
+                isLastClause = root.name === node;
+            }
+            if (!isLastClause && root.parent.kind === 177 && root.parent.parent.kind === 222) {
+                var decl = root.parent.parent.parent;
+                return (decl.kind === 201 && root.parent.parent.token === 102) ||
+                    (decl.kind === 202 && root.parent.parent.token === 79);
+            }
+            return false;
+        }
+        function isQualifiedNameNamespaceReference(node) {
+            var root = node;
+            var isLastClause = true;
+            if (root.parent.kind === 126) {
+                while (root.parent && root.parent.kind === 126) {
+                    root = root.parent;
+                }
+                isLastClause = root.right === node;
+            }
+            return root.parent.kind === 141 && !isLastClause;
+        }
+        function isInRightSideOfImport(node) {
+            while (node.parent.kind === 126) {
+                node = node.parent;
+            }
+            return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node;
+        }
+        function getMeaningFromRightHandSideOfImportEquals(node) {
+            ts.Debug.assert(node.kind === 65);
+            if (node.parent.kind === 126 &&
+                node.parent.right === node &&
+                node.parent.parent.kind === 208) {
+                return 1 | 2 | 4;
+            }
+            return 4;
+        }
+        function getMeaningFromLocation(node) {
+            if (node.parent.kind === 214) {
+                return 1 | 2 | 4;
+            }
+            else if (isInRightSideOfImport(node)) {
+                return getMeaningFromRightHandSideOfImportEquals(node);
+            }
+            else if (ts.isDeclarationName(node)) {
+                return getMeaningFromDeclaration(node.parent);
+            }
+            else if (isTypeReference(node)) {
+                return 2;
+            }
+            else if (isNamespaceReference(node)) {
+                return 4;
+            }
+            else {
+                return 1;
+            }
+        }
+        function getSignatureHelpItems(fileName, position) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            return ts.SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken);
+        }
+        function getSourceFile(fileName) {
+            return syntaxTreeCache.getCurrentSourceFile(fileName);
+        }
+        function getNameOrDottedNameSpan(fileName, startPos, endPos) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            var node = ts.getTouchingPropertyName(sourceFile, startPos);
+            if (!node) {
+                return;
+            }
+            switch (node.kind) {
+                case 155:
+                case 126:
+                case 8:
+                case 80:
+                case 95:
+                case 89:
+                case 91:
+                case 93:
+                case 65:
+                    break;
+                default:
+                    return;
+            }
+            var nodeForStartPos = node;
+            while (true) {
+                if (isRightSideOfPropertyAccess(nodeForStartPos) || isRightSideOfQualifiedName(nodeForStartPos)) {
+                    nodeForStartPos = nodeForStartPos.parent;
+                }
+                else if (isNameOfModuleDeclaration(nodeForStartPos)) {
+                    if (nodeForStartPos.parent.parent.kind === 205 &&
+                        nodeForStartPos.parent.parent.body === nodeForStartPos.parent) {
+                        nodeForStartPos = nodeForStartPos.parent.parent.name;
+                    }
+                    else {
+                        break;
+                    }
+                }
+                else {
+                    break;
+                }
+            }
+            return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd());
+        }
+        function getBreakpointStatementAtPosition(fileName, position) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position);
+        }
+        function getNavigationBarItems(fileName) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return ts.NavigationBar.getNavigationBarItems(sourceFile);
+        }
+        function getSemanticClassifications(fileName, span) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            var typeChecker = program.getTypeChecker();
+            var result = [];
+            processNode(sourceFile);
+            return result;
+            function classifySymbol(symbol, meaningAtPosition) {
+                var flags = symbol.getFlags();
+                if (flags & 32) {
+                    return ClassificationTypeNames.className;
+                }
+                else if (flags & 384) {
+                    return ClassificationTypeNames.enumName;
+                }
+                else if (flags & 524288) {
+                    return ClassificationTypeNames.typeAlias;
+                }
+                else if (meaningAtPosition & 2) {
+                    if (flags & 64) {
+                        return ClassificationTypeNames.interfaceName;
+                    }
+                    else if (flags & 262144) {
+                        return ClassificationTypeNames.typeParameterName;
+                    }
+                }
+                else if (flags & 1536) {
+                    if (meaningAtPosition & 4 ||
+                        (meaningAtPosition & 1 && hasValueSideModule(symbol))) {
+                        return ClassificationTypeNames.moduleName;
+                    }
+                }
+                return undefined;
+                function hasValueSideModule(symbol) {
+                    return ts.forEach(symbol.declarations, function (declaration) {
+                        return declaration.kind === 205 && ts.getModuleInstanceState(declaration) == 1;
+                    });
+                }
+            }
+            function processNode(node) {
+                if (node && ts.textSpanIntersectsWith(span, node.getStart(), node.getWidth())) {
+                    if (node.kind === 65 && node.getWidth() > 0) {
+                        var symbol = typeChecker.getSymbolAtLocation(node);
+                        if (symbol) {
+                            var type = classifySymbol(symbol, getMeaningFromLocation(node));
+                            if (type) {
+                                result.push({
+                                    textSpan: ts.createTextSpan(node.getStart(), node.getWidth()),
+                                    classificationType: type
+                                });
+                            }
+                        }
+                    }
+                    ts.forEachChild(node, processNode);
+                }
+            }
+        }
+        function getSyntacticClassifications(fileName, span) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            var triviaScanner = ts.createScanner(2, false, sourceFile.text);
+            var mergeConflictScanner = ts.createScanner(2, false, sourceFile.text);
+            var result = [];
+            processElement(sourceFile);
+            return result;
+            function classifyLeadingTrivia(token) {
+                var tokenStart = ts.skipTrivia(sourceFile.text, token.pos, false);
+                if (tokenStart === token.pos) {
+                    return;
+                }
+                triviaScanner.setTextPos(token.pos);
+                while (true) {
+                    var start = triviaScanner.getTextPos();
+                    var kind = triviaScanner.scan();
+                    var end = triviaScanner.getTextPos();
+                    var width = end - start;
+                    if (ts.textSpanIntersectsWith(span, start, width)) {
+                        if (!ts.isTrivia(kind)) {
+                            return;
+                        }
+                        if (ts.isComment(kind)) {
+                            result.push({
+                                textSpan: ts.createTextSpan(start, width),
+                                classificationType: ClassificationTypeNames.comment
+                            });
+                            continue;
+                        }
+                        if (kind === 6) {
+                            var text = sourceFile.text;
+                            var ch = text.charCodeAt(start);
+                            if (ch === 60 || ch === 62) {
+                                result.push({
+                                    textSpan: ts.createTextSpan(start, width),
+                                    classificationType: ClassificationTypeNames.comment
+                                });
+                                continue;
+                            }
+                            ts.Debug.assert(ch === 61);
+                            classifyDisabledMergeCode(text, start, end);
+                        }
+                    }
+                }
+            }
+            function classifyDisabledMergeCode(text, start, end) {
+                for (var i = start; i < end; i++) {
+                    if (ts.isLineBreak(text.charCodeAt(i))) {
+                        break;
+                    }
+                }
+                result.push({
+                    textSpan: ts.createTextSpanFromBounds(start, i),
+                    classificationType: ClassificationTypeNames.comment
+                });
+                mergeConflictScanner.setTextPos(i);
+                while (mergeConflictScanner.getTextPos() < end) {
+                    classifyDisabledCodeToken();
+                }
+            }
+            function classifyDisabledCodeToken() {
+                var start = mergeConflictScanner.getTextPos();
+                var tokenKind = mergeConflictScanner.scan();
+                var end = mergeConflictScanner.getTextPos();
+                var type = classifyTokenType(tokenKind);
+                if (type) {
+                    result.push({
+                        textSpan: ts.createTextSpanFromBounds(start, end),
+                        classificationType: type
+                    });
+                }
+            }
+            function classifyToken(token) {
+                classifyLeadingTrivia(token);
+                if (token.getWidth() > 0) {
+                    var type = classifyTokenType(token.kind, token);
+                    if (type) {
+                        result.push({
+                            textSpan: ts.createTextSpan(token.getStart(), token.getWidth()),
+                            classificationType: type
+                        });
+                    }
+                }
+            }
+            function classifyTokenType(tokenKind, token) {
+                if (ts.isKeyword(tokenKind)) {
+                    return ClassificationTypeNames.keyword;
+                }
+                if (tokenKind === 24 || tokenKind === 25) {
+                    if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) {
+                        return ClassificationTypeNames.punctuation;
+                    }
+                }
+                if (ts.isPunctuation(tokenKind)) {
+                    if (token) {
+                        if (tokenKind === 53) {
+                            if (token.parent.kind === 198 ||
+                                token.parent.kind === 132 ||
+                                token.parent.kind === 129) {
+                                return ClassificationTypeNames.operator;
+                            }
+                        }
+                        if (token.parent.kind === 169 ||
+                            token.parent.kind === 167 ||
+                            token.parent.kind === 168 ||
+                            token.parent.kind === 170) {
+                            return ClassificationTypeNames.operator;
+                        }
+                    }
+                    return ClassificationTypeNames.punctuation;
+                }
+                else if (tokenKind === 7) {
+                    return ClassificationTypeNames.numericLiteral;
+                }
+                else if (tokenKind === 8) {
+                    return ClassificationTypeNames.stringLiteral;
+                }
+                else if (tokenKind === 9) {
+                    return ClassificationTypeNames.stringLiteral;
+                }
+                else if (ts.isTemplateLiteralKind(tokenKind)) {
+                    return ClassificationTypeNames.stringLiteral;
+                }
+                else if (tokenKind === 65) {
+                    if (token) {
+                        switch (token.parent.kind) {
+                            case 201:
+                                if (token.parent.name === token) {
+                                    return ClassificationTypeNames.className;
+                                }
+                                return;
+                            case 128:
+                                if (token.parent.name === token) {
+                                    return ClassificationTypeNames.typeParameterName;
+                                }
+                                return;
+                            case 202:
+                                if (token.parent.name === token) {
+                                    return ClassificationTypeNames.interfaceName;
+                                }
+                                return;
+                            case 204:
+                                if (token.parent.name === token) {
+                                    return ClassificationTypeNames.enumName;
+                                }
+                                return;
+                            case 205:
+                                if (token.parent.name === token) {
+                                    return ClassificationTypeNames.moduleName;
+                                }
+                                return;
+                        }
+                    }
+                    return ClassificationTypeNames.text;
+                }
+            }
+            function processElement(element) {
+                if (ts.textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) {
+                    var children = element.getChildren();
+                    for (var _i = 0; _i < children.length; _i++) {
+                        var child = children[_i];
+                        if (ts.isToken(child)) {
+                            classifyToken(child);
+                        }
+                        else {
+                            processElement(child);
+                        }
+                    }
+                }
+            }
+        }
+        function getOutliningSpans(fileName) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return ts.OutliningElementsCollector.collectElements(sourceFile);
+        }
+        function getBraceMatchingAtPosition(fileName, position) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            var result = [];
+            var token = ts.getTouchingToken(sourceFile, position);
+            if (token.getStart(sourceFile) === position) {
+                var matchKind = getMatchingTokenKind(token);
+                if (matchKind) {
+                    var parentElement = token.parent;
+                    var childNodes = parentElement.getChildren(sourceFile);
+                    for (var _i = 0; _i < childNodes.length; _i++) {
+                        var current = childNodes[_i];
+                        if (current.kind === matchKind) {
+                            var range1 = ts.createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile));
+                            var range2 = ts.createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile));
+                            if (range1.start < range2.start) {
+                                result.push(range1, range2);
+                            }
+                            else {
+                                result.push(range2, range1);
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+            return result;
+            function getMatchingTokenKind(token) {
+                switch (token.kind) {
+                    case 14: return 15;
+                    case 16: return 17;
+                    case 18: return 19;
+                    case 24: return 25;
+                    case 15: return 14;
+                    case 17: return 16;
+                    case 19: return 18;
+                    case 25: return 24;
+                }
+                return undefined;
+            }
+        }
+        function getIndentationAtPosition(fileName, position, editorOptions) {
+            var start = new Date().getTime();
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
+            start = new Date().getTime();
+            var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
+            log("getIndentationAtPosition: computeIndentation  : " + (new Date().getTime() - start));
+            return result;
+        }
+        function getFormattingEditsForRange(fileName, start, end, options) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return ts.formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options);
+        }
+        function getFormattingEditsForDocument(fileName, options) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return ts.formatting.formatDocument(sourceFile, getRuleProvider(options), options);
+        }
+        function getFormattingEditsAfterKeystroke(fileName, position, key, options) {
+            var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            if (key === "}") {
+                return ts.formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options);
+            }
+            else if (key === ";") {
+                return ts.formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options);
+            }
+            else if (key === "\n") {
+                return ts.formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options);
+            }
+            return [];
+        }
+        function getTodoComments(fileName, descriptors) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            cancellationToken.throwIfCancellationRequested();
+            var fileContents = sourceFile.text;
+            var result = [];
+            if (descriptors.length > 0) {
+                var regExp = getTodoCommentsRegExp();
+                var matchArray;
+                while (matchArray = regExp.exec(fileContents)) {
+                    cancellationToken.throwIfCancellationRequested();
+                    var firstDescriptorCaptureIndex = 3;
+                    ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex);
+                    var preamble = matchArray[1];
+                    var matchPosition = matchArray.index + preamble.length;
+                    var token = ts.getTokenAtPosition(sourceFile, matchPosition);
+                    if (!isInsideComment(sourceFile, token, matchPosition)) {
+                        continue;
+                    }
+                    var descriptor = undefined;
+                    for (var i = 0, n = descriptors.length; i < n; i++) {
+                        if (matchArray[i + firstDescriptorCaptureIndex]) {
+                            descriptor = descriptors[i];
+                        }
+                    }
+                    ts.Debug.assert(descriptor !== undefined);
+                    if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) {
+                        continue;
+                    }
+                    var message = matchArray[2];
+                    result.push({
+                        descriptor: descriptor,
+                        message: message,
+                        position: matchPosition
+                    });
+                }
+            }
+            return result;
+            function escapeRegExp(str) {
+                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+            }
+            function getTodoCommentsRegExp() {
+                // NOTE: ?:  means 'non-capture group'.  It allows us to have groups without having to
+                // filter them out later in the final result array.
+                var singleLineCommentStart = /(?:\/\/+\s*)/.source;
+                var multiLineCommentStart = /(?:\/\*+\s*)/.source;
+                var anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
+                var preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")";
+                var literals = "(?:" + ts.map(descriptors, function (d) { return "(" + escapeRegExp(d.text) + ")"; }).join("|") + ")";
+                var endOfLineOrEndOfComment = /(?:$|\*\/)/.source;
+                var messageRemainder = /(?:.*?)/.source;
+                var messagePortion = "(" + literals + messageRemainder + ")";
+                var regExpString = preamble + messagePortion + endOfLineOrEndOfComment;
+                return new RegExp(regExpString, "gim");
+            }
+            function isLetterOrDigit(char) {
+                return (char >= 97 && char <= 122) ||
+                    (char >= 65 && char <= 90) ||
+                    (char >= 48 && char <= 57);
+            }
+        }
+        function getRenameInfo(fileName, position) {
+            synchronizeHostData();
+            var sourceFile = getValidSourceFile(fileName);
+            var typeChecker = program.getTypeChecker();
+            var node = ts.getTouchingWord(sourceFile, position);
+            if (node && node.kind === 65) {
+                var symbol = typeChecker.getSymbolAtLocation(node);
+                if (symbol) {
+                    var declarations = symbol.getDeclarations();
+                    if (declarations && declarations.length > 0) {
+                        var defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings());
+                        if (defaultLibFileName) {
+                            for (var _i = 0; _i < declarations.length; _i++) {
+                                var current = declarations[_i];
+                                var sourceFile_1 = current.getSourceFile();
+                                if (sourceFile_1 && getCanonicalFileName(ts.normalizePath(sourceFile_1.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) {
+                                    return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library.key));
+                                }
+                            }
+                        }
+                        var kind = getSymbolKind(symbol, node);
+                        if (kind) {
+                            return {
+                                canRename: true,
+                                localizedErrorMessage: undefined,
+                                displayName: symbol.name,
+                                fullDisplayName: typeChecker.getFullyQualifiedName(symbol),
+                                kind: kind,
+                                kindModifiers: getSymbolModifiers(symbol),
+                                triggerSpan: ts.createTextSpan(node.getStart(), node.getWidth())
+                            };
+                        }
+                    }
+                }
+            }
+            return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_this_element.key));
+            function getRenameInfoError(localizedErrorMessage) {
+                return {
+                    canRename: false,
+                    localizedErrorMessage: localizedErrorMessage,
+                    displayName: undefined,
+                    fullDisplayName: undefined,
+                    kind: undefined,
+                    kindModifiers: undefined,
+                    triggerSpan: undefined
+                };
+            }
+        }
+        return {
+            dispose: dispose,
+            cleanupSemanticCache: cleanupSemanticCache,
+            getSyntacticDiagnostics: getSyntacticDiagnostics,
+            getSemanticDiagnostics: getSemanticDiagnostics,
+            getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics,
+            getSyntacticClassifications: getSyntacticClassifications,
+            getSemanticClassifications: getSemanticClassifications,
+            getCompletionsAtPosition: getCompletionsAtPosition,
+            getCompletionEntryDetails: getCompletionEntryDetails,
+            getSignatureHelpItems: getSignatureHelpItems,
+            getQuickInfoAtPosition: getQuickInfoAtPosition,
+            getDefinitionAtPosition: getDefinitionAtPosition,
+            getReferencesAtPosition: getReferencesAtPosition,
+            findReferences: findReferences,
+            getOccurrencesAtPosition: getOccurrencesAtPosition,
+            getDocumentHighlights: getDocumentHighlights,
+            getNameOrDottedNameSpan: getNameOrDottedNameSpan,
+            getBreakpointStatementAtPosition: getBreakpointStatementAtPosition,
+            getNavigateToItems: getNavigateToItems,
+            getRenameInfo: getRenameInfo,
+            findRenameLocations: findRenameLocations,
+            getNavigationBarItems: getNavigationBarItems,
+            getOutliningSpans: getOutliningSpans,
+            getTodoComments: getTodoComments,
+            getBraceMatchingAtPosition: getBraceMatchingAtPosition,
+            getIndentationAtPosition: getIndentationAtPosition,
+            getFormattingEditsForRange: getFormattingEditsForRange,
+            getFormattingEditsForDocument: getFormattingEditsForDocument,
+            getFormattingEditsAfterKeystroke: getFormattingEditsAfterKeystroke,
+            getEmitOutput: getEmitOutput,
+            getSourceFile: getSourceFile,
+            getProgram: getProgram
+        };
+    }
+    ts.createLanguageService = createLanguageService;
+    function getNameTable(sourceFile) {
+        if (!sourceFile.nameTable) {
+            initializeNameTable(sourceFile);
+        }
+        return sourceFile.nameTable;
+    }
+    ts.getNameTable = getNameTable;
+    function initializeNameTable(sourceFile) {
+        var nameTable = {};
+        walk(sourceFile);
+        sourceFile.nameTable = nameTable;
+        function walk(node) {
+            switch (node.kind) {
+                case 65:
+                    nameTable[node.text] = node.text;
+                    break;
+                case 8:
+                case 7:
+                    if (ts.isDeclarationName(node) ||
+                        node.parent.kind === 219 ||
+                        isArgumentOfElementAccessExpression(node)) {
+                        nameTable[node.text] = node.text;
+                    }
+                    break;
+                default:
+                    ts.forEachChild(node, walk);
+            }
+        }
+    }
+    function isArgumentOfElementAccessExpression(node) {
+        return node &&
+            node.parent &&
+            node.parent.kind === 156 &&
+            node.parent.argumentExpression === node;
+    }
+    function createClassifier() {
+        var scanner = ts.createScanner(2, false);
+        var noRegexTable = [];
+        noRegexTable[65] = true;
+        noRegexTable[8] = true;
+        noRegexTable[7] = true;
+        noRegexTable[9] = true;
+        noRegexTable[93] = true;
+        noRegexTable[38] = true;
+        noRegexTable[39] = true;
+        noRegexTable[17] = true;
+        noRegexTable[19] = true;
+        noRegexTable[15] = true;
+        noRegexTable[95] = true;
+        noRegexTable[80] = true;
+        var templateStack = [];
+        function canFollow(keyword1, keyword2) {
+            if (ts.isAccessibilityModifier(keyword1)) {
+                if (keyword2 === 116 ||
+                    keyword2 === 120 ||
+                    keyword2 === 114 ||
+                    keyword2 === 109) {
+                    return true;
+                }
+                return false;
+            }
+            return true;
+        }
+        function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) {
+            var offset = 0;
+            var token = 0;
+            var lastNonTriviaToken = 0;
+            while (templateStack.length > 0) {
+                templateStack.pop();
+            }
+            switch (lexState) {
+                case 3:
+                    text = '"\\\n' + text;
+                    offset = 3;
+                    break;
+                case 2:
+                    text = "'\\\n" + text;
+                    offset = 3;
+                    break;
+                case 1:
+                    text = "/*\n" + text;
+                    offset = 3;
+                    break;
+                case 4:
+                    text = "`\n" + text;
+                    offset = 2;
+                    break;
+                case 5:
+                    text = "}\n" + text;
+                    offset = 2;
+                case 6:
+                    templateStack.push(11);
+                    break;
+            }
+            scanner.setText(text);
+            var result = {
+                finalLexState: 0,
+                entries: []
+            };
+            var angleBracketStack = 0;
+            do {
+                token = scanner.scan();
+                if (!ts.isTrivia(token)) {
+                    if ((token === 36 || token === 57) && !noRegexTable[lastNonTriviaToken]) {
+                        if (scanner.reScanSlashToken() === 9) {
+                            token = 9;
+                        }
+                    }
+                    else if (lastNonTriviaToken === 20 && isKeyword(token)) {
+                        token = 65;
+                    }
+                    else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) {
+                        token = 65;
+                    }
+                    else if (lastNonTriviaToken === 65 &&
+                        token === 24) {
+                        angleBracketStack++;
+                    }
+                    else if (token === 25 && angleBracketStack > 0) {
+                        angleBracketStack--;
+                    }
+                    else if (token === 112 ||
+                        token === 121 ||
+                        token === 119 ||
+                        token === 113 ||
+                        token === 122) {
+                        if (angleBracketStack > 0 && !syntacticClassifierAbsent) {
+                            token = 65;
+                        }
+                    }
+                    else if (token === 11) {
+                        templateStack.push(token);
+                    }
+                    else if (token === 14) {
+                        if (templateStack.length > 0) {
+                            templateStack.push(token);
+                        }
+                    }
+                    else if (token === 15) {
+                        if (templateStack.length > 0) {
+                            var lastTemplateStackToken = ts.lastOrUndefined(templateStack);
+                            if (lastTemplateStackToken === 11) {
+                                token = scanner.reScanTemplateToken();
+                                if (token === 13) {
+                                    templateStack.pop();
+                                }
+                                else {
+                                    ts.Debug.assert(token === 12, "Should have been a template middle. Was " + token);
+                                }
+                            }
+                            else {
+                                ts.Debug.assert(lastTemplateStackToken === 14, "Should have been an open brace. Was: " + token);
+                                templateStack.pop();
+                            }
+                        }
+                    }
+                    lastNonTriviaToken = token;
+                }
+                processToken();
+            } while (token !== 1);
+            return result;
+            function processToken() {
+                var start = scanner.getTokenPos();
+                var end = scanner.getTextPos();
+                addResult(end - start, classFromKind(token));
+                if (end >= text.length) {
+                    if (token === 8) {
+                        var tokenText = scanner.getTokenText();
+                        if (scanner.isUnterminated()) {
+                            var lastCharIndex = tokenText.length - 1;
+                            var numBackslashes = 0;
+                            while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92) {
+                                numBackslashes++;
+                            }
+                            if (numBackslashes & 1) {
+                                var quoteChar = tokenText.charCodeAt(0);
+                                result.finalLexState = quoteChar === 34
+                                    ? 3
+                                    : 2;
+                            }
+                        }
+                    }
+                    else if (token === 3) {
+                        if (scanner.isUnterminated()) {
+                            result.finalLexState = 1;
+                        }
+                    }
+                    else if (ts.isTemplateLiteralKind(token)) {
+                        if (scanner.isUnterminated()) {
+                            if (token === 13) {
+                                result.finalLexState = 5;
+                            }
+                            else if (token === 10) {
+                                result.finalLexState = 4;
+                            }
+                            else {
+                                ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
+                            }
+                        }
+                    }
+                    else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 11) {
+                        result.finalLexState = 6;
+                    }
+                }
+            }
+            function addResult(length, classification) {
+                if (length > 0) {
+                    if (result.entries.length === 0) {
+                        length -= offset;
+                    }
+                    result.entries.push({ length: length, classification: classification });
+                }
+            }
+        }
+        function isBinaryExpressionOperatorToken(token) {
+            switch (token) {
+                case 35:
+                case 36:
+                case 37:
+                case 33:
+                case 34:
+                case 40:
+                case 41:
+                case 42:
+                case 24:
+                case 25:
+                case 26:
+                case 27:
+                case 87:
+                case 86:
+                case 28:
+                case 29:
+                case 30:
+                case 31:
+                case 43:
+                case 45:
+                case 44:
+                case 48:
+                case 49:
+                case 63:
+                case 62:
+                case 64:
+                case 59:
+                case 60:
+                case 61:
+                case 54:
+                case 55:
+                case 56:
+                case 57:
+                case 58:
+                case 53:
+                case 23:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+        function isPrefixUnaryExpressionOperatorToken(token) {
+            switch (token) {
+                case 33:
+                case 34:
+                case 47:
+                case 46:
+                case 38:
+                case 39:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+        function isKeyword(token) {
+            return token >= 66 && token <= 125;
+        }
+        function classFromKind(token) {
+            if (isKeyword(token)) {
+                return TokenClass.Keyword;
+            }
+            else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) {
+                return TokenClass.Operator;
+            }
+            else if (token >= 14 && token <= 64) {
+                return TokenClass.Punctuation;
+            }
+            switch (token) {
+                case 7:
+                    return TokenClass.NumberLiteral;
+                case 8:
+                    return TokenClass.StringLiteral;
+                case 9:
+                    return TokenClass.RegExpLiteral;
+                case 6:
+                case 3:
+                case 2:
+                    return TokenClass.Comment;
+                case 5:
+                case 4:
+                    return TokenClass.Whitespace;
+                case 65:
+                default:
+                    if (ts.isTemplateLiteralKind(token)) {
+                        return TokenClass.StringLiteral;
+                    }
+                    return TokenClass.Identifier;
+            }
+        }
+        return { getClassificationsForLine: getClassificationsForLine };
+    }
+    ts.createClassifier = createClassifier;
+    function getDefaultLibFilePath(options) {
+        if (typeof __dirname !== "undefined") {
+            return __dirname + ts.directorySeparator + ts.getDefaultLibFileName(options);
+        }
+        throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. ");
+    }
+    ts.getDefaultLibFilePath = getDefaultLibFilePath;
+    function initializeServices() {
+        ts.objectAllocator = {
+            getNodeConstructor: function (kind) {
+                function Node() {
+                }
+                var proto = kind === 227 ? new SourceFileObject() : new NodeObject();
+                proto.kind = kind;
+                proto.pos = 0;
+                proto.end = 0;
+                proto.flags = 0;
+                proto.parent = undefined;
+                Node.prototype = proto;
+                return Node;
+            },
+            getSymbolConstructor: function () { return SymbolObject; },
+            getTypeConstructor: function () { return TypeObject; },
+            getSignatureConstructor: function () { return SignatureObject; },
+        };
+    }
+    initializeServices();
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/shims.js b/dist/typescript/services/shims.js
new file mode 100644
index 000000000..79de27c65
--- /dev/null
+++ b/dist/typescript/services/shims.js
@@ -0,0 +1,563 @@
+//
+// Copyright (c) Microsoft Corporation.  All rights reserved.
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};
+/// <reference path='services.ts' />
+var debugObjectHost = this;
+var ts;
+(function (ts) {
+    function logInternalError(logger, err) {
+        logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message);
+    }
+    var ScriptSnapshotShimAdapter = (function () {
+        function ScriptSnapshotShimAdapter(scriptSnapshotShim) {
+            this.scriptSnapshotShim = scriptSnapshotShim;
+            this.lineStartPositions = null;
+        }
+        ScriptSnapshotShimAdapter.prototype.getText = function (start, end) {
+            return this.scriptSnapshotShim.getText(start, end);
+        };
+        ScriptSnapshotShimAdapter.prototype.getLength = function () {
+            return this.scriptSnapshotShim.getLength();
+        };
+        ScriptSnapshotShimAdapter.prototype.getChangeRange = function (oldSnapshot) {
+            var oldSnapshotShim = oldSnapshot;
+            var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
+            if (encoded == null) {
+                return null;
+            }
+            var decoded = JSON.parse(encoded);
+            return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
+        };
+        return ScriptSnapshotShimAdapter;
+    })();
+    var LanguageServiceShimHostAdapter = (function () {
+        function LanguageServiceShimHostAdapter(shimHost) {
+            this.shimHost = shimHost;
+        }
+        LanguageServiceShimHostAdapter.prototype.log = function (s) {
+            this.shimHost.log(s);
+        };
+        LanguageServiceShimHostAdapter.prototype.trace = function (s) {
+            this.shimHost.trace(s);
+        };
+        LanguageServiceShimHostAdapter.prototype.error = function (s) {
+            this.shimHost.error(s);
+        };
+        LanguageServiceShimHostAdapter.prototype.getCompilationSettings = function () {
+            var settingsJson = this.shimHost.getCompilationSettings();
+            if (settingsJson == null || settingsJson == "") {
+                throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings");
+                return null;
+            }
+            return JSON.parse(settingsJson);
+        };
+        LanguageServiceShimHostAdapter.prototype.getScriptFileNames = function () {
+            var encoded = this.shimHost.getScriptFileNames();
+            return this.files = JSON.parse(encoded);
+        };
+        LanguageServiceShimHostAdapter.prototype.getScriptSnapshot = function (fileName) {
+            if (this.files && this.files.indexOf(fileName) < 0) {
+                return undefined;
+            }
+            var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName);
+            return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
+        };
+        LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) {
+            return this.shimHost.getScriptVersion(fileName);
+        };
+        LanguageServiceShimHostAdapter.prototype.getLocalizedDiagnosticMessages = function () {
+            var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages();
+            if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") {
+                return null;
+            }
+            try {
+                return JSON.parse(diagnosticMessagesJson);
+            }
+            catch (e) {
+                this.log(e.description || "diagnosticMessages.generated.json has invalid JSON format");
+                return null;
+            }
+        };
+        LanguageServiceShimHostAdapter.prototype.getCancellationToken = function () {
+            return this.shimHost.getCancellationToken();
+        };
+        LanguageServiceShimHostAdapter.prototype.getCurrentDirectory = function () {
+            return this.shimHost.getCurrentDirectory();
+        };
+        LanguageServiceShimHostAdapter.prototype.getDefaultLibFileName = function (options) {
+            try {
+                return this.shimHost.getDefaultLibFileName(JSON.stringify(options));
+            }
+            catch (e) {
+                return "";
+            }
+        };
+        return LanguageServiceShimHostAdapter;
+    })();
+    ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter;
+    var CoreServicesShimHostAdapter = (function () {
+        function CoreServicesShimHostAdapter(shimHost) {
+            this.shimHost = shimHost;
+        }
+        CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extension) {
+            var encoded = this.shimHost.readDirectory(rootDir, extension);
+            return JSON.parse(encoded);
+        };
+        return CoreServicesShimHostAdapter;
+    })();
+    ts.CoreServicesShimHostAdapter = CoreServicesShimHostAdapter;
+    function simpleForwardCall(logger, actionDescription, action) {
+        logger.log(actionDescription);
+        var start = Date.now();
+        var result = action();
+        var end = Date.now();
+        logger.log(actionDescription + " completed in " + (end - start) + " msec");
+        if (typeof (result) === "string") {
+            var str = result;
+            if (str.length > 128) {
+                str = str.substring(0, 128) + "...";
+            }
+            logger.log("  result.length=" + str.length + ", result='" + JSON.stringify(str) + "'");
+        }
+        return result;
+    }
+    function forwardJSONCall(logger, actionDescription, action) {
+        try {
+            var result = simpleForwardCall(logger, actionDescription, action);
+            return JSON.stringify({ result: result });
+        }
+        catch (err) {
+            if (err instanceof ts.OperationCanceledException) {
+                return JSON.stringify({ canceled: true });
+            }
+            logInternalError(logger, err);
+            err.description = actionDescription;
+            return JSON.stringify({ error: err });
+        }
+    }
+    var ShimBase = (function () {
+        function ShimBase(factory) {
+            this.factory = factory;
+            factory.registerShim(this);
+        }
+        ShimBase.prototype.dispose = function (dummy) {
+            this.factory.unregisterShim(this);
+        };
+        return ShimBase;
+    })();
+    function realizeDiagnostics(diagnostics, newLine) {
+        return diagnostics.map(function (d) { return realizeDiagnostic(d, newLine); });
+    }
+    ts.realizeDiagnostics = realizeDiagnostics;
+    function realizeDiagnostic(diagnostic, newLine) {
+        return {
+            message: ts.flattenDiagnosticMessageText(diagnostic.messageText, newLine),
+            start: diagnostic.start,
+            length: diagnostic.length,
+            category: ts.DiagnosticCategory[diagnostic.category].toLowerCase(),
+            code: diagnostic.code
+        };
+    }
+    var LanguageServiceShimObject = (function (_super) {
+        __extends(LanguageServiceShimObject, _super);
+        function LanguageServiceShimObject(factory, host, languageService) {
+            _super.call(this, factory);
+            this.host = host;
+            this.languageService = languageService;
+            this.logger = this.host;
+        }
+        LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
+            return forwardJSONCall(this.logger, actionDescription, action);
+        };
+        LanguageServiceShimObject.prototype.dispose = function (dummy) {
+            this.logger.log("dispose()");
+            this.languageService.dispose();
+            this.languageService = null;
+            if (debugObjectHost && debugObjectHost.CollectGarbage) {
+                debugObjectHost.CollectGarbage();
+                this.logger.log("CollectGarbage()");
+            }
+            this.logger = null;
+            _super.prototype.dispose.call(this, dummy);
+        };
+        LanguageServiceShimObject.prototype.refresh = function (throwOnError) {
+            this.forwardJSONCall("refresh(" + throwOnError + ")", function () {
+                return null;
+            });
+        };
+        LanguageServiceShimObject.prototype.cleanupSemanticCache = function () {
+            var _this = this;
+            this.forwardJSONCall("cleanupSemanticCache()", function () {
+                _this.languageService.cleanupSemanticCache();
+                return null;
+            });
+        };
+        LanguageServiceShimObject.prototype.realizeDiagnostics = function (diagnostics) {
+            var newLine = this.getNewLine();
+            return ts.realizeDiagnostics(diagnostics, newLine);
+        };
+        LanguageServiceShimObject.prototype.getSyntacticClassifications = function (fileName, start, length) {
+            var _this = this;
+            return this.forwardJSONCall("getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () {
+                var classifications = _this.languageService.getSyntacticClassifications(fileName, ts.createTextSpan(start, length));
+                return classifications;
+            });
+        };
+        LanguageServiceShimObject.prototype.getSemanticClassifications = function (fileName, start, length) {
+            var _this = this;
+            return this.forwardJSONCall("getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () {
+                var classifications = _this.languageService.getSemanticClassifications(fileName, ts.createTextSpan(start, length));
+                return classifications;
+            });
+        };
+        LanguageServiceShimObject.prototype.getNewLine = function () {
+            return this.host.getNewLine ? this.host.getNewLine() : "\r\n";
+        };
+        LanguageServiceShimObject.prototype.getSyntacticDiagnostics = function (fileName) {
+            var _this = this;
+            return this.forwardJSONCall("getSyntacticDiagnostics('" + fileName + "')", function () {
+                var diagnostics = _this.languageService.getSyntacticDiagnostics(fileName);
+                return _this.realizeDiagnostics(diagnostics);
+            });
+        };
+        LanguageServiceShimObject.prototype.getSemanticDiagnostics = function (fileName) {
+            var _this = this;
+            return this.forwardJSONCall("getSemanticDiagnostics('" + fileName + "')", function () {
+                var diagnostics = _this.languageService.getSemanticDiagnostics(fileName);
+                return _this.realizeDiagnostics(diagnostics);
+            });
+        };
+        LanguageServiceShimObject.prototype.getCompilerOptionsDiagnostics = function () {
+            var _this = this;
+            return this.forwardJSONCall("getCompilerOptionsDiagnostics()", function () {
+                var diagnostics = _this.languageService.getCompilerOptionsDiagnostics();
+                return _this.realizeDiagnostics(diagnostics);
+            });
+        };
+        LanguageServiceShimObject.prototype.getQuickInfoAtPosition = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getQuickInfoAtPosition('" + fileName + "', " + position + ")", function () {
+                var quickInfo = _this.languageService.getQuickInfoAtPosition(fileName, position);
+                return quickInfo;
+            });
+        };
+        LanguageServiceShimObject.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) {
+            var _this = this;
+            return this.forwardJSONCall("getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")", function () {
+                var spanInfo = _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos);
+                return spanInfo;
+            });
+        };
+        LanguageServiceShimObject.prototype.getBreakpointStatementAtPosition = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getBreakpointStatementAtPosition('" + fileName + "', " + position + ")", function () {
+                var spanInfo = _this.languageService.getBreakpointStatementAtPosition(fileName, position);
+                return spanInfo;
+            });
+        };
+        LanguageServiceShimObject.prototype.getSignatureHelpItems = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getSignatureHelpItems('" + fileName + "', " + position + ")", function () {
+                var signatureInfo = _this.languageService.getSignatureHelpItems(fileName, position);
+                return signatureInfo;
+            });
+        };
+        LanguageServiceShimObject.prototype.getDefinitionAtPosition = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getDefinitionAtPosition('" + fileName + "', " + position + ")", function () {
+                return _this.languageService.getDefinitionAtPosition(fileName, position);
+            });
+        };
+        LanguageServiceShimObject.prototype.getRenameInfo = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getRenameInfo('" + fileName + "', " + position + ")", function () {
+                return _this.languageService.getRenameInfo(fileName, position);
+            });
+        };
+        LanguageServiceShimObject.prototype.findRenameLocations = function (fileName, position, findInStrings, findInComments) {
+            var _this = this;
+            return this.forwardJSONCall("findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")", function () {
+                return _this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments);
+            });
+        };
+        LanguageServiceShimObject.prototype.getBraceMatchingAtPosition = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getBraceMatchingAtPosition('" + fileName + "', " + position + ")", function () {
+                var textRanges = _this.languageService.getBraceMatchingAtPosition(fileName, position);
+                return textRanges;
+            });
+        };
+        LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options) {
+            var _this = this;
+            return this.forwardJSONCall("getIndentationAtPosition('" + fileName + "', " + position + ")", function () {
+                var localOptions = JSON.parse(options);
+                return _this.languageService.getIndentationAtPosition(fileName, position, localOptions);
+            });
+        };
+        LanguageServiceShimObject.prototype.getReferencesAtPosition = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getReferencesAtPosition('" + fileName + "', " + position + ")", function () {
+                return _this.languageService.getReferencesAtPosition(fileName, position);
+            });
+        };
+        LanguageServiceShimObject.prototype.findReferences = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("findReferences('" + fileName + "', " + position + ")", function () {
+                return _this.languageService.findReferences(fileName, position);
+            });
+        };
+        LanguageServiceShimObject.prototype.getOccurrencesAtPosition = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getOccurrencesAtPosition('" + fileName + "', " + position + ")", function () {
+                return _this.languageService.getOccurrencesAtPosition(fileName, position);
+            });
+        };
+        LanguageServiceShimObject.prototype.getDocumentHighlights = function (fileName, position, filesToSearch) {
+            var _this = this;
+            return this.forwardJSONCall("getDocumentHighlights('" + fileName + "', " + position + ")", function () {
+                return _this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch));
+            });
+        };
+        LanguageServiceShimObject.prototype.getCompletionsAtPosition = function (fileName, position) {
+            var _this = this;
+            return this.forwardJSONCall("getCompletionsAtPosition('" + fileName + "', " + position + ")", function () {
+                var completion = _this.languageService.getCompletionsAtPosition(fileName, position);
+                return completion;
+            });
+        };
+        LanguageServiceShimObject.prototype.getCompletionEntryDetails = function (fileName, position, entryName) {
+            var _this = this;
+            return this.forwardJSONCall("getCompletionEntryDetails('" + fileName + "', " + position + ", " + entryName + ")", function () {
+                var details = _this.languageService.getCompletionEntryDetails(fileName, position, entryName);
+                return details;
+            });
+        };
+        LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options) {
+            var _this = this;
+            return this.forwardJSONCall("getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")", function () {
+                var localOptions = JSON.parse(options);
+                var edits = _this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions);
+                return edits;
+            });
+        };
+        LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options) {
+            var _this = this;
+            return this.forwardJSONCall("getFormattingEditsForDocument('" + fileName + "')", function () {
+                var localOptions = JSON.parse(options);
+                var edits = _this.languageService.getFormattingEditsForDocument(fileName, localOptions);
+                return edits;
+            });
+        };
+        LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options) {
+            var _this = this;
+            return this.forwardJSONCall("getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')", function () {
+                var localOptions = JSON.parse(options);
+                var edits = _this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions);
+                return edits;
+            });
+        };
+        LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount) {
+            var _this = this;
+            return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ")", function () {
+                var items = _this.languageService.getNavigateToItems(searchValue, maxResultCount);
+                return items;
+            });
+        };
+        LanguageServiceShimObject.prototype.getNavigationBarItems = function (fileName) {
+            var _this = this;
+            return this.forwardJSONCall("getNavigationBarItems('" + fileName + "')", function () {
+                var items = _this.languageService.getNavigationBarItems(fileName);
+                return items;
+            });
+        };
+        LanguageServiceShimObject.prototype.getOutliningSpans = function (fileName) {
+            var _this = this;
+            return this.forwardJSONCall("getOutliningSpans('" + fileName + "')", function () {
+                var items = _this.languageService.getOutliningSpans(fileName);
+                return items;
+            });
+        };
+        LanguageServiceShimObject.prototype.getTodoComments = function (fileName, descriptors) {
+            var _this = this;
+            return this.forwardJSONCall("getTodoComments('" + fileName + "')", function () {
+                var items = _this.languageService.getTodoComments(fileName, JSON.parse(descriptors));
+                return items;
+            });
+        };
+        LanguageServiceShimObject.prototype.getEmitOutput = function (fileName) {
+            var _this = this;
+            return this.forwardJSONCall("getEmitOutput('" + fileName + "')", function () {
+                var output = _this.languageService.getEmitOutput(fileName);
+                output.emitOutputStatus = output.emitSkipped ? 1 : 0;
+                return output;
+            });
+        };
+        return LanguageServiceShimObject;
+    })(ShimBase);
+    var ClassifierShimObject = (function (_super) {
+        __extends(ClassifierShimObject, _super);
+        function ClassifierShimObject(factory) {
+            _super.call(this, factory);
+            this.classifier = ts.createClassifier();
+        }
+        ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) {
+            var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics);
+            var items = classification.entries;
+            var result = "";
+            for (var i = 0; i < items.length; i++) {
+                result += items[i].length + "\n";
+                result += items[i].classification + "\n";
+            }
+            result += classification.finalLexState;
+            return result;
+        };
+        return ClassifierShimObject;
+    })(ShimBase);
+    var CoreServicesShimObject = (function (_super) {
+        __extends(CoreServicesShimObject, _super);
+        function CoreServicesShimObject(factory, logger, host) {
+            _super.call(this, factory);
+            this.logger = logger;
+            this.host = host;
+        }
+        CoreServicesShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
+            return forwardJSONCall(this.logger, actionDescription, action);
+        };
+        CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) {
+            return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () {
+                var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()));
+                var convertResult = {
+                    referencedFiles: [],
+                    importedFiles: [],
+                    isLibFile: result.isLibFile
+                };
+                ts.forEach(result.referencedFiles, function (refFile) {
+                    convertResult.referencedFiles.push({
+                        path: ts.normalizePath(refFile.fileName),
+                        position: refFile.pos,
+                        length: refFile.end - refFile.pos
+                    });
+                });
+                ts.forEach(result.importedFiles, function (importedFile) {
+                    convertResult.importedFiles.push({
+                        path: ts.normalizeSlashes(importedFile.fileName),
+                        position: importedFile.pos,
+                        length: importedFile.end - importedFile.pos
+                    });
+                });
+                return convertResult;
+            });
+        };
+        CoreServicesShimObject.prototype.getTSConfigFileInfo = function (fileName, sourceTextSnapshot) {
+            var _this = this;
+            return this.forwardJSONCall("getTSConfigFileInfo('" + fileName + "')", function () {
+                var text = sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength());
+                var result = ts.parseConfigFileText(fileName, text);
+                if (result.error) {
+                    return {
+                        options: {},
+                        files: [],
+                        errors: [realizeDiagnostic(result.error, '\r\n')]
+                    };
+                }
+                var configFile = ts.parseConfigFile(result.config, _this.host, ts.getDirectoryPath(ts.normalizeSlashes(fileName)));
+                return {
+                    options: configFile.options,
+                    files: configFile.fileNames,
+                    errors: realizeDiagnostics(configFile.errors, '\r\n')
+                };
+            });
+        };
+        CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () {
+            return this.forwardJSONCall("getDefaultCompilationSettings()", function () {
+                return ts.getDefaultCompilerOptions();
+            });
+        };
+        return CoreServicesShimObject;
+    })(ShimBase);
+    var TypeScriptServicesFactory = (function () {
+        function TypeScriptServicesFactory() {
+            this._shims = [];
+            this.documentRegistry = ts.createDocumentRegistry();
+        }
+        TypeScriptServicesFactory.prototype.getServicesVersion = function () {
+            return ts.servicesVersion;
+        };
+        TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) {
+            try {
+                var hostAdapter = new LanguageServiceShimHostAdapter(host);
+                var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry);
+                return new LanguageServiceShimObject(this, host, languageService);
+            }
+            catch (err) {
+                logInternalError(host, err);
+                throw err;
+            }
+        };
+        TypeScriptServicesFactory.prototype.createClassifierShim = function (logger) {
+            try {
+                return new ClassifierShimObject(this);
+            }
+            catch (err) {
+                logInternalError(logger, err);
+                throw err;
+            }
+        };
+        TypeScriptServicesFactory.prototype.createCoreServicesShim = function (host) {
+            try {
+                var adapter = new CoreServicesShimHostAdapter(host);
+                return new CoreServicesShimObject(this, host, adapter);
+            }
+            catch (err) {
+                logInternalError(host, err);
+                throw err;
+            }
+        };
+        TypeScriptServicesFactory.prototype.close = function () {
+            this._shims = [];
+            this.documentRegistry = ts.createDocumentRegistry();
+        };
+        TypeScriptServicesFactory.prototype.registerShim = function (shim) {
+            this._shims.push(shim);
+        };
+        TypeScriptServicesFactory.prototype.unregisterShim = function (shim) {
+            for (var i = 0, n = this._shims.length; i < n; i++) {
+                if (this._shims[i] === shim) {
+                    delete this._shims[i];
+                    return;
+                }
+            }
+            throw new Error("Invalid operation");
+        };
+        return TypeScriptServicesFactory;
+    })();
+    ts.TypeScriptServicesFactory = TypeScriptServicesFactory;
+    if (typeof module !== "undefined" && module.exports) {
+        module.exports = ts;
+    }
+})(ts || (ts = {}));
+var TypeScript;
+(function (TypeScript) {
+    var Services;
+    (function (Services) {
+        Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
+    })(Services = TypeScript.Services || (TypeScript.Services = {}));
+})(TypeScript || (TypeScript = {}));
+var toolsVersion = "1.4";
diff --git a/dist/typescript/services/signatureHelp.js b/dist/typescript/services/signatureHelp.js
new file mode 100644
index 000000000..1a6198e07
--- /dev/null
+++ b/dist/typescript/services/signatureHelp.js
@@ -0,0 +1,315 @@
+///<reference path='services.ts' />
+var ts;
+(function (ts) {
+    var SignatureHelp;
+    (function (SignatureHelp) {
+        var emptyArray = [];
+        var ArgumentListKind;
+        (function (ArgumentListKind) {
+            ArgumentListKind[ArgumentListKind["TypeArguments"] = 0] = "TypeArguments";
+            ArgumentListKind[ArgumentListKind["CallArguments"] = 1] = "CallArguments";
+            ArgumentListKind[ArgumentListKind["TaggedTemplateArguments"] = 2] = "TaggedTemplateArguments";
+        })(ArgumentListKind || (ArgumentListKind = {}));
+        function getSignatureHelpItems(program, sourceFile, position, cancellationToken) {
+            var typeChecker = program.getTypeChecker();
+            var startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position);
+            if (!startingToken) {
+                return undefined;
+            }
+            var argumentInfo = getContainingArgumentInfo(startingToken);
+            cancellationToken.throwIfCancellationRequested();
+            if (!argumentInfo) {
+                return undefined;
+            }
+            var call = argumentInfo.invocation;
+            var candidates = [];
+            var resolvedSignature = typeChecker.getResolvedSignature(call, candidates);
+            cancellationToken.throwIfCancellationRequested();
+            if (!candidates.length) {
+                if (ts.isJavaScript(sourceFile.fileName)) {
+                    return createJavaScriptSignatureHelpItems(argumentInfo);
+                }
+                return undefined;
+            }
+            return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
+            function createJavaScriptSignatureHelpItems(argumentInfo) {
+                if (argumentInfo.invocation.kind !== 157) {
+                    return undefined;
+                }
+                var callExpression = argumentInfo.invocation;
+                var expression = callExpression.expression;
+                var name = expression.kind === 65
+                    ? expression
+                    : expression.kind === 155
+                        ? expression.name
+                        : undefined;
+                if (!name || !name.text) {
+                    return undefined;
+                }
+                var typeChecker = program.getTypeChecker();
+                for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
+                    var sourceFile_1 = _a[_i];
+                    var nameToDeclarations = sourceFile_1.getNamedDeclarations();
+                    var declarations = ts.getProperty(nameToDeclarations, name.text);
+                    if (declarations) {
+                        for (var _b = 0; _b < declarations.length; _b++) {
+                            var declaration = declarations[_b];
+                            var symbol = declaration.symbol;
+                            if (symbol) {
+                                var type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration);
+                                if (type) {
+                                    var callSignatures = type.getCallSignatures();
+                                    if (callSignatures && callSignatures.length) {
+                                        return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            function getImmediatelyContainingArgumentInfo(node) {
+                if (node.parent.kind === 157 || node.parent.kind === 158) {
+                    var callExpression = node.parent;
+                    if (node.kind === 24 ||
+                        node.kind === 16) {
+                        var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
+                        var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
+                        ts.Debug.assert(list !== undefined);
+                        return {
+                            kind: isTypeArgList ? 0 : 1,
+                            invocation: callExpression,
+                            argumentsSpan: getApplicableSpanForArguments(list),
+                            argumentIndex: 0,
+                            argumentCount: getArgumentCount(list)
+                        };
+                    }
+                    var listItemInfo = ts.findListItemInfo(node);
+                    if (listItemInfo) {
+                        var list = listItemInfo.list;
+                        var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
+                        var argumentIndex = getArgumentIndex(list, node);
+                        var argumentCount = getArgumentCount(list);
+                        ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
+                        return {
+                            kind: isTypeArgList ? 0 : 1,
+                            invocation: callExpression,
+                            argumentsSpan: getApplicableSpanForArguments(list),
+                            argumentIndex: argumentIndex,
+                            argumentCount: argumentCount
+                        };
+                    }
+                }
+                else if (node.kind === 10 && node.parent.kind === 159) {
+                    if (ts.isInsideTemplateLiteral(node, position)) {
+                        return getArgumentListInfoForTemplate(node.parent, 0);
+                    }
+                }
+                else if (node.kind === 11 && node.parent.parent.kind === 159) {
+                    var templateExpression = node.parent;
+                    var tagExpression = templateExpression.parent;
+                    ts.Debug.assert(templateExpression.kind === 171);
+                    var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1;
+                    return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
+                }
+                else if (node.parent.kind === 176 && node.parent.parent.parent.kind === 159) {
+                    var templateSpan = node.parent;
+                    var templateExpression = templateSpan.parent;
+                    var tagExpression = templateExpression.parent;
+                    ts.Debug.assert(templateExpression.kind === 171);
+                    if (node.kind === 13 && !ts.isInsideTemplateLiteral(node, position)) {
+                        return undefined;
+                    }
+                    var spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
+                    var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
+                    return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
+                }
+                return undefined;
+            }
+            function getArgumentIndex(argumentsList, node) {
+                var argumentIndex = 0;
+                var listChildren = argumentsList.getChildren();
+                for (var _i = 0; _i < listChildren.length; _i++) {
+                    var child = listChildren[_i];
+                    if (child === node) {
+                        break;
+                    }
+                    if (child.kind !== 23) {
+                        argumentIndex++;
+                    }
+                }
+                return argumentIndex;
+            }
+            function getArgumentCount(argumentsList) {
+                var listChildren = argumentsList.getChildren();
+                var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 23; });
+                if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 23) {
+                    argumentCount++;
+                }
+                return argumentCount;
+            }
+            function getArgumentIndexForTemplatePiece(spanIndex, node) {
+                ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
+                if (ts.isTemplateLiteralKind(node.kind)) {
+                    if (ts.isInsideTemplateLiteral(node, position)) {
+                        return 0;
+                    }
+                    return spanIndex + 2;
+                }
+                return spanIndex + 1;
+            }
+            function getArgumentListInfoForTemplate(tagExpression, argumentIndex) {
+                var argumentCount = tagExpression.template.kind === 10
+                    ? 1
+                    : tagExpression.template.templateSpans.length + 1;
+                ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
+                return {
+                    kind: 2,
+                    invocation: tagExpression,
+                    argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression),
+                    argumentIndex: argumentIndex,
+                    argumentCount: argumentCount
+                };
+            }
+            function getApplicableSpanForArguments(argumentsList) {
+                var applicableSpanStart = argumentsList.getFullStart();
+                var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), false);
+                return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
+            }
+            function getApplicableSpanForTaggedTemplate(taggedTemplate) {
+                var template = taggedTemplate.template;
+                var applicableSpanStart = template.getStart();
+                var applicableSpanEnd = template.getEnd();
+                if (template.kind === 171) {
+                    var lastSpan = ts.lastOrUndefined(template.templateSpans);
+                    if (lastSpan.literal.getFullWidth() === 0) {
+                        applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, false);
+                    }
+                }
+                return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
+            }
+            function getContainingArgumentInfo(node) {
+                for (var n = node; n.kind !== 227; n = n.parent) {
+                    if (ts.isFunctionBlock(n)) {
+                        return undefined;
+                    }
+                    if (n.pos < n.parent.pos || n.end > n.parent.end) {
+                        ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
+                    }
+                    var argumentInfo_1 = getImmediatelyContainingArgumentInfo(n);
+                    if (argumentInfo_1) {
+                        return argumentInfo_1;
+                    }
+                }
+                return undefined;
+            }
+            function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) {
+                var children = parent.getChildren(sourceFile);
+                var indexOfOpenerToken = children.indexOf(openerToken);
+                ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
+                return children[indexOfOpenerToken + 1];
+            }
+            function selectBestInvalidOverloadIndex(candidates, argumentCount) {
+                var maxParamsSignatureIndex = -1;
+                var maxParams = -1;
+                for (var i = 0; i < candidates.length; i++) {
+                    var candidate = candidates[i];
+                    if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
+                        return i;
+                    }
+                    if (candidate.parameters.length > maxParams) {
+                        maxParams = candidate.parameters.length;
+                        maxParamsSignatureIndex = i;
+                    }
+                }
+                return maxParamsSignatureIndex;
+            }
+            function createSignatureHelpItems(candidates, bestSignature, argumentListInfo) {
+                var applicableSpan = argumentListInfo.argumentsSpan;
+                var isTypeParameterList = argumentListInfo.kind === 0;
+                var invocation = argumentListInfo.invocation;
+                var callTarget = ts.getInvokedExpression(invocation);
+                var callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget);
+                var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, undefined, undefined);
+                var items = ts.map(candidates, function (candidateSignature) {
+                    var signatureHelpParameters;
+                    var prefixDisplayParts = [];
+                    var suffixDisplayParts = [];
+                    if (callTargetDisplayParts) {
+                        prefixDisplayParts.push.apply(prefixDisplayParts, callTargetDisplayParts);
+                    }
+                    if (isTypeParameterList) {
+                        prefixDisplayParts.push(ts.punctuationPart(24));
+                        var typeParameters = candidateSignature.typeParameters;
+                        signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
+                        suffixDisplayParts.push(ts.punctuationPart(25));
+                        var parameterParts = ts.mapToDisplayParts(function (writer) {
+                            return typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation);
+                        });
+                        suffixDisplayParts.push.apply(suffixDisplayParts, parameterParts);
+                    }
+                    else {
+                        var typeParameterParts = ts.mapToDisplayParts(function (writer) {
+                            return typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation);
+                        });
+                        prefixDisplayParts.push.apply(prefixDisplayParts, typeParameterParts);
+                        prefixDisplayParts.push(ts.punctuationPart(16));
+                        var parameters = candidateSignature.parameters;
+                        signatureHelpParameters = parameters.length > 0 ? ts.map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
+                        suffixDisplayParts.push(ts.punctuationPart(17));
+                    }
+                    var returnTypeParts = ts.mapToDisplayParts(function (writer) {
+                        return typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation);
+                    });
+                    suffixDisplayParts.push.apply(suffixDisplayParts, returnTypeParts);
+                    return {
+                        isVariadic: candidateSignature.hasRestParameter,
+                        prefixDisplayParts: prefixDisplayParts,
+                        suffixDisplayParts: suffixDisplayParts,
+                        separatorDisplayParts: [ts.punctuationPart(23), ts.spacePart()],
+                        parameters: signatureHelpParameters,
+                        documentation: candidateSignature.getDocumentationComment()
+                    };
+                });
+                var argumentIndex = argumentListInfo.argumentIndex;
+                var argumentCount = argumentListInfo.argumentCount;
+                var selectedItemIndex = candidates.indexOf(bestSignature);
+                if (selectedItemIndex < 0) {
+                    selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
+                }
+                ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex);
+                return {
+                    items: items,
+                    applicableSpan: applicableSpan,
+                    selectedItemIndex: selectedItemIndex,
+                    argumentIndex: argumentIndex,
+                    argumentCount: argumentCount
+                };
+                function createSignatureHelpParameterForParameter(parameter) {
+                    var displayParts = ts.mapToDisplayParts(function (writer) {
+                        return typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation);
+                    });
+                    var isOptional = ts.hasQuestionToken(parameter.valueDeclaration);
+                    return {
+                        name: parameter.name,
+                        documentation: parameter.getDocumentationComment(),
+                        displayParts: displayParts,
+                        isOptional: isOptional
+                    };
+                }
+                function createSignatureHelpParameterForTypeParameter(typeParameter) {
+                    var displayParts = ts.mapToDisplayParts(function (writer) {
+                        return typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation);
+                    });
+                    return {
+                        name: typeParameter.symbol.name,
+                        documentation: emptyArray,
+                        displayParts: displayParts,
+                        isOptional: false
+                    };
+                }
+            }
+        }
+        SignatureHelp.getSignatureHelpItems = getSignatureHelpItems;
+    })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {}));
+})(ts || (ts = {}));
diff --git a/dist/typescript/services/utilities.js b/dist/typescript/services/utilities.js
new file mode 100644
index 000000000..6e92200f2
--- /dev/null
+++ b/dist/typescript/services/utilities.js
@@ -0,0 +1,569 @@
+var ts;
+(function (ts) {
+    function getEndLinePosition(line, sourceFile) {
+        ts.Debug.assert(line >= 0);
+        var lineStarts = sourceFile.getLineStarts();
+        var lineIndex = line;
+        if (lineIndex + 1 === lineStarts.length) {
+            return sourceFile.text.length - 1;
+        }
+        else {
+            var start = lineStarts[lineIndex];
+            var pos = lineStarts[lineIndex + 1] - 1;
+            ts.Debug.assert(ts.isLineBreak(sourceFile.text.charCodeAt(pos)));
+            while (start <= pos && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                pos--;
+            }
+            return pos;
+        }
+    }
+    ts.getEndLinePosition = getEndLinePosition;
+    function getLineStartPositionForPosition(position, sourceFile) {
+        var lineStarts = sourceFile.getLineStarts();
+        var line = sourceFile.getLineAndCharacterOfPosition(position).line;
+        return lineStarts[line];
+    }
+    ts.getLineStartPositionForPosition = getLineStartPositionForPosition;
+    function rangeContainsRange(r1, r2) {
+        return startEndContainsRange(r1.pos, r1.end, r2);
+    }
+    ts.rangeContainsRange = rangeContainsRange;
+    function startEndContainsRange(start, end, range) {
+        return start <= range.pos && end >= range.end;
+    }
+    ts.startEndContainsRange = startEndContainsRange;
+    function rangeContainsStartEnd(range, start, end) {
+        return range.pos <= start && range.end >= end;
+    }
+    ts.rangeContainsStartEnd = rangeContainsStartEnd;
+    function rangeOverlapsWithStartEnd(r1, start, end) {
+        return startEndOverlapsWithStartEnd(r1.pos, r1.end, start, end);
+    }
+    ts.rangeOverlapsWithStartEnd = rangeOverlapsWithStartEnd;
+    function startEndOverlapsWithStartEnd(start1, end1, start2, end2) {
+        var start = Math.max(start1, start2);
+        var end = Math.min(end1, end2);
+        return start < end;
+    }
+    ts.startEndOverlapsWithStartEnd = startEndOverlapsWithStartEnd;
+    function positionBelongsToNode(candidate, position, sourceFile) {
+        return candidate.end > position || !isCompletedNode(candidate, sourceFile);
+    }
+    ts.positionBelongsToNode = positionBelongsToNode;
+    function isCompletedNode(n, sourceFile) {
+        if (ts.nodeIsMissing(n)) {
+            return false;
+        }
+        switch (n.kind) {
+            case 201:
+            case 202:
+            case 204:
+            case 154:
+            case 150:
+            case 145:
+            case 179:
+            case 206:
+            case 207:
+                return nodeEndsWith(n, 15, sourceFile);
+            case 223:
+                return isCompletedNode(n.block, sourceFile);
+            case 158:
+                if (!n.arguments) {
+                    return true;
+                }
+            case 157:
+            case 161:
+            case 149:
+                return nodeEndsWith(n, 17, sourceFile);
+            case 142:
+            case 143:
+                return isCompletedNode(n.type, sourceFile);
+            case 135:
+            case 136:
+            case 137:
+            case 200:
+            case 162:
+            case 134:
+            case 133:
+            case 139:
+            case 138:
+            case 163:
+                if (n.body) {
+                    return isCompletedNode(n.body, sourceFile);
+                }
+                if (n.type) {
+                    return isCompletedNode(n.type, sourceFile);
+                }
+                return hasChildOfKind(n, 17, sourceFile);
+            case 205:
+                return n.body && isCompletedNode(n.body, sourceFile);
+            case 183:
+                if (n.elseStatement) {
+                    return isCompletedNode(n.elseStatement, sourceFile);
+                }
+                return isCompletedNode(n.thenStatement, sourceFile);
+            case 182:
+                return isCompletedNode(n.expression, sourceFile);
+            case 153:
+            case 151:
+            case 156:
+            case 127:
+            case 147:
+                return nodeEndsWith(n, 19, sourceFile);
+            case 140:
+                if (n.type) {
+                    return isCompletedNode(n.type, sourceFile);
+                }
+                return hasChildOfKind(n, 19, sourceFile);
+            case 220:
+            case 221:
+                return false;
+            case 186:
+            case 187:
+            case 188:
+            case 185:
+                return isCompletedNode(n.statement, sourceFile);
+            case 184:
+                var hasWhileKeyword = findChildOfKind(n, 100, sourceFile);
+                if (hasWhileKeyword) {
+                    return nodeEndsWith(n, 17, sourceFile);
+                }
+                return isCompletedNode(n.statement, sourceFile);
+            case 144:
+                return isCompletedNode(n.exprName, sourceFile);
+            case 165:
+            case 164:
+            case 166:
+            case 172:
+            case 173:
+                var unaryWordExpression = n;
+                return isCompletedNode(unaryWordExpression.expression, sourceFile);
+            case 159:
+                return isCompletedNode(n.template, sourceFile);
+            case 171:
+                var lastSpan = ts.lastOrUndefined(n.templateSpans);
+                return isCompletedNode(lastSpan, sourceFile);
+            case 176:
+                return ts.nodeIsPresent(n.literal);
+            case 167:
+                return isCompletedNode(n.operand, sourceFile);
+            case 169:
+                return isCompletedNode(n.right, sourceFile);
+            case 170:
+                return isCompletedNode(n.whenFalse, sourceFile);
+            default:
+                return true;
+        }
+    }
+    ts.isCompletedNode = isCompletedNode;
+    function nodeEndsWith(n, expectedLastToken, sourceFile) {
+        var children = n.getChildren(sourceFile);
+        if (children.length) {
+            var last = children[children.length - 1];
+            if (last.kind === expectedLastToken) {
+                return true;
+            }
+            else if (last.kind === 22 && children.length !== 1) {
+                return children[children.length - 2].kind === expectedLastToken;
+            }
+        }
+        return false;
+    }
+    function findListItemInfo(node) {
+        var list = findContainingList(node);
+        if (!list) {
+            return undefined;
+        }
+        var children = list.getChildren();
+        var listItemIndex = ts.indexOf(children, node);
+        return {
+            listItemIndex: listItemIndex,
+            list: list
+        };
+    }
+    ts.findListItemInfo = findListItemInfo;
+    function hasChildOfKind(n, kind, sourceFile) {
+        return !!findChildOfKind(n, kind, sourceFile);
+    }
+    ts.hasChildOfKind = hasChildOfKind;
+    function findChildOfKind(n, kind, sourceFile) {
+        return ts.forEach(n.getChildren(sourceFile), function (c) { return c.kind === kind && c; });
+    }
+    ts.findChildOfKind = findChildOfKind;
+    function findContainingList(node) {
+        var syntaxList = ts.forEach(node.parent.getChildren(), function (c) {
+            if (c.kind === 228 && c.pos <= node.pos && c.end >= node.end) {
+                return c;
+            }
+        });
+        ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node));
+        return syntaxList;
+    }
+    ts.findContainingList = findContainingList;
+    function getTouchingWord(sourceFile, position) {
+        return getTouchingToken(sourceFile, position, function (n) { return isWord(n.kind); });
+    }
+    ts.getTouchingWord = getTouchingWord;
+    function getTouchingPropertyName(sourceFile, position) {
+        return getTouchingToken(sourceFile, position, function (n) { return isPropertyName(n.kind); });
+    }
+    ts.getTouchingPropertyName = getTouchingPropertyName;
+    function getTouchingToken(sourceFile, position, includeItemAtEndPosition) {
+        return getTokenAtPositionWorker(sourceFile, position, false, includeItemAtEndPosition);
+    }
+    ts.getTouchingToken = getTouchingToken;
+    function getTokenAtPosition(sourceFile, position) {
+        return getTokenAtPositionWorker(sourceFile, position, true, undefined);
+    }
+    ts.getTokenAtPosition = getTokenAtPosition;
+    function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includeItemAtEndPosition) {
+        var current = sourceFile;
+        outer: while (true) {
+            if (isToken(current)) {
+                return current;
+            }
+            for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
+                var child = current.getChildAt(i);
+                var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
+                if (start <= position) {
+                    var end = child.getEnd();
+                    if (position < end || (position === end && child.kind === 1)) {
+                        current = child;
+                        continue outer;
+                    }
+                    else if (includeItemAtEndPosition && end === position) {
+                        var previousToken = findPrecedingToken(position, sourceFile, child);
+                        if (previousToken && includeItemAtEndPosition(previousToken)) {
+                            return previousToken;
+                        }
+                    }
+                }
+            }
+            return current;
+        }
+    }
+    function findTokenOnLeftOfPosition(file, position) {
+        var tokenAtPosition = getTokenAtPosition(file, position);
+        if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) {
+            return tokenAtPosition;
+        }
+        return findPrecedingToken(position, file);
+    }
+    ts.findTokenOnLeftOfPosition = findTokenOnLeftOfPosition;
+    function findNextToken(previousToken, parent) {
+        return find(parent);
+        function find(n) {
+            if (isToken(n) && n.pos === previousToken.end) {
+                return n;
+            }
+            var children = n.getChildren();
+            for (var _i = 0; _i < children.length; _i++) {
+                var child = children[_i];
+                var shouldDiveInChildNode = (child.pos <= previousToken.pos && child.end > previousToken.end) ||
+                    (child.pos === previousToken.end);
+                if (shouldDiveInChildNode && nodeHasTokens(child)) {
+                    return find(child);
+                }
+            }
+            return undefined;
+        }
+    }
+    ts.findNextToken = findNextToken;
+    function findPrecedingToken(position, sourceFile, startNode) {
+        return find(startNode || sourceFile);
+        function findRightmostToken(n) {
+            if (isToken(n)) {
+                return n;
+            }
+            var children = n.getChildren();
+            var candidate = findRightmostChildNodeWithTokens(children, children.length);
+            return candidate && findRightmostToken(candidate);
+        }
+        function find(n) {
+            if (isToken(n)) {
+                return n;
+            }
+            var children = n.getChildren();
+            for (var i = 0, len = children.length; i < len; i++) {
+                var child = children[i];
+                if (nodeHasTokens(child)) {
+                    if (position <= child.end) {
+                        if (child.getStart(sourceFile) >= position) {
+                            var candidate = findRightmostChildNodeWithTokens(children, i);
+                            return candidate && findRightmostToken(candidate);
+                        }
+                        else {
+                            return find(child);
+                        }
+                    }
+                }
+            }
+            ts.Debug.assert(startNode !== undefined || n.kind === 227);
+            if (children.length) {
+                var candidate = findRightmostChildNodeWithTokens(children, children.length);
+                return candidate && findRightmostToken(candidate);
+            }
+        }
+        function findRightmostChildNodeWithTokens(children, exclusiveStartPosition) {
+            for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
+                if (nodeHasTokens(children[i])) {
+                    return children[i];
+                }
+            }
+        }
+    }
+    ts.findPrecedingToken = findPrecedingToken;
+    function nodeHasTokens(n) {
+        return n.getWidth() !== 0;
+    }
+    function getNodeModifiers(node) {
+        var flags = ts.getCombinedNodeFlags(node);
+        var result = [];
+        if (flags & 32)
+            result.push(ts.ScriptElementKindModifier.privateMemberModifier);
+        if (flags & 64)
+            result.push(ts.ScriptElementKindModifier.protectedMemberModifier);
+        if (flags & 16)
+            result.push(ts.ScriptElementKindModifier.publicMemberModifier);
+        if (flags & 128)
+            result.push(ts.ScriptElementKindModifier.staticModifier);
+        if (flags & 1)
+            result.push(ts.ScriptElementKindModifier.exportedModifier);
+        if (ts.isInAmbientContext(node))
+            result.push(ts.ScriptElementKindModifier.ambientModifier);
+        return result.length > 0 ? result.join(',') : ts.ScriptElementKindModifier.none;
+    }
+    ts.getNodeModifiers = getNodeModifiers;
+    function getTypeArgumentOrTypeParameterList(node) {
+        if (node.kind === 141 || node.kind === 157) {
+            return node.typeArguments;
+        }
+        if (ts.isFunctionLike(node) || node.kind === 201 || node.kind === 202) {
+            return node.typeParameters;
+        }
+        return undefined;
+    }
+    ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList;
+    function isToken(n) {
+        return n.kind >= 0 && n.kind <= 125;
+    }
+    ts.isToken = isToken;
+    function isWord(kind) {
+        return kind === 65 || ts.isKeyword(kind);
+    }
+    ts.isWord = isWord;
+    function isPropertyName(kind) {
+        return kind === 8 || kind === 7 || isWord(kind);
+    }
+    function isComment(kind) {
+        return kind === 2 || kind === 3;
+    }
+    ts.isComment = isComment;
+    function isPunctuation(kind) {
+        return 14 <= kind && kind <= 64;
+    }
+    ts.isPunctuation = isPunctuation;
+    function isInsideTemplateLiteral(node, position) {
+        return ts.isTemplateLiteralKind(node.kind)
+            && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd());
+    }
+    ts.isInsideTemplateLiteral = isInsideTemplateLiteral;
+    function isAccessibilityModifier(kind) {
+        switch (kind) {
+            case 108:
+            case 106:
+            case 107:
+                return true;
+        }
+        return false;
+    }
+    ts.isAccessibilityModifier = isAccessibilityModifier;
+    function compareDataObjects(dst, src) {
+        for (var e in dst) {
+            if (typeof dst[e] === "object") {
+                if (!compareDataObjects(dst[e], src[e])) {
+                    return false;
+                }
+            }
+            else if (typeof dst[e] !== "function") {
+                if (dst[e] !== src[e]) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+    ts.compareDataObjects = compareDataObjects;
+})(ts || (ts = {}));
+var ts;
+(function (ts) {
+    function isFirstDeclarationOfSymbolParameter(symbol) {
+        return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 129;
+    }
+    ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter;
+    var displayPartWriter = getDisplayPartWriter();
+    function getDisplayPartWriter() {
+        var displayParts;
+        var lineStart;
+        var indent;
+        resetWriter();
+        return {
+            displayParts: function () { return displayParts; },
+            writeKeyword: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.keyword); },
+            writeOperator: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.operator); },
+            writePunctuation: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); },
+            writeSpace: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.space); },
+            writeStringLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); },
+            writeParameter: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.parameterName); },
+            writeSymbol: writeSymbol,
+            writeLine: writeLine,
+            increaseIndent: function () { indent++; },
+            decreaseIndent: function () { indent--; },
+            clear: resetWriter,
+            trackSymbol: function () { }
+        };
+        function writeIndent() {
+            if (lineStart) {
+                var indentString = ts.getIndentString(indent);
+                if (indentString) {
+                    displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space));
+                }
+                lineStart = false;
+            }
+        }
+        function writeKind(text, kind) {
+            writeIndent();
+            displayParts.push(displayPart(text, kind));
+        }
+        function writeSymbol(text, symbol) {
+            writeIndent();
+            displayParts.push(symbolPart(text, symbol));
+        }
+        function writeLine() {
+            displayParts.push(lineBreakPart());
+            lineStart = true;
+        }
+        function resetWriter() {
+            displayParts = [];
+            lineStart = true;
+            indent = 0;
+        }
+    }
+    function symbolPart(text, symbol) {
+        return displayPart(text, displayPartKind(symbol), symbol);
+        function displayPartKind(symbol) {
+            var flags = symbol.flags;
+            if (flags & 3) {
+                return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName;
+            }
+            else if (flags & 4) {
+                return ts.SymbolDisplayPartKind.propertyName;
+            }
+            else if (flags & 32768) {
+                return ts.SymbolDisplayPartKind.propertyName;
+            }
+            else if (flags & 65536) {
+                return ts.SymbolDisplayPartKind.propertyName;
+            }
+            else if (flags & 8) {
+                return ts.SymbolDisplayPartKind.enumMemberName;
+            }
+            else if (flags & 16) {
+                return ts.SymbolDisplayPartKind.functionName;
+            }
+            else if (flags & 32) {
+                return ts.SymbolDisplayPartKind.className;
+            }
+            else if (flags & 64) {
+                return ts.SymbolDisplayPartKind.interfaceName;
+            }
+            else if (flags & 384) {
+                return ts.SymbolDisplayPartKind.enumName;
+            }
+            else if (flags & 1536) {
+                return ts.SymbolDisplayPartKind.moduleName;
+            }
+            else if (flags & 8192) {
+                return ts.SymbolDisplayPartKind.methodName;
+            }
+            else if (flags & 262144) {
+                return ts.SymbolDisplayPartKind.typeParameterName;
+            }
+            else if (flags & 524288) {
+                return ts.SymbolDisplayPartKind.aliasName;
+            }
+            else if (flags & 8388608) {
+                return ts.SymbolDisplayPartKind.aliasName;
+            }
+            return ts.SymbolDisplayPartKind.text;
+        }
+    }
+    ts.symbolPart = symbolPart;
+    function displayPart(text, kind, symbol) {
+        return {
+            text: text,
+            kind: ts.SymbolDisplayPartKind[kind]
+        };
+    }
+    ts.displayPart = displayPart;
+    function spacePart() {
+        return displayPart(" ", ts.SymbolDisplayPartKind.space);
+    }
+    ts.spacePart = spacePart;
+    function keywordPart(kind) {
+        return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.keyword);
+    }
+    ts.keywordPart = keywordPart;
+    function punctuationPart(kind) {
+        return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.punctuation);
+    }
+    ts.punctuationPart = punctuationPart;
+    function operatorPart(kind) {
+        return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.operator);
+    }
+    ts.operatorPart = operatorPart;
+    function textOrKeywordPart(text) {
+        var kind = ts.stringToToken(text);
+        return kind === undefined
+            ? textPart(text)
+            : keywordPart(kind);
+    }
+    ts.textOrKeywordPart = textOrKeywordPart;
+    function textPart(text) {
+        return displayPart(text, ts.SymbolDisplayPartKind.text);
+    }
+    ts.textPart = textPart;
+    function lineBreakPart() {
+        return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak);
+    }
+    ts.lineBreakPart = lineBreakPart;
+    function mapToDisplayParts(writeDisplayParts) {
+        writeDisplayParts(displayPartWriter);
+        var result = displayPartWriter.displayParts();
+        displayPartWriter.clear();
+        return result;
+    }
+    ts.mapToDisplayParts = mapToDisplayParts;
+    function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) {
+        return mapToDisplayParts(function (writer) {
+            typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+        });
+    }
+    ts.typeToDisplayParts = typeToDisplayParts;
+    function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) {
+        return mapToDisplayParts(function (writer) {
+            typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags);
+        });
+    }
+    ts.symbolToDisplayParts = symbolToDisplayParts;
+    function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) {
+        return mapToDisplayParts(function (writer) {
+            typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
+        });
+    }
+    ts.signatureToDisplayParts = signatureToDisplayParts;
+    function isJavaScript(fileName) {
+        return ts.fileExtensionIs(fileName, ".js");
+    }
+    ts.isJavaScript = isJavaScript;
+})(ts || (ts = {}));
diff --git a/dist/worker/child.js b/dist/worker/child.js
index 3000d647c..34b9a1fba 100644
--- a/dist/worker/child.js
+++ b/dist/worker/child.js
@@ -1,5 +1,7 @@
 ///ts:ref=globals
 /// <reference path="../globals.ts"/> ///ts:ref:generated
+var makeTypeScriptGlobal_1 = require("../typescript/makeTypeScriptGlobal");
+makeTypeScriptGlobal_1.makeTsGlobal();
 var workerLib = require('./lib/workerLib');
 var child = new workerLib.Child();
 var projectService = require('../main/lang/projectService');
diff --git a/lib/globals.ts b/lib/globals.ts
index 2e8f107b9..2e2a37c9a 100644
--- a/lib/globals.ts
+++ b/lib/globals.ts
@@ -1,6 +1,4 @@
 /// <reference path="./typings/tsd.d.ts"/>
-/// <reference path="../node_modules/typescript/bin/typescript.d.ts"/>
-/// <reference path="../node_modules/typescript/bin/typescript_internal.d.ts"/>
 
 // From brackets plugin
 /// <reference path="./typings/bluebird.d.ts"/>
diff --git a/lib/linter.ts b/lib/linter.ts
index 2816ad021..92b0e42e8 100644
--- a/lib/linter.ts
+++ b/lib/linter.ts
@@ -4,6 +4,9 @@
 ///ts:ref=globals
 /// <reference path="./globals.ts"/> ///ts:ref:generated
 
+import {makeTsGlobal} from "./typescript/makeTypeScriptGlobal";
+makeTsGlobal();
+
 ///ts:import=utils
 import utils = require('./main/lang/utils'); ///ts:import:generated
 ///ts:import=parent
diff --git a/lib/main/atom/autoCompleteProvider.ts b/lib/main/atom/autoCompleteProvider.ts
index 0bf3c79d0..7d613be6f 100644
--- a/lib/main/atom/autoCompleteProvider.ts
+++ b/lib/main/atom/autoCompleteProvider.ts
@@ -6,7 +6,6 @@
 import parent = require('../../worker/parent'); ///ts:import:generated
 ///ts:import=atomConfig
 import atomConfig = require('./atomConfig'); ///ts:import:generated
-import ts = require('typescript');
 import fs = require('fs');
 ///ts:import=atomUtils
 import atomUtils = require('./atomUtils'); ///ts:import:generated
diff --git a/lib/main/atom/commands/commands.ts b/lib/main/atom/commands/commands.ts
index c47b9d845..2ab2ce19e 100644
--- a/lib/main/atom/commands/commands.ts
+++ b/lib/main/atom/commands/commands.ts
@@ -3,7 +3,6 @@ import buildView = require("../buildView");
 import atomUtils = require("../atomUtils");
 import autoCompleteProvider = require("../autoCompleteProvider");
 import path = require('path');
-import ts = require('typescript');
 import documentationView = require("../views/documentationView");
 import renameView = require("../views/renameView");
 var apd = require('atom-package-dependencies');
diff --git a/lib/main/atom/debugAtomTs.ts b/lib/main/atom/debugAtomTs.ts
index 190b69d77..c4e3ac439 100644
--- a/lib/main/atom/debugAtomTs.ts
+++ b/lib/main/atom/debugAtomTs.ts
@@ -6,7 +6,6 @@ import atomConfig = require('./atomConfig'); ///ts:import:generated
 ///ts:import=typescriptGrammar
 import typescriptGrammar = require('./typescriptGrammar'); ///ts:import:generated
 
-import ts = require('typescript');
 import TokenClass = ts.TokenClass;
 
 interface AtomTokenizeLineResult {
diff --git a/lib/main/atom/tooltipManager.ts b/lib/main/atom/tooltipManager.ts
index b9db5b675..7f55a4a20 100644
--- a/lib/main/atom/tooltipManager.ts
+++ b/lib/main/atom/tooltipManager.ts
@@ -11,7 +11,6 @@ import parent = require('../../worker/parent'); ///ts:import:generated
 
 import path = require('path');
 import fs = require('fs');
-import ts = require('typescript');
 import emissary = require('emissary');
 var Subscriber = emissary.Subscriber;
 import tooltipView = require('./views/tooltipView');
diff --git a/lib/main/atom/typescriptGrammar.ts b/lib/main/atom/typescriptGrammar.ts
index 8e0468beb..4cba96294 100644
--- a/lib/main/atom/typescriptGrammar.ts
+++ b/lib/main/atom/typescriptGrammar.ts
@@ -6,7 +6,6 @@
 // https://github.com/fdecampredon/brackets-typescript/blob/master/src/main/mode.ts
 // https://github.com/p-e-w/language-javascript-semantic/blob/master/lib/javascript-semantic-grammar.coffee
 
-import ts = require('typescript');
 import TokenClass = ts.TokenClass;
 
 declare class AtomTSBaseGrammar {
diff --git a/lib/main/atom/views/astView.ts b/lib/main/atom/views/astView.ts
index c5ea012c3..461c7e5ec 100644
--- a/lib/main/atom/views/astView.ts
+++ b/lib/main/atom/views/astView.ts
@@ -1,6 +1,5 @@
 import sp = require('atom-space-pen-views');
 import mainPanelView = require('./mainPanelView');
-import ts = require('typescript');
 import atomUtils = require("../atomUtils");
 import * as parent from "../../../worker/parent";
 import * as d3  from "d3";
diff --git a/lib/main/atom/views/dependencyView.ts b/lib/main/atom/views/dependencyView.ts
index 7be92d101..b41787899 100644
--- a/lib/main/atom/views/dependencyView.ts
+++ b/lib/main/atom/views/dependencyView.ts
@@ -1,6 +1,5 @@
 import sp = require('atom-space-pen-views');
 import mainPanelView = require('./mainPanelView');
-import ts = require('typescript');
 import atomUtils = require("../atomUtils");
 import * as parent from "../../../worker/parent";
 import * as d3  from "d3";
diff --git a/lib/main/atom/views/fileSymbolsView.ts b/lib/main/atom/views/fileSymbolsView.ts
index f9259d814..7e8d73815 100644
--- a/lib/main/atom/views/fileSymbolsView.ts
+++ b/lib/main/atom/views/fileSymbolsView.ts
@@ -1,6 +1,5 @@
 import sp = require('atom-space-pen-views');
 import mainPanelView = require('./mainPanelView');
-import ts = require('typescript');
 import atomUtils = require("../atomUtils");
 
 
diff --git a/lib/main/atom/views/projectSymbolsView.ts b/lib/main/atom/views/projectSymbolsView.ts
index 090079d63..ce43e199f 100644
--- a/lib/main/atom/views/projectSymbolsView.ts
+++ b/lib/main/atom/views/projectSymbolsView.ts
@@ -1,6 +1,5 @@
 import sp = require('atom-space-pen-views');
 import mainPanelView = require('./mainPanelView');
-import ts = require('typescript');
 import atomUtils = require("../atomUtils");
 
 
diff --git a/lib/main/atomts.ts b/lib/main/atomts.ts
index 462ac66fd..c31657ac1 100644
--- a/lib/main/atomts.ts
+++ b/lib/main/atomts.ts
@@ -1,6 +1,9 @@
 ///ts:ref=globals
 /// <reference path="../globals.ts"/> ///ts:ref:generated
 
+import {makeTsGlobal} from "../typescript/makeTypeScriptGlobal";
+makeTsGlobal();
+
 import path = require('path');
 import fs = require('fs');
 import os = require('os');
@@ -28,7 +31,6 @@ import typescriptGrammar = require('./atom/typescriptGrammar'); ///ts:import:gen
 import _atom = require('atom');
 import {$} from "atom-space-pen-views";
 
-
 import documentationView = require('./atom/views/documentationView');
 import renameView = require('./atom/views/renameView');
 import mainPanelView = require("./atom/views/mainPanelView");
@@ -60,6 +62,7 @@ var hideIfNotActiveOnStart = debounce(() => {
 
 /** only called once we have our dependencies */
 function readyToActivate() {
+    
     // Add the documentation view
     documentationView.attach();
 
diff --git a/lib/main/lang/core/languageServiceHost2.ts b/lib/main/lang/core/languageServiceHost2.ts
index eaebd8b4a..b4a1be00e 100644
--- a/lib/main/lang/core/languageServiceHost2.ts
+++ b/lib/main/lang/core/languageServiceHost2.ts
@@ -1,4 +1,3 @@
-import ts = require('typescript');
 import path = require('path');
 import utils = require('../utils');
 import fs = require('fs');
diff --git a/lib/main/lang/core/project.ts b/lib/main/lang/core/project.ts
index 9eedb81d9..6d378d04f 100644
--- a/lib/main/lang/core/project.ts
+++ b/lib/main/lang/core/project.ts
@@ -1,7 +1,6 @@
 ///ts:ref=globals
 /// <reference path="../../../globals.ts"/> ///ts:ref:generated
 
-import ts = require('typescript');
 import path = require('path');
 import fs = require('fs');
 import os = require('os');
diff --git a/lib/main/lang/fixmyts/addClassMember.ts b/lib/main/lang/fixmyts/addClassMember.ts
index 425165472..0396fc4ea 100644
--- a/lib/main/lang/fixmyts/addClassMember.ts
+++ b/lib/main/lang/fixmyts/addClassMember.ts
@@ -1,8 +1,6 @@
 import {QuickFix, QuickFixQueryInformation, Refactoring} from "./quickFix";
-import * as ts from "typescript";
 import * as ast from "./astUtils";
 import {EOL} from "os";
-import {displayPartsToString, typeToDisplayParts} from "typescript";
 
 function getIdentifierAndClassNames(error: ts.Diagnostic) {
     var errorText: string = <any>error.messageText;
@@ -58,7 +56,7 @@ class AddClassMember implements QuickFix {
             var type = info.typeChecker.getTypeAtLocation(binaryExpression.right);
 
             /** Discoverd from review of `services.getQuickInfoAtPosition` */
-            typeString = displayPartsToString(typeToDisplayParts(info.typeChecker, type)).replace(/\s+/g, ' ');
+            typeString = ts.displayPartsToString(ts.typeToDisplayParts(info.typeChecker, type)).replace(/\s+/g, ' ');
         }
 
         // Find the containing class declaration
diff --git a/lib/main/lang/fixmyts/astUtils.ts b/lib/main/lang/fixmyts/astUtils.ts
index 47dd8a9e4..f80e31a1d 100644
--- a/lib/main/lang/fixmyts/astUtils.ts
+++ b/lib/main/lang/fixmyts/astUtils.ts
@@ -1,4 +1,3 @@
-import * as ts from "typescript";
 
 export var forEachChild = ts.forEachChild;
 
diff --git a/lib/main/lang/fixmyts/equalsToEquals.ts b/lib/main/lang/fixmyts/equalsToEquals.ts
index 728df1637..1cd7e48a8 100644
--- a/lib/main/lang/fixmyts/equalsToEquals.ts
+++ b/lib/main/lang/fixmyts/equalsToEquals.ts
@@ -1,28 +1,25 @@
 import {QuickFix, QuickFixQueryInformation, Refactoring} from "./quickFix";
-import * as ts from "typescript";
 import * as ast from "./astUtils";
 import {EOL} from "os";
-import {displayPartsToString, typeToDisplayParts, SyntaxKind} from "typescript";
-
 
 class EqualsToEquals implements QuickFix {
     key = EqualsToEquals.name;
 
     canProvideFix(info: QuickFixQueryInformation): string {
-        if (info.positionNode.kind === SyntaxKind.EqualsEqualsToken) {
+        if (info.positionNode.kind === ts.SyntaxKind.EqualsEqualsToken) {
             return "Convert == to ===";
         }
-        if (info.positionNode.kind === SyntaxKind.ExclamationEqualsToken) {
+        if (info.positionNode.kind === ts.SyntaxKind.ExclamationEqualsToken) {
             return "Convert != to !==";
         }
     }
 
     provideFix(info: QuickFixQueryInformation): Refactoring[] {
 
-        if (info.positionNode.kind === SyntaxKind.EqualsEqualsToken) {
+        if (info.positionNode.kind === ts.SyntaxKind.EqualsEqualsToken) {
             var newText = '===';
         }
-        if (info.positionNode.kind === SyntaxKind.ExclamationEqualsToken) {
+        if (info.positionNode.kind === ts.SyntaxKind.ExclamationEqualsToken) {
             var newText = '!==';
         }
 
diff --git a/lib/main/lang/fixmyts/quickFix.ts b/lib/main/lang/fixmyts/quickFix.ts
index 6a2f094c0..2719ada26 100644
--- a/lib/main/lang/fixmyts/quickFix.ts
+++ b/lib/main/lang/fixmyts/quickFix.ts
@@ -1,7 +1,6 @@
 /**
  * Interfaces for quick fixes
  */
-import ts = require("typescript");
 import project = require("../core/project");
 
 
diff --git a/lib/main/lang/fixmyts/quoteToTemplate.ts b/lib/main/lang/fixmyts/quoteToTemplate.ts
index 36040f0c1..a3b9d832c 100644
--- a/lib/main/lang/fixmyts/quoteToTemplate.ts
+++ b/lib/main/lang/fixmyts/quoteToTemplate.ts
@@ -1,14 +1,12 @@
 import {QuickFix, QuickFixQueryInformation, Refactoring} from "./quickFix";
-import * as ts from "typescript";
 import * as ast from "./astUtils";
 import {EOL} from "os";
-import {displayPartsToString, typeToDisplayParts, SyntaxKind} from "typescript";
 
 class QuoteToTemplate implements QuickFix {
     key = QuoteToTemplate.name;
 
     canProvideFix(info: QuickFixQueryInformation): string {
-        if (info.positionNode.kind === SyntaxKind.StringLiteral) {
+        if (info.positionNode.kind === ts.SyntaxKind.StringLiteral) {
             return `Convert to Template String`;
         }
     }
diff --git a/lib/main/lang/fixmyts/quotesToQuotes.ts b/lib/main/lang/fixmyts/quotesToQuotes.ts
index d1f1c1032..0063c6703 100644
--- a/lib/main/lang/fixmyts/quotesToQuotes.ts
+++ b/lib/main/lang/fixmyts/quotesToQuotes.ts
@@ -1,14 +1,12 @@
 import {QuickFix, QuickFixQueryInformation, Refactoring} from "./quickFix";
-import * as ts from "typescript";
 import * as ast from "./astUtils";
 import {EOL} from "os";
-import {displayPartsToString, typeToDisplayParts, SyntaxKind} from "typescript";
 
 class QuotesToQuotes implements QuickFix {
     key = QuotesToQuotes.name;
 
     canProvideFix(info: QuickFixQueryInformation): string {
-        if (info.positionNode.kind === SyntaxKind.StringLiteral) {
+        if (info.positionNode.kind === ts.SyntaxKind.StringLiteral) {
             if (info.positionNode.getText().trim()[0] === `'`) {
                 return `Convert ' to "`;
             }
diff --git a/lib/main/lang/modules/astToText.ts b/lib/main/lang/modules/astToText.ts
index 026f0f5e4..f52843e2a 100644
--- a/lib/main/lang/modules/astToText.ts
+++ b/lib/main/lang/modules/astToText.ts
@@ -6,9 +6,6 @@
 // Inspired by `ts.forEachChild`:
 // https://github.com/Microsoft/TypeScript/blob/65cbd91667acf890f21a3527b3647c7bc994ca32/src/compiler/parser.ts#L43-L320
 
-import * as ts from "typescript";
-import {SyntaxKind, Node} from "typescript";
-
 export function astToText(srcFile: ts.Node) {
 
     //// A useful function for debugging
diff --git a/lib/main/lang/modules/building.ts b/lib/main/lang/modules/building.ts
index d75423b7d..3e9ec4be5 100644
--- a/lib/main/lang/modules/building.ts
+++ b/lib/main/lang/modules/building.ts
@@ -1,4 +1,3 @@
-import ts = require('typescript');
 import project = require('../core/project');
 import mkdirp = require('mkdirp');
 import path = require('path');
diff --git a/lib/main/lang/modules/getExternalModules.ts b/lib/main/lang/modules/getExternalModules.ts
index 41f50a29e..53390fe5e 100644
--- a/lib/main/lang/modules/getExternalModules.ts
+++ b/lib/main/lang/modules/getExternalModules.ts
@@ -1,18 +1,14 @@
 // From https://github.com/Microsoft/TypeScript/pull/2173/files
-import {
-SyntaxKind, ModuleDeclaration, forEachChild, Program
-} from "typescript";
 
-
-export function getExternalModuleNames(program: Program): string[] {
+export function getExternalModuleNames(program: ts.Program): string[] {
     var entries: string[] = [];
 
     program.getSourceFiles().forEach(sourceFile => {
 
         // Look for ambient external module declarations
-        forEachChild(sourceFile, child => {
-            if (child.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>child).name.kind === SyntaxKind.StringLiteral) {
-                entries.push((<ModuleDeclaration>child).name.text);
+        ts.forEachChild(sourceFile, child => {
+            if (child.kind === ts.SyntaxKind.ModuleDeclaration && (<ts.ModuleDeclaration>child).name.kind === ts.SyntaxKind.StringLiteral) {
+                entries.push((<ts.ModuleDeclaration>child).name.text);
             }
         });
     });
diff --git a/lib/main/lang/modules/programDependencies.ts b/lib/main/lang/modules/programDependencies.ts
index ba533b03c..766b4e0ae 100644
--- a/lib/main/lang/modules/programDependencies.ts
+++ b/lib/main/lang/modules/programDependencies.ts
@@ -1,7 +1,6 @@
 
 import {TypeScriptProjectFileDetails, pathIsRelative, consistentPath} from "../../tsconfig/tsconfig";
 import tsconfig = require("../../tsconfig/tsconfig");
-import * as ts from "typescript";
 import * as path from "path";
 import * as fs from "fs";
 
diff --git a/lib/main/lang/projectService.ts b/lib/main/lang/projectService.ts
index 6d9a407ec..001e70412 100644
--- a/lib/main/lang/projectService.ts
+++ b/lib/main/lang/projectService.ts
@@ -4,7 +4,6 @@
 import fs = require('fs');
 import path = require('path');
 import os = require('os');
-import ts = require('typescript');
 import mkdirp = require('mkdirp');
 var fuzzaldrin: { filter: (list: any[], prefix: string, property?: { key: string }) => any } = require('fuzzaldrin');
 
@@ -733,7 +732,7 @@ export function getNavigateToItems(query: FilePathQuery): Promise<GetNavigateToI
 
     var items: NavigateToItem[] = [];
     for (let file of project.getProjectSourceFiles()) {
-        for (let declaration of file.getNamedDeclarations()) {
+        for (let declaration of <any>file.getNamedDeclarations()) {
             let item: NavigateToItem = {
                 name: getDeclarationName(declaration),
                 kind: getNodeKind(declaration),
diff --git a/lib/main/tsconfig/formatting.ts b/lib/main/tsconfig/formatting.ts
index 1e76e519d..2c1bb1177 100644
--- a/lib/main/tsconfig/formatting.ts
+++ b/lib/main/tsconfig/formatting.ts
@@ -1,7 +1,6 @@
 ///ts:ref=globals
 /// <reference path="../../globals.ts"/> ///ts:ref:generated
 
-import ts = require('typescript');
 import os = require('os');
 
 /// The following two interfaces come from typescript.d.ts but camelCased for JSON parsing
diff --git a/lib/main/tsconfig/tsconfig.ts b/lib/main/tsconfig/tsconfig.ts
index e2a11eb51..d5ff3ae3a 100644
--- a/lib/main/tsconfig/tsconfig.ts
+++ b/lib/main/tsconfig/tsconfig.ts
@@ -144,7 +144,6 @@ function errorWithDetails<T>(error: Error, details: T): Error {
 import fs = require('fs');
 import path = require('path');
 import expand = require('glob-expand');
-import ts = require('typescript');
 import os = require('os');
 import formatting = require('./formatting');
 
diff --git a/lib/tsconfig.json b/lib/tsconfig.json
index cc456547d..9b54279c5 100644
--- a/lib/tsconfig.json
+++ b/lib/tsconfig.json
@@ -6,7 +6,7 @@
         "noImplicitAny": false,
         "removeComments": true,
         "noLib": false,
-        "preserveConstEnums": false,
+        "preserveConstEnums": true,
         "outDir": "../dist",
         "sourceMap": false
     },
@@ -67,6 +67,45 @@
         "./main/tsconfig/formatting.ts",
         "./main/tsconfig/simpleValidator.ts",
         "./main/tsconfig/tsconfig.ts",
+        "./typescript/compiler/binder.ts",
+        "./typescript/compiler/checker.ts",
+        "./typescript/compiler/commandLineParser.ts",
+        "./typescript/compiler/core.ts",
+        "./typescript/compiler/declarationEmitter.ts",
+        "./typescript/compiler/diagnosticInformationMap.generated.ts",
+        "./typescript/compiler/emitter.ts",
+        "./typescript/compiler/parser.ts",
+        "./typescript/compiler/program.ts",
+        "./typescript/compiler/scanner.ts",
+        "./typescript/compiler/sys.ts",
+        "./typescript/compiler/types.ts",
+        "./typescript/compiler/utilities.ts",
+        "./typescript/makeTypeScriptGlobal.ts",
+        "./typescript/services/breakpoints.ts",
+        "./typescript/services/formatting/formatting.ts",
+        "./typescript/services/formatting/formattingContext.ts",
+        "./typescript/services/formatting/formattingRequestKind.ts",
+        "./typescript/services/formatting/formattingScanner.ts",
+        "./typescript/services/formatting/references.ts",
+        "./typescript/services/formatting/rule.ts",
+        "./typescript/services/formatting/ruleAction.ts",
+        "./typescript/services/formatting/ruleDescriptor.ts",
+        "./typescript/services/formatting/ruleFlag.ts",
+        "./typescript/services/formatting/ruleOperation.ts",
+        "./typescript/services/formatting/ruleOperationContext.ts",
+        "./typescript/services/formatting/rules.ts",
+        "./typescript/services/formatting/rulesMap.ts",
+        "./typescript/services/formatting/rulesProvider.ts",
+        "./typescript/services/formatting/smartIndenter.ts",
+        "./typescript/services/formatting/tokenRange.ts",
+        "./typescript/services/navigateTo.ts",
+        "./typescript/services/navigationBar.ts",
+        "./typescript/services/outliningElementsCollector.ts",
+        "./typescript/services/patternMatcher.ts",
+        "./typescript/services/services.ts",
+        "./typescript/services/shims.ts",
+        "./typescript/services/signatureHelp.ts",
+        "./typescript/services/utilities.ts",
         "./typings/atom/atom.d.ts",
         "./typings/atompromise.d.ts",
         "./typings/bluebird.d.ts",
diff --git a/lib/typescript/compiler/binder.ts b/lib/typescript/compiler/binder.ts
new file mode 100644
index 000000000..f510a0bef
--- /dev/null
+++ b/lib/typescript/compiler/binder.ts
@@ -0,0 +1,618 @@
+/// <reference path="parser.ts"/>
+
+/* @internal */
+module ts {
+    export let bindTime = 0;
+
+    export const enum ModuleInstanceState {
+        NonInstantiated = 0,
+        Instantiated    = 1,
+        ConstEnumOnly   = 2
+    }
+
+    export function getModuleInstanceState(node: Node): ModuleInstanceState {
+        // A module is uninstantiated if it contains only 
+        // 1. interface declarations, type alias declarations
+        if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.TypeAliasDeclaration) {
+            return ModuleInstanceState.NonInstantiated;
+        }
+        // 2. const enum declarations
+        else if (isConstEnumDeclaration(node)) {
+            return ModuleInstanceState.ConstEnumOnly;
+        }
+        // 3. non-exported import declarations
+        else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && !(node.flags & NodeFlags.Export)) {
+            return ModuleInstanceState.NonInstantiated;
+        }
+        // 4. other uninstantiated module declarations.
+        else if (node.kind === SyntaxKind.ModuleBlock) {
+            let state = ModuleInstanceState.NonInstantiated;
+            forEachChild(node, n => {
+                switch (getModuleInstanceState(n)) {
+                    case ModuleInstanceState.NonInstantiated:
+                        // child is non-instantiated - continue searching
+                        return false;
+                    case ModuleInstanceState.ConstEnumOnly:
+                        // child is const enum only - record state and continue searching
+                        state = ModuleInstanceState.ConstEnumOnly;
+                        return false;
+                    case ModuleInstanceState.Instantiated:
+                        // child is instantiated - record state and stop
+                        state = ModuleInstanceState.Instantiated;
+                        return true;
+                }
+            });
+            return state;
+        }
+        else if (node.kind === SyntaxKind.ModuleDeclaration) {
+            return getModuleInstanceState((<ModuleDeclaration>node).body);
+        }
+        else {
+            return ModuleInstanceState.Instantiated;
+        }
+    }
+
+    export function bindSourceFile(file: SourceFile): void {
+        let start = new Date().getTime();
+        bindSourceFileWorker(file);
+        bindTime += new Date().getTime() - start;
+    }
+
+    function bindSourceFileWorker(file: SourceFile): void {
+        let parent: Node;
+        let container: Node;
+        let blockScopeContainer: Node;
+        let lastContainer: Node;
+        let symbolCount = 0;
+        let Symbol = objectAllocator.getSymbolConstructor();
+
+        if (!file.locals) {
+            file.locals = {};
+            container = file;
+            setBlockScopeContainer(file, /*cleanLocals*/ false);
+            bind(file);
+            file.symbolCount = symbolCount;
+        }
+
+        function createSymbol(flags: SymbolFlags, name: string): Symbol {
+            symbolCount++;
+            return new Symbol(flags, name);
+        }
+
+        function setBlockScopeContainer(node: Node, cleanLocals: boolean) {
+            blockScopeContainer = node;
+            if (cleanLocals) {
+                blockScopeContainer.locals = undefined;
+            }
+        }
+
+        function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolKind: SymbolFlags) {
+            symbol.flags |= symbolKind;
+            if (!symbol.declarations) symbol.declarations = [];
+            symbol.declarations.push(node);
+            if (symbolKind & SymbolFlags.HasExports && !symbol.exports) symbol.exports = {};
+            if (symbolKind & SymbolFlags.HasMembers && !symbol.members) symbol.members = {};
+            node.symbol = symbol;
+            if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node;
+        }
+
+        // Should not be called on a declaration with a computed property name,
+        // unless it is a well known Symbol.
+        function getDeclarationName(node: Declaration): string {
+            if (node.name) {
+                if (node.kind === SyntaxKind.ModuleDeclaration && node.name.kind === SyntaxKind.StringLiteral) {
+                    return '"' + (<LiteralExpression>node.name).text + '"';
+                }
+                if (node.name.kind === SyntaxKind.ComputedPropertyName) {
+                    let nameExpression = (<ComputedPropertyName>node.name).expression;
+                    Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
+                    return getPropertyNameForKnownSymbolName((<PropertyAccessExpression>nameExpression).name.text);
+                }
+                return (<Identifier | LiteralExpression>node.name).text;
+            }
+            switch (node.kind) {
+                case SyntaxKind.ConstructorType:
+                case SyntaxKind.Constructor:
+                    return "__constructor";
+                case SyntaxKind.FunctionType:
+                case SyntaxKind.CallSignature:
+                    return "__call";
+                case SyntaxKind.ConstructSignature:
+                    return "__new";
+                case SyntaxKind.IndexSignature:
+                    return "__index";
+                case SyntaxKind.ExportDeclaration:
+                    return "__export";
+                case SyntaxKind.ExportAssignment:
+                    return (<ExportAssignment>node).isExportEquals ? "export=" : "default";
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.ClassDeclaration:
+                    return node.flags & NodeFlags.Default ? "default" : undefined;
+            }
+        }
+
+        function getDisplayName(node: Declaration): string {
+            return node.name ? declarationNameToString(node.name) : getDeclarationName(node);
+        }
+
+        function declareSymbol(symbols: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
+            Debug.assert(!hasDynamicName(node));
+
+            // The exported symbol for an export default function/class node is always named "default"
+            let name = node.flags & NodeFlags.Default && parent ? "default" : getDeclarationName(node);
+
+            let symbol: Symbol;
+            if (name !== undefined) {
+                symbol = hasProperty(symbols, name) ? symbols[name] : (symbols[name] = createSymbol(0, name));
+                if (symbol.flags & excludes) {
+                    if (node.name) {
+                        node.name.parent = node;
+                    }
+
+                    // Report errors every position with duplicate declaration
+                    // Report errors on previous encountered declarations
+                    let message = symbol.flags & SymbolFlags.BlockScopedVariable
+                        ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 
+                        : Diagnostics.Duplicate_identifier_0;
+
+                    forEach(symbol.declarations, declaration => {
+                        file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
+                    });
+                    file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
+
+                    symbol = createSymbol(0, name);
+                }
+            }
+            else {
+                symbol = createSymbol(0, "__missing");
+            }
+            addDeclarationToSymbol(symbol, node, includes);
+            symbol.parent = parent;
+
+            if ((node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression) && symbol.exports) {
+                // TypeScript 1.0 spec (April 2014): 8.4
+                // Every class automatically contains a static property member named 'prototype', 
+                // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
+                // It is an error to explicitly declare a static property member with the name 'prototype'.
+                let prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
+                if (hasProperty(symbol.exports, prototypeSymbol.name)) {
+                    if (node.name) {
+                        node.name.parent = node;
+                    }
+                    file.bindDiagnostics.push(createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0],
+                        Diagnostics.Duplicate_identifier_0, prototypeSymbol.name));
+                }
+                symbol.exports[prototypeSymbol.name] = prototypeSymbol;
+                prototypeSymbol.parent = symbol;
+            }
+
+            return symbol;
+        }
+
+        function declareModuleMember(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) {
+            let hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export;
+            if (symbolKind & SymbolFlags.Alias) {
+                if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
+                    declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                }
+                else {
+                    declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
+                }
+            }
+            else {
+                // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue,
+                // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set
+                // on it. There are 2 main reasons:
+                //
+                //   1. We treat locals and exports of the same name as mutually exclusive within a container. 
+                //      That means the binder will issue a Duplicate Identifier error if you mix locals and exports
+                //      with the same name in the same container.
+                //      TODO: Make this a more specific error and decouple it from the exclusion logic.
+                //   2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol,
+                //      but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way
+                //      when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
+                if (hasExportModifier || container.flags & NodeFlags.ExportContext) {
+                    let exportKind = (symbolKind & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
+                        (symbolKind & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
+                        (symbolKind & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0);
+                    let local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
+                    local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                    node.localSymbol = local;
+                }
+                else {
+                    declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
+                }
+            }
+        }
+
+        // All container nodes are kept on a linked list in declaration order. This list is used by the getLocalNameOfContainer function
+        // in the type checker to validate that the local name used for a container is unique.
+        function bindChildren(node: Node, symbolKind: SymbolFlags, isBlockScopeContainer: boolean) {
+            if (symbolKind & SymbolFlags.HasLocals) {
+                node.locals = {};
+            }
+
+            let saveParent = parent;
+            let saveContainer = container;
+            let savedBlockScopeContainer = blockScopeContainer;
+            parent = node;
+            if (symbolKind & SymbolFlags.IsContainer) {
+                container = node;
+
+                addToContainerChain(container);
+            }
+
+            if (isBlockScopeContainer) {
+                // in incremental scenarios we might reuse nodes that already have locals being allocated
+                // during the bind step these locals should be dropped to prevent using stale data.
+                // locals should always be dropped unless they were previously initialized by the binder
+                // these cases are:
+                // - node has locals (symbolKind & HasLocals) !== 0
+                // - node is a source file
+                setBlockScopeContainer(node, /*cleanLocals*/  (symbolKind & SymbolFlags.HasLocals) === 0 && node.kind !== SyntaxKind.SourceFile);
+            }
+
+            forEachChild(node, bind);
+            container = saveContainer;
+            parent = saveParent;
+            blockScopeContainer = savedBlockScopeContainer;
+        }
+
+        function addToContainerChain(node: Node) {
+            if (lastContainer) {
+                lastContainer.nextContainer = node;
+            }
+
+            lastContainer = node;
+        }
+
+        function bindDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) {
+            switch (container.kind) {
+                case SyntaxKind.ModuleDeclaration:
+                    declareModuleMember(node, symbolKind, symbolExcludes);
+                    break;
+                case SyntaxKind.SourceFile:
+                    if (isExternalModule(<SourceFile>container)) {
+                        declareModuleMember(node, symbolKind, symbolExcludes);
+                        break;
+                    }
+                case SyntaxKind.FunctionType:
+                case SyntaxKind.ConstructorType:
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.ConstructSignature:
+                case SyntaxKind.IndexSignature:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.Constructor:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                    declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
+                    break;
+                case SyntaxKind.ClassExpression:
+                case SyntaxKind.ClassDeclaration:
+                    if (node.flags & NodeFlags.Static) {
+                        declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                        break;
+                    }
+                case SyntaxKind.TypeLiteral:
+                case SyntaxKind.ObjectLiteralExpression:
+                case SyntaxKind.InterfaceDeclaration:
+                    declareSymbol(container.symbol.members, container.symbol, node, symbolKind, symbolExcludes);
+                    break;
+                case SyntaxKind.EnumDeclaration:
+                    declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
+                    break;
+            }
+            bindChildren(node, symbolKind, isBlockScopeContainer);
+        }
+
+        function isAmbientContext(node: Node): boolean {
+            while (node) {
+                if (node.flags & NodeFlags.Ambient) return true;
+                node = node.parent;
+            }
+            return false;
+        }
+
+        function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean {
+            var body = node.kind === SyntaxKind.SourceFile ? node : (<ModuleDeclaration>node).body;
+            if (body.kind === SyntaxKind.SourceFile || body.kind === SyntaxKind.ModuleBlock) {
+                for (let stat of (<Block>body).statements) {
+                    if (stat.kind === SyntaxKind.ExportDeclaration || stat.kind === SyntaxKind.ExportAssignment) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        function setExportContextFlag(node: ModuleDeclaration | SourceFile) {
+            // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular
+            // declarations with export modifiers) is an export context in which declarations are implicitly exported.
+            if (isAmbientContext(node) && !hasExportDeclarations(node)) {
+                node.flags |= NodeFlags.ExportContext;
+            }
+            else {
+                node.flags &= ~NodeFlags.ExportContext;
+            }
+        }
+
+        function bindModuleDeclaration(node: ModuleDeclaration) {
+            setExportContextFlag(node);
+            if (node.name.kind === SyntaxKind.StringLiteral) {
+                bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
+            }
+            else {
+                let state = getModuleInstanceState(node);
+                if (state === ModuleInstanceState.NonInstantiated) {
+                    bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes, /*isBlockScopeContainer*/ true);
+                }
+                else {
+                    bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
+                    let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
+                    if (node.symbol.constEnumOnlyModule === undefined) {
+                        // non-merged case - use the current state
+                        node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
+                    }
+                    else {
+                        // merged case: module is const enum only if all its pieces are non-instantiated or const enum
+                        node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
+                    }
+                }
+            }
+        }
+
+        function bindFunctionOrConstructorType(node: SignatureDeclaration) {
+            // For a given function symbol "<...>(...) => T" we want to generate a symbol identical
+            // to the one we would get for: { <...>(...): T }
+            //
+            // We do that by making an anonymous type literal symbol, and then setting the function 
+            // symbol as its sole member. To the rest of the system, this symbol will be  indistinguishable 
+            // from an actual type literal symbol you would have gotten had you used the long form.
+
+            let symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node));
+            addDeclarationToSymbol(symbol, node, SymbolFlags.Signature);
+            bindChildren(node, SymbolFlags.Signature, /*isBlockScopeContainer:*/ false);
+
+            let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
+            addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
+            typeLiteralSymbol.members = {};
+            typeLiteralSymbol.members[node.kind === SyntaxKind.FunctionType ? "__call" : "__new"] = symbol
+        }
+
+        function bindAnonymousDeclaration(node: Declaration, symbolKind: SymbolFlags, name: string, isBlockScopeContainer: boolean) {
+            let symbol = createSymbol(symbolKind, name);
+            addDeclarationToSymbol(symbol, node, symbolKind);
+            bindChildren(node, symbolKind, isBlockScopeContainer);
+        }
+
+        function bindCatchVariableDeclaration(node: CatchClause) {
+            bindChildren(node, /*symbolKind:*/ 0, /*isBlockScopeContainer:*/ true);
+        }
+
+        function bindBlockScopedDeclaration(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) {
+            switch (blockScopeContainer.kind) {
+                case SyntaxKind.ModuleDeclaration:
+                    declareModuleMember(node, symbolKind, symbolExcludes);
+                    break;
+                case SyntaxKind.SourceFile:
+                    if (isExternalModule(<SourceFile>container)) {
+                        declareModuleMember(node, symbolKind, symbolExcludes);
+                        break;
+                    }
+                    // fall through.
+                default:
+                    if (!blockScopeContainer.locals) {
+                        blockScopeContainer.locals = {};
+                        addToContainerChain(blockScopeContainer);
+                    }
+                    declareSymbol(blockScopeContainer.locals, undefined, node, symbolKind, symbolExcludes);
+            }
+            bindChildren(node, symbolKind, /*isBlockScopeContainer*/ false);
+        }
+
+        function bindBlockScopedVariableDeclaration(node: Declaration) {
+            bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
+        }
+
+        function getDestructuringParameterName(node: Declaration) {
+            return "__" + indexOf((<SignatureDeclaration>node.parent).parameters, node);
+        }
+
+        function bind(node: Node) {
+            node.parent = parent;
+            
+            switch (node.kind) {
+                case SyntaxKind.TypeParameter:
+                    bindDeclaration(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.Parameter:
+                    bindParameter(<ParameterDeclaration>node);
+                    break;
+                case SyntaxKind.VariableDeclaration:
+                case SyntaxKind.BindingElement:
+                    if (isBindingPattern((<Declaration>node).name)) {
+                        bindChildren(node, 0, /*isBlockScopeContainer*/ false);
+                    }
+                    else if (isBlockOrCatchScoped(<Declaration>node)) {
+                        bindBlockScopedVariableDeclaration(<Declaration>node);
+                    }
+                    else {
+                        bindDeclaration(<Declaration>node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes, /*isBlockScopeContainer*/ false);
+                    }
+                    break;
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property | ((<PropertyDeclaration>node).questionToken ? SymbolFlags.Optional : 0), SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.PropertyAssignment:
+                case SyntaxKind.ShorthandPropertyAssignment:
+                    bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.EnumMember:
+                    bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.ConstructSignature:
+                case SyntaxKind.IndexSignature:
+                    bindDeclaration(<Declaration>node, SymbolFlags.Signature, 0, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                    // If this is an ObjectLiteralExpression method, then it sits in the same space
+                    // as other properties in the object literal.  So we use SymbolFlags.PropertyExcludes
+                    // so that it will conflict with any other object literal members with the same
+                    // name.
+                    bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Method | ((<MethodDeclaration>node).questionToken ? SymbolFlags.Optional : 0),
+                        isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes, /*isBlockScopeContainer*/ true);
+                    break;
+                case SyntaxKind.FunctionDeclaration:
+                    bindDeclaration(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes, /*isBlockScopeContainer*/ true);
+                    break;
+                case SyntaxKind.Constructor:
+                    bindDeclaration(<Declaration>node, SymbolFlags.Constructor, /*symbolExcludes:*/ 0, /*isBlockScopeContainer:*/ true);
+                    break;
+                case SyntaxKind.GetAccessor:
+                    bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes, /*isBlockScopeContainer*/ true);
+                    break;
+                case SyntaxKind.SetAccessor:
+                    bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes, /*isBlockScopeContainer*/ true);
+                    break;
+
+                case SyntaxKind.FunctionType:
+                case SyntaxKind.ConstructorType:
+                    bindFunctionOrConstructorType(<SignatureDeclaration>node);
+                    break;
+
+                case SyntaxKind.TypeLiteral:
+                    bindAnonymousDeclaration(<TypeLiteralNode>node, SymbolFlags.TypeLiteral, "__type", /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.ObjectLiteralExpression:
+                    bindAnonymousDeclaration(<ObjectLiteralExpression>node, SymbolFlags.ObjectLiteral, "__object", /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                    bindAnonymousDeclaration(<FunctionExpression>node, SymbolFlags.Function, "__function", /*isBlockScopeContainer*/ true);
+                    break;
+                case SyntaxKind.ClassExpression:
+                    bindAnonymousDeclaration(<ClassExpression>node, SymbolFlags.Class, "__class", /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.CatchClause:
+                    bindCatchVariableDeclaration(<CatchClause>node);
+                    break;
+                case SyntaxKind.ClassDeclaration:
+                    bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Class, SymbolFlags.ClassExcludes);
+                    break;
+                case SyntaxKind.InterfaceDeclaration:
+                    bindDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.TypeAliasDeclaration:
+                    bindDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.EnumDeclaration:
+                    if (isConst(node)) {
+                        bindDeclaration(<Declaration>node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes, /*isBlockScopeContainer*/ false);
+                    }
+                    else {
+                        bindDeclaration(<Declaration>node, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes, /*isBlockScopeContainer*/ false);
+                    }
+                    break;
+                case SyntaxKind.ModuleDeclaration:
+                    bindModuleDeclaration(<ModuleDeclaration>node);
+                    break;
+                case SyntaxKind.ImportEqualsDeclaration:
+                case SyntaxKind.NamespaceImport:
+                case SyntaxKind.ImportSpecifier:
+                case SyntaxKind.ExportSpecifier:
+                    bindDeclaration(<Declaration>node, SymbolFlags.Alias, SymbolFlags.AliasExcludes, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.ImportClause:
+                    if ((<ImportClause>node).name) {
+                        bindDeclaration(<Declaration>node, SymbolFlags.Alias, SymbolFlags.AliasExcludes, /*isBlockScopeContainer*/ false);
+                    }
+                    else {
+                        bindChildren(node, 0, /*isBlockScopeContainer*/ false);
+                    }
+                    break;
+                case SyntaxKind.ExportDeclaration:
+                    if (!(<ExportDeclaration>node).exportClause) {
+                        // All export * declarations are collected in an __export symbol
+                        declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.ExportStar, 0);
+                    }
+                    bindChildren(node, 0, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.ExportAssignment:
+                    if ((<ExportAssignment>node).expression.kind === SyntaxKind.Identifier) {
+                        // An export default clause with an identifier exports all meanings of that identifier
+                        declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
+                    }
+                    else {
+                        // An export default clause with an expression exports a value
+                        declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
+                    }
+                    bindChildren(node, 0, /*isBlockScopeContainer*/ false);
+                    break;
+                case SyntaxKind.SourceFile:
+                    setExportContextFlag(<SourceFile>node);
+                    if (isExternalModule(<SourceFile>node)) {
+                        bindAnonymousDeclaration(<SourceFile>node, SymbolFlags.ValueModule, '"' + removeFileExtension((<SourceFile>node).fileName) + '"', /*isBlockScopeContainer*/ true);
+                        break;
+                    }
+                case SyntaxKind.Block:
+                    // do not treat function block a block-scope container
+                    // all block-scope locals that reside in this block should go to the function locals.
+                    // Otherwise this won't be considered as redeclaration of a block scoped local:
+                    // function foo() {
+                    //  let x;
+                    //  let x;
+                    // }
+                    // 'let x' will be placed into the function locals and 'let x' - into the locals of the block
+                    bindChildren(node, 0, /*isBlockScopeContainer*/ !isFunctionLike(node.parent));
+                    break;
+                case SyntaxKind.CatchClause:
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                case SyntaxKind.CaseBlock:
+                    bindChildren(node, 0, /*isBlockScopeContainer*/ true);
+                    break;
+                default:
+                    let saveParent = parent;
+                    parent = node;
+                    forEachChild(node, bind);
+                    parent = saveParent;
+            }
+        }
+
+        function bindParameter(node: ParameterDeclaration) {
+            if (isBindingPattern(node.name)) {
+                bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(node), /*isBlockScopeContainer*/ false);
+            }
+            else {
+                bindDeclaration(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false);
+            }
+
+            // If this is a property-parameter, then also declare the property symbol into the 
+            // containing class.
+            if (node.flags & NodeFlags.AccessibilityModifier &&
+                node.parent.kind === SyntaxKind.Constructor &&
+                (node.parent.parent.kind === SyntaxKind.ClassDeclaration || node.parent.parent.kind === SyntaxKind.ClassExpression)) {
+
+                let classDeclaration = <ClassLikeDeclaration>node.parent.parent;
+                declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
+            }
+        }
+
+        function bindPropertyOrMethodOrAccessor(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags, isBlockScopeContainer: boolean) {
+            if (hasDynamicName(node)) {
+                bindAnonymousDeclaration(node, symbolKind, "__computed", isBlockScopeContainer);
+            }
+            else {
+                bindDeclaration(node, symbolKind, symbolExcludes, isBlockScopeContainer);
+            }
+        }
+    }
+}
diff --git a/lib/typescript/compiler/checker.ts b/lib/typescript/compiler/checker.ts
new file mode 100644
index 000000000..c1bc450c0
--- /dev/null
+++ b/lib/typescript/compiler/checker.ts
@@ -0,0 +1,13164 @@
+/// <reference path="binder.ts"/>
+
+/* @internal */
+module ts {
+    let nextSymbolId = 1;
+    let nextNodeId = 1;
+    let nextMergeId = 1;
+
+    export function getNodeId(node: Node): number {
+        if (!node.id) node.id = nextNodeId++;
+        return node.id;
+    }
+
+    export let checkTime = 0;
+
+    export function getSymbolId(symbol: Symbol): number {
+        if (!symbol.id) {
+            symbol.id = nextSymbolId++;
+        }
+
+        return symbol.id;
+    }
+
+    export function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker {
+        let Symbol = objectAllocator.getSymbolConstructor();
+        let Type = objectAllocator.getTypeConstructor();
+        let Signature = objectAllocator.getSignatureConstructor();
+
+        let typeCount = 0;
+
+        let emptyArray: any[] = [];
+        let emptySymbols: SymbolTable = {};
+
+        let compilerOptions = host.getCompilerOptions();
+        let languageVersion = compilerOptions.target || ScriptTarget.ES3;
+
+        let emitResolver = createResolver();
+
+        let undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
+        let argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments");
+
+        let checker: TypeChecker = {
+            getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"),
+            getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"),
+            getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount"),
+            getTypeCount: () => typeCount,
+            isUndefinedSymbol: symbol => symbol === undefinedSymbol,
+            isArgumentsSymbol: symbol => symbol === argumentsSymbol,
+            getDiagnostics,
+            getGlobalDiagnostics,
+            getTypeOfSymbolAtLocation,
+            getDeclaredTypeOfSymbol,
+            getPropertiesOfType,
+            getPropertyOfType,
+            getSignaturesOfType,
+            getIndexTypeOfType,
+            getReturnTypeOfSignature,
+            getSymbolsInScope,
+            getSymbolAtLocation,
+            getShorthandAssignmentValueSymbol,
+            getTypeAtLocation,
+            typeToString,
+            getSymbolDisplayBuilder,
+            symbolToString,
+            getAugmentedPropertiesOfType,
+            getRootSymbols,
+            getContextualType,
+            getFullyQualifiedName,
+            getResolvedSignature,
+            getConstantValue,
+            isValidPropertyAccess,
+            getSignatureFromDeclaration,
+            isImplementationOfOverload,
+            getAliasedSymbol: resolveAlias,
+            getEmitResolver,
+            getExportsOfModule: getExportsOfModuleAsArray,
+        };
+
+        let unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown");
+        let resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__");
+
+        let anyType = createIntrinsicType(TypeFlags.Any, "any");
+        let stringType = createIntrinsicType(TypeFlags.String, "string");
+        let numberType = createIntrinsicType(TypeFlags.Number, "number");
+        let booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean");
+        let esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
+        let voidType = createIntrinsicType(TypeFlags.Void, "void");
+        let undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined");
+        let nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null");
+        let unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
+        let resolvingType = createIntrinsicType(TypeFlags.Any, "__resolving__");
+
+        let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+        let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+        let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+        
+        let anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false);
+        let unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false);
+
+        let globals: SymbolTable = {};
+
+        let globalArraySymbol: Symbol;
+        let globalESSymbolConstructorSymbol: Symbol;
+
+        let globalObjectType: ObjectType;
+        let globalFunctionType: ObjectType;
+        let globalArrayType: ObjectType;
+        let globalStringType: ObjectType;
+        let globalNumberType: ObjectType;
+        let globalBooleanType: ObjectType;
+        let globalRegExpType: ObjectType;
+        let globalTemplateStringsArrayType: ObjectType;
+        let globalESSymbolType: ObjectType;
+        let globalIterableType: ObjectType;
+
+        let anyArrayType: Type;
+        let getGlobalClassDecoratorType: () => ObjectType;
+        let getGlobalParameterDecoratorType: () => ObjectType;
+        let getGlobalPropertyDecoratorType: () => ObjectType;
+        let getGlobalMethodDecoratorType: () => ObjectType;
+        
+        let tupleTypes: Map<TupleType> = {};
+        let unionTypes: Map<UnionType> = {};
+        let stringLiteralTypes: Map<StringLiteralType> = {};
+        let emitExtends = false;
+        let emitDecorate = false;
+        let emitParam = false;
+
+        let mergedSymbols: Symbol[] = [];
+        let symbolLinks: SymbolLinks[] = [];
+        let nodeLinks: NodeLinks[] = [];
+        let potentialThisCollisions: Node[] = [];
+
+        let diagnostics = createDiagnosticCollection();
+
+        let primitiveTypeInfo: Map<{ type: Type; flags: TypeFlags }> = {
+            "string": {
+                type: stringType,
+                flags: TypeFlags.StringLike
+            },
+            "number": {
+                type: numberType,
+                flags: TypeFlags.NumberLike
+            },
+            "boolean": {
+                type: booleanType,
+                flags: TypeFlags.Boolean
+            },
+            "symbol": {
+                type: esSymbolType,
+                flags: TypeFlags.ESSymbol
+            }
+        };
+
+        function getEmitResolver(sourceFile?: SourceFile) {
+            // Ensure we have all the type information in place for this file so that all the
+            // emitter questions of this resolver will return the right information.
+            getDiagnostics(sourceFile);
+            return emitResolver;
+        }
+
+        function error(location: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void {
+            let diagnostic = location
+                ? createDiagnosticForNode(location, message, arg0, arg1, arg2)
+                : createCompilerDiagnostic(message, arg0, arg1, arg2);
+            diagnostics.add(diagnostic);
+        }
+
+        function createSymbol(flags: SymbolFlags, name: string): Symbol {
+            return new Symbol(flags, name);
+        }
+
+        function getExcludedSymbolFlags(flags: SymbolFlags): SymbolFlags {
+            let result: SymbolFlags = 0;
+            if (flags & SymbolFlags.BlockScopedVariable) result |= SymbolFlags.BlockScopedVariableExcludes;
+            if (flags & SymbolFlags.FunctionScopedVariable) result |= SymbolFlags.FunctionScopedVariableExcludes;
+            if (flags & SymbolFlags.Property) result |= SymbolFlags.PropertyExcludes;
+            if (flags & SymbolFlags.EnumMember) result |= SymbolFlags.EnumMemberExcludes;
+            if (flags & SymbolFlags.Function) result |= SymbolFlags.FunctionExcludes;
+            if (flags & SymbolFlags.Class) result |= SymbolFlags.ClassExcludes;
+            if (flags & SymbolFlags.Interface) result |= SymbolFlags.InterfaceExcludes;
+            if (flags & SymbolFlags.RegularEnum) result |= SymbolFlags.RegularEnumExcludes;
+            if (flags & SymbolFlags.ConstEnum) result |= SymbolFlags.ConstEnumExcludes;
+            if (flags & SymbolFlags.ValueModule) result |= SymbolFlags.ValueModuleExcludes;
+            if (flags & SymbolFlags.Method) result |= SymbolFlags.MethodExcludes;
+            if (flags & SymbolFlags.GetAccessor) result |= SymbolFlags.GetAccessorExcludes;
+            if (flags & SymbolFlags.SetAccessor) result |= SymbolFlags.SetAccessorExcludes;
+            if (flags & SymbolFlags.TypeParameter) result |= SymbolFlags.TypeParameterExcludes;
+            if (flags & SymbolFlags.TypeAlias) result |= SymbolFlags.TypeAliasExcludes;
+            if (flags & SymbolFlags.Alias) result |= SymbolFlags.AliasExcludes;
+            return result;
+        }
+
+        function recordMergedSymbol(target: Symbol, source: Symbol) {
+            if (!source.mergeId) source.mergeId = nextMergeId++;
+            mergedSymbols[source.mergeId] = target;
+        }
+
+        function cloneSymbol(symbol: Symbol): Symbol {
+            let result = createSymbol(symbol.flags | SymbolFlags.Merged, symbol.name);
+            result.declarations = symbol.declarations.slice(0);
+            result.parent = symbol.parent;
+            if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
+            if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
+            if (symbol.members) result.members = cloneSymbolTable(symbol.members);
+            if (symbol.exports) result.exports = cloneSymbolTable(symbol.exports);
+            recordMergedSymbol(result, symbol);
+            return result;
+        }
+
+        function mergeSymbol(target: Symbol, source: Symbol) {
+            if (!(target.flags & getExcludedSymbolFlags(source.flags))) {
+                if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
+                    // reset flag when merging instantiated module into value module that has only const enums
+                    target.constEnumOnlyModule = false;
+                }
+                target.flags |= source.flags;
+                if (!target.valueDeclaration && source.valueDeclaration) target.valueDeclaration = source.valueDeclaration;
+                forEach(source.declarations, node => {
+                    target.declarations.push(node);
+                });
+                if (source.members) {
+                    if (!target.members) target.members = {};
+                    mergeSymbolTable(target.members, source.members);
+                }
+                if (source.exports) {
+                    if (!target.exports) target.exports = {};
+                    mergeSymbolTable(target.exports, source.exports);
+                }
+                recordMergedSymbol(target, source);
+            }
+            else {
+                let message = target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable
+                    ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0;
+                forEach(source.declarations, node => {
+                    error(node.name ? node.name : node, message, symbolToString(source));
+                });
+                forEach(target.declarations, node => {
+                    error(node.name ? node.name : node, message, symbolToString(source));
+                });
+            }
+        }
+
+        function cloneSymbolTable(symbolTable: SymbolTable): SymbolTable {
+            let result: SymbolTable = {};
+            for (let id in symbolTable) {
+                if (hasProperty(symbolTable, id)) {
+                    result[id] = symbolTable[id];
+                }
+            }
+            return result;
+        }
+
+        function mergeSymbolTable(target: SymbolTable, source: SymbolTable) {
+            for (let id in source) {
+                if (hasProperty(source, id)) {
+                    if (!hasProperty(target, id)) {
+                        target[id] = source[id];
+                    }
+                    else {
+                        let symbol = target[id];
+                        if (!(symbol.flags & SymbolFlags.Merged)) {
+                            target[id] = symbol = cloneSymbol(symbol);
+                        }
+                        mergeSymbol(symbol, source[id]);
+                    }
+                }
+            }
+        }
+
+        function getSymbolLinks(symbol: Symbol): SymbolLinks {
+            if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
+            var id = getSymbolId(symbol);
+            return symbolLinks[id] || (symbolLinks[id] = {});
+        }
+
+        function getNodeLinks(node: Node): NodeLinks {
+            let nodeId = getNodeId(node);
+            return nodeLinks[nodeId] || (nodeLinks[nodeId] = {});
+        }
+
+        function getSourceFile(node: Node): SourceFile {
+            return <SourceFile>getAncestor(node, SyntaxKind.SourceFile);
+        }
+
+        function isGlobalSourceFile(node: Node) {
+            return node.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>node);
+        }
+
+        function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol {
+            if (meaning && hasProperty(symbols, name)) {
+                let symbol = symbols[name];
+                Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
+                if (symbol.flags & meaning) {
+                    return symbol;
+                }
+                if (symbol.flags & SymbolFlags.Alias) {
+                    let target = resolveAlias(symbol);
+                    // Unknown symbol means an error occurred in alias resolution, treat it as positive answer to avoid cascading errors
+                    if (target === unknownSymbol || target.flags & meaning) {
+                        return symbol;
+                    }
+                }
+            }
+            // return undefined if we can't find a symbol.
+        }
+
+        /** Returns true if node1 is defined before node 2**/
+        function isDefinedBefore(node1: Node, node2: Node): boolean {
+            let file1 = getSourceFileOfNode(node1);
+            let file2 = getSourceFileOfNode(node2);
+            if (file1 === file2) {
+                return node1.pos <= node2.pos;
+            }
+
+            if (!compilerOptions.out) {
+                return true;
+            }
+
+            let sourceFiles = host.getSourceFiles();
+            return sourceFiles.indexOf(file1) <= sourceFiles.indexOf(file2);
+        }
+
+        // Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and
+        // the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with
+        // the given name can be found.
+        function resolveName(location: Node, name: string, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, nameArg: string | Identifier): Symbol {
+            let result: Symbol;
+            let lastLocation: Node;
+            let propertyWithInvalidInitializer: Node;
+            let errorLocation = location;
+            let grandparent: Node;
+
+            loop: while (location) {
+                // Locals of a source file are not in scope (because they get merged into the global symbol table)
+                if (location.locals && !isGlobalSourceFile(location)) {
+                    if (result = getSymbol(location.locals, name, meaning)) {
+                        break loop;
+                    }
+                }
+                switch (location.kind) {
+                    case SyntaxKind.SourceFile:
+                        if (!isExternalModule(<SourceFile>location)) break;
+                    case SyntaxKind.ModuleDeclaration:
+                        if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.ModuleMember)) {
+                            if (result.flags & meaning || !(result.flags & SymbolFlags.Alias && getDeclarationOfAliasSymbol(result).kind === SyntaxKind.ExportSpecifier)) {
+                                break loop;
+                            }
+                            result = undefined;
+                        }
+                        else if (location.kind === SyntaxKind.SourceFile ||
+                            (location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
+                            result = getSymbol(getSymbolOfNode(location).exports, "default", meaning & SymbolFlags.ModuleMember);
+                            let localSymbol = getLocalSymbolForExportDefault(result);
+                            if (result && (result.flags & meaning) && localSymbol && localSymbol.name === name) {
+                                break loop;
+                            }
+                            result = undefined;
+                        }
+                        break;
+                    case SyntaxKind.EnumDeclaration:
+                        if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.EnumMember)) {
+                            break loop;
+                        }
+                        break;
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                        // TypeScript 1.0 spec (April 2014): 8.4.1
+                        // Initializer expressions for instance member variables are evaluated in the scope
+                        // of the class constructor body but are not permitted to reference parameters or
+                        // local variables of the constructor. This effectively means that entities from outer scopes
+                        // by the same name as a constructor parameter or local variable are inaccessible
+                        // in initializer expressions for instance member variables.
+                        if (location.parent.kind === SyntaxKind.ClassDeclaration && !(location.flags & NodeFlags.Static)) {
+                            let ctor = findConstructorDeclaration(<ClassDeclaration>location.parent);
+                            if (ctor && ctor.locals) {
+                                if (getSymbol(ctor.locals, name, meaning & SymbolFlags.Value)) {
+                                    // Remember the property node, it will be used later to report appropriate error
+                                    propertyWithInvalidInitializer = location;
+                                }
+                            }
+                        }
+                        break;
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                        if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & SymbolFlags.Type)) {
+                            if (lastLocation && lastLocation.flags & NodeFlags.Static) {
+                                // TypeScript 1.0 spec (April 2014): 3.4.1
+                                // The scope of a type parameter extends over the entire declaration with which the type
+                                // parameter list is associated, with the exception of static member declarations in classes.
+                                error(errorLocation, Diagnostics.Static_members_cannot_reference_class_type_parameters);
+                                return undefined;
+                            }
+                            break loop;
+                        }
+                        break;
+
+                    // It is not legal to reference a class's own type parameters from a computed property name that
+                    // belongs to the class. For example:
+                    //
+                    //   function foo<T>() { return '' }
+                    //   class C<T> { // <-- Class's own type parameter T
+                    //       [foo<T>()]() { } // <-- Reference to T from class's own computed property
+                    //   }
+                    //
+                    case SyntaxKind.ComputedPropertyName:
+                        grandparent = location.parent.parent;
+                        if (grandparent.kind === SyntaxKind.ClassDeclaration || grandparent.kind === SyntaxKind.InterfaceDeclaration) {
+                            // A reference to this grandparent's type parameters would be an error
+                            if (result = getSymbol(getSymbolOfNode(grandparent).members, name, meaning & SymbolFlags.Type)) {
+                                error(errorLocation, Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type);
+                                return undefined;
+                            }
+                        }
+                        break;
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.ArrowFunction:
+                        if (name === "arguments") {
+                            result = argumentsSymbol;
+                            break loop;
+                        }
+                        break;
+                    case SyntaxKind.FunctionExpression:
+                        if (name === "arguments") {
+                            result = argumentsSymbol;
+                            break loop;
+                        }
+                        let functionName = (<FunctionExpression>location).name;
+                        if (functionName && name === functionName.text) {
+                            result = location.symbol;
+                            break loop;
+                        }
+                        break;
+                    case SyntaxKind.ClassExpression:
+                        let className = (<ClassExpression>location).name;
+                        if (className && name === className.text) {
+                            result = location.symbol;
+                            break loop;
+                        }
+                        break;
+                    case SyntaxKind.Decorator:
+                        // Decorators are resolved at the class declaration. Resolving at the parameter 
+                        // or member would result in looking up locals in the method.
+                        //
+                        //   function y() {}
+                        //   class C {
+                        //       method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
+                        //   }
+                        //
+                        if (location.parent && location.parent.kind === SyntaxKind.Parameter) {
+                            location = location.parent;
+                        }
+                        //
+                        //   function y() {}
+                        //   class C {
+                        //       @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method.
+                        //   }
+                        //
+                        if (location.parent && isClassElement(location.parent)) {
+                            location = location.parent;
+                        }
+                        break;
+                }
+                lastLocation = location;
+                location = location.parent;
+            }
+
+            if (!result) {
+                result = getSymbol(globals, name, meaning);
+            }
+
+            if (!result) {
+                if (nameNotFoundMessage) {
+                    error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg));
+                }
+                return undefined;
+            }
+
+            // Perform extra checks only if error reporting was requested
+            if (nameNotFoundMessage) {
+                if (propertyWithInvalidInitializer) {
+                    // We have a match, but the reference occurred within a property initializer and the identifier also binds
+                    // to a local variable in the constructor where the code will be emitted.
+                    let propertyName = (<PropertyDeclaration>propertyWithInvalidInitializer).name;
+                    error(errorLocation, Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor,
+                        declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg));
+                    return undefined;
+                }
+                if (result.flags & SymbolFlags.BlockScopedVariable) {
+                    checkResolvedBlockScopedVariable(result, errorLocation);
+                }
+            }
+            return result;
+        }
+
+        function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
+            Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0)
+            // Block-scoped variables cannot be used before their definition
+            let declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) ? d : undefined);
+
+            Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
+
+            // first check if usage is lexically located after the declaration
+            let isUsedBeforeDeclaration = !isDefinedBefore(declaration, errorLocation);
+            if (!isUsedBeforeDeclaration) {
+                // lexical check succeeded however code still can be illegal.
+                // - block scoped variables cannot be used in its initializers
+                //   let x = x; // illegal but usage is lexically after definition
+                // - in ForIn/ForOf statements variable cannot be contained in expression part
+                //   for (let x in x)
+                //   for (let x of x)
+
+                // climb up to the variable declaration skipping binding patterns
+                let variableDeclaration = <VariableDeclaration>getAncestor(declaration, SyntaxKind.VariableDeclaration);
+                let container = getEnclosingBlockScopeContainer(variableDeclaration);
+
+                if (variableDeclaration.parent.parent.kind === SyntaxKind.VariableStatement ||
+                    variableDeclaration.parent.parent.kind === SyntaxKind.ForStatement) {
+                    // variable statement/for statement case,
+                    // use site should not be inside variable declaration (initializer of declaration or binding element)
+                    isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, variableDeclaration, container);
+                }
+                else if (variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement ||
+                    variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) {
+                    // ForIn/ForOf case - use site should not be used in expression part
+                    let expression = (<ForInStatement | ForOfStatement>variableDeclaration.parent.parent).expression;
+                    isUsedBeforeDeclaration = isSameScopeDescendentOf(errorLocation, expression, container);
+                }
+            }
+            if (isUsedBeforeDeclaration) {
+                error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
+            }
+        }
+
+        /* Starting from 'initial' node walk up the parent chain until 'stopAt' node is reached.
+         * If at any point current node is equal to 'parent' node - return true.
+         * Return false if 'stopAt' node is reached or isFunctionLike(current) === true.
+         */
+        function isSameScopeDescendentOf(initial: Node, parent: Node, stopAt: Node): boolean {
+            if (!parent) {
+                return false;
+            }
+            for (let current = initial; current && current !== stopAt && !isFunctionLike(current); current = current.parent) {
+                if (current === parent) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        function getAnyImportSyntax(node: Node): AnyImportSyntax {
+            if (isAliasSymbolDeclaration(node)) {
+                if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
+                    return <ImportEqualsDeclaration>node;
+                }
+
+                while (node && node.kind !== SyntaxKind.ImportDeclaration) {
+                    node = node.parent;
+                }
+                return <ImportDeclaration>node;
+            }
+        }
+
+        function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration {
+            return forEach(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined);
+        }
+
+        function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration): Symbol {
+            if (node.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
+                return resolveExternalModuleSymbol(resolveExternalModuleName(node, getExternalModuleImportEqualsDeclarationExpression(node)));
+            }
+            return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>node.moduleReference, node);
+        }
+
+        function getTargetOfImportClause(node: ImportClause): Symbol {
+            let moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent).moduleSpecifier);
+            if (moduleSymbol) {
+                let exportDefaultSymbol = resolveSymbol(moduleSymbol.exports["default"]);
+                if (!exportDefaultSymbol) {
+                    error(node.name, Diagnostics.External_module_0_has_no_default_export, symbolToString(moduleSymbol));
+                }
+                return exportDefaultSymbol;
+            }
+        }
+
+        function getTargetOfNamespaceImport(node: NamespaceImport): Symbol {
+            var moduleSpecifier = (<ImportDeclaration>node.parent.parent).moduleSpecifier;
+            return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier);
+        }
+
+        function getMemberOfModuleVariable(moduleSymbol: Symbol, name: string): Symbol {
+            if (moduleSymbol.flags & SymbolFlags.Variable) {
+                let typeAnnotation = (<VariableDeclaration>moduleSymbol.valueDeclaration).type;
+                if (typeAnnotation) {
+                    return getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name);
+                }
+            }
+        }
+
+        // This function creates a synthetic symbol that combines the value side of one symbol with the
+        // type/namespace side of another symbol. Consider this example:
+        //
+        //   declare module graphics {
+        //       interface Point {
+        //           x: number;
+        //           y: number;
+        //       }
+        //   }
+        //   declare var graphics: {
+        //       Point: new (x: number, y: number) => graphics.Point;
+        //   }
+        //   declare module "graphics" {
+        //       export = graphics;
+        //   }
+        //
+        // An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point'
+        // property with the type/namespace side interface 'Point'.
+        function combineValueAndTypeSymbols(valueSymbol: Symbol, typeSymbol: Symbol): Symbol {
+            if (valueSymbol.flags & (SymbolFlags.Type | SymbolFlags.Namespace)) {
+                return valueSymbol;
+            }
+            let result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.name);
+            result.declarations = concatenate(valueSymbol.declarations, typeSymbol.declarations);
+            result.parent = valueSymbol.parent || typeSymbol.parent;
+            if (valueSymbol.valueDeclaration) result.valueDeclaration = valueSymbol.valueDeclaration;
+            if (typeSymbol.members) result.members = typeSymbol.members;
+            if (valueSymbol.exports) result.exports = valueSymbol.exports;
+            return result;
+        }
+
+        function getExportOfModule(symbol: Symbol, name: string): Symbol {
+            if (symbol.flags & SymbolFlags.Module) {
+                let exports = getExportsOfSymbol(symbol);
+                if (hasProperty(exports, name)) {
+                    return resolveSymbol(exports[name]);
+                }
+            }
+        }
+
+        function getPropertyOfVariable(symbol: Symbol, name: string): Symbol {
+            if (symbol.flags & SymbolFlags.Variable) {
+                var typeAnnotation = (<VariableDeclaration>symbol.valueDeclaration).type;
+                if (typeAnnotation) {
+                    return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name));
+                }
+            }
+        }
+
+        function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration, specifier: ImportOrExportSpecifier): Symbol {
+            let moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
+            let targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier);
+            if (targetSymbol) {
+                let name = specifier.propertyName || specifier.name;
+                if (name.text) {
+                    let symbolFromModule = getExportOfModule(targetSymbol, name.text);
+                    let symbolFromVariable = getPropertyOfVariable(targetSymbol, name.text);
+                    let symbol = symbolFromModule && symbolFromVariable ?
+                        combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) :
+                        symbolFromModule || symbolFromVariable;
+                    if (!symbol) {
+                        error(name, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), declarationNameToString(name));
+                    }
+                    return symbol;
+                }
+            }
+        }
+
+        function getTargetOfImportSpecifier(node: ImportSpecifier): Symbol {
+            return getExternalModuleMember(<ImportDeclaration>node.parent.parent.parent, node);
+        }
+
+        function getTargetOfExportSpecifier(node: ExportSpecifier): Symbol {
+            return (<ExportDeclaration>node.parent.parent).moduleSpecifier ?
+                getExternalModuleMember(<ExportDeclaration>node.parent.parent, node) :
+                resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
+        }
+
+        function getTargetOfExportAssignment(node: ExportAssignment): Symbol {
+            return resolveEntityName(<Identifier>node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
+        }
+
+        function getTargetOfAliasDeclaration(node: Declaration): Symbol {
+            switch (node.kind) {
+                case SyntaxKind.ImportEqualsDeclaration:
+                    return getTargetOfImportEqualsDeclaration(<ImportEqualsDeclaration>node);
+                case SyntaxKind.ImportClause:
+                    return getTargetOfImportClause(<ImportClause>node);
+                case SyntaxKind.NamespaceImport:
+                    return getTargetOfNamespaceImport(<NamespaceImport>node);
+                case SyntaxKind.ImportSpecifier:
+                    return getTargetOfImportSpecifier(<ImportSpecifier>node);
+                case SyntaxKind.ExportSpecifier:
+                    return getTargetOfExportSpecifier(<ExportSpecifier>node);
+                case SyntaxKind.ExportAssignment:
+                    return getTargetOfExportAssignment(<ExportAssignment>node);
+            }
+        }
+
+        function resolveSymbol(symbol: Symbol): Symbol {
+            return symbol && symbol.flags & SymbolFlags.Alias && !(symbol.flags & (SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace)) ? resolveAlias(symbol) : symbol;
+        }
+
+        function resolveAlias(symbol: Symbol): Symbol {
+            Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here.");
+            let links = getSymbolLinks(symbol);
+            if (!links.target) {
+                links.target = resolvingSymbol;
+                let node = getDeclarationOfAliasSymbol(symbol);
+                let target = getTargetOfAliasDeclaration(node);
+                if (links.target === resolvingSymbol) {
+                    links.target = target || unknownSymbol;
+                }
+                else {
+                    error(node, Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol));
+                }
+            }
+            else if (links.target === resolvingSymbol) {
+                links.target = unknownSymbol;
+            }
+            return links.target;
+        }
+
+        function markExportAsReferenced(node: ImportEqualsDeclaration | ExportAssignment | ExportSpecifier) {
+            let symbol = getSymbolOfNode(node);
+            let target = resolveAlias(symbol);
+            if (target) {
+                let markAlias =
+                    (target === unknownSymbol && compilerOptions.separateCompilation) ||
+                    (target !== unknownSymbol && (target.flags & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target));
+
+                if (markAlias) {
+                    markAliasSymbolAsReferenced(symbol);
+                }
+            }
+        }
+
+        // When an alias symbol is referenced, we need to mark the entity it references as referenced and in turn repeat that until
+        // we reach a non-alias or an exported entity (which is always considered referenced). We do this by checking the target of
+        // the alias as an expression (which recursively takes us back here if the target references another alias).
+        function markAliasSymbolAsReferenced(symbol: Symbol) {
+            let links = getSymbolLinks(symbol);
+            if (!links.referenced) {
+                links.referenced = true;
+                let node = getDeclarationOfAliasSymbol(symbol);
+                if (node.kind === SyntaxKind.ExportAssignment) {
+                    // export default <symbol>
+                    checkExpressionCached((<ExportAssignment>node).expression);
+                }
+                else if (node.kind === SyntaxKind.ExportSpecifier) {
+                    // export { <symbol> } or export { <symbol> as foo }
+                    checkExpressionCached((<ExportSpecifier>node).propertyName || (<ExportSpecifier>node).name);
+                }
+                else if (isInternalModuleImportEqualsDeclaration(node)) {
+                    // import foo = <symbol>
+                    checkExpressionCached(<Expression>(<ImportEqualsDeclaration>node).moduleReference);
+                }
+            }
+        }
+
+        // This function is only for imports with entity names
+        function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, importDeclaration?: ImportEqualsDeclaration): Symbol {
+            if (!importDeclaration) {
+                importDeclaration = <ImportEqualsDeclaration>getAncestor(entityName, SyntaxKind.ImportEqualsDeclaration);
+                Debug.assert(importDeclaration !== undefined);
+            }
+            // There are three things we might try to look for. In the following examples,
+            // the search term is enclosed in |...|:
+            //
+            //     import a = |b|; // Namespace
+            //     import a = |b.c|; // Value, type, namespace
+            //     import a = |b.c|.d; // Namespace
+            if (entityName.kind === SyntaxKind.Identifier && isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
+                entityName = <QualifiedName>entityName.parent;
+            }
+            // Check for case 1 and 3 in the above example
+            if (entityName.kind === SyntaxKind.Identifier || entityName.parent.kind === SyntaxKind.QualifiedName) {
+                return resolveEntityName(entityName, SymbolFlags.Namespace);
+            }
+            else {
+                // Case 2 in above example
+                // entityName.kind could be a QualifiedName or a Missing identifier
+                Debug.assert(entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration);
+                return resolveEntityName(entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
+            }
+        }
+
+        function getFullyQualifiedName(symbol: Symbol): string {
+            return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
+        }
+
+        // Resolves a qualified name and any involved aliases
+        function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags): Symbol {
+            if (nodeIsMissing(name)) {
+                return undefined;
+            }
+
+            let symbol: Symbol;
+            if (name.kind === SyntaxKind.Identifier) {
+                symbol = resolveName(name, (<Identifier>name).text, meaning, Diagnostics.Cannot_find_name_0, <Identifier>name);
+                if (!symbol) {
+                    return undefined;
+                }
+            }
+            else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) {
+                let left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessExpression>name).expression;
+                let right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
+
+                let namespace = resolveEntityName(left, SymbolFlags.Namespace);
+                if (!namespace || namespace === unknownSymbol || nodeIsMissing(right)) {
+                    return undefined;
+                }
+                symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning);
+                if (!symbol) {
+                    error(right, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString(right));
+                    return undefined;
+                }
+            }
+            else {
+                Debug.fail("Unknown entity name kind.");
+            }
+            Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
+            return symbol.flags & meaning ? symbol : resolveAlias(symbol);
+        }
+
+        function isExternalModuleNameRelative(moduleName: string): boolean {
+            // TypeScript 1.0 spec (April 2014): 11.2.1
+            // An external module name is "relative" if the first term is "." or "..".
+            return moduleName.substr(0, 2) === "./" || moduleName.substr(0, 3) === "../" || moduleName.substr(0, 2) === ".\\" || moduleName.substr(0, 3) === "..\\";
+        }
+
+        function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol {
+            if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral) {
+                return;
+            }
+
+            let moduleReferenceLiteral = <LiteralExpression>moduleReferenceExpression;
+            let searchPath = getDirectoryPath(getSourceFile(location).fileName);
+
+            // Module names are escaped in our symbol table.  However, string literal values aren't.
+            // Escape the name in the "require(...)" clause to ensure we find the right symbol.
+            let moduleName = escapeIdentifier(moduleReferenceLiteral.text);
+
+            if (!moduleName) return;
+            let isRelative = isExternalModuleNameRelative(moduleName);
+            if (!isRelative) {
+                let symbol = getSymbol(globals, '"' + moduleName + '"', SymbolFlags.ValueModule);
+                if (symbol) {
+                    return symbol;
+                }
+            }
+            let sourceFile: SourceFile;
+            while (true) {
+                let fileName = normalizePath(combinePaths(searchPath, moduleName));
+                sourceFile = host.getSourceFile(fileName + ".ts") || host.getSourceFile(fileName + ".d.ts");
+                if (sourceFile || isRelative) {
+                    break;
+                }
+                let parentPath = getDirectoryPath(searchPath);
+                if (parentPath === searchPath) {
+                    break;
+                }
+                searchPath = parentPath;
+            }
+            if (sourceFile) {
+                if (sourceFile.symbol) {
+                    return sourceFile.symbol;
+                }
+                error(moduleReferenceLiteral, Diagnostics.File_0_is_not_an_external_module, sourceFile.fileName);
+                return;
+            }
+            error(moduleReferenceLiteral, Diagnostics.Cannot_find_external_module_0, moduleName);
+        }
+
+        // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration,
+        // and an external module with no 'export =' declaration resolves to the module itself.
+        function resolveExternalModuleSymbol(moduleSymbol: Symbol): Symbol {
+            return moduleSymbol && resolveSymbol(moduleSymbol.exports["export="]) || moduleSymbol;
+        }
+
+        // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export ='
+        // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may
+        // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable).
+        function resolveESModuleSymbol(moduleSymbol: Symbol, moduleReferenceExpression: Expression): Symbol {
+            let symbol = resolveExternalModuleSymbol(moduleSymbol);
+            if (symbol && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) {
+                error(moduleReferenceExpression, Diagnostics.External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
+                symbol = undefined;
+            }
+            return symbol;
+        }
+
+        function getExportAssignmentSymbol(moduleSymbol: Symbol): Symbol {
+            return moduleSymbol.exports["export="];
+        }
+
+        function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] {
+            return symbolsToArray(getExportsOfModule(moduleSymbol));
+        }
+
+        function getExportsOfSymbol(symbol: Symbol): SymbolTable {
+            return symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : symbol.exports || emptySymbols;
+        }
+
+        function getExportsOfModule(moduleSymbol: Symbol): SymbolTable {
+            let links = getSymbolLinks(moduleSymbol);
+            return links.resolvedExports || (links.resolvedExports = getExportsForModule(moduleSymbol));
+        }
+
+        function extendExportSymbols(target: SymbolTable, source: SymbolTable) {
+            for (let id in source) {
+                if (id !== "default" && !hasProperty(target, id)) {
+                    target[id] = source[id];
+                }
+            }
+        }
+
+        function getExportsForModule(moduleSymbol: Symbol): SymbolTable {
+            let result: SymbolTable;
+            let visitedSymbols: Symbol[] = [];
+            visit(moduleSymbol);
+            return result || moduleSymbol.exports;
+
+            // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
+            // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
+            function visit(symbol: Symbol) {
+                if (symbol && symbol.flags & SymbolFlags.HasExports && !contains(visitedSymbols, symbol)) {
+                    visitedSymbols.push(symbol);
+                    if (symbol !== moduleSymbol) {
+                        if (!result) {
+                            result = cloneSymbolTable(moduleSymbol.exports);
+                        }
+                        extendExportSymbols(result, symbol.exports);
+                    }
+                    // All export * declarations are collected in an __export symbol by the binder
+                    let exportStars = symbol.exports["__export"];
+                    if (exportStars) {
+                        for (let node of exportStars.declarations) {
+                            visit(resolveExternalModuleName(node, (<ExportDeclaration>node).moduleSpecifier));
+                        }
+                    }
+                }
+            }
+        }
+
+        function getMergedSymbol(symbol: Symbol): Symbol {
+            let merged: Symbol;
+            return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol;
+        }
+
+        function getSymbolOfNode(node: Node): Symbol {
+            return getMergedSymbol(node.symbol);
+        }
+
+        function getParentOfSymbol(symbol: Symbol): Symbol {
+            return getMergedSymbol(symbol.parent);
+        }
+
+        function getExportSymbolOfValueSymbolIfExported(symbol: Symbol): Symbol {
+            return symbol && (symbol.flags & SymbolFlags.ExportValue) !== 0
+                ? getMergedSymbol(symbol.exportSymbol)
+                : symbol;
+        }
+
+        function symbolIsValue(symbol: Symbol): boolean {
+            // If it is an instantiated symbol, then it is a value if the symbol it is an
+            // instantiation of is a value.
+            if (symbol.flags & SymbolFlags.Instantiated) {
+                return symbolIsValue(getSymbolLinks(symbol).target);
+            }
+
+            // If the symbol has the value flag, it is trivially a value.
+            if (symbol.flags & SymbolFlags.Value) {
+                return true;
+            }
+
+            // If it is an alias, then it is a value if the symbol it resolves to is a value.
+            if (symbol.flags & SymbolFlags.Alias) {
+                return (resolveAlias(symbol).flags & SymbolFlags.Value) !== 0;
+            }
+
+            return false;
+        }
+
+        function findConstructorDeclaration(node: ClassDeclaration): ConstructorDeclaration {
+            let members = node.members;
+            for (let member of members) {
+                if (member.kind === SyntaxKind.Constructor && nodeIsPresent((<ConstructorDeclaration>member).body)) {
+                    return <ConstructorDeclaration>member;
+                }
+            }
+        }
+
+        function createType(flags: TypeFlags): Type {
+            let result = new Type(checker, flags);
+            result.id = typeCount++;
+            return result;
+        }
+
+        function createIntrinsicType(kind: TypeFlags, intrinsicName: string): IntrinsicType {
+            let type = <IntrinsicType>createType(kind);
+            type.intrinsicName = intrinsicName;
+            return type;
+        }
+
+        function createObjectType(kind: TypeFlags, symbol?: Symbol): ObjectType {
+            let type = <ObjectType>createType(kind);
+            type.symbol = symbol;
+            return type;
+        }
+
+        // A reserved member name starts with two underscores, but the third character cannot be an underscore
+        // or the @ symbol. A third underscore indicates an escaped form of an identifer that started
+        // with at least two underscores. The @ character indicates that the name is denoted by a well known ES
+        // Symbol instance.
+        function isReservedMemberName(name: string) {
+            return name.charCodeAt(0) === CharacterCodes._ &&
+                name.charCodeAt(1) === CharacterCodes._ &&
+                name.charCodeAt(2) !== CharacterCodes._ &&
+                name.charCodeAt(2) !== CharacterCodes.at;
+        }
+
+        function getNamedMembers(members: SymbolTable): Symbol[] {
+            let result: Symbol[];
+            for (let id in members) {
+                if (hasProperty(members, id)) {
+                    if (!isReservedMemberName(id)) {
+                        if (!result) result = [];
+                        let symbol = members[id];
+                        if (symbolIsValue(symbol)) {
+                            result.push(symbol);
+                        }
+                    }
+                }
+            }
+            return result || emptyArray;
+        }
+
+        function setObjectTypeMembers(type: ObjectType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexType: Type, numberIndexType: Type): ResolvedType {
+            (<ResolvedType>type).members = members;
+            (<ResolvedType>type).properties = getNamedMembers(members);
+            (<ResolvedType>type).callSignatures = callSignatures;
+            (<ResolvedType>type).constructSignatures = constructSignatures;
+            if (stringIndexType) (<ResolvedType>type).stringIndexType = stringIndexType;
+            if (numberIndexType) (<ResolvedType>type).numberIndexType = numberIndexType;
+            return <ResolvedType>type;
+        }
+
+        function createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexType: Type, numberIndexType: Type): ResolvedType {
+            return setObjectTypeMembers(createObjectType(TypeFlags.Anonymous, symbol),
+                members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+
+        function forEachSymbolTableInScope<T>(enclosingDeclaration: Node, callback: (symbolTable: SymbolTable) => T): T {
+            let result: T;
+            for (let location = enclosingDeclaration; location; location = location.parent) {
+                // Locals of a source file are not in scope (because they get merged into the global symbol table)
+                if (location.locals && !isGlobalSourceFile(location)) {
+                    if (result = callback(location.locals)) {
+                        return result;
+                    }
+                }
+                switch (location.kind) {
+                    case SyntaxKind.SourceFile:
+                        if (!isExternalModule(<SourceFile>location)) {
+                            break;
+                        }
+                    case SyntaxKind.ModuleDeclaration:
+                        if (result = callback(getSymbolOfNode(location).exports)) {
+                            return result;
+                        }
+                        break;
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                        if (result = callback(getSymbolOfNode(location).members)) {
+                            return result;
+                        }
+                        break;
+                }
+            }
+
+            return callback(globals);
+        }
+
+        function getQualifiedLeftMeaning(rightMeaning: SymbolFlags) {
+            // If we are looking in value space, the parent meaning is value, other wise it is namespace
+            return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace;
+        }
+
+        function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] {
+            function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] {
+                function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) {
+                    // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
+                    if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
+                        return true;
+                    }
+
+                    // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too
+                    let accessibleParent = getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
+                    return !!accessibleParent;
+                }
+
+                function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol) {
+                    if (symbol === (resolvedAliasSymbol || symbolFromSymbolTable)) {
+                        // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table)
+                        // and if symbolfrom symbolTable or alias resolution matches the symbol,
+                        // check the symbol can be qualified, it is only then this symbol is accessible
+                        return !forEach(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) &&
+                            canQualifySymbol(symbolFromSymbolTable, meaning);
+                    }
+                }
+
+                // If symbol is directly available by its name in the symbol table
+                if (isAccessible(lookUp(symbols, symbol.name))) {
+                    return [symbol];
+                }
+
+                // Check if symbol is any of the alias
+                return forEachValue(symbols, symbolFromSymbolTable => {
+                    if (symbolFromSymbolTable.flags & SymbolFlags.Alias && symbolFromSymbolTable.name !== "export=") {
+                        if (!useOnlyExternalAliasing || // We can use any type of alias to get the name
+                            // Is this external alias, then use it to name
+                            ts.forEach(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) {
+
+                            let resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
+                            if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
+                                return [symbolFromSymbolTable];
+                            }
+
+                            // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
+                            // but only if the symbolFromSymbolTable can be qualified
+                            let accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTable(resolvedImportedSymbol.exports) : undefined;
+                            if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
+                                return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
+                            }
+                        }
+                    }
+                });
+            }
+
+            if (symbol) {
+                return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
+            }
+        }
+
+        function needsQualification(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags) {
+            let qualify = false;
+            forEachSymbolTableInScope(enclosingDeclaration, symbolTable => {
+                // If symbol of this name is not available in the symbol table we are ok
+                if (!hasProperty(symbolTable, symbol.name)) {
+                    // Continue to the next symbol table
+                    return false;
+                }
+                // If the symbol with this name is present it should refer to the symbol
+                let symbolFromSymbolTable = symbolTable[symbol.name];
+                if (symbolFromSymbolTable === symbol) {
+                    // No need to qualify
+                    return true;
+                }
+
+                // Qualify if the symbol from symbol table has same meaning as expected
+                symbolFromSymbolTable = (symbolFromSymbolTable.flags & SymbolFlags.Alias) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable;
+                if (symbolFromSymbolTable.flags & meaning) {
+                    qualify = true;
+                    return true;
+                }
+
+                // Continue to the next symbol table
+                return false;
+            });
+
+            return qualify;
+        }
+
+        function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult {
+            if (symbol && enclosingDeclaration && !(symbol.flags & SymbolFlags.TypeParameter)) {
+                let initialSymbol = symbol;
+                let meaningToLook = meaning;
+                while (symbol) {
+                    // Symbol is accessible if it by itself is accessible
+                    let accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false);
+                    if (accessibleSymbolChain) {
+                        let hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]);
+                        if (!hasAccessibleDeclarations) {
+                            return <SymbolAccessiblityResult>{
+                                accessibility: SymbolAccessibility.NotAccessible,
+                                errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
+                                errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, SymbolFlags.Namespace) : undefined,
+                            };
+                        }
+                        return hasAccessibleDeclarations;
+                    }
+
+                    // If we haven't got the accessible symbol, it doesn't mean the symbol is actually inaccessible.
+                    // It could be a qualified symbol and hence verify the path
+                    // e.g.:
+                    // module m {
+                    //     export class c {
+                    //     }
+                    // }
+                    // let x: typeof m.c
+                    // In the above example when we start with checking if typeof m.c symbol is accessible,
+                    // we are going to see if c can be accessed in scope directly.
+                    // But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible
+                    // It is accessible if the parent m is accessible because then m.c can be accessed through qualification
+                    meaningToLook = getQualifiedLeftMeaning(meaning);
+                    symbol = getParentOfSymbol(symbol);
+                }
+
+                // This could be a symbol that is not exported in the external module
+                // or it could be a symbol from different external module that is not aliased and hence cannot be named
+                let symbolExternalModule = forEach(initialSymbol.declarations, getExternalModuleContainer);
+                if (symbolExternalModule) {
+                    let enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration);
+                    if (symbolExternalModule !== enclosingExternalModule) {
+                        // name from different external module that is not visible
+                        return {
+                            accessibility: SymbolAccessibility.CannotBeNamed,
+                            errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
+                            errorModuleName: symbolToString(symbolExternalModule)
+                        };
+                    }
+                }
+
+                // Just a local name that is not accessible
+                return {
+                    accessibility: SymbolAccessibility.NotAccessible,
+                    errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
+                };
+            }
+
+            return { accessibility: SymbolAccessibility.Accessible };
+
+            function getExternalModuleContainer(declaration: Node) {
+                for (; declaration; declaration = declaration.parent) {
+                    if (hasExternalModuleSymbol(declaration)) {
+                        return getSymbolOfNode(declaration);
+                    }
+                }
+            }
+        }
+
+        function hasExternalModuleSymbol(declaration: Node) {
+            return (declaration.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>declaration).name.kind === SyntaxKind.StringLiteral) ||
+                (declaration.kind === SyntaxKind.SourceFile && isExternalModule(<SourceFile>declaration));
+        }
+
+        function hasVisibleDeclarations(symbol: Symbol): SymbolVisibilityResult {
+            let aliasesToMakeVisible: AnyImportSyntax[];
+            if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) {
+                return undefined;
+            }
+            return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible };
+
+            function getIsDeclarationVisible(declaration: Declaration) {
+                if (!isDeclarationVisible(declaration)) {
+                    // Mark the unexported alias as visible if its parent is visible
+                    // because these kind of aliases can be used to name types in declaration file
+
+                    var anyImportSyntax = getAnyImportSyntax(declaration);
+                    if (anyImportSyntax &&
+                        !(anyImportSyntax.flags & NodeFlags.Export) && // import clause without export
+                        isDeclarationVisible(<Declaration>anyImportSyntax.parent)) {
+                        getNodeLinks(declaration).isVisible = true;
+                        if (aliasesToMakeVisible) {
+                            if (!contains(aliasesToMakeVisible, anyImportSyntax)) {
+                                aliasesToMakeVisible.push(anyImportSyntax);
+                            }
+                        }
+                        else {
+                            aliasesToMakeVisible = [anyImportSyntax];
+                        }
+                        return true;
+                    }
+
+                    // Declaration is not visible
+                    return false;
+                }
+
+                return true;
+            }
+        }
+
+        function isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult {
+            // get symbol of the first identifier of the entityName
+            let meaning: SymbolFlags;
+            if (entityName.parent.kind === SyntaxKind.TypeQuery) {
+                // Typeof value
+                meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
+            }
+            else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression ||
+                entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) {
+                // Left identifier from type reference or TypeAlias
+                // Entity name of the import declaration
+                meaning = SymbolFlags.Namespace;
+            }
+            else {
+                // Type Reference or TypeAlias entity = Identifier
+                meaning = SymbolFlags.Type;
+            }
+
+            let firstIdentifier = getFirstIdentifier(entityName);
+            let symbol = resolveName(enclosingDeclaration, (<Identifier>firstIdentifier).text, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
+
+            // Verify if the symbol is accessible
+            return (symbol && hasVisibleDeclarations(symbol)) || <SymbolVisibilityResult>{
+                accessibility: SymbolAccessibility.NotAccessible,
+                errorSymbolName: getTextOfNode(firstIdentifier),
+                errorNode: firstIdentifier
+            };
+        }
+
+        function writeKeyword(writer: SymbolWriter, kind: SyntaxKind) {
+            writer.writeKeyword(tokenToString(kind));
+        }
+
+        function writePunctuation(writer: SymbolWriter, kind: SyntaxKind) {
+            writer.writePunctuation(tokenToString(kind));
+        }
+
+        function writeSpace(writer: SymbolWriter) {
+            writer.writeSpace(" ");
+        }
+
+        function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string {
+            let writer = getSingleLineStringWriter();
+            getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning);
+
+            let result = writer.string();
+            releaseStringWriter(writer);
+
+            return result;
+        }
+
+        function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
+            let writer = getSingleLineStringWriter();
+            getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+
+            let result = writer.string();
+            releaseStringWriter(writer);
+
+            let maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100;
+            if (maxLength && result.length >= maxLength) {
+                result = result.substr(0, maxLength - "...".length) + "...";
+            }
+
+            return result;
+        }
+
+        function getTypeAliasForTypeLiteral(type: Type): Symbol {
+            if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral) {
+                let node = type.symbol.declarations[0].parent;
+                while (node.kind === SyntaxKind.ParenthesizedType) {
+                    node = node.parent;
+                }
+                if (node.kind === SyntaxKind.TypeAliasDeclaration) {
+                    return getSymbolOfNode(node);
+                }
+            }
+            return undefined;
+        }
+
+        // This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
+        let _displayBuilder: SymbolDisplayBuilder;
+        function getSymbolDisplayBuilder(): SymbolDisplayBuilder {
+            /**
+             * Writes only the name of the symbol out to the writer. Uses the original source text
+             * for the name of the symbol if it is available to match how the user inputted the name.
+             */
+            function appendSymbolNameOnly(symbol: Symbol, writer: SymbolWriter): void {
+                if (symbol.declarations && symbol.declarations.length > 0) {
+                    let declaration = symbol.declarations[0];
+                    if (declaration.name) {
+                        writer.writeSymbol(declarationNameToString(declaration.name), symbol);
+                        return;
+                    }
+                }
+
+                writer.writeSymbol(symbol.name, symbol);
+            }
+
+            /**
+             * Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
+             * Meaning needs to be specified if the enclosing declaration is given
+             */
+            function buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags, typeFlags?: TypeFormatFlags): void {
+                let parentSymbol: Symbol;
+                function appendParentTypeArgumentsAndSymbolName(symbol: Symbol): void {
+                    if (parentSymbol) {
+                        // Write type arguments of instantiated class/interface here
+                        if (flags & SymbolFormatFlags.WriteTypeParametersOrArguments) {
+                            if (symbol.flags & SymbolFlags.Instantiated) {
+                                buildDisplayForTypeArgumentsAndDelimiters(getTypeParametersOfClassOrInterface(parentSymbol),
+                                    (<TransientSymbol>symbol).mapper, writer, enclosingDeclaration);
+                            }
+                            else {
+                                buildTypeParameterDisplayFromSymbol(parentSymbol, writer, enclosingDeclaration);
+                            }
+                        }
+                        writePunctuation(writer, SyntaxKind.DotToken);
+                    }
+                    parentSymbol = symbol;
+                    appendSymbolNameOnly(symbol, writer);
+                }
+
+                // Let the writer know we just wrote out a symbol.  The declaration emitter writer uses
+                // this to determine if an import it has previously seen (and not written out) needs
+                // to be written to the file once the walk of the tree is complete.
+                //
+                // NOTE(cyrusn): This approach feels somewhat unfortunate.  A simple pass over the tree
+                // up front (for example, during checking) could determine if we need to emit the imports
+                // and we could then access that data during declaration emit.
+                writer.trackSymbol(symbol, enclosingDeclaration, meaning);
+                function walkSymbol(symbol: Symbol, meaning: SymbolFlags): void {
+                    if (symbol) {
+                        let accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & SymbolFormatFlags.UseOnlyExternalAliasing));
+
+                        if (!accessibleSymbolChain ||
+                            needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
+
+                            // Go up and add our parent.
+                            walkSymbol(
+                                getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol),
+                                getQualifiedLeftMeaning(meaning));
+                        }
+
+                        if (accessibleSymbolChain) {
+                            for (let accessibleSymbol of accessibleSymbolChain) {
+                                appendParentTypeArgumentsAndSymbolName(accessibleSymbol);
+                            }
+                        }
+                        else {
+                            // If we didn't find accessible symbol chain for this symbol, break if this is external module
+                            if (!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) {
+                                return;
+                            }
+
+                            // if this is anonymous type break
+                            if (symbol.flags & SymbolFlags.TypeLiteral || symbol.flags & SymbolFlags.ObjectLiteral) {
+                                return;
+                            }
+
+                            appendParentTypeArgumentsAndSymbolName(symbol);
+                        }
+                    }
+                }
+
+                // Get qualified name if the symbol is not a type parameter
+                // and there is an enclosing declaration or we specifically
+                // asked for it
+                let isTypeParameter = symbol.flags & SymbolFlags.TypeParameter;
+                let typeFormatFlag = TypeFormatFlags.UseFullyQualifiedType & typeFlags;
+                if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) {
+                    walkSymbol(symbol, meaning);
+                    return;
+                }
+
+                return appendParentTypeArgumentsAndSymbolName(symbol);
+            }
+
+            function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, typeStack?: Type[]) {
+                let globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike;
+                return writeType(type, globalFlags);
+
+                function writeType(type: Type, flags: TypeFormatFlags) {
+                    // Write undefined/null type as any
+                    if (type.flags & TypeFlags.Intrinsic) {
+                        // Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
+                        writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) &&
+                            (type.flags & TypeFlags.Any) ? "any" : (<IntrinsicType>type).intrinsicName);
+                    }
+                    else if (type.flags & TypeFlags.Reference) {
+                        writeTypeReference(<TypeReference>type, flags);
+                    }
+                    else if (type.flags & (TypeFlags.Class | TypeFlags.Interface | TypeFlags.Enum | TypeFlags.TypeParameter)) {
+                        // The specified symbol flags need to be reinterpreted as type flags
+                        buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
+                    }
+                    else if (type.flags & TypeFlags.Tuple) {
+                        writeTupleType(<TupleType>type);
+                    }
+                    else if (type.flags & TypeFlags.Union) {
+                        writeUnionType(<UnionType>type, flags);
+                    }
+                    else if (type.flags & TypeFlags.Anonymous) {
+                        writeAnonymousType(<ObjectType>type, flags);
+                    }
+                    else if (type.flags & TypeFlags.StringLiteral) {
+                        writer.writeStringLiteral((<StringLiteralType>type).text);
+                    }
+                    else {
+                        // Should never get here
+                        // { ... }
+                        writePunctuation(writer, SyntaxKind.OpenBraceToken);
+                        writeSpace(writer);
+                        writePunctuation(writer, SyntaxKind.DotDotDotToken);
+                        writeSpace(writer);
+                        writePunctuation(writer, SyntaxKind.CloseBraceToken);
+                    }
+                }
+
+                function writeTypeList(types: Type[], union: boolean) {
+                    for (let i = 0; i < types.length; i++) {
+                        if (i > 0) {
+                            if (union) {
+                                writeSpace(writer);
+                            }
+                            writePunctuation(writer, union ? SyntaxKind.BarToken : SyntaxKind.CommaToken);
+                            writeSpace(writer);
+                        }
+                        writeType(types[i], union ? TypeFormatFlags.InElementType : TypeFormatFlags.None);
+                    }
+                }
+
+                function writeTypeReference(type: TypeReference, flags: TypeFormatFlags) {
+                    if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) {
+                        writeType(type.typeArguments[0], TypeFormatFlags.InElementType);
+                        writePunctuation(writer, SyntaxKind.OpenBracketToken);
+                        writePunctuation(writer, SyntaxKind.CloseBracketToken);
+                    }
+                    else {
+                        buildSymbolDisplay(type.target.symbol, writer, enclosingDeclaration, SymbolFlags.Type);
+                        writePunctuation(writer, SyntaxKind.LessThanToken);
+                        writeTypeList(type.typeArguments, /*union*/ false);
+                        writePunctuation(writer, SyntaxKind.GreaterThanToken);
+                    }
+                }
+
+                function writeTupleType(type: TupleType) {
+                    writePunctuation(writer, SyntaxKind.OpenBracketToken);
+                    writeTypeList(type.elementTypes, /*union*/ false);
+                    writePunctuation(writer, SyntaxKind.CloseBracketToken);
+                }
+
+                function writeUnionType(type: UnionType, flags: TypeFormatFlags) {
+                    if (flags & TypeFormatFlags.InElementType) {
+                        writePunctuation(writer, SyntaxKind.OpenParenToken);
+                    }
+                    writeTypeList(type.types, /*union*/ true);
+                    if (flags & TypeFormatFlags.InElementType) {
+                        writePunctuation(writer, SyntaxKind.CloseParenToken);
+                    }
+                }
+
+                function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) {
+                    // Always use 'typeof T' for type of class, enum, and module objects
+                    if (type.symbol && type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
+                        writeTypeofSymbol(type, flags);
+                    }
+                    // Use 'typeof T' for types of functions and methods that circularly reference themselves
+                    else if (shouldWriteTypeOfFunctionSymbol()) {
+                        writeTypeofSymbol(type, flags);
+                    }
+                    else if (typeStack && contains(typeStack, type)) {
+                        // If type is an anonymous type literal in a type alias declaration, use type alias name
+                        let typeAlias = getTypeAliasForTypeLiteral(type);
+                        if (typeAlias) {
+                            // The specified symbol flags need to be reinterpreted as type flags
+                            buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
+                        }
+                        else {
+                            // Recursive usage, use any
+                            writeKeyword(writer, SyntaxKind.AnyKeyword);
+                        }
+                    }
+                    else {
+                        if (!typeStack) {
+                            typeStack = [];
+                        }
+                        typeStack.push(type);
+                        writeLiteralType(type, flags);
+                        typeStack.pop();
+                    }
+
+                    function shouldWriteTypeOfFunctionSymbol() {
+                        if (type.symbol) {
+                            let isStaticMethodSymbol = !!(type.symbol.flags & SymbolFlags.Method &&  // typeof static method
+                                ts.forEach(type.symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
+                            let isNonLocalFunctionSymbol = !!(type.symbol.flags & SymbolFlags.Function) &&
+                                (type.symbol.parent || // is exported function symbol
+                                    ts.forEach(type.symbol.declarations, declaration =>
+                                        declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
+
+                            if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
+                                // typeof is allowed only for static/non local functions
+                                return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
+                                    (typeStack && contains(typeStack, type)); // it is type of the symbol uses itself recursively
+                            }
+                        }
+                    }
+                }
+
+                function writeTypeofSymbol(type: ObjectType, typeFormatFlags?: TypeFormatFlags) {
+                    writeKeyword(writer, SyntaxKind.TypeOfKeyword);
+                    writeSpace(writer);
+                    buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Value, SymbolFormatFlags.None, typeFormatFlags);
+                }
+
+                function getIndexerParameterName(type: ObjectType, indexKind: IndexKind, fallbackName: string): string {
+                    let declaration = <SignatureDeclaration>getIndexDeclarationOfSymbol(type.symbol, indexKind);
+                    if (!declaration) {
+                        // declaration might not be found if indexer was added from the contextual type.
+                        // in this case use fallback name
+                        return fallbackName;
+                    }
+                    Debug.assert(declaration.parameters.length !== 0);
+                    return declarationNameToString(declaration.parameters[0].name);
+                }
+
+                function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) {
+                    let resolved = resolveObjectOrUnionTypeMembers(type);
+                    if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) {
+                        if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
+                            writePunctuation(writer, SyntaxKind.OpenBraceToken);
+                            writePunctuation(writer, SyntaxKind.CloseBraceToken);
+                            return;
+                        }
+
+                        if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
+                            if (flags & TypeFormatFlags.InElementType) {
+                                writePunctuation(writer, SyntaxKind.OpenParenToken);
+                            }
+                            buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack);
+                            if (flags & TypeFormatFlags.InElementType) {
+                                writePunctuation(writer, SyntaxKind.CloseParenToken);
+                            }
+                            return;
+                        }
+                        if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
+                            if (flags & TypeFormatFlags.InElementType) {
+                                writePunctuation(writer, SyntaxKind.OpenParenToken);
+                            }
+                            writeKeyword(writer, SyntaxKind.NewKeyword);
+                            writeSpace(writer);
+                            buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack);
+                            if (flags & TypeFormatFlags.InElementType) {
+                                writePunctuation(writer, SyntaxKind.CloseParenToken);
+                            }
+                            return;
+                        }
+                    }
+
+                    writePunctuation(writer, SyntaxKind.OpenBraceToken);
+                    writer.writeLine();
+                    writer.increaseIndent();
+                    for (let signature of resolved.callSignatures) {
+                        buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
+                        writePunctuation(writer, SyntaxKind.SemicolonToken);
+                        writer.writeLine();
+                    }
+                    for (let signature of resolved.constructSignatures) {
+                        writeKeyword(writer, SyntaxKind.NewKeyword);
+                        writeSpace(writer);
+
+                        buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
+                        writePunctuation(writer, SyntaxKind.SemicolonToken);
+                        writer.writeLine();
+                    }
+                    if (resolved.stringIndexType) {
+                        // [x: string]:
+                        writePunctuation(writer, SyntaxKind.OpenBracketToken);
+                        writer.writeParameter(getIndexerParameterName(resolved, IndexKind.String, /*fallbackName*/"x"));
+                        writePunctuation(writer, SyntaxKind.ColonToken);
+                        writeSpace(writer);
+                        writeKeyword(writer, SyntaxKind.StringKeyword);
+                        writePunctuation(writer, SyntaxKind.CloseBracketToken);
+                        writePunctuation(writer, SyntaxKind.ColonToken);
+                        writeSpace(writer);
+                        writeType(resolved.stringIndexType, TypeFormatFlags.None);
+                        writePunctuation(writer, SyntaxKind.SemicolonToken);
+                        writer.writeLine();
+                    }
+                    if (resolved.numberIndexType) {
+                        // [x: number]:
+                        writePunctuation(writer, SyntaxKind.OpenBracketToken);
+                        writer.writeParameter(getIndexerParameterName(resolved, IndexKind.Number, /*fallbackName*/"x"));
+                        writePunctuation(writer, SyntaxKind.ColonToken);
+                        writeSpace(writer);
+                        writeKeyword(writer, SyntaxKind.NumberKeyword);
+                        writePunctuation(writer, SyntaxKind.CloseBracketToken);
+                        writePunctuation(writer, SyntaxKind.ColonToken);
+                        writeSpace(writer);
+                        writeType(resolved.numberIndexType, TypeFormatFlags.None);
+                        writePunctuation(writer, SyntaxKind.SemicolonToken);
+                        writer.writeLine();
+                    }
+                    for (let p of resolved.properties) {
+                        let t = getTypeOfSymbol(p);
+                        if (p.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(t).length) {
+                            let signatures = getSignaturesOfType(t, SignatureKind.Call);
+                            for (let signature of signatures) {
+                                buildSymbolDisplay(p, writer);
+                                if (p.flags & SymbolFlags.Optional) {
+                                    writePunctuation(writer, SyntaxKind.QuestionToken);
+                                }
+                                buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
+                                writePunctuation(writer, SyntaxKind.SemicolonToken);
+                                writer.writeLine();
+                            }
+                        }
+                        else {
+                            buildSymbolDisplay(p, writer);
+                            if (p.flags & SymbolFlags.Optional) {
+                                writePunctuation(writer, SyntaxKind.QuestionToken);
+                            }
+                            writePunctuation(writer, SyntaxKind.ColonToken);
+                            writeSpace(writer);
+                            writeType(t, TypeFormatFlags.None);
+                            writePunctuation(writer, SyntaxKind.SemicolonToken);
+                            writer.writeLine();
+                        }
+                    }
+                    writer.decreaseIndent();
+                    writePunctuation(writer, SyntaxKind.CloseBraceToken);
+                }
+            }
+
+            function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags) {
+                let targetSymbol = getTargetSymbol(symbol);
+                if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface) {
+                    buildDisplayForTypeParametersAndDelimiters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
+                }
+            }
+
+            function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
+                appendSymbolNameOnly(tp.symbol, writer);
+                let constraint = getConstraintOfTypeParameter(tp);
+                if (constraint) {
+                    writeSpace(writer);
+                    writeKeyword(writer, SyntaxKind.ExtendsKeyword);
+                    writeSpace(writer);
+                    buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, typeStack);
+                }
+            }
+
+            function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
+                if (hasDotDotDotToken(p.valueDeclaration)) {
+                    writePunctuation(writer, SyntaxKind.DotDotDotToken);
+                }
+                appendSymbolNameOnly(p, writer);
+                if (hasQuestionToken(p.valueDeclaration) || (<ParameterDeclaration>p.valueDeclaration).initializer) {
+                    writePunctuation(writer, SyntaxKind.QuestionToken);
+                }
+                writePunctuation(writer, SyntaxKind.ColonToken);
+                writeSpace(writer);
+
+                buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
+            }
+
+            function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
+                if (typeParameters && typeParameters.length) {
+                    writePunctuation(writer, SyntaxKind.LessThanToken);
+                    for (let i = 0; i < typeParameters.length; i++) {
+                        if (i > 0) {
+                            writePunctuation(writer, SyntaxKind.CommaToken);
+                            writeSpace(writer);
+                        }
+                        buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, typeStack);
+                    }
+                    writePunctuation(writer, SyntaxKind.GreaterThanToken);
+                }
+            }
+
+            function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
+                if (typeParameters && typeParameters.length) {
+                    writePunctuation(writer, SyntaxKind.LessThanToken);
+                    for (let i = 0; i < typeParameters.length; i++) {
+                        if (i > 0) {
+                            writePunctuation(writer, SyntaxKind.CommaToken);
+                            writeSpace(writer);
+                        }
+                        buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, TypeFormatFlags.None);
+                    }
+                    writePunctuation(writer, SyntaxKind.GreaterThanToken);
+                }
+            }
+
+            function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
+                writePunctuation(writer, SyntaxKind.OpenParenToken);
+                for (let i = 0; i < parameters.length; i++) {
+                    if (i > 0) {
+                        writePunctuation(writer, SyntaxKind.CommaToken);
+                        writeSpace(writer);
+                    }
+                    buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack);
+                }
+                writePunctuation(writer, SyntaxKind.CloseParenToken);
+            }
+
+            function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
+                if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
+                    writeSpace(writer);
+                    writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken);
+                }
+                else {
+                    writePunctuation(writer, SyntaxKind.ColonToken);
+                }
+                writeSpace(writer);
+                buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack);
+            }
+
+            function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
+                if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
+                    // Instantiated signature, write type arguments instead
+                    // This is achieved by passing in the mapper separately
+                    buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
+                }
+                else {
+                    buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
+                }
+
+                buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack);
+                buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack);
+            }
+
+            return _displayBuilder || (_displayBuilder = {
+                symbolToString: symbolToString,
+                typeToString: typeToString,
+                buildSymbolDisplay: buildSymbolDisplay,
+                buildTypeDisplay: buildTypeDisplay,
+                buildTypeParameterDisplay: buildTypeParameterDisplay,
+                buildParameterDisplay: buildParameterDisplay,
+                buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
+                buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
+                buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
+                buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
+                buildSignatureDisplay: buildSignatureDisplay,
+                buildReturnTypeDisplay: buildReturnTypeDisplay
+            });
+        }
+
+        function isDeclarationVisible(node: Declaration): boolean {
+            function getContainingExternalModule(node: Node) {
+                for (; node; node = node.parent) {
+                    if (node.kind === SyntaxKind.ModuleDeclaration) {
+                        if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral) {
+                            return node;
+                        }
+                    }
+                    else if (node.kind === SyntaxKind.SourceFile) {
+                        return isExternalModule(<SourceFile>node) ? node : undefined;
+                    }
+                }
+                Debug.fail("getContainingModule cant reach here");
+            }
+
+            function isUsedInExportAssignment(node: Node) {
+                // Get source File and see if it is external module and has export assigned symbol
+                let externalModule = getContainingExternalModule(node);
+                let exportAssignmentSymbol: Symbol;
+                let resolvedExportSymbol: Symbol;
+                if (externalModule) {
+                    // This is export assigned symbol node
+                    let externalModuleSymbol = getSymbolOfNode(externalModule);
+                    exportAssignmentSymbol = getExportAssignmentSymbol(externalModuleSymbol);
+                    let symbolOfNode = getSymbolOfNode(node);
+                    if (isSymbolUsedInExportAssignment(symbolOfNode)) {
+                        return true;
+                    }
+
+                    // if symbolOfNode is alias declaration, resolve the symbol declaration and check
+                    if (symbolOfNode.flags & SymbolFlags.Alias) {
+                        return isSymbolUsedInExportAssignment(resolveAlias(symbolOfNode));
+                    }
+                }
+
+                // Check if the symbol is used in export assignment
+                function isSymbolUsedInExportAssignment(symbol: Symbol) {
+                    if (exportAssignmentSymbol === symbol) {
+                        return true;
+                    }
+
+                    if (exportAssignmentSymbol && !!(exportAssignmentSymbol.flags & SymbolFlags.Alias)) {
+                        // if export assigned symbol is alias declaration, resolve the alias
+                        resolvedExportSymbol = resolvedExportSymbol || resolveAlias(exportAssignmentSymbol);
+                        if (resolvedExportSymbol === symbol) {
+                            return true;
+                        }
+
+                        // Container of resolvedExportSymbol is visible
+                        return forEach(resolvedExportSymbol.declarations, (current: Node) => {
+                            while (current) {
+                                if (current === node) {
+                                    return true;
+                                }
+                                current = current.parent;
+                            }
+                        });
+                    }
+                }
+            }
+
+            function determineIfDeclarationIsVisible() {
+                switch (node.kind) {
+                    case SyntaxKind.BindingElement:
+                        return isDeclarationVisible(<Declaration>node.parent.parent);
+                    case SyntaxKind.VariableDeclaration:
+                        if (isBindingPattern(node.name) &&
+                            !(<BindingPattern>node.name).elements.length) {
+                            // If the binding pattern is empty, this variable declaration is not visible
+                            return false;
+                        }
+                        // Otherwise fall through
+                    case SyntaxKind.ModuleDeclaration:
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.TypeAliasDeclaration:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.ImportEqualsDeclaration:
+                        let parent = getDeclarationContainer(node);
+                        // If the node is not exported or it is not ambient module element (except import declaration)
+                        if (!(getCombinedNodeFlags(node) & NodeFlags.Export) &&
+                            !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) {
+                            return isGlobalSourceFile(parent);
+                        }
+                        // Exported members/ambient module elements (exception import declaration) are visible if parent is visible
+                        return isDeclarationVisible(<Declaration>parent);
+
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                        if (node.flags & (NodeFlags.Private | NodeFlags.Protected)) {
+                            // Private/protected properties/methods are not visible
+                            return false;
+                        }
+                    // Public properties/methods are visible if its parents are visible, so let it fall into next case statement
+
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.ConstructSignature:
+                    case SyntaxKind.CallSignature:
+                    case SyntaxKind.IndexSignature:
+                    case SyntaxKind.Parameter:
+                    case SyntaxKind.ModuleBlock:
+                    case SyntaxKind.FunctionType:
+                    case SyntaxKind.ConstructorType:
+                    case SyntaxKind.TypeLiteral:
+                    case SyntaxKind.TypeReference:
+                    case SyntaxKind.ArrayType:
+                    case SyntaxKind.TupleType:
+                    case SyntaxKind.UnionType:
+                    case SyntaxKind.ParenthesizedType:
+                        return isDeclarationVisible(<Declaration>node.parent);
+
+                    // Default binding, import specifier and namespace import is visible 
+                    // only on demand so by default it is not visible
+                    case SyntaxKind.ImportClause:
+                    case SyntaxKind.NamespaceImport:
+                    case SyntaxKind.ImportSpecifier:
+                        return false;
+
+                    // Type parameters are always visible
+                    case SyntaxKind.TypeParameter:
+                    // Source file is always visible
+                    case SyntaxKind.SourceFile:
+                        return true;
+
+                    // Export assignements do not create name bindings outside the module
+                    case SyntaxKind.ExportAssignment:
+                        return false;
+
+                    default:
+                        Debug.fail("isDeclarationVisible unknown: SyntaxKind: " + node.kind);
+                }
+            }
+
+            if (node) {
+                let links = getNodeLinks(node);
+                if (links.isVisible === undefined) {
+                    links.isVisible = !!determineIfDeclarationIsVisible();
+                }
+                return links.isVisible;
+            }
+        }
+
+        function collectLinkedAliases(node: Identifier): Node[]{
+            var exportSymbol: Symbol;
+            if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) {
+                exportSymbol = resolveName(node.parent, node.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, Diagnostics.Cannot_find_name_0, node);
+            }
+            else if (node.parent.kind === SyntaxKind.ExportSpecifier) {
+                exportSymbol = getTargetOfExportSpecifier(<ExportSpecifier>node.parent);
+            }
+            var result: Node[] = [];
+            if (exportSymbol) {
+                buildVisibleNodeList(exportSymbol.declarations);
+            }
+            return result;
+
+            function buildVisibleNodeList(declarations: Declaration[]) {
+                forEach(declarations, declaration => {
+                    getNodeLinks(declaration).isVisible = true;
+                    var resultNode = getAnyImportSyntax(declaration) || declaration;
+                    if (!contains(result, resultNode)) {
+                        result.push(resultNode);
+                    }
+
+                    if (isInternalModuleImportEqualsDeclaration(declaration)) {
+                        // Add the referenced top container visible
+                        var internalModuleReference = <Identifier | QualifiedName>(<ImportEqualsDeclaration>declaration).moduleReference;
+                        var firstIdentifier = getFirstIdentifier(internalModuleReference);
+                        var importSymbol = resolveName(declaration, firstIdentifier.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace,
+                            Diagnostics.Cannot_find_name_0, firstIdentifier);
+                        buildVisibleNodeList(importSymbol.declarations);
+                    }
+                });
+            }
+        }
+
+        function getRootDeclaration(node: Node): Node {
+            while (node.kind === SyntaxKind.BindingElement) {
+                node = node.parent.parent;
+            }
+            return node;
+        }
+
+        function getDeclarationContainer(node: Node): Node {
+            node = getRootDeclaration(node);
+
+            // Parent chain:
+            // VaribleDeclaration -> VariableDeclarationList -> VariableStatement -> 'Declaration Container'
+            return node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent.parent : node.parent;
+        }
+
+        function getTypeOfPrototypeProperty(prototype: Symbol): Type {
+            // TypeScript 1.0 spec (April 2014): 8.4
+            // Every class automatically contains a static property member named 'prototype',
+            // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
+            // It is an error to explicitly declare a static property member with the name 'prototype'.
+            let classType = <InterfaceType>getDeclaredTypeOfSymbol(prototype.parent);
+            return classType.typeParameters ? createTypeReference(<GenericType>classType, map(classType.typeParameters, _ => anyType)) : classType;
+        }
+
+        // Return the type of the given property in the given type, or undefined if no such property exists
+        function getTypeOfPropertyOfType(type: Type, name: string): Type {
+            let prop = getPropertyOfType(type, name);
+            return prop ? getTypeOfSymbol(prop) : undefined;
+        }
+
+        // Return the inferred type for a binding element
+        function getTypeForBindingElement(declaration: BindingElement): Type {
+            let pattern = <BindingPattern>declaration.parent;
+            let parentType = getTypeForVariableLikeDeclaration(<VariableLikeDeclaration>pattern.parent);
+            // If parent has the unknown (error) type, then so does this binding element
+            if (parentType === unknownType) {
+                return unknownType;
+            }
+            // If no type was specified or inferred for parent, or if the specified or inferred type is any,
+            // infer from the initializer of the binding element if one is present. Otherwise, go with the
+            // undefined or any type of the parent.
+            if (!parentType || parentType === anyType) {
+                if (declaration.initializer) {
+                    return checkExpressionCached(declaration.initializer);
+                }
+                return parentType;
+            }
+
+            let type: Type;
+            if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
+                // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
+                let name = declaration.propertyName || <Identifier>declaration.name;
+                // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
+                // or otherwise the type of the string index signature.
+                type = getTypeOfPropertyOfType(parentType, name.text) ||
+                    isNumericLiteralName(name.text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
+                    getIndexTypeOfType(parentType, IndexKind.String);
+                if (!type) {
+                    error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), declarationNameToString(name));
+                    return unknownType;
+                }
+            }
+            else {
+                // This elementType will be used if the specific property corresponding to this index is not
+                // present (aka the tuple element property). This call also checks that the parentType is in
+                // fact an iterable or array (depending on target language).
+                let elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false);
+                if (!declaration.dotDotDotToken) {
+                    if (elementType.flags & TypeFlags.Any) {
+                        return elementType;
+                    }
+
+                    // Use specific property type when parent is a tuple or numeric index type when parent is an array
+                    let propName = "" + indexOf(pattern.elements, declaration);
+                    type = isTupleLikeType(parentType)
+                        ? getTypeOfPropertyOfType(parentType, propName)
+                        : elementType;
+                    if (!type) {
+                        if (isTupleType(parentType)) {
+                            error(declaration, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(parentType), (<TupleType>parentType).elementTypes.length, pattern.elements.length);
+                        }
+                        else {
+                            error(declaration, Diagnostics.Type_0_has_no_property_1, typeToString(parentType), propName);
+                        }
+                        return unknownType;
+                    }
+                }
+                else {
+                    // Rest element has an array type with the same element type as the parent type
+                    type = createArrayType(elementType);
+                }
+            }
+            return type;
+        }
+
+        // Return the inferred type for a variable, parameter, or property declaration
+        function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): Type {
+            // A variable declared in a for..in statement is always of type any
+            if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
+                return anyType;
+            }
+            if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
+                // checkRightHandSideOfForOf will return undefined if the for-of expression type was
+                // missing properties/signatures required to get its iteratedType (like
+                // [Symbol.iterator] or next). This may be because we accessed properties from anyType,
+                // or it may have led to an error inside getIteratedType.
+                return checkRightHandSideOfForOf((<ForOfStatement>declaration.parent.parent).expression) || anyType;
+            }
+            if (isBindingPattern(declaration.parent)) {
+                return getTypeForBindingElement(<BindingElement>declaration);
+            }
+            // Use type from type annotation if one is present
+            if (declaration.type) {
+                return getTypeFromTypeNode(declaration.type);
+            }
+            if (declaration.kind === SyntaxKind.Parameter) {
+                let func = <FunctionLikeDeclaration>declaration.parent;
+                // For a parameter of a set accessor, use the type of the get accessor if one is present
+                if (func.kind === SyntaxKind.SetAccessor && !hasDynamicName(func)) {
+                    let getter = <AccessorDeclaration>getDeclarationOfKind(declaration.parent.symbol, SyntaxKind.GetAccessor);
+                    if (getter) {
+                        return getReturnTypeOfSignature(getSignatureFromDeclaration(getter));
+                    }
+                }
+                // Use contextual parameter type if one is available
+                let type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
+                if (type) {
+                    return type;
+                }
+            }
+            // Use the type of the initializer expression if one is present
+            if (declaration.initializer) {
+                return checkExpressionCached(declaration.initializer);
+            }
+            // If it is a short-hand property assignment, use the type of the identifier
+            if (declaration.kind === SyntaxKind.ShorthandPropertyAssignment) {
+                return checkIdentifier(<Identifier>declaration.name);
+            }
+            // No type specified and nothing can be inferred
+            return undefined;
+        }
+
+        // Return the type implied by a binding pattern element. This is the type of the initializer of the element if
+        // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding
+        // pattern. Otherwise, it is the type any.
+        function getTypeFromBindingElement(element: BindingElement): Type {
+            if (element.initializer) {
+                return getWidenedType(checkExpressionCached(element.initializer));
+            }
+            if (isBindingPattern(element.name)) {
+                return getTypeFromBindingPattern(<BindingPattern>element.name);
+            }
+            return anyType;
+        }
+
+        // Return the type implied by an object binding pattern
+        function getTypeFromObjectBindingPattern(pattern: BindingPattern): Type {
+            let members: SymbolTable = {};
+            forEach(pattern.elements, e => {
+                let flags = SymbolFlags.Property | SymbolFlags.Transient | (e.initializer ? SymbolFlags.Optional : 0);
+                let name = e.propertyName || <Identifier>e.name;
+                let symbol = <TransientSymbol>createSymbol(flags, name.text);
+                symbol.type = getTypeFromBindingElement(e);
+                members[symbol.name] = symbol;
+            });
+            return createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
+        }
+
+        // Return the type implied by an array binding pattern
+        function getTypeFromArrayBindingPattern(pattern: BindingPattern): Type {
+            let hasSpreadElement: boolean = false;
+            let elementTypes: Type[] = [];
+            forEach(pattern.elements, e => {
+                elementTypes.push(e.kind === SyntaxKind.OmittedExpression || e.dotDotDotToken ? anyType : getTypeFromBindingElement(e));
+                if (e.dotDotDotToken) {
+                    hasSpreadElement = true;
+                }
+            });
+            if (!elementTypes.length) {
+                return languageVersion >= ScriptTarget.ES6 ? createIterableType(anyType) : anyArrayType;
+            }
+            else if (hasSpreadElement) {
+                let unionOfElements = getUnionType(elementTypes);
+                return languageVersion >= ScriptTarget.ES6 ? createIterableType(unionOfElements) : createArrayType(unionOfElements);
+            }
+
+            // If the pattern has at least one element, and no rest element, then it should imply a tuple type.
+            return createTupleType(elementTypes);
+        }
+
+        // Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself
+        // and without regard to its context (i.e. without regard any type annotation or initializer associated with the
+        // declaration in which the binding pattern is contained). For example, the implied type of [x, y] is [any, any]
+        // and the implied type of { x, y: z = 1 } is { x: any; y: number; }. The type implied by a binding pattern is
+        // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring
+        // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of
+        // the parameter.
+        function getTypeFromBindingPattern(pattern: BindingPattern): Type {
+            return pattern.kind === SyntaxKind.ObjectBindingPattern
+                ? getTypeFromObjectBindingPattern(pattern)
+                : getTypeFromArrayBindingPattern(pattern);
+        }
+
+        // Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type
+        // specified in a type annotation or inferred from an initializer. However, in the case of a destructuring declaration it
+        // is a bit more involved. For example:
+        //
+        //   var [x, s = ""] = [1, "one"];
+        //
+        // Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the
+        // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the
+        // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string.
+        function getWidenedTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, reportErrors?: boolean): Type {
+            let type = getTypeForVariableLikeDeclaration(declaration);
+            if (type) {
+                if (reportErrors) {
+                    reportErrorsFromWidening(declaration, type);
+                }
+                // During a normal type check we'll never get to here with a property assignment (the check of the containing
+                // object literal uses a different path). We exclude widening only so that language services and type verification
+                // tools see the actual type.
+                return declaration.kind !== SyntaxKind.PropertyAssignment ? getWidenedType(type) : type;
+            }
+            // If no type was specified and nothing could be inferred, and if the declaration specifies a binding pattern, use
+            // the type implied by the binding pattern
+            if (isBindingPattern(declaration.name)) {
+                return getTypeFromBindingPattern(<BindingPattern>declaration.name);
+            }
+            // Rest parameters default to type any[], other parameters default to type any
+            type = declaration.dotDotDotToken ? anyArrayType : anyType;
+            // Report implicit any errors unless this is a private property within an ambient declaration
+            if (reportErrors && compilerOptions.noImplicitAny) {
+                let root = getRootDeclaration(declaration);
+                if (!isPrivateWithinAmbient(root) && !(root.kind === SyntaxKind.Parameter && isPrivateWithinAmbient(root.parent))) {
+                    reportImplicitAnyError(declaration, type);
+                }
+            }
+            return type;
+        }
+
+        function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.type) {
+                // Handle prototype property
+                if (symbol.flags & SymbolFlags.Prototype) {
+                    return links.type = getTypeOfPrototypeProperty(symbol);
+                }
+                // Handle catch clause variables
+                let declaration = symbol.valueDeclaration;
+                if (declaration.parent.kind === SyntaxKind.CatchClause) {
+                    return links.type = anyType;
+                }
+                // Handle export default expressions
+                if (declaration.kind === SyntaxKind.ExportAssignment) {
+                    return links.type = checkExpression((<ExportAssignment>declaration).expression);
+                }
+                // Handle variable, parameter or property
+                links.type = resolvingType;
+                let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
+                if (links.type === resolvingType) {
+                    links.type = type;
+                }
+            }
+            else if (links.type === resolvingType) {
+                links.type = anyType;
+                if (compilerOptions.noImplicitAny) {
+                    let diagnostic = (<VariableLikeDeclaration>symbol.valueDeclaration).type ?
+                        Diagnostics._0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation :
+                        Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer;
+                    error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
+                }
+            }
+            return links.type;
+        }
+
+        function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode {
+            return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
+        }
+
+        function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type {
+            if (accessor) {
+                if (accessor.kind === SyntaxKind.GetAccessor) {
+                    return accessor.type && getTypeFromTypeNode(accessor.type);
+                }
+                else {
+                    let setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor);
+                    return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
+                }
+            }
+            return undefined;
+        }
+
+        function getTypeOfAccessors(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            checkAndStoreTypeOfAccessors(symbol, links);
+            return links.type;
+        }
+
+        function checkAndStoreTypeOfAccessors(symbol: Symbol, links?: SymbolLinks) {
+            links = links || getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = resolvingType;
+                let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
+                let setter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.SetAccessor);
+
+                let type: Type;
+
+                // First try to see if the user specified a return type on the get-accessor.
+                let getterReturnType = getAnnotatedAccessorType(getter);
+                if (getterReturnType) {
+                    type = getterReturnType;
+                }
+                else {
+                    // If the user didn't specify a return type, try to use the set-accessor's parameter type.
+                    let setterParameterType = getAnnotatedAccessorType(setter);
+                    if (setterParameterType) {
+                        type = setterParameterType;
+                    }
+                    else {
+                        // If there are no specified types, try to infer it from the body of the get accessor if it exists.
+                        if (getter && getter.body) {
+                            type = getReturnTypeFromBody(getter);
+                        }
+                        // Otherwise, fall back to 'any'.
+                        else {
+                            if (compilerOptions.noImplicitAny) {
+                                error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
+                            }
+
+                            type = anyType;
+                        }
+                    }
+                }
+
+                if (links.type === resolvingType) {
+                    links.type = type;
+                }
+            }
+            else if (links.type === resolvingType) {
+                links.type = anyType;
+                if (compilerOptions.noImplicitAny) {
+                    let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
+                    error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
+                }
+            }
+        }
+
+        function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = createObjectType(TypeFlags.Anonymous, symbol);
+            }
+            return links.type;
+        }
+
+        function getTypeOfEnumMember(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = getDeclaredTypeOfEnum(getParentOfSymbol(symbol));
+            }
+            return links.type;
+        }
+
+        function getTypeOfAlias(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = getTypeOfSymbol(resolveAlias(symbol));
+            }
+            return links.type;
+        }
+
+        function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.type) {
+                links.type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
+            }
+            return links.type;
+        }
+
+        function getTypeOfSymbol(symbol: Symbol): Type {
+            if (symbol.flags & SymbolFlags.Instantiated) {
+                return getTypeOfInstantiatedSymbol(symbol);
+            }
+            if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
+                return getTypeOfVariableOrParameterOrProperty(symbol);
+            }
+            if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
+                return getTypeOfFuncClassEnumModule(symbol);
+            }
+            if (symbol.flags & SymbolFlags.EnumMember) {
+                return getTypeOfEnumMember(symbol);
+            }
+            if (symbol.flags & SymbolFlags.Accessor) {
+                return getTypeOfAccessors(symbol);
+            }
+            if (symbol.flags & SymbolFlags.Alias) {
+                return getTypeOfAlias(symbol);
+            }
+            return unknownType;
+        }
+
+        function getTargetType(type: ObjectType): Type {
+            return type.flags & TypeFlags.Reference ? (<TypeReference>type).target : type;
+        }
+
+        function hasBaseType(type: InterfaceType, checkBase: InterfaceType) {
+            return check(type);
+            function check(type: InterfaceType): boolean {
+                let target = <InterfaceType>getTargetType(type);
+                return target === checkBase || forEach(getBaseTypes(target), check);
+            }
+        }
+
+        // Return combined list of type parameters from all declarations of a class or interface. Elsewhere we check they're all
+        // the same, but even if they're not we still need the complete list to ensure instantiations supply type arguments
+        // for all type parameters.
+        function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] {
+            let result: TypeParameter[];
+            forEach(symbol.declarations, node => {
+                if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ClassDeclaration) {
+                    let declaration = <InterfaceDeclaration>node;
+                    if (declaration.typeParameters && declaration.typeParameters.length) {
+                        forEach(declaration.typeParameters, node => {
+                            let tp = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
+                            if (!result) {
+                                result = [tp];
+                            }
+                            else if (!contains(result, tp)) {
+                                result.push(tp);
+                            }
+                        });
+                    }
+                }
+            });
+            return result;
+        }
+
+        function getBaseTypes(type: InterfaceType): ObjectType[]{
+            let typeWithBaseTypes = <InterfaceTypeWithBaseTypes>type;
+            if (!typeWithBaseTypes.baseTypes) {
+                if (type.symbol.flags & SymbolFlags.Class) {
+                    resolveBaseTypesOfClass(typeWithBaseTypes);
+                }
+                else if (type.symbol.flags & SymbolFlags.Interface) {
+                    resolveBaseTypesOfInterface(typeWithBaseTypes);
+                }
+                else {
+                    Debug.fail("type must be class or interface");
+                }
+            }
+
+            return typeWithBaseTypes.baseTypes;
+        }
+
+        function resolveBaseTypesOfClass(type: InterfaceTypeWithBaseTypes): void {
+            type.baseTypes = [];
+            let declaration = <ClassDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration);
+            let baseTypeNode = getClassExtendsHeritageClauseElement(declaration);
+            if (baseTypeNode) {
+                let baseType = getTypeFromHeritageClauseElement(baseTypeNode);
+                if (baseType !== unknownType) {
+                    if (getTargetType(baseType).flags & TypeFlags.Class) {
+                        if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
+                            type.baseTypes.push(baseType);
+                        }
+                        else {
+                            error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
+                        }
+                    }
+                    else {
+                        error(baseTypeNode, Diagnostics.A_class_may_only_extend_another_class);
+                    }
+                }
+            }
+        }
+
+        function resolveBaseTypesOfInterface(type: InterfaceTypeWithBaseTypes): void {
+            type.baseTypes = [];
+            for (let declaration of type.symbol.declarations) {
+                if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
+                    for (let node of getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
+                        let baseType = getTypeFromHeritageClauseElement(node);
+
+                        if (baseType !== unknownType) {
+                            if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
+                                if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
+                                    type.baseTypes.push(baseType);
+                                }
+                                else {
+                                    error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
+                                }
+                            }
+                            else {
+                                error(node, Diagnostics.An_interface_may_only_extend_a_class_or_another_interface);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType {
+            let links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                let kind = symbol.flags & SymbolFlags.Class ? TypeFlags.Class : TypeFlags.Interface;
+                let type = links.declaredType = <InterfaceType>createObjectType(kind, symbol);
+                let typeParameters = getTypeParametersOfClassOrInterface(symbol);
+                if (typeParameters) {
+                    type.flags |= TypeFlags.Reference;
+                    type.typeParameters = typeParameters;
+                    (<GenericType>type).instantiations = {};
+                    (<GenericType>type).instantiations[getTypeListId(type.typeParameters)] = <GenericType>type;
+                    (<GenericType>type).target = <GenericType>type;
+                    (<GenericType>type).typeArguments = type.typeParameters;
+                }
+            }
+            return <InterfaceType>links.declaredType;
+        }
+
+        function getDeclaredTypeOfTypeAlias(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                links.declaredType = resolvingType;
+                let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
+                let type = getTypeFromTypeNode(declaration.type);
+                if (links.declaredType === resolvingType) {
+                    links.declaredType = type;
+                }
+            }
+            else if (links.declaredType === resolvingType) {
+                links.declaredType = unknownType;
+                let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
+                error(declaration.name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
+            }
+            return links.declaredType;
+        }
+
+        function getDeclaredTypeOfEnum(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                let type = createType(TypeFlags.Enum);
+                type.symbol = symbol;
+                links.declaredType = type;
+            }
+            return links.declaredType;
+        }
+
+        function getDeclaredTypeOfTypeParameter(symbol: Symbol): TypeParameter {
+            let links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                let type = <TypeParameter>createType(TypeFlags.TypeParameter);
+                type.symbol = symbol;
+                if (!(<TypeParameterDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter)).constraint) {
+                    type.constraint = noConstraintType;
+                }
+                links.declaredType = type;
+            }
+            return <TypeParameter>links.declaredType;
+        }
+
+        function getDeclaredTypeOfAlias(symbol: Symbol): Type {
+            let links = getSymbolLinks(symbol);
+            if (!links.declaredType) {
+                links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol));
+            }
+            return links.declaredType;
+        }
+
+        function getDeclaredTypeOfSymbol(symbol: Symbol): Type {
+            Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0);
+            if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
+                return getDeclaredTypeOfClassOrInterface(symbol);
+            }
+            if (symbol.flags & SymbolFlags.TypeAlias) {
+                return getDeclaredTypeOfTypeAlias(symbol);
+            }
+            if (symbol.flags & SymbolFlags.Enum) {
+                return getDeclaredTypeOfEnum(symbol);
+            }
+            if (symbol.flags & SymbolFlags.TypeParameter) {
+                return getDeclaredTypeOfTypeParameter(symbol);
+            }
+            if (symbol.flags & SymbolFlags.Alias) {
+                return getDeclaredTypeOfAlias(symbol);
+            }
+            return unknownType;
+        }
+
+        function createSymbolTable(symbols: Symbol[]): SymbolTable {
+            let result: SymbolTable = {};
+            for (let symbol of symbols) {
+                result[symbol.name] = symbol;
+            }
+            return result;
+        }
+
+        function createInstantiatedSymbolTable(symbols: Symbol[], mapper: TypeMapper): SymbolTable {
+            let result: SymbolTable = {};
+            for (let symbol of symbols) {
+                result[symbol.name] = instantiateSymbol(symbol, mapper);
+            }
+            return result;
+        }
+
+        function addInheritedMembers(symbols: SymbolTable, baseSymbols: Symbol[]) {
+            for (let s of baseSymbols) {
+                if (!hasProperty(symbols, s.name)) {
+                    symbols[s.name] = s;
+                }
+            }
+        }
+
+        function addInheritedSignatures(signatures: Signature[], baseSignatures: Signature[]) {
+            if (baseSignatures) {
+                for (let signature of baseSignatures) {
+                    signatures.push(signature);
+                }
+            }
+        }
+
+        function resolveDeclaredMembers(type: InterfaceType): InterfaceTypeWithDeclaredMembers {
+            if (!(<InterfaceTypeWithDeclaredMembers>type).declaredProperties) {
+                var symbol = type.symbol;
+                (<InterfaceTypeWithDeclaredMembers>type).declaredProperties = getNamedMembers(symbol.members);
+                (<InterfaceTypeWithDeclaredMembers>type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]);
+                (<InterfaceTypeWithDeclaredMembers>type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]);
+                (<InterfaceTypeWithDeclaredMembers>type).declaredStringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
+                (<InterfaceTypeWithDeclaredMembers>type).declaredNumberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
+            }
+            return <InterfaceTypeWithDeclaredMembers>type;
+        }
+
+        function resolveClassOrInterfaceMembers(type: InterfaceType): void {
+            let target = resolveDeclaredMembers(type);
+            let members = target.symbol.members;
+            let callSignatures = target.declaredCallSignatures;
+            let constructSignatures = target.declaredConstructSignatures;
+            let stringIndexType = target.declaredStringIndexType;
+            let numberIndexType = target.declaredNumberIndexType;
+            let baseTypes = getBaseTypes(target);
+            if (baseTypes.length) {
+                members = createSymbolTable(target.declaredProperties);
+                for (let baseType of baseTypes) {
+                    addInheritedMembers(members, getPropertiesOfObjectType(baseType));
+                    callSignatures = concatenate(callSignatures, getSignaturesOfType(baseType, SignatureKind.Call));
+                    constructSignatures = concatenate(constructSignatures, getSignaturesOfType(baseType, SignatureKind.Construct));
+                    stringIndexType = stringIndexType || getIndexTypeOfType(baseType, IndexKind.String);
+                    numberIndexType = numberIndexType || getIndexTypeOfType(baseType, IndexKind.Number);
+                }
+            }
+            setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+
+        function resolveTypeReferenceMembers(type: TypeReference): void {
+            let target = resolveDeclaredMembers(type.target);
+            let mapper = createTypeMapper(target.typeParameters, type.typeArguments);
+            let members = createInstantiatedSymbolTable(target.declaredProperties, mapper);
+            let callSignatures = instantiateList(target.declaredCallSignatures, mapper, instantiateSignature);
+            let constructSignatures = instantiateList(target.declaredConstructSignatures, mapper, instantiateSignature);
+            let stringIndexType = target.declaredStringIndexType ? instantiateType(target.declaredStringIndexType, mapper) : undefined;
+            let numberIndexType = target.declaredNumberIndexType ? instantiateType(target.declaredNumberIndexType, mapper) : undefined;
+            forEach(getBaseTypes(target), baseType => {
+                let instantiatedBaseType = instantiateType(baseType, mapper);
+                addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
+                callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
+                constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
+                stringIndexType = stringIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.String);
+                numberIndexType = numberIndexType || getIndexTypeOfType(instantiatedBaseType, IndexKind.Number);
+            });
+            setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+
+        function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[],
+            resolvedReturnType: Type, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
+            let sig = new Signature(checker);
+            sig.declaration = declaration;
+            sig.typeParameters = typeParameters;
+            sig.parameters = parameters;
+            sig.resolvedReturnType = resolvedReturnType;
+            sig.minArgumentCount = minArgumentCount;
+            sig.hasRestParameter = hasRestParameter;
+            sig.hasStringLiterals = hasStringLiterals;
+            return sig;
+        }
+
+        function cloneSignature(sig: Signature): Signature {
+            return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType,
+                sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
+        }
+
+        function getDefaultConstructSignatures(classType: InterfaceType): Signature[]{
+            let baseTypes = getBaseTypes(classType);
+            if (baseTypes.length) {
+                let baseType = baseTypes[0];
+                let baseSignatures = getSignaturesOfType(getTypeOfSymbol(baseType.symbol), SignatureKind.Construct);
+                return map(baseSignatures, baseSignature => {
+                    let signature = baseType.flags & TypeFlags.Reference ?
+                        getSignatureInstantiation(baseSignature, (<TypeReference>baseType).typeArguments) : cloneSignature(baseSignature);
+                    signature.typeParameters = classType.typeParameters;
+                    signature.resolvedReturnType = classType;
+                    return signature;
+                });
+            }
+            return [createSignature(undefined, classType.typeParameters, emptyArray, classType, 0, false, false)];
+        }
+
+        function createTupleTypeMemberSymbols(memberTypes: Type[]): SymbolTable {
+            let members: SymbolTable = {};
+            for (let i = 0; i < memberTypes.length; i++) {
+                let symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "" + i);
+                symbol.type = memberTypes[i];
+                members[i] = symbol;
+            }
+            return members;
+        }
+
+        function resolveTupleTypeMembers(type: TupleType) {
+            let arrayType = resolveObjectOrUnionTypeMembers(createArrayType(getUnionType(type.elementTypes)));
+            let members = createTupleTypeMemberSymbols(type.elementTypes);
+            addInheritedMembers(members, arrayType.properties);
+            setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
+        }
+
+        function signatureListsIdentical(s: Signature[], t: Signature[]): boolean {
+            if (s.length !== t.length) {
+                return false;
+            }
+            for (let i = 0; i < s.length; i++) {
+                if (!compareSignatures(s[i], t[i], /*compareReturnTypes*/ false, compareTypes)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // If the lists of call or construct signatures in the given types are all identical except for return types,
+        // and if none of the signatures are generic, return a list of signatures that has substitutes a union of the
+        // return types of the corresponding signatures in each resulting signature.
+        function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] {
+            let signatureLists = map(types, t => getSignaturesOfType(t, kind));
+            let signatures = signatureLists[0];
+            for (let signature of signatures) {
+                if (signature.typeParameters) {
+                    return emptyArray;
+                }
+            }
+            for (let i = 1; i < signatureLists.length; i++) {
+                if (!signatureListsIdentical(signatures, signatureLists[i])) {
+                    return emptyArray;
+                }
+            }
+            let result = map(signatures, cloneSignature);
+            for (var i = 0; i < result.length; i++) {
+                let s = result[i];
+                // Clear resolved return type we possibly got from cloneSignature
+                s.resolvedReturnType = undefined;
+                s.unionSignatures = map(signatureLists, signatures => signatures[i]);
+            }
+            return result;
+        }
+
+        function getUnionIndexType(types: Type[], kind: IndexKind): Type {
+            let indexTypes: Type[] = [];
+            for (let type of types) {
+                let indexType = getIndexTypeOfType(type, kind);
+                if (!indexType) {
+                    return undefined;
+                }
+                indexTypes.push(indexType);
+            }
+            return getUnionType(indexTypes);
+        }
+
+        function resolveUnionTypeMembers(type: UnionType) {
+            // The members and properties collections are empty for union types. To get all properties of a union
+            // type use getPropertiesOfType (only the language service uses this).
+            let callSignatures = getUnionSignatures(type.types, SignatureKind.Call);
+            let constructSignatures = getUnionSignatures(type.types, SignatureKind.Construct);
+            let stringIndexType = getUnionIndexType(type.types, IndexKind.String);
+            let numberIndexType = getUnionIndexType(type.types, IndexKind.Number);
+            setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+
+        function resolveAnonymousTypeMembers(type: ObjectType) {
+            let symbol = type.symbol;
+            let members: SymbolTable;
+            let callSignatures: Signature[];
+            let constructSignatures: Signature[];
+            let stringIndexType: Type;
+            let numberIndexType: Type;
+
+            if (symbol.flags & SymbolFlags.TypeLiteral) {
+                members = symbol.members;
+                callSignatures = getSignaturesOfSymbol(members["__call"]);
+                constructSignatures = getSignaturesOfSymbol(members["__new"]);
+                stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
+                numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
+            }
+            else {
+                // Combinations of function, class, enum and module
+                members = emptySymbols;
+                callSignatures = emptyArray;
+                constructSignatures = emptyArray;
+                if (symbol.flags & SymbolFlags.HasExports) {
+                    members = getExportsOfSymbol(symbol);
+                }
+                if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
+                    callSignatures = getSignaturesOfSymbol(symbol);
+                }
+                if (symbol.flags & SymbolFlags.Class) {
+                    let classType = getDeclaredTypeOfClassOrInterface(symbol);
+                    constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
+                    if (!constructSignatures.length) {
+                        constructSignatures = getDefaultConstructSignatures(classType);
+                    }
+                    let baseTypes = getBaseTypes(classType);
+                    if (baseTypes.length) {
+                        members = createSymbolTable(getNamedMembers(members));
+                        addInheritedMembers(members, getPropertiesOfObjectType(getTypeOfSymbol(baseTypes[0].symbol)));
+                    }
+                }
+                stringIndexType = undefined;
+                numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined;
+            }
+            setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
+        }
+
+        function resolveObjectOrUnionTypeMembers(type: ObjectType): ResolvedType {
+            if (!(<ResolvedType>type).members) {
+                if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) {
+                    resolveClassOrInterfaceMembers(<InterfaceType>type);
+                }
+                else if (type.flags & TypeFlags.Anonymous) {
+                    resolveAnonymousTypeMembers(<ObjectType>type);
+                }
+                else if (type.flags & TypeFlags.Tuple) {
+                    resolveTupleTypeMembers(<TupleType>type);
+                }
+                else if (type.flags & TypeFlags.Union) {
+                    resolveUnionTypeMembers(<UnionType>type);
+                }
+                else {
+                    resolveTypeReferenceMembers(<TypeReference>type);
+                }
+            }
+            return <ResolvedType>type;
+        }
+
+        // Return properties of an object type or an empty array for other types
+        function getPropertiesOfObjectType(type: Type): Symbol[] {
+            if (type.flags & TypeFlags.ObjectType) {
+                return resolveObjectOrUnionTypeMembers(<ObjectType>type).properties;
+            }
+            return emptyArray;
+        }
+
+        // If the given type is an object type and that type has a property by the given name, return
+        // the symbol for that property. Otherwise return undefined.
+        function getPropertyOfObjectType(type: Type, name: string): Symbol {
+            if (type.flags & TypeFlags.ObjectType) {
+                let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
+                if (hasProperty(resolved.members, name)) {
+                    let symbol = resolved.members[name];
+                    if (symbolIsValue(symbol)) {
+                        return symbol;
+                    }
+                }
+            }
+        }
+
+        function getPropertiesOfUnionType(type: UnionType): Symbol[] {
+            let result: Symbol[] = [];
+            forEach(getPropertiesOfType(type.types[0]), prop => {
+                let unionProp = getPropertyOfUnionType(type, prop.name);
+                if (unionProp) {
+                    result.push(unionProp);
+                }
+            });
+            return result;
+        }
+
+        function getPropertiesOfType(type: Type): Symbol[] {
+            type = getApparentType(type);
+            return type.flags & TypeFlags.Union ? getPropertiesOfUnionType(<UnionType>type) : getPropertiesOfObjectType(type);
+        }
+
+        // For a type parameter, return the base constraint of the type parameter. For the string, number,
+        // boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
+        // type itself. Note that the apparent type of a union type is the union type itself.
+        function getApparentType(type: Type): Type {
+            if (type.flags & TypeFlags.Union) {
+                type = getReducedTypeOfUnionType(<UnionType>type);
+            }
+            if (type.flags & TypeFlags.TypeParameter) {
+                do {
+                    type = getConstraintOfTypeParameter(<TypeParameter>type);
+                } while (type && type.flags & TypeFlags.TypeParameter);
+                if (!type) {
+                    type = emptyObjectType;
+                }
+            }
+            if (type.flags & TypeFlags.StringLike) {
+                type = globalStringType;
+            }
+            else if (type.flags & TypeFlags.NumberLike) {
+                type = globalNumberType;
+            }
+            else if (type.flags & TypeFlags.Boolean) {
+                type = globalBooleanType;
+            }
+            else if (type.flags & TypeFlags.ESSymbol) {
+                type = globalESSymbolType;
+            }
+            return type;
+        }
+
+        function createUnionProperty(unionType: UnionType, name: string): Symbol {
+            let types = unionType.types;
+            let props: Symbol[];
+            for (let current of types) {
+                let type = getApparentType(current);
+                if (type !== unknownType) {
+                    let prop = getPropertyOfType(type, name);
+                    if (!prop || getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected)) {
+                        return undefined;
+                    }
+                    if (!props) {
+                        props = [prop];
+                    }
+                    else {
+                        props.push(prop);
+                    }
+                }
+            }
+            let propTypes: Type[] = [];
+            let declarations: Declaration[] = [];
+            for (let prop of props) {
+                if (prop.declarations) {
+                    declarations.push.apply(declarations, prop.declarations);
+                }
+                propTypes.push(getTypeOfSymbol(prop));
+            }
+            let result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.UnionProperty, name);
+            result.unionType = unionType;
+            result.declarations = declarations;
+            result.type = getUnionType(propTypes);
+            return result;
+        }
+
+        function getPropertyOfUnionType(type: UnionType, name: string): Symbol {
+            let properties = type.resolvedProperties || (type.resolvedProperties = {});
+            if (hasProperty(properties, name)) {
+                return properties[name];
+            }
+            let property = createUnionProperty(type, name);
+            if (property) {
+                properties[name] = property;
+            }
+            return property;
+        }
+
+        // Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
+        // necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
+        // Object and Function as appropriate.
+        function getPropertyOfType(type: Type, name: string): Symbol {
+            type = getApparentType(type);
+            if (type.flags & TypeFlags.ObjectType) {
+                let resolved = resolveObjectOrUnionTypeMembers(type);
+                if (hasProperty(resolved.members, name)) {
+                    let symbol = resolved.members[name];
+                    if (symbolIsValue(symbol)) {
+                        return symbol;
+                    }
+                }
+                if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
+                    let symbol = getPropertyOfObjectType(globalFunctionType, name);
+                    if (symbol) {
+                        return symbol;
+                    }
+                }
+                return getPropertyOfObjectType(globalObjectType, name);
+            }
+            if (type.flags & TypeFlags.Union) {
+                return getPropertyOfUnionType(<UnionType>type, name);
+            }
+            return undefined;
+        }
+
+        function getSignaturesOfObjectOrUnionType(type: Type, kind: SignatureKind): Signature[] {
+            if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
+                let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
+                return kind === SignatureKind.Call ? resolved.callSignatures : resolved.constructSignatures;
+            }
+            return emptyArray;
+        }
+
+        // Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and
+        // maps primitive types and type parameters are to their apparent types.
+        function getSignaturesOfType(type: Type, kind: SignatureKind): Signature[] {
+            return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
+        }
+
+        function typeHasCallOrConstructSignatures(type: Type): boolean {
+            let apparentType = getApparentType(type);
+            if (apparentType.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
+                let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
+                return resolved.callSignatures.length > 0
+                    || resolved.constructSignatures.length > 0;
+            }
+            return false;
+        }
+
+        function getIndexTypeOfObjectOrUnionType(type: Type, kind: IndexKind): Type {
+            if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
+                let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
+                return kind === IndexKind.String ? resolved.stringIndexType : resolved.numberIndexType;
+            }
+        }
+
+        // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
+        // maps primitive types and type parameters are to their apparent types.
+        function getIndexTypeOfType(type: Type, kind: IndexKind): Type {
+            return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind);
+        }
+
+        // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual
+        // type checking functions).
+        function getTypeParametersFromDeclaration(typeParameterDeclarations: TypeParameterDeclaration[]): TypeParameter[] {
+            let result: TypeParameter[] = [];
+            forEach(typeParameterDeclarations, node => {
+                let tp = getDeclaredTypeOfTypeParameter(node.symbol);
+                if (!contains(result, tp)) {
+                    result.push(tp);
+                }
+            });
+            return result;
+        }
+
+        function symbolsToArray(symbols: SymbolTable): Symbol[] {
+            let result: Symbol[] = [];
+            for (let id in symbols) {
+                if (!isReservedMemberName(id)) {
+                    result.push(symbols[id]);
+                }
+            }
+            return result;
+        }
+
+        function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature {
+            let links = getNodeLinks(declaration);
+            if (!links.resolvedSignature) {
+                let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClassOrInterface((<ClassDeclaration>declaration.parent).symbol) : undefined;
+                let typeParameters = classType ? classType.typeParameters :
+                    declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined;
+                let parameters: Symbol[] = [];
+                let hasStringLiterals = false;
+                let minArgumentCount = -1;
+                for (let i = 0, n = declaration.parameters.length; i < n; i++) {
+                    let param = declaration.parameters[i];
+                    parameters.push(param.symbol);
+                    if (param.type && param.type.kind === SyntaxKind.StringLiteral) {
+                        hasStringLiterals = true;
+                    }
+                    if (minArgumentCount < 0) {
+                        if (param.initializer || param.questionToken || param.dotDotDotToken) {
+                            minArgumentCount = i;
+                        }
+                    }
+                }
+
+                if (minArgumentCount < 0) {
+                    minArgumentCount = declaration.parameters.length;
+                }
+
+                let returnType: Type;
+                if (classType) {
+                    returnType = classType;
+                }
+                else if (declaration.type) {
+                    returnType = getTypeFromTypeNode(declaration.type);
+                }
+                else {
+                    // TypeScript 1.0 spec (April 2014):
+                    // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation.
+                    if (declaration.kind === SyntaxKind.GetAccessor && !hasDynamicName(declaration)) {
+                        let setter = <AccessorDeclaration>getDeclarationOfKind(declaration.symbol, SyntaxKind.SetAccessor);
+                        returnType = getAnnotatedAccessorType(setter);
+                    }
+
+                    if (!returnType && nodeIsMissing((<FunctionLikeDeclaration>declaration).body)) {
+                        returnType = anyType;
+                    }
+                }
+
+                links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType,
+                    minArgumentCount, hasRestParameters(declaration), hasStringLiterals);
+            }
+            return links.resolvedSignature;
+        }
+
+        function getSignaturesOfSymbol(symbol: Symbol): Signature[] {
+            if (!symbol) return emptyArray;
+            let result: Signature[] = [];
+            for (let i = 0, len = symbol.declarations.length; i < len; i++) {
+                let node = symbol.declarations[i];
+                switch (node.kind) {
+                    case SyntaxKind.FunctionType:
+                    case SyntaxKind.ConstructorType:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.CallSignature:
+                    case SyntaxKind.ConstructSignature:
+                    case SyntaxKind.IndexSignature:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.ArrowFunction:
+                        // Don't include signature if node is the implementation of an overloaded function. A node is considered
+                        // an implementation node if it has a body and the previous node is of the same kind and immediately
+                        // precedes the implementation node (i.e. has the same parent and ends where the implementation starts).
+                        if (i > 0 && (<FunctionLikeDeclaration>node).body) {
+                            let previous = symbol.declarations[i - 1];
+                            if (node.parent === previous.parent && node.kind === previous.kind && node.pos === previous.end) {
+                                break;
+                            }
+                        }
+                        result.push(getSignatureFromDeclaration(<SignatureDeclaration>node));
+                }
+            }
+            return result;
+        }
+
+        function getReturnTypeOfSignature(signature: Signature): Type {
+            if (!signature.resolvedReturnType) {
+                signature.resolvedReturnType = resolvingType;
+                let type: Type;
+                if (signature.target) {
+                    type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper);
+                }
+                else if (signature.unionSignatures) {
+                    type = getUnionType(map(signature.unionSignatures, getReturnTypeOfSignature));
+                }
+                else {
+                    type = getReturnTypeFromBody(<FunctionLikeDeclaration>signature.declaration);
+                }
+                if (signature.resolvedReturnType === resolvingType) {
+                    signature.resolvedReturnType = type;
+                }
+            }
+            else if (signature.resolvedReturnType === resolvingType) {
+                signature.resolvedReturnType = anyType;
+                if (compilerOptions.noImplicitAny) {
+                    let declaration = <Declaration>signature.declaration;
+                    if (declaration.name) {
+                        error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name));
+                    }
+                    else {
+                        error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
+                    }
+                }
+            }
+            return signature.resolvedReturnType;
+        }
+
+        function getRestTypeOfSignature(signature: Signature): Type {
+            if (signature.hasRestParameter) {
+                let type = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
+                if (type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType) {
+                    return (<TypeReference>type).typeArguments[0];
+                }
+            }
+            return anyType;
+        }
+
+        function getSignatureInstantiation(signature: Signature, typeArguments: Type[]): Signature {
+            return instantiateSignature(signature, createTypeMapper(signature.typeParameters, typeArguments), true);
+        }
+
+        function getErasedSignature(signature: Signature): Signature {
+            if (!signature.typeParameters) return signature;
+            if (!signature.erasedSignatureCache) {
+                if (signature.target) {
+                    signature.erasedSignatureCache = instantiateSignature(getErasedSignature(signature.target), signature.mapper);
+                }
+                else {
+                    signature.erasedSignatureCache = instantiateSignature(signature, createTypeEraser(signature.typeParameters), true);
+                }
+            }
+            return signature.erasedSignatureCache;
+        }
+
+        function getOrCreateTypeFromSignature(signature: Signature): ObjectType {
+            // There are two ways to declare a construct signature, one is by declaring a class constructor
+            // using the constructor keyword, and the other is declaring a bare construct signature in an
+            // object type literal or interface (using the new keyword). Each way of declaring a constructor
+            // will result in a different declaration kind.
+            if (!signature.isolatedSignatureType) {
+                let isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature;
+                let type = <ResolvedType>createObjectType(TypeFlags.Anonymous | TypeFlags.FromSignature);
+                type.members = emptySymbols;
+                type.properties = emptyArray;
+                type.callSignatures = !isConstructor ? [signature] : emptyArray;
+                type.constructSignatures = isConstructor ? [signature] : emptyArray;
+                signature.isolatedSignatureType = type;
+            }
+
+            return signature.isolatedSignatureType;
+        }
+
+        function getIndexSymbol(symbol: Symbol): Symbol {
+            return symbol.members["__index"];
+        }
+
+        function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): SignatureDeclaration {
+            let syntaxKind = kind === IndexKind.Number ? SyntaxKind.NumberKeyword : SyntaxKind.StringKeyword;
+            let indexSymbol = getIndexSymbol(symbol);
+            if (indexSymbol) {
+                let len = indexSymbol.declarations.length;
+                for (let decl of indexSymbol.declarations) {
+                    let node = <SignatureDeclaration>decl;
+                    if (node.parameters.length === 1) {
+                        let parameter = node.parameters[0];
+                        if (parameter && parameter.type && parameter.type.kind === syntaxKind) {
+                            return node;
+                        }
+                    }
+                }
+            }
+
+            return undefined;
+        }
+
+        function getIndexTypeOfSymbol(symbol: Symbol, kind: IndexKind): Type {
+            let declaration = getIndexDeclarationOfSymbol(symbol, kind);
+            return declaration
+                ? declaration.type ? getTypeFromTypeNode(declaration.type) : anyType
+                : undefined;
+        }
+
+        function getConstraintOfTypeParameter(type: TypeParameter): Type {
+            if (!type.constraint) {
+                if (type.target) {
+                    let targetConstraint = getConstraintOfTypeParameter(type.target);
+                    type.constraint = targetConstraint ? instantiateType(targetConstraint, type.mapper) : noConstraintType;
+                }
+                else {
+                    type.constraint = getTypeFromTypeNode((<TypeParameterDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint);
+                }
+            }
+            return type.constraint === noConstraintType ? undefined : type.constraint;
+        }
+
+        function getTypeListId(types: Type[]) {
+            switch (types.length) {
+                case 1:
+                    return "" + types[0].id;
+                case 2:
+                    return types[0].id + "," + types[1].id;
+                default:
+                    let result = "";
+                    for (let i = 0; i < types.length; i++) {
+                        if (i > 0) {
+                            result += ",";
+                        }
+
+                        result += types[i].id;
+                    }
+                    return result;
+            }
+        }
+
+        // This function is used to propagate widening flags when creating new object types references and union types.
+        // It is only necessary to do so if a constituent type might be the undefined type, the null type, or the type
+        // of an object literal (since those types have widening related information we need to track).
+        function getWideningFlagsOfTypes(types: Type[]): TypeFlags {
+            let result: TypeFlags = 0;
+            for (let type of types) {
+                result |= type.flags;
+            }
+            return result & TypeFlags.RequiresWidening;
+        }
+
+        function createTypeReference(target: GenericType, typeArguments: Type[]): TypeReference {
+            let id = getTypeListId(typeArguments);
+            let type = target.instantiations[id];
+            if (!type) {
+                let flags = TypeFlags.Reference | getWideningFlagsOfTypes(typeArguments);
+                type = target.instantiations[id] = <TypeReference>createObjectType(flags, target.symbol);
+                type.target = target;
+                type.typeArguments = typeArguments;
+            }
+            return type;
+        }
+
+        function isTypeParameterReferenceIllegalInConstraint(typeReferenceNode: TypeReferenceNode | HeritageClauseElement, typeParameterSymbol: Symbol): boolean {
+            let links = getNodeLinks(typeReferenceNode);
+            if (links.isIllegalTypeReferenceInConstraint !== undefined) {
+                return links.isIllegalTypeReferenceInConstraint;
+            }
+
+            // bubble up to the declaration
+            let currentNode: Node = typeReferenceNode;
+            // forEach === exists
+            while (!forEach(typeParameterSymbol.declarations, d => d.parent === currentNode.parent)) {
+                currentNode = currentNode.parent;
+            }
+            // if last step was made from the type parameter this means that path has started somewhere in constraint which is illegal
+            links.isIllegalTypeReferenceInConstraint = currentNode.kind === SyntaxKind.TypeParameter;
+            return links.isIllegalTypeReferenceInConstraint;
+        }
+
+        function checkTypeParameterHasIllegalReferencesInConstraint(typeParameter: TypeParameterDeclaration): void {
+            let typeParameterSymbol: Symbol;
+            function check(n: Node): void {
+                if (n.kind === SyntaxKind.TypeReference && (<TypeReferenceNode>n).typeName.kind === SyntaxKind.Identifier) {
+                    let links = getNodeLinks(n);
+                    if (links.isIllegalTypeReferenceInConstraint === undefined) {
+                        let symbol = resolveName(typeParameter, (<Identifier>(<TypeReferenceNode>n).typeName).text, SymbolFlags.Type, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
+                        if (symbol && (symbol.flags & SymbolFlags.TypeParameter)) {
+                            // TypeScript 1.0 spec (April 2014): 3.4.1
+                            // Type parameters declared in a particular type parameter list
+                            // may not be referenced in constraints in that type parameter list
+
+                            // symbol.declaration.parent === typeParameter.parent
+                            // -> typeParameter and symbol.declaration originate from the same type parameter list
+                            // -> illegal for all declarations in symbol
+                            // forEach === exists
+                            links.isIllegalTypeReferenceInConstraint = forEach(symbol.declarations, d => d.parent == typeParameter.parent);
+                        }
+                    }
+                    if (links.isIllegalTypeReferenceInConstraint) {
+                        error(typeParameter, Diagnostics.Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list);
+                    }
+                }
+                forEachChild(n, check);
+            }
+
+            if (typeParameter.constraint) {
+                typeParameterSymbol = getSymbolOfNode(typeParameter);
+                check(typeParameter.constraint);
+            }
+        }
+
+        function getTypeFromTypeReference(node: TypeReferenceNode): Type {
+            return getTypeFromTypeReferenceOrHeritageClauseElement(node);
+        }
+
+        function getTypeFromHeritageClauseElement(node: HeritageClauseElement): Type {
+            return getTypeFromTypeReferenceOrHeritageClauseElement(node);
+        }
+
+        function getTypeFromTypeReferenceOrHeritageClauseElement(node: TypeReferenceNode | HeritageClauseElement): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                let type: Type;
+
+                // We don't currently support heritage clauses with complex expressions in them.
+                // For these cases, we just set the type to be the unknownType.
+                if (node.kind !== SyntaxKind.HeritageClauseElement || isSupportedHeritageClauseElement(<HeritageClauseElement>node)) {
+                    let typeNameOrExpression = node.kind === SyntaxKind.TypeReference
+                        ? (<TypeReferenceNode>node).typeName
+                        : (<HeritageClauseElement>node).expression;
+
+                    let symbol = resolveEntityName(typeNameOrExpression, SymbolFlags.Type);
+                    if (symbol) {
+                        if ((symbol.flags & SymbolFlags.TypeParameter) && isTypeParameterReferenceIllegalInConstraint(node, symbol)) {
+                            // TypeScript 1.0 spec (April 2014): 3.4.1
+                            // Type parameters declared in a particular type parameter list
+                            // may not be referenced in constraints in that type parameter list
+                            // Implementation: such type references are resolved to 'unknown' type that usually denotes error
+                            type = unknownType;
+                        }
+                        else {
+                            type = getDeclaredTypeOfSymbol(symbol);
+                            if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) {
+                                let typeParameters = (<InterfaceType>type).typeParameters;
+                                if (node.typeArguments && node.typeArguments.length === typeParameters.length) {
+                                    type = createTypeReference(<GenericType>type, map(node.typeArguments, getTypeFromTypeNode));
+                                }
+                                else {
+                                    error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
+                                    type = undefined;
+                                }
+                            }
+                            else {
+                                if (node.typeArguments) {
+                                    error(node, Diagnostics.Type_0_is_not_generic, typeToString(type));
+                                    type = undefined;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                links.resolvedType = type || unknownType;
+            }
+            return links.resolvedType;
+        }
+
+        function getTypeFromTypeQueryNode(node: TypeQueryNode): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                // TypeScript 1.0 spec (April 2014): 3.6.3
+                // The expression is processed as an identifier expression (section 4.3)
+                // or property access expression(section 4.10),
+                // the widened type(section 3.9) of which becomes the result.
+                links.resolvedType = getWidenedType(checkExpressionOrQualifiedName(node.exprName));
+            }
+            return links.resolvedType;
+        }
+
+        function getTypeOfGlobalSymbol(symbol: Symbol, arity: number): ObjectType {
+
+            function getTypeDeclaration(symbol: Symbol): Declaration {
+                let declarations = symbol.declarations;
+                for (let declaration of declarations) {
+                    switch (declaration.kind) {
+                        case SyntaxKind.ClassDeclaration:
+                        case SyntaxKind.InterfaceDeclaration:
+                        case SyntaxKind.EnumDeclaration:
+                            return declaration;
+                    }
+                }
+            }
+
+            if (!symbol) {
+                return emptyObjectType;
+            }
+            let type = getDeclaredTypeOfSymbol(symbol);
+            if (!(type.flags & TypeFlags.ObjectType)) {
+                error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbol.name);
+                return emptyObjectType;
+            }
+            if (((<InterfaceType>type).typeParameters ? (<InterfaceType>type).typeParameters.length : 0) !== arity) {
+                error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbol.name, arity);
+                return emptyObjectType;
+            }
+            return <ObjectType>type;
+        }
+
+        function getGlobalValueSymbol(name: string): Symbol {
+            return getGlobalSymbol(name, SymbolFlags.Value, Diagnostics.Cannot_find_global_value_0);
+        }
+
+        function getGlobalTypeSymbol(name: string): Symbol {
+            return getGlobalSymbol(name, SymbolFlags.Type, Diagnostics.Cannot_find_global_type_0);
+        }
+
+        function getGlobalSymbol(name: string, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol {
+            return resolveName(undefined, name, meaning, diagnostic, name);
+        }
+
+        function getGlobalType(name: string, arity = 0): ObjectType {
+            return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity);
+        }
+
+        function getGlobalESSymbolConstructorSymbol() {
+            return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"));
+        }
+
+        function createIterableType(elementType: Type): Type {
+            return globalIterableType !== emptyObjectType ? createTypeReference(<GenericType>globalIterableType, [elementType]) : emptyObjectType;
+        }
+
+        function createArrayType(elementType: Type): Type {
+            // globalArrayType will be undefined if we get here during creation of the Array type. This for example happens if
+            // user code augments the Array type with call or construct signatures that have an array type as the return type.
+            // We instead use globalArraySymbol to obtain the (not yet fully constructed) Array type.
+            let arrayType = globalArrayType || getDeclaredTypeOfSymbol(globalArraySymbol);
+            return arrayType !== emptyObjectType ? createTypeReference(<GenericType>arrayType, [elementType]) : emptyObjectType;
+        }
+
+        function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
+            }
+            return links.resolvedType;
+        }
+
+        function createTupleType(elementTypes: Type[]) {
+            let id = getTypeListId(elementTypes);
+            let type = tupleTypes[id];
+            if (!type) {
+                type = tupleTypes[id] = <TupleType>createObjectType(TypeFlags.Tuple);
+                type.elementTypes = elementTypes;
+            }
+            return type;
+        }
+
+        function getTypeFromTupleTypeNode(node: TupleTypeNode): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode));
+            }
+            return links.resolvedType;
+        }
+
+        function addTypeToSortedSet(sortedSet: Type[], type: Type) {
+            if (type.flags & TypeFlags.Union) {
+                addTypesToSortedSet(sortedSet, (<UnionType>type).types);
+            }
+            else {
+                let i = 0;
+                let id = type.id;
+                while (i < sortedSet.length && sortedSet[i].id < id) {
+                    i++;
+                }
+                if (i === sortedSet.length || sortedSet[i].id !== id) {
+                    sortedSet.splice(i, 0, type);
+                }
+            }
+        }
+
+        function addTypesToSortedSet(sortedTypes: Type[], types: Type[]) {
+            for (let type of types) {
+                addTypeToSortedSet(sortedTypes, type);
+            }
+        }
+
+        function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
+            for (let type of types) {
+                if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        function removeSubtypes(types: Type[]) {
+            let i = types.length;
+            while (i > 0) {
+                i--;
+                if (isSubtypeOfAny(types[i], types)) {
+                    types.splice(i, 1);
+                }
+            }
+        }
+
+        function containsAnyType(types: Type[]) {
+            for (let type of types) {
+                if (type.flags & TypeFlags.Any) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        function removeAllButLast(types: Type[], typeToRemove: Type) {
+            let i = types.length;
+            while (i > 0 && types.length > 1) {
+                i--;
+                if (types[i] === typeToRemove) {
+                    types.splice(i, 1);
+                }
+            }
+        }
+
+        // The noSubtypeReduction flag is there because it isn't possible to always do subtype reduction. The flag
+        // is true when creating a union type from a type node and when instantiating a union type. In both of those
+        // cases subtype reduction has to be deferred to properly support recursive union types. For example, a
+        // type alias of the form "type Item = string | (() => Item)" cannot be reduced during its declaration.
+        function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type {
+            if (types.length === 0) {
+                return emptyObjectType;
+            }
+            let sortedTypes: Type[] = [];
+            addTypesToSortedSet(sortedTypes, types);
+            if (noSubtypeReduction) {
+                if (containsAnyType(sortedTypes)) {
+                    return anyType;
+                }
+                removeAllButLast(sortedTypes, undefinedType);
+                removeAllButLast(sortedTypes, nullType);
+            }
+            else {
+                removeSubtypes(sortedTypes);
+            }
+            if (sortedTypes.length === 1) {
+                return sortedTypes[0];
+            }
+            let id = getTypeListId(sortedTypes);
+            let type = unionTypes[id];
+            if (!type) {
+                type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(sortedTypes));
+                type.types = sortedTypes;
+                type.reducedType = noSubtypeReduction ? undefined : type;
+            }
+            return type;
+        }
+
+        function getReducedTypeOfUnionType(type: UnionType): Type {
+            // If union type was created without subtype reduction, perform the deferred reduction now
+            if (!type.reducedType) {
+                type.reducedType = getUnionType(type.types, /*noSubtypeReduction*/ false);
+            }
+            return type.reducedType;
+        }
+
+        function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noSubtypeReduction*/ true);
+            }
+            return links.resolvedType;
+        }
+
+        function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                // Deferred resolution of members is handled by resolveObjectTypeMembers
+                links.resolvedType = createObjectType(TypeFlags.Anonymous, node.symbol);
+            }
+            return links.resolvedType;
+        }
+
+        function getStringLiteralType(node: StringLiteral): StringLiteralType {
+            if (hasProperty(stringLiteralTypes, node.text)) {
+                return stringLiteralTypes[node.text];
+            }
+
+            let type = stringLiteralTypes[node.text] = <StringLiteralType>createType(TypeFlags.StringLiteral);
+            type.text = getTextOfNode(node);
+            return type;
+        }
+
+        function getTypeFromStringLiteral(node: StringLiteral): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = getStringLiteralType(node);
+            }
+            return links.resolvedType;
+        }
+
+        function getTypeFromTypeNode(node: TypeNode): Type {
+            switch (node.kind) {
+                case SyntaxKind.AnyKeyword:
+                    return anyType;
+                case SyntaxKind.StringKeyword:
+                    return stringType;
+                case SyntaxKind.NumberKeyword:
+                    return numberType;
+                case SyntaxKind.BooleanKeyword:
+                    return booleanType;
+                case SyntaxKind.SymbolKeyword:
+                    return esSymbolType;
+                case SyntaxKind.VoidKeyword:
+                    return voidType;
+                case SyntaxKind.StringLiteral:
+                    return getTypeFromStringLiteral(<StringLiteral>node);
+                case SyntaxKind.TypeReference:
+                    return getTypeFromTypeReference(<TypeReferenceNode>node);
+                case SyntaxKind.HeritageClauseElement:
+                    return getTypeFromHeritageClauseElement(<HeritageClauseElement>node);
+                case SyntaxKind.TypeQuery:
+                    return getTypeFromTypeQueryNode(<TypeQueryNode>node);
+                case SyntaxKind.ArrayType:
+                    return getTypeFromArrayTypeNode(<ArrayTypeNode>node);
+                case SyntaxKind.TupleType:
+                    return getTypeFromTupleTypeNode(<TupleTypeNode>node);
+                case SyntaxKind.UnionType:
+                    return getTypeFromUnionTypeNode(<UnionTypeNode>node);
+                case SyntaxKind.ParenthesizedType:
+                    return getTypeFromTypeNode((<ParenthesizedTypeNode>node).type);
+                case SyntaxKind.FunctionType:
+                case SyntaxKind.ConstructorType:
+                case SyntaxKind.TypeLiteral:
+                    return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
+                // This function assumes that an identifier or qualified name is a type expression
+                // Callers should first ensure this by calling isTypeNode
+                case SyntaxKind.Identifier:
+                case SyntaxKind.QualifiedName:
+                    let symbol = getSymbolInfo(node);
+                    return symbol && getDeclaredTypeOfSymbol(symbol);
+                default:
+                    return unknownType;
+            }
+        }
+
+        function instantiateList<T>(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] {
+            if (items && items.length) {
+                let result: T[] = [];
+                for (let v of items) {
+                    result.push(instantiator(v, mapper));
+                }
+                return result;
+            }
+            return items;
+        }
+
+        function createUnaryTypeMapper(source: Type, target: Type): TypeMapper {
+            return t => t === source ? target : t;
+        }
+
+        function createBinaryTypeMapper(source1: Type, target1: Type, source2: Type, target2: Type): TypeMapper {
+            return t => t === source1 ? target1 : t === source2 ? target2 : t;
+        }
+
+        function createTypeMapper(sources: Type[], targets: Type[]): TypeMapper {
+            switch (sources.length) {
+                case 1: return createUnaryTypeMapper(sources[0], targets[0]);
+                case 2: return createBinaryTypeMapper(sources[0], targets[0], sources[1], targets[1]);
+            }
+            return t => {
+                for (let i = 0; i < sources.length; i++) {
+                    if (t === sources[i]) {
+                        return targets[i];
+                    }
+                }
+                return t;
+            };
+        }
+
+        function createUnaryTypeEraser(source: Type): TypeMapper {
+            return t => t === source ? anyType : t;
+        }
+
+        function createBinaryTypeEraser(source1: Type, source2: Type): TypeMapper {
+            return t => t === source1 || t === source2 ? anyType : t;
+        }
+
+        function createTypeEraser(sources: Type[]): TypeMapper {
+            switch (sources.length) {
+                case 1: return createUnaryTypeEraser(sources[0]);
+                case 2: return createBinaryTypeEraser(sources[0], sources[1]);
+            }
+            return t => {
+                for (let source of sources) {
+                    if (t === source) {
+                        return anyType;
+                    }
+                }
+                return t;
+            };
+        }
+
+        function createInferenceMapper(context: InferenceContext): TypeMapper {
+            return t => {
+                for (let i = 0; i < context.typeParameters.length; i++) {
+                    if (t === context.typeParameters[i]) {
+                        context.inferences[i].isFixed = true;
+                        return getInferredType(context, i);
+                    }
+                }
+                return t;
+            }
+        }
+
+        function identityMapper(type: Type): Type {
+            return type;
+        }
+
+        function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
+            return t => instantiateType(mapper1(t), mapper2);
+        }
+
+        function instantiateTypeParameter(typeParameter: TypeParameter, mapper: TypeMapper): TypeParameter {
+            let result = <TypeParameter>createType(TypeFlags.TypeParameter);
+            result.symbol = typeParameter.symbol;
+            if (typeParameter.constraint) {
+                result.constraint = instantiateType(typeParameter.constraint, mapper);
+            }
+            else {
+                result.target = typeParameter;
+                result.mapper = mapper;
+            }
+            return result;
+        }
+
+        function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature {
+            let freshTypeParameters: TypeParameter[];
+            if (signature.typeParameters && !eraseTypeParameters) {
+                freshTypeParameters = instantiateList(signature.typeParameters, mapper, instantiateTypeParameter);
+                mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper);
+            }
+            let result = createSignature(signature.declaration, freshTypeParameters,
+                instantiateList(signature.parameters, mapper, instantiateSymbol),
+                signature.resolvedReturnType ? instantiateType(signature.resolvedReturnType, mapper) : undefined,
+                signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
+            result.target = signature;
+            result.mapper = mapper;
+            return result;
+        }
+
+        function instantiateSymbol(symbol: Symbol, mapper: TypeMapper): Symbol {
+            if (symbol.flags & SymbolFlags.Instantiated) {
+                let links = getSymbolLinks(symbol);
+                // If symbol being instantiated is itself a instantiation, fetch the original target and combine the
+                // type mappers. This ensures that original type identities are properly preserved and that aliases
+                // always reference a non-aliases.
+                symbol = links.target;
+                mapper = combineTypeMappers(links.mapper, mapper);
+            }
+
+            // Keep the flags from the symbol we're instantiating.  Mark that is instantiated, and
+            // also transient so that we can just store data on it directly.
+            let result = <TransientSymbol>createSymbol(SymbolFlags.Instantiated | SymbolFlags.Transient | symbol.flags, symbol.name);
+            result.declarations = symbol.declarations;
+            result.parent = symbol.parent;
+            result.target = symbol;
+            result.mapper = mapper;
+            if (symbol.valueDeclaration) {
+                result.valueDeclaration = symbol.valueDeclaration;
+            }
+
+            return result;
+        }
+
+        function instantiateAnonymousType(type: ObjectType, mapper: TypeMapper): ObjectType {
+            let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
+            result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
+            result.members = createSymbolTable(result.properties);
+            result.callSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Call), mapper, instantiateSignature);
+            result.constructSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Construct), mapper, instantiateSignature);
+            let stringIndexType = getIndexTypeOfType(type, IndexKind.String);
+            let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
+            if (stringIndexType) result.stringIndexType = instantiateType(stringIndexType, mapper);
+            if (numberIndexType) result.numberIndexType = instantiateType(numberIndexType, mapper);
+            return result;
+        }
+
+        function instantiateType(type: Type, mapper: TypeMapper): Type {
+            if (mapper !== identityMapper) {
+                if (type.flags & TypeFlags.TypeParameter) {
+                    return mapper(<TypeParameter>type);
+                }
+                if (type.flags & TypeFlags.Anonymous) {
+                    return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) ?
+                        instantiateAnonymousType(<ObjectType>type, mapper) : type;
+                }
+                if (type.flags & TypeFlags.Reference) {
+                    return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType));
+                }
+                if (type.flags & TypeFlags.Tuple) {
+                    return createTupleType(instantiateList((<TupleType>type).elementTypes, mapper, instantiateType));
+                }
+                if (type.flags & TypeFlags.Union) {
+                    return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noSubtypeReduction*/ true);
+                }
+            }
+            return type;
+        }
+
+        // Returns true if the given expression contains (at any level of nesting) a function or arrow expression
+        // that is subject to contextual typing.
+        function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElement): boolean {
+            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
+            switch (node.kind) {
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                    return isContextSensitiveFunctionLikeDeclaration(<FunctionExpression>node);
+                case SyntaxKind.ObjectLiteralExpression:
+                    return forEach((<ObjectLiteralExpression>node).properties, isContextSensitive);
+                case SyntaxKind.ArrayLiteralExpression:
+                    return forEach((<ArrayLiteralExpression>node).elements, isContextSensitive);
+                case SyntaxKind.ConditionalExpression:
+                    return isContextSensitive((<ConditionalExpression>node).whenTrue) ||
+                        isContextSensitive((<ConditionalExpression>node).whenFalse);
+                case SyntaxKind.BinaryExpression:
+                    return (<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken &&
+                        (isContextSensitive((<BinaryExpression>node).left) || isContextSensitive((<BinaryExpression>node).right));
+                case SyntaxKind.PropertyAssignment:
+                    return isContextSensitive((<PropertyAssignment>node).initializer);
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                    return isContextSensitiveFunctionLikeDeclaration(<MethodDeclaration>node);
+                case SyntaxKind.ParenthesizedExpression:
+                    return isContextSensitive((<ParenthesizedExpression>node).expression);
+            }
+
+            return false;
+        }
+
+        function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) {
+            return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type);
+        }
+
+        function getTypeWithoutConstructors(type: Type): Type {
+            if (type.flags & TypeFlags.ObjectType) {
+                let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
+                if (resolved.constructSignatures.length) {
+                    let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
+                    result.members = resolved.members;
+                    result.properties = resolved.properties;
+                    result.callSignatures = resolved.callSignatures;
+                    result.constructSignatures = emptyArray;
+                    type = result;
+                }
+            }
+            return type;
+        }
+
+        // TYPE CHECKING
+
+        let subtypeRelation: Map<RelationComparisonResult> = {};
+        let assignableRelation: Map<RelationComparisonResult> = {};
+        let identityRelation: Map<RelationComparisonResult> = {};
+
+        function isTypeIdenticalTo(source: Type, target: Type): boolean {
+            return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined);
+        }
+
+        function compareTypes(source: Type, target: Type): Ternary {
+            return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? Ternary.True : Ternary.False;
+        }
+
+        function isTypeSubtypeOf(source: Type, target: Type): boolean {
+            return checkTypeSubtypeOf(source, target, /*errorNode*/ undefined);
+        }
+
+        function isTypeAssignableTo(source: Type, target: Type): boolean {
+            return checkTypeAssignableTo(source, target, /*errorNode*/ undefined);
+        }
+
+        function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean {
+            return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain);
+        }
+
+        function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage): boolean {
+            return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage);
+        }
+
+        function isSignatureAssignableTo(source: Signature, target: Signature): boolean {
+            let sourceType = getOrCreateTypeFromSignature(source);
+            let targetType = getOrCreateTypeFromSignature(target);
+            return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined);
+        }
+
+        function checkTypeRelatedTo(
+            source: Type,
+            target: Type,
+            relation: Map<RelationComparisonResult>,
+            errorNode: Node,
+            headMessage?: DiagnosticMessage,
+            containingMessageChain?: DiagnosticMessageChain): boolean {
+
+            let errorInfo: DiagnosticMessageChain;
+            let sourceStack: ObjectType[];
+            let targetStack: ObjectType[];
+            let maybeStack: Map<RelationComparisonResult>[];
+            let expandingFlags: number;
+            let depth = 0;
+            let overflow = false;
+            let elaborateErrors = false;
+
+            Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
+
+            let result = isRelatedTo(source, target, errorNode !== undefined, headMessage);
+            if (overflow) {
+                error(errorNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
+            }
+            else if (errorInfo) {
+                // If we already computed this relation, but in a context where we didn't want to report errors (e.g. overload resolution),
+                // then we'll only have a top-level error (e.g. 'Class X does not implement interface Y') without any details. If this happened,
+                // request a recompuation to get a complete error message. This will be skipped if we've already done this computation in a context
+                // where errors were being reported.
+                if (errorInfo.next === undefined) {
+                    errorInfo = undefined;
+                    elaborateErrors = true;
+                    isRelatedTo(source, target, errorNode !== undefined, headMessage);
+                }
+                if (containingMessageChain) {
+                    errorInfo = concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
+                }
+
+                diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo));
+            }
+            return result !== Ternary.False;
+
+            function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void {
+                errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
+            }
+
+            // Compare two types and return
+            // Ternary.True if they are related with no assumptions,
+            // Ternary.Maybe if they are related with assumptions of other relationships, or
+            // Ternary.False if they are not related.
+            function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary {
+                let result: Ternary;
+                // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
+                if (source === target) return Ternary.True;
+                if (relation !== identityRelation) {
+                    if (target.flags & TypeFlags.Any) return Ternary.True;
+                    if (source === undefinedType) return Ternary.True;
+                    if (source === nullType && target !== undefinedType) return Ternary.True;
+                    if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True;
+                    if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True;
+                    if (relation === assignableRelation) {
+                        if (source.flags & TypeFlags.Any) return Ternary.True;
+                        if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
+                    }
+                }
+                let saveErrorInfo = errorInfo;
+                if (source.flags & TypeFlags.Union || target.flags & TypeFlags.Union) {
+                    if (relation === identityRelation) {
+                        if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union) {
+                            if (result = unionTypeRelatedToUnionType(<UnionType>source, <UnionType>target)) {
+                                if (result &= unionTypeRelatedToUnionType(<UnionType>target, <UnionType>source)) {
+                                    return result;
+                                }
+                            }
+                        }
+                        else if (source.flags & TypeFlags.Union) {
+                            if (result = unionTypeRelatedToType(<UnionType>source, target, reportErrors)) {
+                                return result;
+                            }
+                        }
+                        else {
+                            if (result = unionTypeRelatedToType(<UnionType>target, source, reportErrors)) {
+                                return result;
+                            }
+                        }
+                    }
+                    else {
+                        if (source.flags & TypeFlags.Union) {
+                            if (result = unionTypeRelatedToType(<UnionType>source, target, reportErrors)) {
+                                return result;
+                            }
+                        }
+                        else {
+                            if (result = typeRelatedToUnionType(source, <UnionType>target, reportErrors)) {
+                                return result;
+                            }
+                        }
+                    }
+                }
+                else if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
+                    if (result = typeParameterRelatedTo(<TypeParameter>source, <TypeParameter>target, reportErrors)) {
+                        return result;
+                    }
+                }
+                else if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
+                    // We have type references to same target type, see if relationship holds for all type arguments
+                    if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
+                        return result;
+                    }
+                }
+
+                // Even if relationship doesn't hold for unions, type parameters, or generic type references,
+                // it may hold in a structural comparison.
+                // Report structural errors only if we haven't reported any errors yet
+                let reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
+                // identity relation does not use apparent type
+                let sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
+                if (sourceOrApparentType.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
+                    if (result = objectTypeRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
+                        errorInfo = saveErrorInfo;
+                        return result;
+                    }
+                }
+                else if (source.flags & TypeFlags.TypeParameter && sourceOrApparentType.flags & TypeFlags.Union) {
+                    // We clear the errors first because the following check often gives a better error than
+                    // the union comparison above if it is applicable.
+                    errorInfo = saveErrorInfo;
+                    if (result = isRelatedTo(sourceOrApparentType, target, reportErrors)) {
+                        return result;
+                    }
+                }
+
+                if (reportErrors) {
+                    headMessage = headMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
+                    let sourceType = typeToString(source);
+                    let targetType = typeToString(target);
+                    if (sourceType === targetType) {
+                        sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
+                        targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
+                    }
+                    reportError(headMessage, sourceType, targetType);
+                }
+                return Ternary.False;
+            }
+
+            function unionTypeRelatedToUnionType(source: UnionType, target: UnionType): Ternary {
+                let result = Ternary.True;
+                let sourceTypes = source.types;
+                for (let sourceType of sourceTypes) {
+                    let related = typeRelatedToUnionType(sourceType, target, false);
+                    if (!related) {
+                        return Ternary.False;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+
+            function typeRelatedToUnionType(source: Type, target: UnionType, reportErrors: boolean): Ternary {
+                let targetTypes = target.types;
+                for (let i = 0, len = targetTypes.length; i < len; i++) {
+                    let related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
+                    if (related) {
+                        return related;
+                    }
+                }
+                return Ternary.False;
+            }
+
+            function unionTypeRelatedToType(source: UnionType, target: Type, reportErrors: boolean): Ternary {
+                let result = Ternary.True;
+                let sourceTypes = source.types;
+                for (let sourceType of sourceTypes) {
+                    let related = isRelatedTo(sourceType, target, reportErrors);
+                    if (!related) {
+                        return Ternary.False;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+
+            function typesRelatedTo(sources: Type[], targets: Type[], reportErrors: boolean): Ternary {
+                let result = Ternary.True;
+                for (let i = 0, len = sources.length; i < len; i++) {
+                    let related = isRelatedTo(sources[i], targets[i], reportErrors);
+                    if (!related) {
+                        return Ternary.False;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+
+            function typeParameterRelatedTo(source: TypeParameter, target: TypeParameter, reportErrors: boolean): Ternary {
+                if (relation === identityRelation) {
+                    if (source.symbol.name !== target.symbol.name) {
+                        return Ternary.False;
+                    }
+                    // covers case when both type parameters does not have constraint (both equal to noConstraintType)
+                    if (source.constraint === target.constraint) {
+                        return Ternary.True;
+                    }
+                    if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
+                        return Ternary.False;
+                    }
+                    return isRelatedTo(source.constraint, target.constraint, reportErrors);
+                }
+                else {
+                    while (true) {
+                        let constraint = getConstraintOfTypeParameter(source);
+                        if (constraint === target) return Ternary.True;
+                        if (!(constraint && constraint.flags & TypeFlags.TypeParameter)) break;
+                        source = <TypeParameter>constraint;
+                    }
+                    return Ternary.False;
+                }
+            }
+
+            // Determine if two object types are related by structure. First, check if the result is already available in the global cache.
+            // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
+            // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
+            // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
+            // and issue an error. Otherwise, actually compare the structure of the two types.
+            function objectTypeRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
+                if (overflow) {
+                    return Ternary.False;
+                }
+                let id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
+                let related = relation[id];
+                //let related: RelationComparisonResult = undefined; // relation[id];
+                if (related !== undefined) {
+                    // If we computed this relation already and it was failed and reported, or if we're not being asked to elaborate
+                    // errors, we can use the cached value. Otherwise, recompute the relation
+                    if (!elaborateErrors || (related === RelationComparisonResult.FailedAndReported)) {
+                        return related === RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
+                    }
+                }
+                if (depth > 0) {
+                    for (let i = 0; i < depth; i++) {
+                        // If source and target are already being compared, consider them related with assumptions
+                        if (maybeStack[i][id]) {
+                            return Ternary.Maybe;
+                        }
+                    }
+                    if (depth === 100) {
+                        overflow = true;
+                        return Ternary.False;
+                    }
+                }
+                else {
+                    sourceStack = [];
+                    targetStack = [];
+                    maybeStack = [];
+                    expandingFlags = 0;
+                }
+                sourceStack[depth] = source;
+                targetStack[depth] = target;
+                maybeStack[depth] = {};
+                maybeStack[depth][id] = RelationComparisonResult.Succeeded;
+                depth++;
+                let saveExpandingFlags = expandingFlags;
+                if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack)) expandingFlags |= 1;
+                if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack)) expandingFlags |= 2;
+                let result: Ternary;
+                if (expandingFlags === 3) {
+                    result = Ternary.Maybe;
+                }
+                else {
+                    result = propertiesRelatedTo(source, target, reportErrors);
+                    if (result) {
+                        result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportErrors);
+                        if (result) {
+                            result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportErrors);
+                            if (result) {
+                                result &= stringIndexTypesRelatedTo(source, target, reportErrors);
+                                if (result) {
+                                    result &= numberIndexTypesRelatedTo(source, target, reportErrors);
+                                }
+                            }
+                        }
+                    }
+                }
+                expandingFlags = saveExpandingFlags;
+                depth--;
+                if (result) {
+                    let maybeCache = maybeStack[depth];
+                    // If result is definitely true, copy assumptions to global cache, else copy to next level up
+                    let destinationCache = (result === Ternary.True || depth === 0) ? relation : maybeStack[depth - 1];
+                    copyMap(maybeCache, destinationCache);
+                }
+                else {
+                    // A false result goes straight into global cache (when something is false under assumptions it
+                    // will also be false without assumptions)
+                    relation[id] = reportErrors ? RelationComparisonResult.FailedAndReported : RelationComparisonResult.Failed;
+                }
+                return result;
+            }
+
+            // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case
+            // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible,
+            // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding.
+            // Effectively, we will generate a false positive when two types are structurally equal to at least 10 levels, but unequal at
+            // some level beyond that.
+            function isDeeplyNestedGeneric(type: ObjectType, stack: ObjectType[]): boolean {
+                if (type.flags & TypeFlags.Reference && depth >= 10) {
+                    let target = (<TypeReference>type).target;
+                    let count = 0;
+                    for (let i = 0; i < depth; i++) {
+                        let t = stack[i];
+                        if (t.flags & TypeFlags.Reference && (<TypeReference>t).target === target) {
+                            count++;
+                            if (count >= 10) return true;
+                        }
+                    }
+                }
+                return false;
+            }
+
+            function propertiesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
+                if (relation === identityRelation) {
+                    return propertiesIdenticalTo(source, target);
+                }
+                let result = Ternary.True;
+                let properties = getPropertiesOfObjectType(target);
+                let requireOptionalProperties = relation === subtypeRelation && !(source.flags & TypeFlags.ObjectLiteral);
+                for (let targetProp of properties) {
+                    let sourceProp = getPropertyOfType(source, targetProp.name);
+                    if (sourceProp !== targetProp) {
+                        if (!sourceProp) {
+                            if (!(targetProp.flags & SymbolFlags.Optional) || requireOptionalProperties) {
+                                if (reportErrors) {
+                                    reportError(Diagnostics.Property_0_is_missing_in_type_1, symbolToString(targetProp), typeToString(source));
+                                }
+                                return Ternary.False;
+                            }
+                        }
+                        else if (!(targetProp.flags & SymbolFlags.Prototype)) {
+                            let sourceFlags = getDeclarationFlagsFromSymbol(sourceProp);
+                            let targetFlags = getDeclarationFlagsFromSymbol(targetProp);
+                            if (sourceFlags & NodeFlags.Private || targetFlags & NodeFlags.Private) {
+                                if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
+                                    if (reportErrors) {
+                                        if (sourceFlags & NodeFlags.Private && targetFlags & NodeFlags.Private) {
+                                            reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
+                                        }
+                                        else {
+                                            reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp),
+                                                typeToString(sourceFlags & NodeFlags.Private ? source : target),
+                                                typeToString(sourceFlags & NodeFlags.Private ? target : source));
+                                        }
+                                    }
+                                    return Ternary.False;
+                                }
+                            }
+                            else if (targetFlags & NodeFlags.Protected) {
+                                let sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & SymbolFlags.Class;
+                                let sourceClass = sourceDeclaredInClass ? <InterfaceType>getDeclaredTypeOfSymbol(sourceProp.parent) : undefined;
+                                let targetClass = <InterfaceType>getDeclaredTypeOfSymbol(targetProp.parent);
+                                if (!sourceClass || !hasBaseType(sourceClass, targetClass)) {
+                                    if (reportErrors) {
+                                        reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2,
+                                            symbolToString(targetProp), typeToString(sourceClass || source), typeToString(targetClass));
+                                    }
+                                    return Ternary.False;
+                                }
+                            }
+                            else if (sourceFlags & NodeFlags.Protected) {
+                                if (reportErrors) {
+                                    reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2,
+                                        symbolToString(targetProp), typeToString(source), typeToString(target));
+                                }
+                                return Ternary.False;
+                            }
+                            let related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors);
+                            if (!related) {
+                                if (reportErrors) {
+                                    reportError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
+                                }
+                                return Ternary.False;
+                            }
+                            result &= related;
+                            if (sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
+                                // TypeScript 1.0 spec (April 2014): 3.8.3
+                                // S is a subtype of a type T, and T is a supertype of S if ...
+                                // S' and T are object types and, for each member M in T..
+                                // M is a property and S' contains a property N where
+                                // if M is a required property, N is also a required property
+                                // (M - property in T)
+                                // (N - property in S)
+                                if (reportErrors) {
+                                    reportError(Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2,
+                                        symbolToString(targetProp), typeToString(source), typeToString(target));
+                                }
+                                return Ternary.False;
+                            }
+                        }
+                    }
+                }
+                return result;
+            }
+
+            function propertiesIdenticalTo(source: ObjectType, target: ObjectType): Ternary {
+                let sourceProperties = getPropertiesOfObjectType(source);
+                let targetProperties = getPropertiesOfObjectType(target);
+                if (sourceProperties.length !== targetProperties.length) {
+                    return Ternary.False;
+                }
+                let result = Ternary.True;
+                for (let sourceProp of sourceProperties) {
+                    let targetProp = getPropertyOfObjectType(target, sourceProp.name);
+                    if (!targetProp) {
+                        return Ternary.False;
+                    }
+                    let related = compareProperties(sourceProp, targetProp, isRelatedTo);
+                    if (!related) {
+                        return Ternary.False;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+
+            function signaturesRelatedTo(source: ObjectType, target: ObjectType, kind: SignatureKind, reportErrors: boolean): Ternary {
+                if (relation === identityRelation) {
+                    return signaturesIdenticalTo(source, target, kind);
+                }
+                if (target === anyFunctionType || source === anyFunctionType) {
+                    return Ternary.True;
+                }
+                let sourceSignatures = getSignaturesOfType(source, kind);
+                let targetSignatures = getSignaturesOfType(target, kind);
+                let result = Ternary.True;
+                let saveErrorInfo = errorInfo;
+                outer: for (let t of targetSignatures) {
+                    if (!t.hasStringLiterals || target.flags & TypeFlags.FromSignature) {
+                        let localErrors = reportErrors;
+                        for (let s of sourceSignatures) {
+                            if (!s.hasStringLiterals || source.flags & TypeFlags.FromSignature) {
+                                let related = signatureRelatedTo(s, t, localErrors);
+                                if (related) {
+                                    result &= related;
+                                    errorInfo = saveErrorInfo;
+                                    continue outer;
+                                }
+                                // Only report errors from the first failure
+                                localErrors = false;
+                            }
+                        }
+                        return Ternary.False;
+                    }
+                }
+                return result;
+            }
+
+            function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary {
+                if (source === target) {
+                    return Ternary.True;
+                }
+                if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) {
+                    return Ternary.False;
+                }
+                let sourceMax = source.parameters.length;
+                let targetMax = target.parameters.length;
+                let checkCount: number;
+                if (source.hasRestParameter && target.hasRestParameter) {
+                    checkCount = sourceMax > targetMax ? sourceMax : targetMax;
+                    sourceMax--;
+                    targetMax--;
+                }
+                else if (source.hasRestParameter) {
+                    sourceMax--;
+                    checkCount = targetMax;
+                }
+                else if (target.hasRestParameter) {
+                    targetMax--;
+                    checkCount = sourceMax;
+                }
+                else {
+                    checkCount = sourceMax < targetMax ? sourceMax : targetMax;
+                }
+                // Spec 1.0 Section 3.8.3 & 3.8.4:
+                // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
+                source = getErasedSignature(source);
+                target = getErasedSignature(target);
+                let result = Ternary.True;
+                for (let i = 0; i < checkCount; i++) {
+                    let s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
+                    let t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
+                    let saveErrorInfo = errorInfo;
+                    let related = isRelatedTo(s, t, reportErrors);
+                    if (!related) {
+                        related = isRelatedTo(t, s, false);
+                        if (!related) {
+                            if (reportErrors) {
+                                reportError(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
+                                    source.parameters[i < sourceMax ? i : sourceMax].name,
+                                    target.parameters[i < targetMax ? i : targetMax].name);
+                            }
+                            return Ternary.False;
+                        }
+                        errorInfo = saveErrorInfo;
+                    }
+                    result &= related;
+                }
+                let t = getReturnTypeOfSignature(target);
+                if (t === voidType) return result;
+                let s = getReturnTypeOfSignature(source);
+                return result & isRelatedTo(s, t, reportErrors);
+            }
+
+            function signaturesIdenticalTo(source: ObjectType, target: ObjectType, kind: SignatureKind): Ternary {
+                let sourceSignatures = getSignaturesOfType(source, kind);
+                let targetSignatures = getSignaturesOfType(target, kind);
+                if (sourceSignatures.length !== targetSignatures.length) {
+                    return Ternary.False;
+                }
+                let result = Ternary.True;
+                for (let i = 0, len = sourceSignatures.length; i < len; ++i) {
+                    let related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*compareReturnTypes*/ true, isRelatedTo);
+                    if (!related) {
+                        return Ternary.False;
+                    }
+                    result &= related;
+                }
+                return result;
+            }
+
+            function stringIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
+                if (relation === identityRelation) {
+                    return indexTypesIdenticalTo(IndexKind.String, source, target);
+                }
+                let targetType = getIndexTypeOfType(target, IndexKind.String);
+                if (targetType) {
+                    let sourceType = getIndexTypeOfType(source, IndexKind.String);
+                    if (!sourceType) {
+                        if (reportErrors) {
+                            reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
+                        }
+                        return Ternary.False;
+                    }
+                    let related = isRelatedTo(sourceType, targetType, reportErrors);
+                    if (!related) {
+                        if (reportErrors) {
+                            reportError(Diagnostics.Index_signatures_are_incompatible);
+                        }
+                        return Ternary.False;
+                    }
+                    return related;
+                }
+                return Ternary.True;
+            }
+
+            function numberIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
+                if (relation === identityRelation) {
+                    return indexTypesIdenticalTo(IndexKind.Number, source, target);
+                }
+                let targetType = getIndexTypeOfType(target, IndexKind.Number);
+                if (targetType) {
+                    let sourceStringType = getIndexTypeOfType(source, IndexKind.String);
+                    let sourceNumberType = getIndexTypeOfType(source, IndexKind.Number);
+                    if (!(sourceStringType || sourceNumberType)) {
+                        if (reportErrors) {
+                            reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
+                        }
+                        return Ternary.False;
+                    }
+                    let related: Ternary;
+                    if (sourceStringType && sourceNumberType) {
+                        // If we know for sure we're testing both string and numeric index types then only report errors from the second one
+                        related = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
+                    }
+                    else {
+                        related = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
+                    }
+                    if (!related) {
+                        if (reportErrors) {
+                            reportError(Diagnostics.Index_signatures_are_incompatible);
+                        }
+                        return Ternary.False;
+                    }
+                    return related;
+                }
+                return Ternary.True;
+            }
+
+            function indexTypesIdenticalTo(indexKind: IndexKind, source: ObjectType, target: ObjectType): Ternary {
+                let targetType = getIndexTypeOfType(target, indexKind);
+                let sourceType = getIndexTypeOfType(source, indexKind);
+                if (!sourceType && !targetType) {
+                    return Ternary.True;
+                }
+                if (sourceType && targetType) {
+                    return isRelatedTo(sourceType, targetType);
+                }
+                return Ternary.False;
+            }
+        }
+
+        function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
+            return compareProperties(sourceProp, targetProp, compareTypes) !== Ternary.False;
+        }
+
+        function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary {
+            // Two members are considered identical when
+            // - they are public properties with identical names, optionality, and types,
+            // - they are private or protected properties originating in the same declaration and having identical types
+            if (sourceProp === targetProp) {
+                return Ternary.True;
+            }
+            let sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (NodeFlags.Private | NodeFlags.Protected);
+            let targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (NodeFlags.Private | NodeFlags.Protected);
+            if (sourcePropAccessibility !== targetPropAccessibility) {
+                return Ternary.False;
+            }
+            if (sourcePropAccessibility) {
+                if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) {
+                    return Ternary.False;
+                }
+            }
+            else {
+                if ((sourceProp.flags & SymbolFlags.Optional) !== (targetProp.flags & SymbolFlags.Optional)) {
+                    return Ternary.False;
+                }
+            }
+            return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
+        }
+
+        function compareSignatures(source: Signature, target: Signature, compareReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
+            if (source === target) {
+                return Ternary.True;
+            }
+            if (source.parameters.length !== target.parameters.length ||
+                source.minArgumentCount !== target.minArgumentCount ||
+                source.hasRestParameter !== target.hasRestParameter) {
+                return Ternary.False;
+            }
+            let result = Ternary.True;
+            if (source.typeParameters && target.typeParameters) {
+                if (source.typeParameters.length !== target.typeParameters.length) {
+                    return Ternary.False;
+                }
+                for (let i = 0, len = source.typeParameters.length; i < len; ++i) {
+                    let related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
+                    if (!related) {
+                        return Ternary.False;
+                    }
+                    result &= related;
+                }
+            }
+            else if (source.typeParameters || target.typeParameters) {
+                return Ternary.False;
+            }
+            // Spec 1.0 Section 3.8.3 & 3.8.4:
+            // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
+            source = getErasedSignature(source);
+            target = getErasedSignature(target);
+            for (let i = 0, len = source.parameters.length; i < len; i++) {
+                let s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
+                let t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
+                let related = compareTypes(s, t);
+                if (!related) {
+                    return Ternary.False;
+                }
+                result &= related;
+            }
+            if (compareReturnTypes) {
+                result &= compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
+            }
+            return result;
+        }
+
+        function isSupertypeOfEach(candidate: Type, types: Type[]): boolean {
+            for (let type of types) {
+                if (candidate !== type && !isTypeSubtypeOf(type, candidate)) return false;
+            }
+            return true;
+        }
+
+        function getCommonSupertype(types: Type[]): Type {
+            return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined);
+        }
+
+        function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void {
+            // The downfallType/bestSupertypeDownfallType is the first type that caused a particular candidate
+            // to not be the common supertype. So if it weren't for this one downfallType (and possibly others),
+            // the type in question could have been the common supertype.
+            let bestSupertype: Type;
+            let bestSupertypeDownfallType: Type;
+            let bestSupertypeScore = 0;
+
+            for (let i = 0; i < types.length; i++) {
+                let score = 0;
+                let downfallType: Type = undefined;
+                for (let j = 0; j < types.length; j++) {
+                    if (isTypeSubtypeOf(types[j], types[i])) {
+                        score++;
+                    }
+                    else if (!downfallType) {
+                        downfallType = types[j];
+                    }
+                }
+
+                Debug.assert(!!downfallType, "If there is no common supertype, each type should have a downfallType");
+
+                if (score > bestSupertypeScore) {
+                    bestSupertype = types[i];
+                    bestSupertypeDownfallType = downfallType;
+                    bestSupertypeScore = score;
+                }
+
+                // types.length - 1 is the maximum score, given that getCommonSupertype returned false
+                if (bestSupertypeScore === types.length - 1) {
+                    break;
+                }
+            }
+
+            // In the following errors, the {1} slot is before the {0} slot because checkTypeSubtypeOf supplies the
+            // subtype as the first argument to the error
+            checkTypeSubtypeOf(bestSupertypeDownfallType, bestSupertype, errorLocation,
+                Diagnostics.Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0,
+                errorMessageChainHead);
+        }
+
+        function isArrayType(type: Type): boolean {
+            return type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType;
+        }
+
+        function isArrayLikeType(type: Type): boolean {
+            // A type is array-like if it is not the undefined or null type and if it is assignable to any[]
+            return !(type.flags & (TypeFlags.Undefined | TypeFlags.Null)) && isTypeAssignableTo(type, anyArrayType);
+        }
+
+        function isTupleLikeType(type: Type): boolean {
+            return !!getPropertyOfType(type, "0");
+        }
+
+        /**
+         * Check if a Type was written as a tuple type literal.
+         * Prefer using isTupleLikeType() unless the use of `elementTypes` is required.
+         */
+        function isTupleType(type: Type): boolean {
+            return (type.flags & TypeFlags.Tuple) && !!(<TupleType>type).elementTypes;
+        }
+
+        function getWidenedTypeOfObjectLiteral(type: Type): Type {
+            let properties = getPropertiesOfObjectType(type);
+            let members: SymbolTable = {};
+            forEach(properties, p => {
+                let propType = getTypeOfSymbol(p);
+                let widenedType = getWidenedType(propType);
+                if (propType !== widenedType) {
+                    let symbol = <TransientSymbol>createSymbol(p.flags | SymbolFlags.Transient, p.name);
+                    symbol.declarations = p.declarations;
+                    symbol.parent = p.parent;
+                    symbol.type = widenedType;
+                    symbol.target = p;
+                    if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
+                    p = symbol;
+                }
+                members[p.name] = p;
+            });
+            let stringIndexType = getIndexTypeOfType(type, IndexKind.String);
+            let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
+            if (stringIndexType) stringIndexType = getWidenedType(stringIndexType);
+            if (numberIndexType) numberIndexType = getWidenedType(numberIndexType);
+            return createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
+        }
+
+        function getWidenedType(type: Type): Type {
+            if (type.flags & TypeFlags.RequiresWidening) {
+                if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
+                    return anyType;
+                }
+                if (type.flags & TypeFlags.ObjectLiteral) {
+                    return getWidenedTypeOfObjectLiteral(type);
+                }
+                if (type.flags & TypeFlags.Union) {
+                    return getUnionType(map((<UnionType>type).types, getWidenedType));
+                }
+                if (isArrayType(type)) {
+                    return createArrayType(getWidenedType((<TypeReference>type).typeArguments[0]));
+                }
+            }
+            return type;
+        }
+
+        function reportWideningErrorsInType(type: Type): boolean {
+            if (type.flags & TypeFlags.Union) {
+                let errorReported = false;
+                forEach((<UnionType>type).types, t => {
+                    if (reportWideningErrorsInType(t)) {
+                        errorReported = true;
+                    }
+                });
+                return errorReported;
+            }
+            if (isArrayType(type)) {
+                return reportWideningErrorsInType((<TypeReference>type).typeArguments[0]);
+            }
+            if (type.flags & TypeFlags.ObjectLiteral) {
+                let errorReported = false;
+                forEach(getPropertiesOfObjectType(type), p => {
+                    let t = getTypeOfSymbol(p);
+                    if (t.flags & TypeFlags.ContainsUndefinedOrNull) {
+                        if (!reportWideningErrorsInType(t)) {
+                            error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
+                        }
+                        errorReported = true;
+                    }
+                });
+                return errorReported;
+            }
+            return false;
+        }
+
+        function reportImplicitAnyError(declaration: Declaration, type: Type) {
+            let typeAsString = typeToString(getWidenedType(type));
+            let diagnostic: DiagnosticMessage;
+            switch (declaration.kind) {
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    diagnostic = Diagnostics.Member_0_implicitly_has_an_1_type;
+                    break;
+                case SyntaxKind.Parameter:
+                    diagnostic = (<ParameterDeclaration>declaration).dotDotDotToken ?
+                        Diagnostics.Rest_parameter_0_implicitly_has_an_any_type :
+                        Diagnostics.Parameter_0_implicitly_has_an_1_type;
+                    break;
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                    if (!declaration.name) {
+                        error(declaration, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
+                        return;
+                    }
+                    diagnostic = Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type;
+                    break;
+                default:
+                    diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type;
+            }
+            error(declaration, diagnostic, declarationNameToString(declaration.name), typeAsString);
+        }
+
+        function reportErrorsFromWidening(declaration: Declaration, type: Type) {
+            if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefinedOrNull) {
+                // Report implicit any error within type if possible, otherwise report error on declaration
+                if (!reportWideningErrorsInType(type)) {
+                    reportImplicitAnyError(declaration, type);
+                }
+            }
+        }
+
+        function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
+            let sourceMax = source.parameters.length;
+            let targetMax = target.parameters.length;
+            let count: number;
+            if (source.hasRestParameter && target.hasRestParameter) {
+                count = sourceMax > targetMax ? sourceMax : targetMax;
+                sourceMax--;
+                targetMax--;
+            }
+            else if (source.hasRestParameter) {
+                sourceMax--;
+                count = targetMax;
+            }
+            else if (target.hasRestParameter) {
+                targetMax--;
+                count = sourceMax;
+            }
+            else {
+                count = sourceMax < targetMax ? sourceMax : targetMax;
+            }
+            for (let i = 0; i < count; i++) {
+                let s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
+                let t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
+                callback(s, t);
+            }
+        }
+
+        function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext {
+            let inferences: TypeInferences[] = [];
+            for (let unused of typeParameters) {
+                inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
+            }
+            return {
+                typeParameters,
+                inferUnionTypes,
+                inferences,
+                inferredTypes: new Array(typeParameters.length),
+            };
+        }
+
+        function inferTypes(context: InferenceContext, source: Type, target: Type) {
+            let sourceStack: Type[];
+            let targetStack: Type[];
+            let depth = 0;
+            let inferiority = 0;
+            inferFromTypes(source, target);
+
+            function isInProcess(source: Type, target: Type) {
+                for (let i = 0; i < depth; i++) {
+                    if (source === sourceStack[i] && target === targetStack[i]) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+
+            function isWithinDepthLimit(type: Type, stack: Type[]) {
+                if (depth >= 5) {
+                    let target = (<TypeReference>type).target;
+                    let count = 0;
+                    for (let i = 0; i < depth; i++) {
+                        let t = stack[i];
+                        if (t.flags & TypeFlags.Reference && (<TypeReference>t).target === target) {
+                            count++;
+                        }
+                    }
+                    return count < 5;
+                }
+                return true;
+            }
+
+            function inferFromTypes(source: Type, target: Type) {
+                if (source === anyFunctionType) {
+                    return;
+                }
+                if (target.flags & TypeFlags.TypeParameter) {
+                    // If target is a type parameter, make an inference
+                    let typeParameters = context.typeParameters;
+                    for (let i = 0; i < typeParameters.length; i++) {
+                        if (target === typeParameters[i]) {
+                            let inferences = context.inferences[i];
+                            if (!inferences.isFixed) {
+                                // Any inferences that are made to a type parameter in a union type are inferior
+                                // to inferences made to a flat (non-union) type. This is because if we infer to
+                                // T | string[], we really don't know if we should be inferring to T or not (because
+                                // the correct constituent on the target side could be string[]). Therefore, we put
+                                // such inferior inferences into a secondary bucket, and only use them if the primary
+                                // bucket is empty.
+                                let candidates = inferiority ?
+                                    inferences.secondary || (inferences.secondary = []) :
+                                    inferences.primary || (inferences.primary = []);
+                                if (!contains(candidates, source)) {
+                                    candidates.push(source);
+                                }
+                            }
+                            return;
+                        }
+                    }
+                }
+                else if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
+                    // If source and target are references to the same generic type, infer from type arguments
+                    let sourceTypes = (<TypeReference>source).typeArguments;
+                    let targetTypes = (<TypeReference>target).typeArguments;
+                    for (let i = 0; i < sourceTypes.length; i++) {
+                        inferFromTypes(sourceTypes[i], targetTypes[i]);
+                    }
+                }
+                else if (target.flags & TypeFlags.Union) {
+                    let targetTypes = (<UnionType>target).types;
+                    let typeParameterCount = 0;
+                    let typeParameter: TypeParameter;
+                    // First infer to each type in union that isn't a type parameter
+                    for (let t of targetTypes) {
+                        if (t.flags & TypeFlags.TypeParameter && contains(context.typeParameters, t)) {
+                            typeParameter = <TypeParameter>t;
+                            typeParameterCount++;
+                        }
+                        else {
+                            inferFromTypes(source, t);
+                        }
+                    }
+                    // If union contains a single naked type parameter, make a secondary inference to that type parameter
+                    if (typeParameterCount === 1) {
+                        inferiority++;
+                        inferFromTypes(source, typeParameter);
+                        inferiority--;
+                    }
+                }
+                else if (source.flags & TypeFlags.Union) {
+                    // Source is a union type, infer from each consituent type
+                    let sourceTypes = (<UnionType>source).types;
+                    for (let sourceType of sourceTypes) {
+                        inferFromTypes(sourceType, target);
+                    }
+                }
+                else if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
+                    (target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral))) {
+                    // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
+                    if (!isInProcess(source, target) && isWithinDepthLimit(source, sourceStack) && isWithinDepthLimit(target, targetStack)) {
+                        if (depth === 0) {
+                            sourceStack = [];
+                            targetStack = [];
+                        }
+                        sourceStack[depth] = source;
+                        targetStack[depth] = target;
+                        depth++;
+                        inferFromProperties(source, target);
+                        inferFromSignatures(source, target, SignatureKind.Call);
+                        inferFromSignatures(source, target, SignatureKind.Construct);
+                        inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String);
+                        inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number);
+                        inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number);
+                        depth--;
+                    }
+                }
+            }
+
+            function inferFromProperties(source: Type, target: Type) {
+                let properties = getPropertiesOfObjectType(target);
+                for (let targetProp of properties) {
+                    let sourceProp = getPropertyOfObjectType(source, targetProp.name);
+                    if (sourceProp) {
+                        inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
+                    }
+                }
+            }
+
+            function inferFromSignatures(source: Type, target: Type, kind: SignatureKind) {
+                let sourceSignatures = getSignaturesOfType(source, kind);
+                let targetSignatures = getSignaturesOfType(target, kind);
+                let sourceLen = sourceSignatures.length;
+                let targetLen = targetSignatures.length;
+                let len = sourceLen < targetLen ? sourceLen : targetLen;
+                for (let i = 0; i < len; i++) {
+                    inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]));
+                }
+            }
+
+            function inferFromSignature(source: Signature, target: Signature) {
+                forEachMatchingParameterType(source, target, inferFromTypes);
+                inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
+            }
+
+            function inferFromIndexTypes(source: Type, target: Type, sourceKind: IndexKind, targetKind: IndexKind) {
+                let targetIndexType = getIndexTypeOfType(target, targetKind);
+                if (targetIndexType) {
+                    let sourceIndexType = getIndexTypeOfType(source, sourceKind);
+                    if (sourceIndexType) {
+                        inferFromTypes(sourceIndexType, targetIndexType);
+                    }
+                }
+            }
+        }
+
+        function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
+            let inferences = context.inferences[index];
+            return inferences.primary || inferences.secondary || emptyArray;
+        }
+
+        function getInferredType(context: InferenceContext, index: number): Type {
+            let inferredType = context.inferredTypes[index];
+            let inferenceSucceeded: boolean;
+            if (!inferredType) {
+                let inferences = getInferenceCandidates(context, index);
+                if (inferences.length) {
+                    // Infer widened union or supertype, or the unknown type for no common supertype
+                    let unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences);
+                    inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
+                    inferenceSucceeded = !!unionOrSuperType;
+                }
+                else {
+                    // Infer the empty object type when no inferences were made. It is important to remember that
+                    // in this case, inference still succeeds, meaning there is no error for not having inference
+                    // candidates. An inference error only occurs when there are *conflicting* candidates, i.e.
+                    // candidates with no common supertype.
+                    inferredType = emptyObjectType;
+                    inferenceSucceeded = true;
+                }
+
+                // Only do the constraint check if inference succeeded (to prevent cascading errors)
+                if (inferenceSucceeded) {
+                    let constraint = getConstraintOfTypeParameter(context.typeParameters[index]);
+                    inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType;
+                }
+                else if (context.failedTypeParameterIndex === undefined || context.failedTypeParameterIndex > index) {
+                    // If inference failed, it is necessary to record the index of the failed type parameter (the one we are on).
+                    // It might be that inference has already failed on a later type parameter on a previous call to inferTypeArguments.
+                    // So if this failure is on preceding type parameter, this type parameter is the new failure index.
+                    context.failedTypeParameterIndex = index;
+                }
+                context.inferredTypes[index] = inferredType;
+            }
+            return inferredType;
+        }
+
+        function getInferredTypes(context: InferenceContext): Type[] {
+            for (let i = 0; i < context.inferredTypes.length; i++) {
+                getInferredType(context, i);
+            }
+
+            return context.inferredTypes;
+        }
+
+        function hasAncestor(node: Node, kind: SyntaxKind): boolean {
+            return getAncestor(node, kind) !== undefined;
+        }
+
+        // EXPRESSION TYPE CHECKING
+
+        function getResolvedSymbol(node: Identifier): Symbol {
+            let links = getNodeLinks(node);
+            if (!links.resolvedSymbol) {
+                links.resolvedSymbol = (!nodeIsMissing(node) && resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node)) || unknownSymbol;
+            }
+            return links.resolvedSymbol;
+        }
+
+        function isInTypeQuery(node: Node): boolean {
+            // TypeScript 1.0 spec (April 2014): 3.6.3
+            // A type query consists of the keyword typeof followed by an expression.
+            // The expression is restricted to a single identifier or a sequence of identifiers separated by periods
+            while (node) {
+                switch (node.kind) {
+                    case SyntaxKind.TypeQuery:
+                        return true;
+                    case SyntaxKind.Identifier:
+                    case SyntaxKind.QualifiedName:
+                        node = node.parent;
+                        continue;
+                    default:
+                        return false;
+                }
+            }
+            Debug.fail("should not get here");
+        }
+
+        // For a union type, remove all constituent types that are of the given type kind (when isOfTypeKind is true)
+        // or not of the given type kind (when isOfTypeKind is false)
+        function removeTypesFromUnionType(type: Type, typeKind: TypeFlags, isOfTypeKind: boolean, allowEmptyUnionResult: boolean): Type {
+            if (type.flags & TypeFlags.Union) {
+                let types = (<UnionType>type).types;
+                if (forEach(types, t => !!(t.flags & typeKind) === isOfTypeKind)) {
+                    // Above we checked if we have anything to remove, now use the opposite test to do the removal
+                    let narrowedType = getUnionType(filter(types, t => !(t.flags & typeKind) === isOfTypeKind));
+                    if (allowEmptyUnionResult || narrowedType !== emptyObjectType) {
+                        return narrowedType;
+                    }
+                }
+            }
+            else if (allowEmptyUnionResult && !!(type.flags & typeKind) === isOfTypeKind) {
+                // Use getUnionType(emptyArray) instead of emptyObjectType in case the way empty union types
+                // are represented ever changes.
+                return getUnionType(emptyArray);
+            }
+            return type;
+        }
+
+        function hasInitializer(node: VariableLikeDeclaration): boolean {
+            return !!(node.initializer || isBindingPattern(node.parent) && hasInitializer(<VariableLikeDeclaration>node.parent.parent));
+        }
+
+        // Check if a given variable is assigned within a given syntax node
+        function isVariableAssignedWithin(symbol: Symbol, node: Node): boolean {
+            let links = getNodeLinks(node);
+            if (links.assignmentChecks) {
+                let cachedResult = links.assignmentChecks[symbol.id];
+                if (cachedResult !== undefined) {
+                    return cachedResult;
+                }
+            }
+            else {
+                links.assignmentChecks = {};
+            }
+            return links.assignmentChecks[symbol.id] = isAssignedIn(node);
+
+            function isAssignedInBinaryExpression(node: BinaryExpression) {
+                if (node.operatorToken.kind >= SyntaxKind.FirstAssignment && node.operatorToken.kind <= SyntaxKind.LastAssignment) {
+                    let n = node.left;
+                    while (n.kind === SyntaxKind.ParenthesizedExpression) {
+                        n = (<ParenthesizedExpression>n).expression;
+                    }
+                    if (n.kind === SyntaxKind.Identifier && getResolvedSymbol(<Identifier>n) === symbol) {
+                        return true;
+                    }
+                }
+                return forEachChild(node, isAssignedIn);
+            }
+
+            function isAssignedInVariableDeclaration(node: VariableLikeDeclaration) {
+                if (!isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) {
+                    return true;
+                }
+                return forEachChild(node, isAssignedIn);
+            }
+
+            function isAssignedIn(node: Node): boolean {
+                switch (node.kind) {
+                    case SyntaxKind.BinaryExpression:
+                        return isAssignedInBinaryExpression(<BinaryExpression>node);
+                    case SyntaxKind.VariableDeclaration:
+                    case SyntaxKind.BindingElement:
+                        return isAssignedInVariableDeclaration(<VariableLikeDeclaration>node);
+                    case SyntaxKind.ObjectBindingPattern:
+                    case SyntaxKind.ArrayBindingPattern:
+                    case SyntaxKind.ArrayLiteralExpression:
+                    case SyntaxKind.ObjectLiteralExpression:
+                    case SyntaxKind.PropertyAccessExpression:
+                    case SyntaxKind.ElementAccessExpression:
+                    case SyntaxKind.CallExpression:
+                    case SyntaxKind.NewExpression:
+                    case SyntaxKind.TypeAssertionExpression:
+                    case SyntaxKind.ParenthesizedExpression:
+                    case SyntaxKind.PrefixUnaryExpression:
+                    case SyntaxKind.DeleteExpression:
+                    case SyntaxKind.TypeOfExpression:
+                    case SyntaxKind.VoidExpression:
+                    case SyntaxKind.PostfixUnaryExpression:
+                    case SyntaxKind.ConditionalExpression:
+                    case SyntaxKind.SpreadElementExpression:
+                    case SyntaxKind.Block:
+                    case SyntaxKind.VariableStatement:
+                    case SyntaxKind.ExpressionStatement:
+                    case SyntaxKind.IfStatement:
+                    case SyntaxKind.DoStatement:
+                    case SyntaxKind.WhileStatement:
+                    case SyntaxKind.ForStatement:
+                    case SyntaxKind.ForInStatement:
+                    case SyntaxKind.ForOfStatement:
+                    case SyntaxKind.ReturnStatement:
+                    case SyntaxKind.WithStatement:
+                    case SyntaxKind.SwitchStatement:
+                    case SyntaxKind.CaseClause:
+                    case SyntaxKind.DefaultClause:
+                    case SyntaxKind.LabeledStatement:
+                    case SyntaxKind.ThrowStatement:
+                    case SyntaxKind.TryStatement:
+                    case SyntaxKind.CatchClause:
+                        return forEachChild(node, isAssignedIn);
+                }
+                return false;
+            }
+        }
+
+        function resolveLocation(node: Node) {
+            // Resolve location from top down towards node if it is a context sensitive expression
+            // That helps in making sure not assigning types as any when resolved out of order
+            let containerNodes: Node[] = [];
+            for (let parent = node.parent; parent; parent = parent.parent) {
+                if ((isExpression(parent) || isObjectLiteralMethod(node)) &&
+                    isContextSensitive(<Expression>parent)) {
+                    containerNodes.unshift(parent);
+                }
+            }
+
+            ts.forEach(containerNodes, node => { getTypeOfNode(node); });
+        }
+
+        function getSymbolAtLocation(node: Node): Symbol {
+            resolveLocation(node);
+            return getSymbolInfo(node);
+        }
+
+        function getTypeAtLocation(node: Node): Type {
+            resolveLocation(node);
+            return getTypeOfNode(node);
+        }
+
+        function getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type {
+            resolveLocation(node);
+            // Get the narrowed type of symbol at given location instead of just getting
+            // the type of the symbol.
+            // eg.
+            // function foo(a: string | number) {
+            //     if (typeof a === "string") {
+            //         a/**/
+            //     }
+            // }
+            // getTypeOfSymbol for a would return type of parameter symbol string | number
+            // Unless we provide location /**/, checker wouldn't know how to narrow the type
+            // By using getNarrowedTypeOfSymbol would return string since it would be able to narrow
+            // it by typeguard in the if true condition
+            return getNarrowedTypeOfSymbol(symbol, node);
+        }
+
+        // Get the narrowed type of a given symbol at a given location
+        function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) {
+            let type = getTypeOfSymbol(symbol);
+            // Only narrow when symbol is variable of type any or an object, union, or type parameter type
+            if (node && symbol.flags & SymbolFlags.Variable && type.flags & (TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) {
+                loop: while (node.parent) {
+                    let child = node;
+                    node = node.parent;
+                    let narrowedType = type;
+                    switch (node.kind) {
+                        case SyntaxKind.IfStatement:
+                            // In a branch of an if statement, narrow based on controlling expression
+                            if (child !== (<IfStatement>node).expression) {
+                                narrowedType = narrowType(type, (<IfStatement>node).expression, /*assumeTrue*/ child === (<IfStatement>node).thenStatement);
+                            }
+                            break;
+                        case SyntaxKind.ConditionalExpression:
+                            // In a branch of a conditional expression, narrow based on controlling condition
+                            if (child !== (<ConditionalExpression>node).condition) {
+                                narrowedType = narrowType(type, (<ConditionalExpression>node).condition, /*assumeTrue*/ child === (<ConditionalExpression>node).whenTrue);
+                            }
+                            break;
+                        case SyntaxKind.BinaryExpression:
+                            // In the right operand of an && or ||, narrow based on left operand
+                            if (child === (<BinaryExpression>node).right) {
+                                if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
+                                    narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ true);
+                                }
+                                else if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken) {
+                                    narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ false);
+                                }
+                            }
+                            break;
+                        case SyntaxKind.SourceFile:
+                        case SyntaxKind.ModuleDeclaration:
+                        case SyntaxKind.FunctionDeclaration:
+                        case SyntaxKind.MethodDeclaration:
+                        case SyntaxKind.MethodSignature:
+                        case SyntaxKind.GetAccessor:
+                        case SyntaxKind.SetAccessor:
+                        case SyntaxKind.Constructor:
+                            // Stop at the first containing function or module declaration
+                            break loop;
+                    }
+                    // Use narrowed type if construct contains no assignments to variable
+                    if (narrowedType !== type) {
+                        if (isVariableAssignedWithin(symbol, node)) {
+                            break;
+                        }
+                        type = narrowedType;
+                    }
+                }
+            }
+            return type;
+
+            function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
+                // Check that we have 'typeof <symbol>' on the left and string literal on the right
+                if (expr.left.kind !== SyntaxKind.TypeOfExpression || expr.right.kind !== SyntaxKind.StringLiteral) {
+                    return type;
+                }
+                let left = <TypeOfExpression>expr.left;
+                let right = <LiteralExpression>expr.right;
+                if (left.expression.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>left.expression) !== symbol) {
+                    return type;
+                }
+                let typeInfo = primitiveTypeInfo[right.text];
+                if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) {
+                    assumeTrue = !assumeTrue;
+                }
+                if (assumeTrue) {
+                    // Assumed result is true. If check was not for a primitive type, remove all primitive types
+                    if (!typeInfo) {
+                        return removeTypesFromUnionType(type, /*typeKind*/ TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.Boolean | TypeFlags.ESSymbol,
+                            /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ false);
+                    }
+                    // Check was for a primitive type, return that primitive type if it is a subtype
+                    if (isTypeSubtypeOf(typeInfo.type, type)) {
+                        return typeInfo.type;
+                    }
+                    // Otherwise, remove all types that aren't of the primitive type kind. This can happen when the type is
+                    // union of enum types and other types.
+                    return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ false, /*allowEmptyUnionResult*/ false);
+                }
+                else {
+                    // Assumed result is false. If check was for a primitive type, remove that primitive type
+                    if (typeInfo) {
+                        return removeTypesFromUnionType(type, /*typeKind*/ typeInfo.flags, /*isOfTypeKind*/ true, /*allowEmptyUnionResult*/ false);
+                    }
+                    // Otherwise we don't have enough information to do anything.
+                    return type;
+                }
+            }
+
+            function narrowTypeByAnd(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
+                if (assumeTrue) {
+                    // The assumed result is true, therefore we narrow assuming each operand to be true.
+                    return narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ true);
+                }
+                else {
+                    // The assumed result is false. This means either the first operand was false, or the first operand was true
+                    // and the second operand was false. We narrow with those assumptions and union the two resulting types.
+                    return getUnionType([
+                        narrowType(type, expr.left, /*assumeTrue*/ false),
+                        narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ false)
+                    ]);
+                }
+            }
+
+            function narrowTypeByOr(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
+                if (assumeTrue) {
+                    // The assumed result is true. This means either the first operand was true, or the first operand was false
+                    // and the second operand was true. We narrow with those assumptions and union the two resulting types.
+                    return getUnionType([
+                        narrowType(type, expr.left, /*assumeTrue*/ true),
+                        narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ true)
+                    ]);
+                }
+                else {
+                    // The assumed result is false, therefore we narrow assuming each operand to be false.
+                    return narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ false);
+                }
+            }
+
+            function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
+                // Check that type is not any, assumed result is true, and we have variable symbol on the left
+                if (type.flags & TypeFlags.Any || !assumeTrue || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
+                    return type;
+                }
+                // Check that right operand is a function type with a prototype property
+                let rightType = checkExpression(expr.right);
+                if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
+                    return type;
+                }
+                // Target type is type of prototype property
+                let prototypeProperty = getPropertyOfType(rightType, "prototype");
+                if (!prototypeProperty) {
+                    return type;
+                }
+                let targetType = getTypeOfSymbol(prototypeProperty);
+                // Narrow to target type if it is a subtype of current type
+                if (isTypeSubtypeOf(targetType, type)) {
+                    return targetType;
+                }
+                // If current type is a union type, remove all constituents that aren't subtypes of target type
+                if (type.flags & TypeFlags.Union) {
+                    return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, targetType)));
+                }
+                return type;
+            }
+
+            // Narrow the given type based on the given expression having the assumed boolean value. The returned type
+            // will be a subtype or the same type as the argument.
+            function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type {
+                switch (expr.kind) {
+                    case SyntaxKind.ParenthesizedExpression:
+                        return narrowType(type, (<ParenthesizedExpression>expr).expression, assumeTrue);
+                    case SyntaxKind.BinaryExpression:
+                        let operator = (<BinaryExpression>expr).operatorToken.kind;
+                        if (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
+                            return narrowTypeByEquality(type, <BinaryExpression>expr, assumeTrue);
+                        }
+                        else if (operator === SyntaxKind.AmpersandAmpersandToken) {
+                            return narrowTypeByAnd(type, <BinaryExpression>expr, assumeTrue);
+                        }
+                        else if (operator === SyntaxKind.BarBarToken) {
+                            return narrowTypeByOr(type, <BinaryExpression>expr, assumeTrue);
+                        }
+                        else if (operator === SyntaxKind.InstanceOfKeyword) {
+                            return narrowTypeByInstanceof(type, <BinaryExpression>expr, assumeTrue);
+                        }
+                        break;
+                    case SyntaxKind.PrefixUnaryExpression:
+                        if ((<PrefixUnaryExpression>expr).operator === SyntaxKind.ExclamationToken) {
+                            return narrowType(type, (<PrefixUnaryExpression>expr).operand, !assumeTrue);
+                        }
+                        break;
+                }
+                return type;
+            }
+        }
+
+        function checkIdentifier(node: Identifier): Type {
+            let symbol = getResolvedSymbol(node);
+
+            // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects.
+            // Although in down-level emit of arrow function, we emit it using function expression which means that
+            // arguments objects will be bound to the inner object; emitting arrow function natively in ES6, arguments objects
+            // will be bound to non-arrow function that contain this arrow function. This results in inconsistent behavior.
+            // To avoid that we will give an error to users if they use arguments objects in arrow function so that they
+            // can explicitly bound arguments objects
+            if (symbol === argumentsSymbol && getContainingFunction(node).kind === SyntaxKind.ArrowFunction && languageVersion < ScriptTarget.ES6) {
+                error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
+            }
+
+            if (symbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
+                markAliasSymbolAsReferenced(symbol);
+            }
+
+            checkCollisionWithCapturedSuperVariable(node, node);
+            checkCollisionWithCapturedThisVariable(node, node);
+            checkBlockScopedBindingCapturedInLoop(node, symbol);
+
+            return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
+        }
+
+        function isInsideFunction(node: Node, threshold: Node): boolean {
+            let current = node;
+            while (current && current !== threshold) {
+                if (isFunctionLike(current)) {
+                    return true;
+                }
+                current = current.parent;
+            }
+
+            return false;
+        }
+
+        function checkBlockScopedBindingCapturedInLoop(node: Identifier, symbol: Symbol): void {
+            if (languageVersion >= ScriptTarget.ES6 ||
+                (symbol.flags & SymbolFlags.BlockScopedVariable) === 0 ||
+                symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) {
+                return;
+            }
+
+            // - check if binding is used in some function
+            // (stop the walk when reaching container of binding declaration)
+            // - if first check succeeded - check if variable is declared inside the loop
+
+            // nesting structure:
+            // (variable declaration or binding element) -> variable declaration list -> container
+            let container: Node = symbol.valueDeclaration;
+            while (container.kind !== SyntaxKind.VariableDeclarationList) {
+                container = container.parent;
+            }
+            // get the parent of variable declaration list
+            container = container.parent;
+            if (container.kind === SyntaxKind.VariableStatement) {
+                // if parent is variable statement - get its parent
+                container = container.parent;
+            }
+
+            let inFunction = isInsideFunction(node.parent, container);
+
+            let current = container;
+            while (current && !nodeStartsNewLexicalEnvironment(current)) {
+                if (isIterationStatement(current, /*lookInLabeledStatements*/ false)) {
+                    if (inFunction) {
+                        grammarErrorOnFirstToken(current, Diagnostics.Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher, declarationNameToString(node));
+                    }
+                    // mark value declaration so during emit they can have a special handling
+                    getNodeLinks(<VariableDeclaration>symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
+                    break;
+                }
+                current = current.parent;
+            }
+        }
+
+        function captureLexicalThis(node: Node, container: Node): void {
+            let classNode = container.parent && container.parent.kind === SyntaxKind.ClassDeclaration ? container.parent : undefined;
+            getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis;
+            if (container.kind === SyntaxKind.PropertyDeclaration || container.kind === SyntaxKind.Constructor) {
+                getNodeLinks(classNode).flags |= NodeCheckFlags.CaptureThis;
+            }
+            else {
+                getNodeLinks(container).flags |= NodeCheckFlags.CaptureThis;
+            }
+        }
+
+        function checkThisExpression(node: Node): Type {
+            // Stop at the first arrow function so that we can
+            // tell whether 'this' needs to be captured.
+            let container = getThisContainer(node, /* includeArrowFunctions */ true);
+            let needToCaptureLexicalThis = false;
+
+            // Now skip arrow functions to get the "real" owner of 'this'.
+            if (container.kind === SyntaxKind.ArrowFunction) {
+                container = getThisContainer(container, /* includeArrowFunctions */ false);
+
+                // When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code
+                needToCaptureLexicalThis = (languageVersion < ScriptTarget.ES6);
+            }
+
+            switch (container.kind) {
+                case SyntaxKind.ModuleDeclaration:
+                    error(node, Diagnostics.this_cannot_be_referenced_in_a_module_body);
+                    // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
+                    break;
+                case SyntaxKind.EnumDeclaration:
+                    error(node, Diagnostics.this_cannot_be_referenced_in_current_location);
+                    // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
+                    break;
+                case SyntaxKind.Constructor:
+                    if (isInConstructorArgumentInitializer(node, container)) {
+                        error(node, Diagnostics.this_cannot_be_referenced_in_constructor_arguments);
+                        // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
+                    }
+                    break;
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    if (container.flags & NodeFlags.Static) {
+                        error(node, Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer);
+                        // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
+                    }
+                    break;
+                case SyntaxKind.ComputedPropertyName:
+                    error(node, Diagnostics.this_cannot_be_referenced_in_a_computed_property_name);
+                    break;
+            }
+
+            if (needToCaptureLexicalThis) {
+                captureLexicalThis(node, container);
+            }
+
+            let classNode = container.parent && container.parent.kind === SyntaxKind.ClassDeclaration ? container.parent : undefined;
+            if (classNode) {
+                let symbol = getSymbolOfNode(classNode);
+                return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol);
+            }
+            return anyType;
+        }
+
+        function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean {
+            for (let n = node; n && n !== constructorDecl; n = n.parent) {
+                if (n.kind === SyntaxKind.Parameter) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        function checkSuperExpression(node: Node): Type {
+            let isCallExpression = node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).expression === node;
+            let enclosingClass = <ClassDeclaration>getAncestor(node, SyntaxKind.ClassDeclaration);
+            let baseClass: Type;
+            if (enclosingClass && getClassExtendsHeritageClauseElement(enclosingClass)) {
+                let classType = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClass));
+                let baseTypes = getBaseTypes(classType);
+                baseClass = baseTypes.length && baseTypes[0];
+            }
+
+            if (!baseClass) {
+                error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class);
+                return unknownType;
+            }
+
+            let container = getSuperContainer(node, /*includeFunctions*/ true);
+
+            if (container) {
+                let canUseSuperExpression = false;
+                let needToCaptureLexicalThis: boolean;
+                if (isCallExpression) {
+                    // TS 1.0 SPEC (April 2014): 4.8.1
+                    // Super calls are only permitted in constructors of derived classes
+                    canUseSuperExpression = container.kind === SyntaxKind.Constructor;
+                }
+                else {
+                    // TS 1.0 SPEC (April 2014)
+                    // 'super' property access is allowed
+                    // - In a constructor, instance member function, instance member accessor, or instance member variable initializer where this references a derived class instance
+                    // - In a static member function or static member accessor
+
+                    // super property access might appear in arrow functions with arbitrary deep nesting
+                    needToCaptureLexicalThis = false;
+                    while (container && container.kind === SyntaxKind.ArrowFunction) {
+                        container = getSuperContainer(container, /*includeFunctions*/ true);
+                        needToCaptureLexicalThis = languageVersion < ScriptTarget.ES6;
+                    }
+
+                    // topmost container must be something that is directly nested in the class declaration
+                    if (container && container.parent && container.parent.kind === SyntaxKind.ClassDeclaration) {
+                        if (container.flags & NodeFlags.Static) {
+                            canUseSuperExpression =
+                                container.kind === SyntaxKind.MethodDeclaration ||
+                                container.kind === SyntaxKind.MethodSignature ||
+                                container.kind === SyntaxKind.GetAccessor ||
+                                container.kind === SyntaxKind.SetAccessor;
+                        }
+                        else {
+                            canUseSuperExpression =
+                                container.kind === SyntaxKind.MethodDeclaration ||
+                                container.kind === SyntaxKind.MethodSignature ||
+                                container.kind === SyntaxKind.GetAccessor ||
+                                container.kind === SyntaxKind.SetAccessor ||
+                                container.kind === SyntaxKind.PropertyDeclaration ||
+                                container.kind === SyntaxKind.PropertySignature ||
+                                container.kind === SyntaxKind.Constructor;
+                        }
+                    }
+                }
+
+                if (canUseSuperExpression) {
+                    let returnType: Type;
+
+                    if ((container.flags & NodeFlags.Static) || isCallExpression) {
+                        getNodeLinks(node).flags |= NodeCheckFlags.SuperStatic;
+                        returnType = getTypeOfSymbol(baseClass.symbol);
+                    }
+                    else {
+                        getNodeLinks(node).flags |= NodeCheckFlags.SuperInstance;
+                        returnType = baseClass;
+                    }
+
+                    if (container.kind === SyntaxKind.Constructor && isInConstructorArgumentInitializer(node, container)) {
+                        // issue custom error message for super property access in constructor arguments (to be aligned with old compiler)
+                        error(node, Diagnostics.super_cannot_be_referenced_in_constructor_arguments);
+                        returnType = unknownType;
+                    }
+
+                    if (!isCallExpression && needToCaptureLexicalThis) {
+                        // call expressions are allowed only in constructors so they should always capture correct 'this'
+                        // super property access expressions can also appear in arrow functions -
+                        // in this case they should also use correct lexical this
+                        captureLexicalThis(node.parent, container);
+                    }
+
+                    return returnType;
+                }
+            }
+
+            if (container && container.kind === SyntaxKind.ComputedPropertyName) {
+                error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
+            }
+            else if (isCallExpression) {
+                error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors);
+            }
+            else {
+                error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class);
+            }
+
+            return unknownType;
+        }
+
+        // Return contextual type of parameter or undefined if no contextual type is available
+        function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
+            if (isFunctionExpressionOrArrowFunction(parameter.parent)) {
+                let func = <FunctionExpression>parameter.parent;
+                if (isContextSensitive(func)) {
+                    let contextualSignature = getContextualSignature(func);
+                    if (contextualSignature) {
+
+                        let funcHasRestParameters = hasRestParameters(func);
+                        let len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
+                        let indexOfParameter = indexOf(func.parameters, parameter);
+                        if (indexOfParameter < len) {
+                            return getTypeAtPosition(contextualSignature, indexOfParameter);
+                        }
+
+                        // If last parameter is contextually rest parameter get its type
+                        if (indexOfParameter === (func.parameters.length - 1) &&
+                            funcHasRestParameters && contextualSignature.hasRestParameter && func.parameters.length >= contextualSignature.parameters.length) {
+                            return getTypeOfSymbol(contextualSignature.parameters[contextualSignature.parameters.length - 1]);
+                        }
+                    }
+                }
+            }
+            return undefined;
+        }
+
+        // In a variable, parameter or property declaration with a type annotation, the contextual type of an initializer
+        // expression is the type of the variable, parameter or property. Otherwise, in a parameter declaration of a
+        // contextually typed function expression, the contextual type of an initializer expression is the contextual type
+        // of the parameter. Otherwise, in a variable or parameter declaration with a binding pattern name, the contextual
+        // type of an initializer expression is the type implied by the binding pattern.
+        function getContextualTypeForInitializerExpression(node: Expression): Type {
+            let declaration = <VariableLikeDeclaration>node.parent;
+            if (node === declaration.initializer) {
+                if (declaration.type) {
+                    return getTypeFromTypeNode(declaration.type);
+                }
+                if (declaration.kind === SyntaxKind.Parameter) {
+                    let type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
+                    if (type) {
+                        return type;
+                    }
+                }
+                if (isBindingPattern(declaration.name)) {
+                    return getTypeFromBindingPattern(<BindingPattern>declaration.name);
+                }
+            }
+            return undefined;
+        }
+
+        function getContextualTypeForReturnExpression(node: Expression): Type {
+            let func = getContainingFunction(node);
+            if (func) {
+                // If the containing function has a return type annotation, is a constructor, or is a get accessor whose
+                // corresponding set accessor has a type annotation, return statements in the function are contextually typed
+                if (func.type || func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(<AccessorDeclaration>getDeclarationOfKind(func.symbol, SyntaxKind.SetAccessor))) {
+                    return getReturnTypeOfSignature(getSignatureFromDeclaration(func));
+                }
+                // Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
+                // and that call signature is non-generic, return statements are contextually typed by the return type of the signature
+                let signature = getContextualSignatureForFunctionLikeDeclaration(<FunctionExpression>func);
+                if (signature) {
+                    return getReturnTypeOfSignature(signature);
+                }
+            }
+            return undefined;
+        }
+
+        // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter.
+        function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type {
+            let args = getEffectiveCallArguments(callTarget);
+            let argIndex = indexOf(args, arg);
+            if (argIndex >= 0) {
+                let signature = getResolvedSignature(callTarget);
+                return getTypeAtPosition(signature, argIndex);
+            }
+            return undefined;
+        }
+
+        function getContextualTypeForSubstitutionExpression(template: TemplateExpression, substitutionExpression: Expression) {
+            if (template.parent.kind === SyntaxKind.TaggedTemplateExpression) {
+                return getContextualTypeForArgument(<TaggedTemplateExpression>template.parent, substitutionExpression);
+            }
+
+            return undefined;
+        }
+
+        function getContextualTypeForBinaryOperand(node: Expression): Type {
+            let binaryExpression = <BinaryExpression>node.parent;
+            let operator = binaryExpression.operatorToken.kind;
+            if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
+                // In an assignment expression, the right operand is contextually typed by the type of the left operand.
+                if (node === binaryExpression.right) {
+                    return checkExpression(binaryExpression.left);
+                }
+            }
+            else if (operator === SyntaxKind.BarBarToken) {
+                // When an || expression has a contextual type, the operands are contextually typed by that type. When an ||
+                // expression has no contextual type, the right operand is contextually typed by the type of the left operand.
+                let type = getContextualType(binaryExpression);
+                if (!type && node === binaryExpression.right) {
+                    type = checkExpression(binaryExpression.left);
+                }
+                return type;
+            }
+            return undefined;
+        }
+
+        // Apply a mapping function to a contextual type and return the resulting type. If the contextual type
+        // is a union type, the mapping function is applied to each constituent type and a union of the resulting
+        // types is returned.
+        function applyToContextualType(type: Type, mapper: (t: Type) => Type): Type {
+            if (!(type.flags & TypeFlags.Union)) {
+                return mapper(type);
+            }
+            let types = (<UnionType>type).types;
+            let mappedType: Type;
+            let mappedTypes: Type[];
+            for (let current of types) {
+                let t = mapper(current);
+                if (t) {
+                    if (!mappedType) {
+                        mappedType = t;
+                    }
+                    else if (!mappedTypes) {
+                        mappedTypes = [mappedType, t];
+                    }
+                    else {
+                        mappedTypes.push(t);
+                    }
+                }
+            }
+            return mappedTypes ? getUnionType(mappedTypes) : mappedType;
+        }
+
+        function getTypeOfPropertyOfContextualType(type: Type, name: string) {
+            return applyToContextualType(type, t => {
+                let prop = getPropertyOfObjectType(t, name);
+                return prop ? getTypeOfSymbol(prop) : undefined;
+            });
+        }
+
+        function getIndexTypeOfContextualType(type: Type, kind: IndexKind) {
+            return applyToContextualType(type, t => getIndexTypeOfObjectOrUnionType(t, kind));
+        }
+
+        // Return true if the given contextual type is a tuple-like type
+        function contextualTypeIsTupleLikeType(type: Type): boolean {
+            return !!(type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isTupleLikeType) : isTupleLikeType(type));
+        }
+
+        // Return true if the given contextual type provides an index signature of the given kind
+        function contextualTypeHasIndexSignature(type: Type, kind: IndexKind): boolean {
+            return !!(type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, t => getIndexTypeOfObjectOrUnionType(t, kind)) : getIndexTypeOfObjectOrUnionType(type, kind));
+        }
+
+        // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of
+        // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one
+        // exists. Otherwise, it is the type of the string index signature in T, if one exists.
+        function getContextualTypeForObjectLiteralMethod(node: MethodDeclaration): Type {
+            Debug.assert(isObjectLiteralMethod(node));
+            if (isInsideWithStatementBody(node)) {
+                // We cannot answer semantic questions within a with block, do not proceed any further
+                return undefined;
+            }
+
+            return getContextualTypeForObjectLiteralElement(node);
+        }
+
+        function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElement) {
+            let objectLiteral = <ObjectLiteralExpression>element.parent;
+            let type = getContextualType(objectLiteral);
+            if (type) {
+                if (!hasDynamicName(element)) {
+                    // For a (non-symbol) computed property, there is no reason to look up the name
+                    // in the type. It will just be "__computed", which does not appear in any
+                    // SymbolTable.
+                    let symbolName = getSymbolOfNode(element).name;
+                    let propertyType = getTypeOfPropertyOfContextualType(type, symbolName);
+                    if (propertyType) {
+                        return propertyType;
+                    }
+                }
+
+                return isNumericName(element.name) && getIndexTypeOfContextualType(type, IndexKind.Number) ||
+                    getIndexTypeOfContextualType(type, IndexKind.String);
+            }
+
+            return undefined;
+        }
+
+        // In an array literal contextually typed by a type T, the contextual type of an element expression at index N is
+        // the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature,
+        // it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated
+        // type of T.
+        function getContextualTypeForElementExpression(node: Expression): Type {
+            let arrayLiteral = <ArrayLiteralExpression>node.parent;
+            let type = getContextualType(arrayLiteral);
+            if (type) {
+                let index = indexOf(arrayLiteral.elements, node);
+                return getTypeOfPropertyOfContextualType(type, "" + index)
+                    || getIndexTypeOfContextualType(type, IndexKind.Number)
+                    || (languageVersion >= ScriptTarget.ES6 ? checkIteratedType(type, /*expressionForError*/ undefined) : undefined);
+            }
+            return undefined;
+        }
+
+        // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type.
+        function getContextualTypeForConditionalOperand(node: Expression): Type {
+            let conditional = <ConditionalExpression>node.parent;
+            return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined;
+        }
+
+        // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
+        // be "pushed" onto a node using the contextualType property.
+        function getContextualType(node: Expression): Type {
+            if (isInsideWithStatementBody(node)) {
+                // We cannot answer semantic questions within a with block, do not proceed any further
+                return undefined;
+            }
+            if (node.contextualType) {
+                return node.contextualType;
+            }
+            let parent = node.parent;
+            switch (parent.kind) {
+                case SyntaxKind.VariableDeclaration:
+                case SyntaxKind.Parameter:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.BindingElement:
+                    return getContextualTypeForInitializerExpression(node);
+                case SyntaxKind.ArrowFunction:
+                case SyntaxKind.ReturnStatement:
+                    return getContextualTypeForReturnExpression(node);
+                case SyntaxKind.CallExpression:
+                case SyntaxKind.NewExpression:
+                    return getContextualTypeForArgument(<CallExpression>parent, node);
+                case SyntaxKind.TypeAssertionExpression:
+                    return getTypeFromTypeNode((<TypeAssertion>parent).type);
+                case SyntaxKind.BinaryExpression:
+                    return getContextualTypeForBinaryOperand(node);
+                case SyntaxKind.PropertyAssignment:
+                    return getContextualTypeForObjectLiteralElement(<ObjectLiteralElement>parent);
+                case SyntaxKind.ArrayLiteralExpression:
+                    return getContextualTypeForElementExpression(node);
+                case SyntaxKind.ConditionalExpression:
+                    return getContextualTypeForConditionalOperand(node);
+                case SyntaxKind.TemplateSpan:
+                    Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression);
+                    return getContextualTypeForSubstitutionExpression(<TemplateExpression>parent.parent, node);
+                case SyntaxKind.ParenthesizedExpression:
+                    return getContextualType(<ParenthesizedExpression>parent);
+            }
+            return undefined;
+        }
+
+        // If the given type is an object or union type, if that type has a single signature, and if
+        // that signature is non-generic, return the signature. Otherwise return undefined.
+        function getNonGenericSignature(type: Type): Signature {
+            let signatures = getSignaturesOfObjectOrUnionType(type, SignatureKind.Call);
+            if (signatures.length === 1) {
+                let signature = signatures[0];
+                if (!signature.typeParameters) {
+                    return signature;
+                }
+            }
+        }
+
+        function isFunctionExpressionOrArrowFunction(node: Node): boolean {
+            return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction;
+        }
+
+        function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature {
+            // Only function expressions and arrow functions are contextually typed.
+            return isFunctionExpressionOrArrowFunction(node) ? getContextualSignature(<FunctionExpression>node) : undefined;
+        }
+
+        // Return the contextual signature for a given expression node. A contextual type provides a
+        // contextual signature if it has a single call signature and if that call signature is non-generic.
+        // If the contextual type is a union type, get the signature from each type possible and if they are
+        // all identical ignoring their return type, the result is same signature but with return type as
+        // union type of return types from these signatures
+        function getContextualSignature(node: FunctionExpression | MethodDeclaration): Signature {
+            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
+            let type = isObjectLiteralMethod(node)
+                ? getContextualTypeForObjectLiteralMethod(<MethodDeclaration>node)
+                : getContextualType(<FunctionExpression>node);
+            if (!type) {
+                return undefined;
+            }
+            if (!(type.flags & TypeFlags.Union)) {
+                return getNonGenericSignature(type);
+            }
+            let signatureList: Signature[];
+            let types = (<UnionType>type).types;
+            for (let current of types) {
+                // The signature set of all constituent type with call signatures should match
+                // So number of signatures allowed is either 0 or 1
+                if (signatureList &&
+                    getSignaturesOfObjectOrUnionType(current, SignatureKind.Call).length > 1) {
+                    return undefined;
+                }
+
+                let signature = getNonGenericSignature(current);
+                if (signature) {
+                    if (!signatureList) {
+                        // This signature will contribute to contextual union signature
+                        signatureList = [signature];
+                    }
+                    else if (!compareSignatures(signatureList[0], signature, /*compareReturnTypes*/ false, compareTypes)) {
+                        // Signatures aren't identical, do not use
+                        return undefined;
+                    }
+                    else {
+                        // Use this signature for contextual union signature
+                        signatureList.push(signature);
+                    }
+                }
+            }
+
+            // Result is union of signatures collected (return type is union of return types of this signature set)
+            let result: Signature;
+            if (signatureList) {
+                result = cloneSignature(signatureList[0]);
+                // Clear resolved return type we possibly got from cloneSignature
+                result.resolvedReturnType = undefined;
+                result.unionSignatures = signatureList;
+            }
+            return result;
+        }
+
+        // Presence of a contextual type mapper indicates inferential typing, except the identityMapper object is
+        // used as a special marker for other purposes.
+        function isInferentialContext(mapper: TypeMapper) {
+            return mapper && mapper !== identityMapper;
+        }
+
+        // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
+        // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is
+        // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'.
+        function isAssignmentTarget(node: Node): boolean {
+            let parent = node.parent;
+            if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operatorToken.kind === SyntaxKind.EqualsToken && (<BinaryExpression>parent).left === node) {
+                return true;
+            }
+            if (parent.kind === SyntaxKind.PropertyAssignment) {
+                return isAssignmentTarget(parent.parent);
+            }
+            if (parent.kind === SyntaxKind.ArrayLiteralExpression) {
+                return isAssignmentTarget(parent);
+            }
+            return false;
+        }
+
+        function checkSpreadElementExpression(node: SpreadElementExpression, contextualMapper?: TypeMapper): Type {
+            // It is usually not safe to call checkExpressionCached if we can be contextually typing.
+            // You can tell that we are contextually typing because of the contextualMapper parameter.
+            // While it is true that a spread element can have a contextual type, it does not do anything
+            // with this type. It is neither affected by it, nor does it propagate it to its operand.
+            // So the fact that contextualMapper is passed is not important, because the operand of a spread
+            // element is not contextually typed.
+            let arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
+            return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
+        }
+
+        function checkArrayLiteral(node: ArrayLiteralExpression, contextualMapper?: TypeMapper): Type {
+            let elements = node.elements;
+            if (!elements.length) {
+                return createArrayType(undefinedType);
+            }
+            let hasSpreadElement = false;
+            let elementTypes: Type[] = [];
+            let inDestructuringPattern = isAssignmentTarget(node);
+            for (let e of elements) {
+                if (inDestructuringPattern && e.kind === SyntaxKind.SpreadElementExpression) {
+                    // Given the following situation:
+                    //    var c: {};
+                    //    [...c] = ["", 0];
+                    //
+                    // c is represented in the tree as a spread element in an array literal.
+                    // But c really functions as a rest element, and its purpose is to provide
+                    // a contextual type for the right hand side of the assignment. Therefore,
+                    // instead of calling checkExpression on "...c", which will give an error 
+                    // if c is not iterable/array-like, we need to act as if we are trying to
+                    // get the contextual element type from it. So we do something similar to
+                    // getContextualTypeForElementExpression, which will crucially not error
+                    // if there is no index type / iterated type.
+                    let restArrayType = checkExpression((<SpreadElementExpression>e).expression, contextualMapper);
+                    let restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
+                        (languageVersion >= ScriptTarget.ES6 ? checkIteratedType(restArrayType, /*expressionForError*/ undefined) : undefined);
+                    
+                    if (restElementType) {
+                        elementTypes.push(restElementType);
+                    }
+                }
+                else {
+                    let type = checkExpression(e, contextualMapper);
+                    elementTypes.push(type);
+                }
+                hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElementExpression;
+            }
+            if (!hasSpreadElement) {
+                let contextualType = getContextualType(node);
+                if (contextualType && contextualTypeIsTupleLikeType(contextualType) || inDestructuringPattern) {
+                    return createTupleType(elementTypes);
+                }
+            }
+            return createArrayType(getUnionType(elementTypes));
+        }
+
+        function isNumericName(name: DeclarationName): boolean {
+            return name.kind === SyntaxKind.ComputedPropertyName ? isNumericComputedName(<ComputedPropertyName>name) : isNumericLiteralName((<Identifier>name).text);
+        }
+
+        function isNumericComputedName(name: ComputedPropertyName): boolean {
+            // It seems odd to consider an expression of type Any to result in a numeric name,
+            // but this behavior is consistent with checkIndexedAccess
+            return allConstituentTypesHaveKind(checkComputedPropertyName(name), TypeFlags.Any | TypeFlags.NumberLike);
+        }
+
+        function isNumericLiteralName(name: string) {
+            // The intent of numeric names is that
+            //     - they are names with text in a numeric form, and that
+            //     - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit',
+            //         acquired by applying the abstract 'ToNumber' operation on the name's text.
+            //
+            // The subtlety is in the latter portion, as we cannot reliably say that anything that looks like a numeric literal is a numeric name.
+            // In fact, it is the case that the text of the name must be equal to 'ToString(numLit)' for this to hold.
+            //
+            // Consider the property name '"0xF00D"'. When one indexes with '0xF00D', they are actually indexing with the value of 'ToString(0xF00D)'
+            // according to the ECMAScript specification, so it is actually as if the user indexed with the string '"61453"'.
+            // Thus, the text of all numeric literals equivalent to '61543' such as '0xF00D', '0xf00D', '0170015', etc. are not valid numeric names
+            // because their 'ToString' representation is not equal to their original text.
+            // This is motivated by ECMA-262 sections 9.3.1, 9.8.1, 11.1.5, and 11.2.1.
+            //
+            // Here, we test whether 'ToString(ToNumber(name))' is exactly equal to 'name'.
+            // The '+' prefix operator is equivalent here to applying the abstract ToNumber operation.
+            // Applying the 'toString()' method on a number gives us the abstract ToString operation on a number.
+            //
+            // Note that this accepts the values 'Infinity', '-Infinity', and 'NaN', and that this is intentional.
+            // This is desired behavior, because when indexing with them as numeric entities, you are indexing
+            // with the strings '"Infinity"', '"-Infinity"', and '"NaN"' respectively.
+            return (+name).toString() === name;
+        }
+
+        function checkComputedPropertyName(node: ComputedPropertyName): Type {
+            let links = getNodeLinks(node.expression);
+            if (!links.resolvedType) {
+                links.resolvedType = checkExpression(node.expression);
+
+                // This will allow types number, string, symbol or any. It will also allow enums, the unknown
+                // type, and any union of these types (like string | number).
+                if (!allConstituentTypesHaveKind(links.resolvedType, TypeFlags.Any | TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) {
+                    error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
+                }
+                else {
+                    checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, /*reportError*/ true);
+                }
+            }
+
+            return links.resolvedType;
+        }
+
+        function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type {
+            // Grammar checking
+            checkGrammarObjectLiteralExpression(node);
+
+            let propertiesTable: SymbolTable = {};
+            let propertiesArray: Symbol[] = [];
+            let contextualType = getContextualType(node);
+            let typeFlags: TypeFlags;
+
+            for (let memberDecl of node.properties) {
+                let member = memberDecl.symbol;
+                if (memberDecl.kind === SyntaxKind.PropertyAssignment ||
+                    memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ||
+                    isObjectLiteralMethod(memberDecl)) {
+                    let type: Type;
+                    if (memberDecl.kind === SyntaxKind.PropertyAssignment) {
+                        type = checkPropertyAssignment(<PropertyAssignment>memberDecl, contextualMapper);
+                    }
+                    else if (memberDecl.kind === SyntaxKind.MethodDeclaration) {
+                        type = checkObjectLiteralMethod(<MethodDeclaration>memberDecl, contextualMapper);
+                    }
+                    else {
+                        Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment);
+                        type = checkExpression((<ShorthandPropertyAssignment>memberDecl).name, contextualMapper);
+                    }
+                    typeFlags |= type.flags;
+                    let prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
+                    prop.declarations = member.declarations;
+                    prop.parent = member.parent;
+                    if (member.valueDeclaration) {
+                        prop.valueDeclaration = member.valueDeclaration;
+                    }
+
+                    prop.type = type;
+                    prop.target = member;
+                    member = prop;
+                }
+                else {
+                    // TypeScript 1.0 spec (April 2014)
+                    // A get accessor declaration is processed in the same manner as
+                    // an ordinary function declaration(section 6.1) with no parameters.
+                    // A set accessor declaration is processed in the same manner
+                    // as an ordinary function declaration with a single parameter and a Void return type.
+                    Debug.assert(memberDecl.kind === SyntaxKind.GetAccessor || memberDecl.kind === SyntaxKind.SetAccessor);
+                    checkAccessorDeclaration(<AccessorDeclaration>memberDecl);
+                }
+
+                if (!hasDynamicName(memberDecl)) {
+                    propertiesTable[member.name] = member;
+                }
+                propertiesArray.push(member);
+            }
+
+            let stringIndexType = getIndexType(IndexKind.String);
+            let numberIndexType = getIndexType(IndexKind.Number);
+            let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
+            result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull);
+            return result;
+
+            function getIndexType(kind: IndexKind) {
+                if (contextualType && contextualTypeHasIndexSignature(contextualType, kind)) {
+                    let propTypes: Type[] = [];
+                    for (let i = 0; i < propertiesArray.length; i++) {
+                        let propertyDecl = node.properties[i];
+                        if (kind === IndexKind.String || isNumericName(propertyDecl.name)) {
+                            // Do not call getSymbolOfNode(propertyDecl), as that will get the
+                            // original symbol for the node. We actually want to get the symbol
+                            // created by checkObjectLiteral, since that will be appropriately
+                            // contextually typed and resolved.
+                            let type = getTypeOfSymbol(propertiesArray[i]);
+                            if (!contains(propTypes, type)) {
+                                propTypes.push(type);
+                            }
+                        }
+                    }
+                    let result = propTypes.length ? getUnionType(propTypes) : undefinedType;
+                    typeFlags |= result.flags;
+                    return result;
+                }
+                return undefined;
+            }
+        }
+
+        // If a symbol is a synthesized symbol with no value declaration, we assume it is a property. Example of this are the synthesized
+        // '.prototype' property as well as synthesized tuple index properties.
+        function getDeclarationKindFromSymbol(s: Symbol) {
+            return s.valueDeclaration ? s.valueDeclaration.kind : SyntaxKind.PropertyDeclaration;
+        }
+
+        function getDeclarationFlagsFromSymbol(s: Symbol) {
+            return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : s.flags & SymbolFlags.Prototype ? NodeFlags.Public | NodeFlags.Static : 0;
+        }
+
+        function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, type: Type, prop: Symbol) {
+            let flags = getDeclarationFlagsFromSymbol(prop);
+            // Public properties are always accessible
+            if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) {
+                return;
+            }
+            // Property is known to be private or protected at this point
+            // Get the declaring and enclosing class instance types
+            let enclosingClassDeclaration = getAncestor(node, SyntaxKind.ClassDeclaration);
+            let enclosingClass = enclosingClassDeclaration ? <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined;
+            let declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(prop.parent);
+            // Private property is accessible if declaring and enclosing class are the same
+            if (flags & NodeFlags.Private) {
+                if (declaringClass !== enclosingClass) {
+                    error(node, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass));
+                }
+                return;
+            }
+            // Property is known to be protected at this point
+            // All protected properties of a supertype are accessible in a super access
+            if (left.kind === SyntaxKind.SuperKeyword) {
+                return;
+            }
+            // A protected property is accessible in the declaring class and classes derived from it
+            if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) {
+                error(node, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass));
+                return;
+            }
+            // No further restrictions for static properties
+            if (flags & NodeFlags.Static) {
+                return;
+            }
+            // An instance property must be accessed through an instance of the enclosing class
+            if (!(getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface) && hasBaseType(<InterfaceType>type, enclosingClass))) {
+                error(node, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
+            }
+        }
+
+        function checkPropertyAccessExpression(node: PropertyAccessExpression) {
+            return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name);
+        }
+
+        function checkQualifiedName(node: QualifiedName) {
+            return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
+        }
+
+        function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
+            let type = checkExpressionOrQualifiedName(left);
+            if (type === unknownType) return type;
+            if (type !== anyType) {
+                let apparentType = getApparentType(getWidenedType(type));
+                if (apparentType === unknownType) {
+                    // handle cases when type is Type parameter with invalid constraint
+                    return unknownType;
+                }
+                let prop = getPropertyOfType(apparentType, right.text);
+                if (!prop) {
+                    if (right.text) {
+                        error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type));
+                    }
+                    return unknownType;
+                }
+                getNodeLinks(node).resolvedSymbol = prop;
+                if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
+                    // TS 1.0 spec (April 2014): 4.8.2
+                    // - In a constructor, instance member function, instance member accessor, or
+                    //   instance member variable initializer where this references a derived class instance,
+                    //   a super property access is permitted and must specify a public instance member function of the base class.
+                    // - In a static member function or static member accessor
+                    //   where this references the constructor function object of a derived class,
+                    //   a super property access is permitted and must specify a public static member function of the base class.
+                    if (left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) {
+                        error(right, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
+                    }
+                    else {
+                        checkClassPropertyAccess(node, left, type, prop);
+                    }
+                }
+                return getTypeOfSymbol(prop);
+            }
+            return anyType;
+        }
+
+        function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
+            let left = node.kind === SyntaxKind.PropertyAccessExpression
+                ? (<PropertyAccessExpression>node).expression
+                : (<QualifiedName>node).left;
+
+            let type = checkExpressionOrQualifiedName(left);
+            if (type !== unknownType && type !== anyType) {
+                let prop = getPropertyOfType(getWidenedType(type), propertyName);
+                if (prop && prop.parent && prop.parent.flags & SymbolFlags.Class) {
+                    if (left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) {
+                        return false;
+                    }
+                    else {
+                        let modificationCount = diagnostics.getModificationCount();
+                        checkClassPropertyAccess(node, left, type, prop);
+                        return diagnostics.getModificationCount() === modificationCount;
+                    }
+                }
+            }
+            return true;
+        }
+
+        function checkIndexedAccess(node: ElementAccessExpression): Type {
+            // Grammar checking
+            if (!node.argumentExpression) {
+                let sourceFile = getSourceFile(node);
+                if (node.parent.kind === SyntaxKind.NewExpression && (<NewExpression>node.parent).expression === node) {
+                    let start = skipTrivia(sourceFile.text, node.expression.end);
+                    let end = node.end;
+                    grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
+                }
+                else {
+                    let start = node.end - "]".length;
+                    let end = node.end;
+                    grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.Expression_expected);
+                }
+            }
+
+            // Obtain base constraint such that we can bail out if the constraint is an unknown type
+            let objectType = getApparentType(checkExpression(node.expression));
+            let indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType;
+
+            if (objectType === unknownType) {
+                return unknownType;
+            }
+
+            let isConstEnum = isConstEnumObjectType(objectType);
+            if (isConstEnum &&
+                (!node.argumentExpression || node.argumentExpression.kind !== SyntaxKind.StringLiteral)) {
+                error(node.argumentExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
+                return unknownType;
+            }
+
+            // TypeScript 1.0 spec (April 2014): 4.10 Property Access
+            // - If IndexExpr is a string literal or a numeric literal and ObjExpr's apparent type has a property with the name
+            //    given by that literal(converted to its string representation in the case of a numeric literal), the property access is of the type of that property.
+            // - Otherwise, if ObjExpr's apparent type has a numeric index signature and IndexExpr is of type Any, the Number primitive type, or an enum type,
+            //    the property access is of the type of that index signature.
+            // - Otherwise, if ObjExpr's apparent type has a string index signature and IndexExpr is of type Any, the String or Number primitive type, or an enum type,
+            //    the property access is of the type of that index signature.
+            // - Otherwise, if IndexExpr is of type Any, the String or Number primitive type, or an enum type, the property access is of type Any.
+
+            // See if we can index as a property.
+            if (node.argumentExpression) {
+                let name = getPropertyNameForIndexedAccess(node.argumentExpression, indexType);
+                if (name !== undefined) {
+                    let prop = getPropertyOfType(objectType, name);
+                    if (prop) {
+                        getNodeLinks(node).resolvedSymbol = prop;
+                        return getTypeOfSymbol(prop);
+                    }
+                    else if (isConstEnum) {
+                        error(node.argumentExpression, Diagnostics.Property_0_does_not_exist_on_const_enum_1, name, symbolToString(objectType.symbol));
+                        return unknownType;
+                    }
+                }
+            }
+
+            // Check for compatible indexer types.
+            if (allConstituentTypesHaveKind(indexType, TypeFlags.Any | TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
+
+                // Try to use a number indexer.
+                if (allConstituentTypesHaveKind(indexType, TypeFlags.Any | TypeFlags.NumberLike)) {
+                    let numberIndexType = getIndexTypeOfType(objectType, IndexKind.Number);
+                    if (numberIndexType) {
+                        return numberIndexType;
+                    }
+                }
+
+                // Try to use string indexing.
+                let stringIndexType = getIndexTypeOfType(objectType, IndexKind.String);
+                if (stringIndexType) {
+                    return stringIndexType;
+                }
+
+                // Fall back to any.
+                if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && objectType !== anyType) {
+                    error(node, Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type);
+                }
+
+                return anyType;
+            }
+
+            // REVIEW: Users should know the type that was actually used.
+            error(node, Diagnostics.An_index_expression_argument_must_be_of_type_string_number_symbol_or_any);
+
+            return unknownType;
+        }
+
+        /**
+         * If indexArgumentExpression is a string literal or number literal, returns its text.
+         * If indexArgumentExpression is a well known symbol, returns the property name corresponding
+         *    to this symbol, as long as it is a proper symbol reference.
+         * Otherwise, returns undefined.
+         */
+        function getPropertyNameForIndexedAccess(indexArgumentExpression: Expression, indexArgumentType: Type): string {
+            if (indexArgumentExpression.kind === SyntaxKind.StringLiteral || indexArgumentExpression.kind === SyntaxKind.NumericLiteral) {
+                return (<LiteralExpression>indexArgumentExpression).text;
+            }
+            if (checkThatExpressionIsProperSymbolReference(indexArgumentExpression, indexArgumentType, /*reportError*/ false)) {
+                let rightHandSideName = (<Identifier>(<PropertyAccessExpression>indexArgumentExpression).name).text;
+                return getPropertyNameForKnownSymbolName(rightHandSideName);
+            }
+
+            return undefined;
+        }
+
+        /**
+         * A proper symbol reference requires the following:
+         *   1. The property access denotes a property that exists
+         *   2. The expression is of the form Symbol.<identifier>
+         *   3. The property access is of the primitive type symbol.
+         *   4. Symbol in this context resolves to the global Symbol object
+         */
+        function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean {
+            if (expressionType === unknownType) {
+                // There is already an error, so no need to report one.
+                return false;
+            }
+
+            if (!isWellKnownSymbolSyntactically(expression)) {
+                return false;
+            }
+
+            // Make sure the property type is the primitive symbol type
+            if ((expressionType.flags & TypeFlags.ESSymbol) === 0) {
+                if (reportError) {
+                    error(expression, Diagnostics.A_computed_property_name_of_the_form_0_must_be_of_type_symbol, getTextOfNode(expression));
+                }
+                return false;
+            }
+
+            // The name is Symbol.<someName>, so make sure Symbol actually resolves to the
+            // global Symbol object
+            let leftHandSide = <Identifier>(<PropertyAccessExpression>expression).expression;
+            let leftHandSideSymbol = getResolvedSymbol(leftHandSide);
+            if (!leftHandSideSymbol) {
+                return false;
+            }
+
+            let globalESSymbol = getGlobalESSymbolConstructorSymbol();
+            if (!globalESSymbol) {
+                // Already errored when we tried to look up the symbol
+                return false;
+            }
+
+            if (leftHandSideSymbol !== globalESSymbol) {
+                if (reportError) {
+                    error(leftHandSide, Diagnostics.Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object);
+                }
+                return false;
+            }
+
+            return true;
+        }
+
+        function resolveUntypedCall(node: CallLikeExpression): Signature {
+            if (node.kind === SyntaxKind.TaggedTemplateExpression) {
+                checkExpression((<TaggedTemplateExpression>node).template);
+            }
+            else {
+                forEach((<CallExpression>node).arguments, argument => {
+                    checkExpression(argument);
+                });
+            }
+            return anySignature;
+        }
+
+        function resolveErrorCall(node: CallLikeExpression): Signature {
+            resolveUntypedCall(node);
+            return unknownSignature;
+        }
+
+        // Re-order candidate signatures into the result array. Assumes the result array to be empty.
+        // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
+        // A nit here is that we reorder only signatures that belong to the same symbol,
+        // so order how inherited signatures are processed is still preserved.
+        // interface A { (x: string): void }
+        // interface B extends A { (x: 'foo'): string }
+        // let b: B;
+        // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void]
+        function reorderCandidates(signatures: Signature[], result: Signature[]): void {
+            let lastParent: Node;
+            let lastSymbol: Symbol;
+            let cutoffIndex: number = 0;
+            let index: number;
+            let specializedIndex: number = -1;
+            let spliceIndex: number;
+            Debug.assert(!result.length);
+            for (let signature of signatures) {
+                let symbol = signature.declaration && getSymbolOfNode(signature.declaration);
+                let parent = signature.declaration && signature.declaration.parent;
+                if (!lastSymbol || symbol === lastSymbol) {
+                    if (lastParent && parent === lastParent) {
+                        index++;
+                    }
+                    else {
+                        lastParent = parent;
+                        index = cutoffIndex;
+                    }
+                }
+                else {
+                    // current declaration belongs to a different symbol
+                    // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex
+                    index = cutoffIndex = result.length;
+                    lastParent = parent;
+                }
+                lastSymbol = symbol;
+
+                // specialized signatures always need to be placed before non-specialized signatures regardless
+                // of the cutoff position; see GH#1133
+                if (signature.hasStringLiterals) {
+                    specializedIndex++;
+                    spliceIndex = specializedIndex;
+                    // The cutoff index always needs to be greater than or equal to the specialized signature index
+                    // in order to prevent non-specialized signatures from being added before a specialized
+                    // signature.
+                    cutoffIndex++;
+                }
+                else {
+                    spliceIndex = index;
+                }
+
+                result.splice(spliceIndex, 0, signature);
+            }
+        }
+
+        function getSpreadArgumentIndex(args: Expression[]): number {
+            for (let i = 0; i < args.length; i++) {
+                if (args[i].kind === SyntaxKind.SpreadElementExpression) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature) {
+            let adjustedArgCount: number;            // Apparent number of arguments we will have in this call
+            let typeArguments: NodeArray<TypeNode>;  // Type arguments (undefined if none)
+            let callIsIncomplete: boolean;           // In incomplete call we want to be lenient when we have too few arguments
+
+            if (node.kind === SyntaxKind.TaggedTemplateExpression) {
+                let tagExpression = <TaggedTemplateExpression>node;
+
+                // Even if the call is incomplete, we'll have a missing expression as our last argument,
+                // so we can say the count is just the arg list length
+                adjustedArgCount = args.length;
+                typeArguments = undefined;
+
+                if (tagExpression.template.kind === SyntaxKind.TemplateExpression) {
+                    // If a tagged template expression lacks a tail literal, the call is incomplete.
+                    // Specifically, a template only can end in a TemplateTail or a Missing literal.
+                    let templateExpression = <TemplateExpression>tagExpression.template;
+                    let lastSpan = lastOrUndefined(templateExpression.templateSpans);
+                    Debug.assert(lastSpan !== undefined); // we should always have at least one span.
+                    callIsIncomplete = nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated;
+                }
+                else {
+                    // If the template didn't end in a backtick, or its beginning occurred right prior to EOF,
+                    // then this might actually turn out to be a TemplateHead in the future;
+                    // so we consider the call to be incomplete.
+                    let templateLiteral = <LiteralExpression>tagExpression.template;
+                    Debug.assert(templateLiteral.kind === SyntaxKind.NoSubstitutionTemplateLiteral);
+                    callIsIncomplete = !!templateLiteral.isUnterminated;
+                }
+            }
+            else {
+                let callExpression = <CallExpression>node;
+                if (!callExpression.arguments) {
+                    // This only happens when we have something of the form: 'new C'
+                    Debug.assert(callExpression.kind === SyntaxKind.NewExpression);
+
+                    return signature.minArgumentCount === 0;
+                }
+
+                // For IDE scenarios we may have an incomplete call, so a trailing comma is tantamount to adding another argument.
+                adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
+
+                // If we are missing the close paren, the call is incomplete.
+                callIsIncomplete = (<CallExpression>callExpression).arguments.end === callExpression.end;
+
+                typeArguments = callExpression.typeArguments;
+            }
+
+            // If the user supplied type arguments, but the number of type arguments does not match
+            // the declared number of type parameters, the call has an incorrect arity.
+            let hasRightNumberOfTypeArgs = !typeArguments ||
+                (signature.typeParameters && typeArguments.length === signature.typeParameters.length);
+            if (!hasRightNumberOfTypeArgs) {
+                return false;
+            }
+
+            // If spread arguments are present, check that they correspond to a rest parameter. If so, no
+            // further checking is necessary.
+            let spreadArgIndex = getSpreadArgumentIndex(args);
+            if (spreadArgIndex >= 0) {
+                return signature.hasRestParameter && spreadArgIndex >= signature.parameters.length - 1;
+            }
+
+            // Too many arguments implies incorrect arity.
+            if (!signature.hasRestParameter && adjustedArgCount > signature.parameters.length) {
+                return false;
+            }
+
+            // If the call is incomplete, we should skip the lower bound check.
+            let hasEnoughArguments = adjustedArgCount >= signature.minArgumentCount;
+            return callIsIncomplete || hasEnoughArguments;
+        }
+
+        // If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
+        function getSingleCallSignature(type: Type): Signature {
+            if (type.flags & TypeFlags.ObjectType) {
+                let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
+                if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 &&
+                    resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
+                    return resolved.callSignatures[0];
+                }
+            }
+            return undefined;
+        }
+
+        // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
+        function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature {
+            let context = createInferenceContext(signature.typeParameters, /*inferUnionTypes*/ true);
+            forEachMatchingParameterType(contextualSignature, signature, (source, target) => {
+                // Type parameters from outer context referenced by source type are fixed by instantiation of the source type
+                inferTypes(context, instantiateType(source, contextualMapper), target);
+            });
+            return getSignatureInstantiation(signature, getInferredTypes(context));
+        }
+
+        function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
+            let typeParameters = signature.typeParameters;
+            let inferenceMapper = createInferenceMapper(context);
+
+            // Clear out all the inference results from the last time inferTypeArguments was called on this context
+            for (let i = 0; i < typeParameters.length; i++) {
+                // As an optimization, we don't have to clear (and later recompute) inferred types
+                // for type parameters that have already been fixed on the previous call to inferTypeArguments.
+                // It would be just as correct to reset all of them. But then we'd be repeating the same work
+                // for the type parameters that were fixed, namely the work done by getInferredType.
+                if (!context.inferences[i].isFixed) {
+                    context.inferredTypes[i] = undefined;
+                }
+            }
+
+            // On this call to inferTypeArguments, we may get more inferences for certain type parameters that were not
+            // fixed last time. This means that a type parameter that failed inference last time may succeed this time,
+            // or vice versa. Therefore, the failedTypeParameterIndex is useless if it points to an unfixed type parameter,
+            // because it may change. So here we reset it. However, getInferredType will not revisit any type parameters
+            // that were previously fixed. So if a fixed type parameter failed previously, it will fail again because
+            // it will contain the exact same set of inferences. So if we reset the index from a fixed type parameter,
+            // we will lose information that we won't recover this time around.
+            if (context.failedTypeParameterIndex !== undefined && !context.inferences[context.failedTypeParameterIndex].isFixed) {
+                context.failedTypeParameterIndex = undefined;
+            }
+
+            // We perform two passes over the arguments. In the first pass we infer from all arguments, but use
+            // wildcards for all context sensitive function expressions.
+            for (let i = 0; i < args.length; i++) {
+                let arg = args[i];
+                if (arg.kind !== SyntaxKind.OmittedExpression) {
+                    let paramType = getTypeAtPosition(signature, i);
+                    let argType: Type;
+                    if (i === 0 && args[i].parent.kind === SyntaxKind.TaggedTemplateExpression) {
+                        argType = globalTemplateStringsArrayType;
+                    }
+                    else {
+                        // For context sensitive arguments we pass the identityMapper, which is a signal to treat all
+                        // context sensitive function expressions as wildcards
+                        let mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : inferenceMapper;
+                        argType = checkExpressionWithContextualType(arg, paramType, mapper);
+                    }
+                    inferTypes(context, argType, paramType);
+                }
+            }
+
+            // In the second pass we visit only context sensitive arguments, and only those that aren't excluded, this
+            // time treating function expressions normally (which may cause previously inferred type arguments to be fixed
+            // as we construct types for contextually typed parameters)
+            if (excludeArgument) {
+                for (let i = 0; i < args.length; i++) {
+                    // No need to check for omitted args and template expressions, their exlusion value is always undefined
+                    if (excludeArgument[i] === false) {
+                        let arg = args[i];
+                        let paramType = getTypeAtPosition(signature, i);
+                        inferTypes(context, checkExpressionWithContextualType(arg, paramType, inferenceMapper), paramType);
+                    }
+                }
+            }
+
+            getInferredTypes(context);
+        }
+
+        function checkTypeArguments(signature: Signature, typeArguments: TypeNode[], typeArgumentResultTypes: Type[], reportErrors: boolean): boolean {
+            let typeParameters = signature.typeParameters;
+            let typeArgumentsAreAssignable = true;
+            for (let i = 0; i < typeParameters.length; i++) {
+                let typeArgNode = typeArguments[i];
+                let typeArgument = getTypeFromTypeNode(typeArgNode);
+                // Do not push on this array! It has a preallocated length
+                typeArgumentResultTypes[i] = typeArgument;
+                if (typeArgumentsAreAssignable /* so far */) {
+                    let constraint = getConstraintOfTypeParameter(typeParameters[i]);
+                    if (constraint) {
+                        typeArgumentsAreAssignable = checkTypeAssignableTo(typeArgument, constraint, reportErrors ? typeArgNode : undefined,
+                            Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
+                    }
+                }
+            }
+            return typeArgumentsAreAssignable;
+        }
+
+        function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[], reportErrors: boolean) {
+            for (let i = 0; i < args.length; i++) {
+                let arg = args[i];
+                if (arg.kind !== SyntaxKind.OmittedExpression) {
+                    // Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter)
+                    let paramType = getTypeAtPosition(signature, i);
+                    // A tagged template expression provides a special first argument, and string literals get string literal types
+                    // unless we're reporting errors
+                    let argType = i === 0 && node.kind === SyntaxKind.TaggedTemplateExpression
+                        ? globalTemplateStringsArrayType
+                        : arg.kind === SyntaxKind.StringLiteral && !reportErrors
+                            ? getStringLiteralType(<StringLiteral>arg)
+                            : checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
+
+                    // Use argument expression as error location when reporting errors
+                    if (!checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined,
+                        Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+
+        /**
+         * Returns the effective arguments for an expression that works like a function invocation.
+         *
+         * If 'node' is a CallExpression or a NewExpression, then its argument list is returned.
+         * If 'node' is a TaggedTemplateExpression, a new argument list is constructed from the substitution
+         *    expressions, where the first element of the list is the template for error reporting purposes.
+         */
+        function getEffectiveCallArguments(node: CallLikeExpression): Expression[] {
+            let args: Expression[];
+            if (node.kind === SyntaxKind.TaggedTemplateExpression) {
+                let template = (<TaggedTemplateExpression>node).template;
+                args = [template];
+
+                if (template.kind === SyntaxKind.TemplateExpression) {
+                    forEach((<TemplateExpression>template).templateSpans, span => {
+                        args.push(span.expression);
+                    });
+                }
+            }
+            else {
+                args = (<CallExpression>node).arguments || emptyArray;
+            }
+
+            return args;
+        }
+
+        /**
+         * In a 'super' call, type arguments are not provided within the CallExpression node itself.
+         * Instead, they must be fetched from the class declaration's base type node.
+         *
+         * If 'node' is a 'super' call (e.g. super(...), new super(...)), then we attempt to fetch
+         * the type arguments off the containing class's first heritage clause (if one exists). Note that if
+         * type arguments are supplied on the 'super' call, they are ignored (though this is syntactically incorrect).
+         *
+         * In all other cases, the call's explicit type arguments are returned.
+         */
+        function getEffectiveTypeArguments(callExpression: CallExpression): TypeNode[] {
+            if (callExpression.expression.kind === SyntaxKind.SuperKeyword) {
+                let containingClass = <ClassDeclaration>getAncestor(callExpression, SyntaxKind.ClassDeclaration);
+                let baseClassTypeNode = containingClass && getClassExtendsHeritageClauseElement(containingClass);
+                return baseClassTypeNode && baseClassTypeNode.typeArguments;
+            }
+            else {
+                // Ordinary case - simple function invocation.
+                return callExpression.typeArguments;
+            }
+        }
+
+        function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[]): Signature {
+            let isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
+
+            let typeArguments: TypeNode[];
+
+            if (!isTaggedTemplate) {
+                typeArguments = getEffectiveTypeArguments(<CallExpression>node);
+
+                // We already perform checking on the type arguments on the class declaration itself.
+                if ((<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
+                    forEach(typeArguments, checkSourceElement);
+                }
+            }
+
+            let candidates = candidatesOutArray || [];
+            // reorderCandidates fills up the candidates array directly
+            reorderCandidates(signatures, candidates);
+            if (!candidates.length) {
+                error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
+                return resolveErrorCall(node);
+            }
+
+            let args = getEffectiveCallArguments(node);
+
+            // The following applies to any value of 'excludeArgument[i]':
+            //    - true:      the argument at 'i' is susceptible to a one-time permanent contextual typing.
+            //    - undefined: the argument at 'i' is *not* susceptible to permanent contextual typing.
+            //    - false:     the argument at 'i' *was* and *has been* permanently contextually typed.
+            //
+            // The idea is that we will perform type argument inference & assignability checking once
+            // without using the susceptible parameters that are functions, and once more for each of those
+            // parameters, contextually typing each as we go along.
+            //
+            // For a tagged template, then the first argument be 'undefined' if necessary
+            // because it represents a TemplateStringsArray.
+            let excludeArgument: boolean[];
+            for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) {
+                if (isContextSensitive(args[i])) {
+                    if (!excludeArgument) {
+                        excludeArgument = new Array(args.length);
+                    }
+                    excludeArgument[i] = true;
+                }
+            }
+
+            // The following variables are captured and modified by calls to chooseOverload.
+            // If overload resolution or type argument inference fails, we want to report the
+            // best error possible. The best error is one which says that an argument was not
+            // assignable to a parameter. This implies that everything else about the overload
+            // was fine. So if there is any overload that is only incorrect because of an
+            // argument, we will report an error on that one.
+            //
+            //     function foo(s: string) {}
+            //     function foo(n: number) {} // Report argument error on this overload
+            //     function foo() {}
+            //     foo(true);
+            //
+            // If none of the overloads even made it that far, there are two possibilities.
+            // There was a problem with type arguments for some overload, in which case
+            // report an error on that. Or none of the overloads even had correct arity,
+            // in which case give an arity error.
+            //
+            //     function foo<T>(x: T, y: T) {} // Report type argument inference error
+            //     function foo() {}
+            //     foo(0, true);
+            //
+            let candidateForArgumentError: Signature;
+            let candidateForTypeArgumentError: Signature;
+            let resultOfFailedInference: InferenceContext;
+            let result: Signature;
+
+            // Section 4.12.1:
+            // if the candidate list contains one or more signatures for which the type of each argument
+            // expression is a subtype of each corresponding parameter type, the return type of the first
+            // of those signatures becomes the return type of the function call.
+            // Otherwise, the return type of the first signature in the candidate list becomes the return
+            // type of the function call.
+            //
+            // Whether the call is an error is determined by assignability of the arguments. The subtype pass
+            // is just important for choosing the best signature. So in the case where there is only one
+            // signature, the subtype pass is useless. So skipping it is an optimization.
+            if (candidates.length > 1) {
+                result = chooseOverload(candidates, subtypeRelation);
+            }
+            if (!result) {
+                // Reinitialize these pointers for round two
+                candidateForArgumentError = undefined;
+                candidateForTypeArgumentError = undefined;
+                resultOfFailedInference = undefined;
+                result = chooseOverload(candidates, assignableRelation);
+            }
+            if (result) {
+                return result;
+            }
+
+            // No signatures were applicable. Now report errors based on the last applicable signature with
+            // no arguments excluded from assignability checks.
+            // If candidate is undefined, it means that no candidates had a suitable arity. In that case,
+            // skip the checkApplicableSignature check.
+            if (candidateForArgumentError) {
+                // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...]
+                // The importance of excludeArgument is to prevent us from typing function expression parameters
+                // in arguments too early. If possible, we'd like to only type them once we know the correct
+                // overload. However, this matters for the case where the call is correct. When the call is
+                // an error, we don't need to exclude any arguments, although it would cause no harm to do so.
+                checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
+            }
+            else if (candidateForTypeArgumentError) {
+                if (!isTaggedTemplate && (<CallExpression>node).typeArguments) {
+                    checkTypeArguments(candidateForTypeArgumentError, (<CallExpression>node).typeArguments, [], /*reportErrors*/ true)
+                }
+                else {
+                    Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0);
+                    let failedTypeParameter = candidateForTypeArgumentError.typeParameters[resultOfFailedInference.failedTypeParameterIndex];
+                    let inferenceCandidates = getInferenceCandidates(resultOfFailedInference, resultOfFailedInference.failedTypeParameterIndex);
+
+                    let diagnosticChainHead = chainDiagnosticMessages(/*details*/ undefined, // details will be provided by call to reportNoCommonSupertypeError
+                        Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
+                        typeToString(failedTypeParameter));
+
+                    reportNoCommonSupertypeError(inferenceCandidates, (<CallExpression>node).expression || (<TaggedTemplateExpression>node).tag, diagnosticChainHead);
+                }
+            }
+            else {
+                error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
+            }
+
+            // No signature was applicable. We have already reported the errors for the invalid signature.
+            // If this is a type resolution session, e.g. Language Service, try to get better information that anySignature.
+            // Pick the first candidate that matches the arity. This way we can get a contextual type for cases like:
+            //  declare function f(a: { xa: number; xb: number; });
+            //  f({ |
+            if (!produceDiagnostics) {
+                for (let candidate of candidates) {
+                    if (hasCorrectArity(node, args, candidate)) {
+                        return candidate;
+                    }
+                }
+            }
+
+            return resolveErrorCall(node);
+
+            function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
+                for (let originalCandidate of candidates) {
+                    if (!hasCorrectArity(node, args, originalCandidate)) {
+                        continue;
+                    }
+                    
+                    let candidate: Signature;
+                    let typeArgumentsAreValid: boolean;
+                    let inferenceContext = originalCandidate.typeParameters
+                        ? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false)
+                        : undefined;
+
+                    while (true) {
+                        candidate = originalCandidate;
+                        if (candidate.typeParameters) {
+                            let typeArgumentTypes: Type[];
+                            if (typeArguments) {
+                                typeArgumentTypes = new Array<Type>(candidate.typeParameters.length);
+                                typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)
+                            }
+                            else {
+                                inferTypeArguments(candidate, args, excludeArgument, inferenceContext);
+                                typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
+                                typeArgumentTypes = inferenceContext.inferredTypes;
+                            }
+                            if (!typeArgumentsAreValid) {
+                                break;
+                            }
+                            candidate = getSignatureInstantiation(candidate, typeArgumentTypes);
+                        }
+                        if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
+                            break;
+                        }
+                        let index = excludeArgument ? indexOf(excludeArgument, true) : -1;
+                        if (index < 0) {
+                            return candidate;
+                        }
+                        excludeArgument[index] = false;
+                    }
+
+                    // A post-mortem of this iteration of the loop. The signature was not applicable,
+                    // so we want to track it as a candidate for reporting an error. If the candidate
+                    // had no type parameters, or had no issues related to type arguments, we can
+                    // report an error based on the arguments. If there was an issue with type
+                    // arguments, then we can only report an error based on the type arguments.
+                    if (originalCandidate.typeParameters) {
+                        let instantiatedCandidate = candidate;
+                        if (typeArgumentsAreValid) {
+                            candidateForArgumentError = instantiatedCandidate;
+                        }
+                        else {
+                            candidateForTypeArgumentError = originalCandidate;
+                            if (!typeArguments) {
+                                resultOfFailedInference = inferenceContext;
+                            }
+                        }
+                    }
+                    else {
+                        Debug.assert(originalCandidate === candidate);
+                        candidateForArgumentError = originalCandidate;
+                    }
+                }
+
+                return undefined;
+            }
+
+        }
+
+        function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[]): Signature {
+            if (node.expression.kind === SyntaxKind.SuperKeyword) {
+                let superType = checkSuperExpression(node.expression);
+                if (superType !== unknownType) {
+                    return resolveCall(node, getSignaturesOfType(superType, SignatureKind.Construct), candidatesOutArray);
+                }
+                return resolveUntypedCall(node);
+            }
+
+            let funcType = checkExpression(node.expression);
+            let apparentType = getApparentType(funcType);
+
+            if (apparentType === unknownType) {
+                // Another error has already been reported
+                return resolveErrorCall(node);
+            }
+
+            // Technically, this signatures list may be incomplete. We are taking the apparent type,
+            // but we are not including call signatures that may have been added to the Object or
+            // Function interface, since they have none by default. This is a bit of a leap of faith
+            // that the user will not add any.
+            let callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
+
+            let constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
+            // TS 1.0 spec: 4.12
+            // If FuncExpr is of type Any, or of an object type that has no call or construct signatures
+            // but is a subtype of the Function interface, the call is an untyped function call. In an
+            // untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
+            // types are provided for the argument expressions, and the result is always of type Any.
+            // We exclude union types because we may have a union of function types that happen to have
+            // no common signatures.
+            if (funcType === anyType || (!callSignatures.length && !constructSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
+                if (node.typeArguments) {
+                    error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
+                }
+                return resolveUntypedCall(node);
+            }
+            // If FuncExpr's apparent type(section 3.8.1) is a function type, the call is a typed function call.
+            // TypeScript employs overload resolution in typed function calls in order to support functions
+            // with multiple call signatures.
+            if (!callSignatures.length) {
+                if (constructSignatures.length) {
+                    error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
+                }
+                else {
+                    error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
+                }
+                return resolveErrorCall(node);
+            }
+            return resolveCall(node, callSignatures, candidatesOutArray);
+        }
+
+        function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature {
+            if (node.arguments && languageVersion < ScriptTarget.ES6) {
+                let spreadIndex = getSpreadArgumentIndex(node.arguments);
+                if (spreadIndex >= 0) {
+                    error(node.arguments[spreadIndex], Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher);
+                }
+            }
+
+            let expressionType = checkExpression(node.expression);
+            // TS 1.0 spec: 4.11
+            // If ConstructExpr is of type Any, Args can be any argument
+            // list and the result of the operation is of type Any.
+            if (expressionType === anyType) {
+                if (node.typeArguments) {
+                    error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
+                }
+                return resolveUntypedCall(node);
+            }
+
+            // If ConstructExpr's apparent type(section 3.8.1) is an object type with one or
+            // more construct signatures, the expression is processed in the same manner as a
+            // function call, but using the construct signatures as the initial set of candidate
+            // signatures for overload resolution.The result type of the function call becomes
+            // the result type of the operation.
+            expressionType = getApparentType(expressionType);
+            if (expressionType === unknownType) {
+                // Another error has already been reported
+                return resolveErrorCall(node);
+            }
+
+            // Technically, this signatures list may be incomplete. We are taking the apparent type,
+            // but we are not including construct signatures that may have been added to the Object or
+            // Function interface, since they have none by default. This is a bit of a leap of faith
+            // that the user will not add any.
+            let constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct);
+            if (constructSignatures.length) {
+                return resolveCall(node, constructSignatures, candidatesOutArray);
+            }
+
+            // If ConstructExpr's apparent type is an object type with no construct signatures but
+            // one or more call signatures, the expression is processed as a function call. A compile-time
+            // error occurs if the result of the function call is not Void. The type of the result of the
+            // operation is Any.
+            let callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
+            if (callSignatures.length) {
+                let signature = resolveCall(node, callSignatures, candidatesOutArray);
+                if (getReturnTypeOfSignature(signature) !== voidType) {
+                    error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
+                }
+                return signature;
+            }
+
+            error(node, Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature);
+            return resolveErrorCall(node);
+        }
+
+        function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[]): Signature {
+            let tagType = checkExpression(node.tag);
+            let apparentType = getApparentType(tagType);
+
+            if (apparentType === unknownType) {
+                // Another error has already been reported
+                return resolveErrorCall(node);
+            }
+
+            let callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
+
+            if (tagType === anyType || (!callSignatures.length && !(tagType.flags & TypeFlags.Union) && isTypeAssignableTo(tagType, globalFunctionType))) {
+                return resolveUntypedCall(node);
+            }
+
+            if (!callSignatures.length) {
+                error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature);
+                return resolveErrorCall(node);
+            }
+
+            return resolveCall(node, callSignatures, candidatesOutArray);
+        }
+
+        // candidatesOutArray is passed by signature help in the language service, and collectCandidates
+        // must fill it up with the appropriate candidate signatures
+        function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
+            let links = getNodeLinks(node);
+            // If getResolvedSignature has already been called, we will have cached the resolvedSignature.
+            // However, it is possible that either candidatesOutArray was not passed in the first time,
+            // or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
+            // to correctly fill the candidatesOutArray.
+            if (!links.resolvedSignature || candidatesOutArray) {
+                links.resolvedSignature = anySignature;
+
+                if (node.kind === SyntaxKind.CallExpression) {
+                    links.resolvedSignature = resolveCallExpression(<CallExpression>node, candidatesOutArray);
+                }
+                else if (node.kind === SyntaxKind.NewExpression) {
+                    links.resolvedSignature = resolveNewExpression(<NewExpression>node, candidatesOutArray);
+                }
+                else if (node.kind === SyntaxKind.TaggedTemplateExpression) {
+                    links.resolvedSignature = resolveTaggedTemplateExpression(<TaggedTemplateExpression>node, candidatesOutArray);
+                }
+                else {
+                    Debug.fail("Branch in 'getResolvedSignature' should be unreachable.");
+                }
+            }
+            return links.resolvedSignature;
+        }
+
+        function checkCallExpression(node: CallExpression): Type {
+            // Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true
+            checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
+
+            let signature = getResolvedSignature(node);
+            if (node.expression.kind === SyntaxKind.SuperKeyword) {
+                return voidType;
+            }
+            if (node.kind === SyntaxKind.NewExpression) {
+                let declaration = signature.declaration;
+                if (declaration &&
+                    declaration.kind !== SyntaxKind.Constructor &&
+                    declaration.kind !== SyntaxKind.ConstructSignature &&
+                    declaration.kind !== SyntaxKind.ConstructorType) {
+
+                    // When resolved signature is a call signature (and not a construct signature) the result type is any
+                    if (compilerOptions.noImplicitAny) {
+                        error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
+                    }
+                    return anyType;
+                }
+            }
+            return getReturnTypeOfSignature(signature);
+        }
+
+        function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
+            return getReturnTypeOfSignature(getResolvedSignature(node));
+        }
+
+        function checkTypeAssertion(node: TypeAssertion): Type {
+            let exprType = checkExpression(node.expression);
+            let targetType = getTypeFromTypeNode(node.type);
+            if (produceDiagnostics && targetType !== unknownType) {
+                let widenedType = getWidenedType(exprType);
+                if (!(isTypeAssignableTo(targetType, widenedType))) {
+                    checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
+                }
+            }
+            return targetType;
+        }
+
+        function getTypeAtPosition(signature: Signature, pos: number): Type {
+            return signature.hasRestParameter ?
+                pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
+                pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType;
+        }
+
+        function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
+            let len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
+            for (let i = 0; i < len; i++) {
+                let parameter = signature.parameters[i];
+                let links = getSymbolLinks(parameter);
+                links.type = instantiateType(getTypeAtPosition(context, i), mapper);
+            }
+            if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
+                let parameter = signature.parameters[signature.parameters.length - 1];
+                let links = getSymbolLinks(parameter);
+                links.type = instantiateType(getTypeOfSymbol(context.parameters[context.parameters.length - 1]), mapper);
+            }
+        }
+
+        function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
+            let contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
+            if (!func.body) {
+                return unknownType;
+            }
+            let type: Type;
+            if (func.body.kind !== SyntaxKind.Block) {
+                type = checkExpressionCached(<Expression>func.body, contextualMapper);
+            }
+            else {
+                // Aggregate the types of expressions within all the return statements.
+                let types = checkAndAggregateReturnExpressionTypes(<Block>func.body, contextualMapper);
+                if (types.length === 0) {
+                    return voidType;
+                }
+                // When return statements are contextually typed we allow the return type to be a union type. Otherwise we require the
+                // return expressions to have a best common supertype.
+                type = contextualSignature ? getUnionType(types) : getCommonSupertype(types);
+                if (!type) {
+                    error(func, Diagnostics.No_best_common_type_exists_among_return_expressions);
+                    return unknownType;
+                }
+            }
+            if (!contextualSignature) {
+                reportErrorsFromWidening(func, type);
+            }
+            return getWidenedType(type);
+        }
+
+        /// Returns a set of types relating to every return expression relating to a function block.
+        function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper): Type[] {
+            let aggregatedTypes: Type[] = [];
+
+            forEachReturnStatement(body, returnStatement => {
+                let expr = returnStatement.expression;
+                if (expr) {
+                    let type = checkExpressionCached(expr, contextualMapper);
+                    if (!contains(aggregatedTypes, type)) {
+                        aggregatedTypes.push(type);
+                    }
+                }
+            });
+
+            return aggregatedTypes;
+        }
+
+        function bodyContainsAReturnStatement(funcBody: Block) {
+            return forEachReturnStatement(funcBody, returnStatement => {
+                return true;
+            });
+        }
+
+        function bodyContainsSingleThrowStatement(body: Block) {
+            return (body.statements.length === 1) && (body.statements[0].kind === SyntaxKind.ThrowStatement);
+        }
+
+        // TypeScript Specification 1.0 (6.3) - July 2014
+        // An explicitly typed function whose return type isn't the Void or the Any type
+        // must have at least one return statement somewhere in its body.
+        // An exception to this rule is if the function implementation consists of a single 'throw' statement.
+        function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionLikeDeclaration, returnType: Type): void {
+            if (!produceDiagnostics) {
+                return;
+            }
+
+            // Functions that return 'void' or 'any' don't need any return expressions.
+            if (returnType === voidType || returnType === anyType) {
+                return;
+            }
+
+            // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
+            if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block) {
+                return;
+            }
+
+            let bodyBlock = <Block>func.body;
+
+            // Ensure the body has at least one return expression.
+            if (bodyContainsAReturnStatement(bodyBlock)) {
+                return;
+            }
+
+            // If there are no return expressions, then we need to check if
+            // the function body consists solely of a throw statement;
+            // this is to make an exception for unimplemented functions.
+            if (bodyContainsSingleThrowStatement(bodyBlock)) {
+                return;
+            }
+
+            // This function does not conform to the specification.
+            error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement);
+        }
+
+        function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type {
+            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
+
+            // Grammar checking
+            let hasGrammarError = checkGrammarDeclarationNameInStrictMode(node) || checkGrammarFunctionLikeDeclaration(node);
+            if (!hasGrammarError && node.kind === SyntaxKind.FunctionExpression) {
+                checkGrammarFunctionName(node.name) || checkGrammarForGenerator(node);
+            }
+
+            // The identityMapper object is used to indicate that function expressions are wildcards
+            if (contextualMapper === identityMapper && isContextSensitive(node)) {
+                return anyFunctionType;
+            }
+            let links = getNodeLinks(node);
+            let type = getTypeOfSymbol(node.symbol);
+            // Check if function expression is contextually typed and assign parameter types if so
+            if (!(links.flags & NodeCheckFlags.ContextChecked)) {
+                let contextualSignature = getContextualSignature(node);
+                // If a type check is started at a function expression that is an argument of a function call, obtaining the
+                // contextual type may recursively get back to here during overload resolution of the call. If so, we will have
+                // already assigned contextual types.
+                if (!(links.flags & NodeCheckFlags.ContextChecked)) {
+                    links.flags |= NodeCheckFlags.ContextChecked;
+                    if (contextualSignature) {
+                        let signature = getSignaturesOfType(type, SignatureKind.Call)[0];
+                        if (isContextSensitive(node)) {
+                            assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper);
+                        }
+                        if (!node.type) {
+                            signature.resolvedReturnType = resolvingType;
+                            let returnType = getReturnTypeFromBody(node, contextualMapper);
+                            if (signature.resolvedReturnType === resolvingType) {
+                                signature.resolvedReturnType = returnType;
+                            }
+                        }
+                    }
+                    checkSignatureDeclaration(node);
+                }
+            }
+
+            if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
+                checkCollisionWithCapturedSuperVariable(node, (<FunctionExpression>node).name);
+                checkCollisionWithCapturedThisVariable(node, (<FunctionExpression>node).name);
+            }
+
+            return type;
+        }
+
+        function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
+            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
+            if (node.type && !node.asteriskToken) {
+                checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
+            }
+
+            if (node.body) {
+                if (node.body.kind === SyntaxKind.Block) {
+                    checkSourceElement(node.body);
+                }
+                else {
+                    let exprType = checkExpression(<Expression>node.body);
+                    if (node.type) {
+                        checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
+                    }
+                    checkFunctionExpressionBodies(node.body);
+                }
+            }
+        }
+
+        function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean {
+            if (!allConstituentTypesHaveKind(type, TypeFlags.Any | TypeFlags.NumberLike)) {
+                error(operand, diagnostic);
+                return false;
+            }
+            return true;
+        }
+
+        function checkReferenceExpression(n: Node, invalidReferenceMessage: DiagnosticMessage, constantVariableMessage: DiagnosticMessage): boolean {
+            function findSymbol(n: Node): Symbol {
+                let symbol = getNodeLinks(n).resolvedSymbol;
+                // Because we got the symbol from the resolvedSymbol property, it might be of kind
+                // SymbolFlags.ExportValue. In this case it is necessary to get the actual export
+                // symbol, which will have the correct flags set on it.
+                return symbol && getExportSymbolOfValueSymbolIfExported(symbol);
+            }
+
+            function isReferenceOrErrorExpression(n: Node): boolean {
+                // TypeScript 1.0 spec (April 2014):
+                // Expressions are classified as values or references.
+                // References are the subset of expressions that are permitted as the target of an assignment.
+                // Specifically, references are combinations of identifiers(section 4.3), parentheses(section 4.7),
+                // and property accesses(section 4.10).
+                // All other expression constructs described in this chapter are classified as values.
+                switch (n.kind) {
+                    case SyntaxKind.Identifier: {
+                        let symbol = findSymbol(n);
+                        // TypeScript 1.0 spec (April 2014): 4.3
+                        // An identifier expression that references a variable or parameter is classified as a reference.
+                        // An identifier expression that references any other kind of entity is classified as a value(and therefore cannot be the target of an assignment).
+                        return !symbol || symbol === unknownSymbol || symbol === argumentsSymbol || (symbol.flags & SymbolFlags.Variable) !== 0;
+                    }
+                    case SyntaxKind.PropertyAccessExpression: {
+                        let symbol = findSymbol(n);
+                        // TypeScript 1.0 spec (April 2014): 4.10
+                        // A property access expression is always classified as a reference.
+                        // NOTE (not in spec): assignment to enum members should not be allowed
+                        return !symbol || symbol === unknownSymbol || (symbol.flags & ~SymbolFlags.EnumMember) !== 0;
+                    }
+                    case SyntaxKind.ElementAccessExpression:
+                        //  old compiler doesn't check indexed assess
+                        return true;
+                    case SyntaxKind.ParenthesizedExpression:
+                        return isReferenceOrErrorExpression((<ParenthesizedExpression>n).expression);
+                    default:
+                        return false;
+                }
+            }
+
+            function isConstVariableReference(n: Node): boolean {
+                switch (n.kind) {
+                    case SyntaxKind.Identifier:
+                    case SyntaxKind.PropertyAccessExpression: {
+                        let symbol = findSymbol(n);
+                        return symbol && (symbol.flags & SymbolFlags.Variable) !== 0 && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0;
+                    }
+                    case SyntaxKind.ElementAccessExpression: {
+                        let index = (<ElementAccessExpression>n).argumentExpression;
+                        let symbol = findSymbol((<ElementAccessExpression>n).expression);
+                        if (symbol && index && index.kind === SyntaxKind.StringLiteral) {
+                            let name = (<LiteralExpression>index).text;
+                            let prop = getPropertyOfType(getTypeOfSymbol(symbol), name);
+                            return prop && (prop.flags & SymbolFlags.Variable) !== 0 && (getDeclarationFlagsFromSymbol(prop) & NodeFlags.Const) !== 0;
+                        }
+                        return false;
+                    }
+                    case SyntaxKind.ParenthesizedExpression:
+                        return isConstVariableReference((<ParenthesizedExpression>n).expression);
+                    default:
+                        return false;
+                }
+            }
+
+            if (!isReferenceOrErrorExpression(n)) {
+                error(n, invalidReferenceMessage);
+                return false;
+            }
+
+            if (isConstVariableReference(n)) {
+                error(n, constantVariableMessage);
+                return false;
+            }
+
+            return true;
+        }
+
+        function checkDeleteExpression(node: DeleteExpression): Type {
+            // Grammar checking
+            if (node.parserContextFlags & ParserContextFlags.StrictMode && node.expression.kind === SyntaxKind.Identifier) {
+                // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
+                // UnaryExpression is a direct reference to a variable, function argument, or function name
+                grammarErrorOnNode(node.expression, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode);
+            }
+
+            let operandType = checkExpression(node.expression);
+            return booleanType;
+        }
+
+        function checkTypeOfExpression(node: TypeOfExpression): Type {
+            let operandType = checkExpression(node.expression);
+            return stringType;
+        }
+
+        function checkVoidExpression(node: VoidExpression): Type {
+            let operandType = checkExpression(node.expression);
+            return undefinedType;
+        }
+
+        function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
+            // Grammar checking
+            // The identifier eval or arguments may not appear as the LeftHandSideExpression of an
+            // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
+            // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
+            if ((node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken)) {
+                checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.operand);
+            }
+
+            let operandType = checkExpression(node.operand);
+            switch (node.operator) {
+                case SyntaxKind.PlusToken:
+                case SyntaxKind.MinusToken:
+                case SyntaxKind.TildeToken:
+                    if (someConstituentTypeHasKind(operandType, TypeFlags.ESSymbol)) {
+                        error(node.operand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(node.operator));
+                    }
+                    return numberType;
+                case SyntaxKind.ExclamationToken:
+                    return booleanType;
+                case SyntaxKind.PlusPlusToken:
+                case SyntaxKind.MinusMinusToken:
+                    let ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
+                    if (ok) {
+                        // run check only if former checks succeeded to avoid reporting cascading errors
+                        checkReferenceExpression(node.operand,
+                            Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer,
+                            Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
+                    }
+                    return numberType;
+            }
+            return unknownType;
+        }
+
+        function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type {
+            // Grammar checking
+            // The identifier eval or arguments may not appear as the LeftHandSideExpression of an
+            // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
+            // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
+            checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.operand);
+
+            let operandType = checkExpression(node.operand);
+            let ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
+            if (ok) {
+                // run check only if former checks succeeded to avoid reporting cascading errors
+                checkReferenceExpression(node.operand,
+                    Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer,
+                    Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
+            }
+            return numberType;
+        }
+
+        // Just like isTypeOfKind below, except that it returns true if *any* constituent
+        // has this kind.
+        function someConstituentTypeHasKind(type: Type, kind: TypeFlags): boolean {
+            if (type.flags & kind) {
+                return true;
+            }
+            if (type.flags & TypeFlags.Union) {
+                let types = (<UnionType>type).types;
+                for (let current of types) {
+                    if (current.flags & kind) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+            return false;
+        }
+
+        // Return true if type has the given flags, or is a union type composed of types that all have those flags.
+        function allConstituentTypesHaveKind(type: Type, kind: TypeFlags): boolean {
+            if (type.flags & kind) {
+                return true;
+            }
+            if (type.flags & TypeFlags.Union) {
+                let types = (<UnionType>type).types;
+                for (let current of types) {
+                    if (!(current.flags & kind)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+
+        function isConstEnumObjectType(type: Type): boolean {
+            return type.flags & (TypeFlags.ObjectType | TypeFlags.Anonymous) && type.symbol && isConstEnumSymbol(type.symbol);
+        }
+
+        function isConstEnumSymbol(symbol: Symbol): boolean {
+            return (symbol.flags & SymbolFlags.ConstEnum) !== 0;
+        }
+
+        function checkInstanceOfExpression(node: BinaryExpression, leftType: Type, rightType: Type): Type {
+            // TypeScript 1.0 spec (April 2014): 4.15.4
+            // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type,
+            // and the right operand to be of type Any or a subtype of the 'Function' interface type.
+            // The result is always of the Boolean primitive type.
+            // NOTE: do not raise error if leftType is unknown as related error was already reported
+            if (allConstituentTypesHaveKind(leftType, TypeFlags.Primitive)) {
+                error(node.left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
+            }
+            // NOTE: do not raise error if right is unknown as related error was already reported
+            if (!(rightType.flags & TypeFlags.Any || isTypeSubtypeOf(rightType, globalFunctionType))) {
+                error(node.right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
+            }
+            return booleanType;
+        }
+
+        function checkInExpression(node: BinaryExpression, leftType: Type, rightType: Type): Type {
+            // TypeScript 1.0 spec (April 2014): 4.15.5
+            // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
+            // and the right operand to be of type Any, an object type, or a type parameter type.
+            // The result is always of the Boolean primitive type.
+            if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
+                error(node.left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
+            }
+            if (!allConstituentTypesHaveKind(rightType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
+                error(node.right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
+            }
+            return booleanType;
+        }
+
+        function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
+            let properties = node.properties;
+            for (let p of properties) {
+                if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
+                    // TODO(andersh): Computed property support
+                    let name = <Identifier>(<PropertyAssignment>p).name;
+                    let type = sourceType.flags & TypeFlags.Any ? sourceType :
+                        getTypeOfPropertyOfType(sourceType, name.text) ||
+                        isNumericLiteralName(name.text) && getIndexTypeOfType(sourceType, IndexKind.Number) ||
+                        getIndexTypeOfType(sourceType, IndexKind.String);
+                    if (type) {
+                        checkDestructuringAssignment((<PropertyAssignment>p).initializer || name, type);
+                    }
+                    else {
+                        error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(sourceType), declarationNameToString(name));
+                    }
+                }
+                else {
+                    error(p, Diagnostics.Property_assignment_expected);
+                }
+            }
+            return sourceType;
+        }
+
+        function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
+            // This elementType will be used if the specific property corresponding to this index is not
+            // present (aka the tuple element property). This call also checks that the parentType is in
+            // fact an iterable or array (depending on target language).
+            let elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false) || unknownType;
+            let elements = node.elements;
+            for (let i = 0; i < elements.length; i++) {
+                let e = elements[i];
+                if (e.kind !== SyntaxKind.OmittedExpression) {
+                    if (e.kind !== SyntaxKind.SpreadElementExpression) {
+                        let propName = "" + i;
+                        let type = sourceType.flags & TypeFlags.Any ? sourceType :
+                            isTupleLikeType(sourceType)
+                                ? getTypeOfPropertyOfType(sourceType, propName)
+                                : elementType;
+                        if (type) {
+                            checkDestructuringAssignment(e, type, contextualMapper);
+                        }
+                        else {
+                            if (isTupleType(sourceType)) {
+                                error(e, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), (<TupleType>sourceType).elementTypes.length, elements.length);
+                            }
+                            else {
+                                error(e, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
+                            }
+                        }
+                    }
+                    else {
+                        if (i < elements.length - 1) {
+                            error(e, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
+                        }
+                        else {
+                            let restExpression = (<SpreadElementExpression>e).expression;
+                            if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
+                                error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
+                            }
+                            else {
+                                checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
+                            }
+                        }
+                    }
+                }
+            }
+            return sourceType;
+        }
+
+        function checkDestructuringAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type {
+            if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operatorToken.kind === SyntaxKind.EqualsToken) {
+                checkBinaryExpression(<BinaryExpression>target, contextualMapper);
+                target = (<BinaryExpression>target).left;
+            }
+            if (target.kind === SyntaxKind.ObjectLiteralExpression) {
+                return checkObjectLiteralAssignment(<ObjectLiteralExpression>target, sourceType, contextualMapper);
+            }
+            if (target.kind === SyntaxKind.ArrayLiteralExpression) {
+                return checkArrayLiteralAssignment(<ArrayLiteralExpression>target, sourceType, contextualMapper);
+            }
+            return checkReferenceAssignment(target, sourceType, contextualMapper);
+        }
+
+        function checkReferenceAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type {
+            let targetType = checkExpression(target, contextualMapper);
+            if (checkReferenceExpression(target, Diagnostics.Invalid_left_hand_side_of_assignment_expression, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant)) {
+                checkTypeAssignableTo(sourceType, targetType, target, /*headMessage*/ undefined);
+            }
+            return sourceType;
+        }
+
+        function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) {
+            // Grammar checking
+            if (isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) {
+                // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
+                // Assignment operator(11.13) or of a PostfixExpression(11.3)
+                checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.left);
+            }
+
+            let operator = node.operatorToken.kind;
+            if (operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
+                return checkDestructuringAssignment(node.left, checkExpression(node.right, contextualMapper), contextualMapper);
+            }
+            let leftType = checkExpression(node.left, contextualMapper);
+            let rightType = checkExpression(node.right, contextualMapper);
+            switch (operator) {
+                case SyntaxKind.AsteriskToken:
+                case SyntaxKind.AsteriskEqualsToken:
+                case SyntaxKind.SlashToken:
+                case SyntaxKind.SlashEqualsToken:
+                case SyntaxKind.PercentToken:
+                case SyntaxKind.PercentEqualsToken:
+                case SyntaxKind.MinusToken:
+                case SyntaxKind.MinusEqualsToken:
+                case SyntaxKind.LessThanLessThanToken:
+                case SyntaxKind.LessThanLessThanEqualsToken:
+                case SyntaxKind.GreaterThanGreaterThanToken:
+                case SyntaxKind.GreaterThanGreaterThanEqualsToken:
+                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
+                case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
+                case SyntaxKind.BarToken:
+                case SyntaxKind.BarEqualsToken:
+                case SyntaxKind.CaretToken:
+                case SyntaxKind.CaretEqualsToken:
+                case SyntaxKind.AmpersandToken:
+                case SyntaxKind.AmpersandEqualsToken:
+                    // TypeScript 1.0 spec (April 2014): 4.15.1
+                    // These operators require their operands to be of type Any, the Number primitive type,
+                    // or an enum type. Operands of an enum type are treated
+                    // as having the primitive type Number. If one operand is the null or undefined value,
+                    // it is treated as having the type of the other operand.
+                    // The result is always of the Number primitive type.
+                    if (leftType.flags & (TypeFlags.Undefined | TypeFlags.Null)) leftType = rightType;
+                    if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType;
+
+                    let suggestedOperator: SyntaxKind;
+                    // if a user tries to apply a bitwise operator to 2 boolean operands
+                    // try and return them a helpful suggestion
+                    if ((leftType.flags & TypeFlags.Boolean) &&
+                        (rightType.flags & TypeFlags.Boolean) &&
+                        (suggestedOperator = getSuggestedBooleanOperator(node.operatorToken.kind)) !== undefined) {
+                        error(node, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(node.operatorToken.kind), tokenToString(suggestedOperator));
+                    }
+                    else {
+                        // otherwise just check each operand separately and report errors as normal
+                        let leftOk = checkArithmeticOperandType(node.left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
+                        let rightOk = checkArithmeticOperandType(node.right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
+                        if (leftOk && rightOk) {
+                            checkAssignmentOperator(numberType);
+                        }
+                    }
+
+                    return numberType;
+                case SyntaxKind.PlusToken:
+                case SyntaxKind.PlusEqualsToken:
+                    // TypeScript 1.0 spec (April 2014): 4.15.2
+                    // The binary + operator requires both operands to be of the Number primitive type or an enum type,
+                    // or at least one of the operands to be of type Any or the String primitive type.
+
+                    // If one operand is the null or undefined value, it is treated as having the type of the other operand.
+                    if (leftType.flags & (TypeFlags.Undefined | TypeFlags.Null)) leftType = rightType;
+                    if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType;
+
+                    let resultType: Type;
+                    if (allConstituentTypesHaveKind(leftType, TypeFlags.NumberLike) && allConstituentTypesHaveKind(rightType, TypeFlags.NumberLike)) {
+                        // Operands of an enum type are treated as having the primitive type Number.
+                        // If both operands are of the Number primitive type, the result is of the Number primitive type.
+                        resultType = numberType;
+                    }
+                    else {
+                        if (allConstituentTypesHaveKind(leftType, TypeFlags.StringLike) || allConstituentTypesHaveKind(rightType, TypeFlags.StringLike)) {
+                            // If one or both operands are of the String primitive type, the result is of the String primitive type.
+                            resultType = stringType;
+                        }
+                        else if (leftType.flags & TypeFlags.Any || rightType.flags & TypeFlags.Any) {
+                            // Otherwise, the result is of type Any.
+                            // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we.
+                            resultType = anyType;
+                        }
+
+                        // Symbols are not allowed at all in arithmetic expressions
+                        if (resultType && !checkForDisallowedESSymbolOperand(operator)) {
+                            return resultType;
+                        }
+                    }
+
+                    if (!resultType) {
+                        reportOperatorError();
+                        return anyType;
+                    }
+
+                    if (operator === SyntaxKind.PlusEqualsToken) {
+                        checkAssignmentOperator(resultType);
+                    }
+                    return resultType;
+                case SyntaxKind.LessThanToken:
+                case SyntaxKind.GreaterThanToken:
+                case SyntaxKind.LessThanEqualsToken:
+                case SyntaxKind.GreaterThanEqualsToken:
+                    if (!checkForDisallowedESSymbolOperand(operator)) {
+                        return booleanType;
+                    }
+                    // Fall through
+                case SyntaxKind.EqualsEqualsToken:
+                case SyntaxKind.ExclamationEqualsToken:
+                case SyntaxKind.EqualsEqualsEqualsToken:
+                case SyntaxKind.ExclamationEqualsEqualsToken:
+                    if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) {
+                        reportOperatorError();
+                    }
+                    return booleanType;
+                case SyntaxKind.InstanceOfKeyword:
+                    return checkInstanceOfExpression(node, leftType, rightType);
+                case SyntaxKind.InKeyword:
+                    return checkInExpression(node, leftType, rightType);
+                case SyntaxKind.AmpersandAmpersandToken:
+                    return rightType;
+                case SyntaxKind.BarBarToken:
+                    return getUnionType([leftType, rightType]);
+                case SyntaxKind.EqualsToken:
+                    checkAssignmentOperator(rightType);
+                    return rightType;
+                case SyntaxKind.CommaToken:
+                    return rightType;
+            }
+
+            // Return true if there was no error, false if there was an error.
+            function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean {
+                let offendingSymbolOperand =
+                    someConstituentTypeHasKind(leftType, TypeFlags.ESSymbol) ? node.left :
+                    someConstituentTypeHasKind(rightType, TypeFlags.ESSymbol) ? node.right :
+                    undefined;
+                if (offendingSymbolOperand) {
+                    error(offendingSymbolOperand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(operator));
+                    return false;
+                }
+
+                return true;
+            }
+
+            function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind {
+                switch (operator) {
+                    case SyntaxKind.BarToken:
+                    case SyntaxKind.BarEqualsToken:
+                        return SyntaxKind.BarBarToken;
+                    case SyntaxKind.CaretToken:
+                    case SyntaxKind.CaretEqualsToken:
+                        return SyntaxKind.ExclamationEqualsEqualsToken;
+                    case SyntaxKind.AmpersandToken:
+                    case SyntaxKind.AmpersandEqualsToken:
+                        return SyntaxKind.AmpersandAmpersandToken;
+                    default:
+                        return undefined;
+                }
+            }
+
+            function checkAssignmentOperator(valueType: Type): void {
+                if (produceDiagnostics && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
+                    // TypeScript 1.0 spec (April 2014): 4.17
+                    // An assignment of the form
+                    //    VarExpr = ValueExpr
+                    // requires VarExpr to be classified as a reference
+                    // A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1)
+                    // and the type of the non - compound operation to be assignable to the type of VarExpr.
+                    let ok = checkReferenceExpression(node.left, Diagnostics.Invalid_left_hand_side_of_assignment_expression, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant);
+                    // Use default messages
+                    if (ok) {
+                        // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
+                        checkTypeAssignableTo(valueType, leftType, node.left, /*headMessage*/ undefined);
+                    }
+                }
+            }
+
+            function reportOperatorError() {
+                error(node, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, tokenToString(node.operatorToken.kind), typeToString(leftType), typeToString(rightType));
+            }
+        }
+
+        function checkYieldExpression(node: YieldExpression): void {
+            // Grammar checking
+            if (!(node.parserContextFlags & ParserContextFlags.Yield)) {
+                grammarErrorOnFirstToken(node, Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
+            }
+            else {
+                grammarErrorOnFirstToken(node, Diagnostics.yield_expressions_are_not_currently_supported);
+            }
+        }
+
+        function checkConditionalExpression(node: ConditionalExpression, contextualMapper?: TypeMapper): Type {
+            checkExpression(node.condition);
+            let type1 = checkExpression(node.whenTrue, contextualMapper);
+            let type2 = checkExpression(node.whenFalse, contextualMapper);
+            return getUnionType([type1, type2]);
+        }
+
+        function checkTemplateExpression(node: TemplateExpression): Type {
+            // We just want to check each expressions, but we are unconcerned with
+            // the type of each expression, as any value may be coerced into a string.
+            // It is worth asking whether this is what we really want though.
+            // A place where we actually *are* concerned with the expressions' types are
+            // in tagged templates.
+            forEach((<TemplateExpression>node).templateSpans, templateSpan => {
+                checkExpression(templateSpan.expression);
+            });
+
+            return stringType;
+        }
+
+        function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper?: TypeMapper): Type {
+            let saveContextualType = node.contextualType;
+            node.contextualType = contextualType;
+            let result = checkExpression(node, contextualMapper);
+            node.contextualType = saveContextualType;
+            return result;
+        }
+
+        function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
+            let links = getNodeLinks(node);
+            if (!links.resolvedType) {
+                links.resolvedType = checkExpression(node, contextualMapper);
+            }
+            return links.resolvedType;
+        }
+
+        function checkPropertyAssignment(node: PropertyAssignment, contextualMapper?: TypeMapper): Type {
+            // Do not use hasDynamicName here, because that returns false for well known symbols.
+            // We want to perform checkComputedPropertyName for all computed properties, including
+            // well known symbols.
+            if (node.name.kind === SyntaxKind.ComputedPropertyName) {
+                checkComputedPropertyName(<ComputedPropertyName>node.name);
+            }
+
+            return checkExpression((<PropertyAssignment>node).initializer, contextualMapper);
+        }
+
+        function checkObjectLiteralMethod(node: MethodDeclaration, contextualMapper?: TypeMapper): Type {
+            // Grammar checking
+            checkGrammarMethod(node);
+
+            // Do not use hasDynamicName here, because that returns false for well known symbols.
+            // We want to perform checkComputedPropertyName for all computed properties, including
+            // well known symbols.
+            if (node.name.kind === SyntaxKind.ComputedPropertyName) {
+                checkComputedPropertyName(<ComputedPropertyName>node.name);
+            }
+
+            let uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper);
+            return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper);
+        }
+
+        function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, contextualMapper?: TypeMapper) {
+            if (contextualMapper && contextualMapper !== identityMapper) {
+                let signature = getSingleCallSignature(type);
+                if (signature && signature.typeParameters) {
+                    let contextualType = getContextualType(<Expression>node);
+                    if (contextualType) {
+                        let contextualSignature = getSingleCallSignature(contextualType);
+                        if (contextualSignature && !contextualSignature.typeParameters) {
+                            return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
+                        }
+                    }
+                }
+            }
+
+            return type;
+        }
+
+        function checkExpression(node: Expression, contextualMapper?: TypeMapper): Type {
+            checkGrammarIdentifierInStrictMode(node);
+            return checkExpressionOrQualifiedName(node, contextualMapper);
+        }
+
+        // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
+        // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
+        // expression is being inferentially typed (section 4.12.2 in spec) and provides the type mapper to use in
+        // conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function
+        // object, it serves as an indicator that all contained function and arrow expressions should be considered to
+        // have the wildcard function type; this form of type check is used during overload resolution to exclude
+        // contextually typed function and arrow expressions in the initial phase.
+        function checkExpressionOrQualifiedName(node: Expression | QualifiedName, contextualMapper?: TypeMapper): Type {
+            let type: Type;
+            if (node.kind == SyntaxKind.QualifiedName) {
+                type = checkQualifiedName(<QualifiedName>node);
+            }
+            else {
+                let uninstantiatedType = checkExpressionWorker(<Expression>node, contextualMapper);
+                type = instantiateTypeWithSingleGenericCallSignature(<Expression>node, uninstantiatedType, contextualMapper);
+            }
+
+            if (isConstEnumObjectType(type)) {
+                // enum object type for const enums are only permitted in:
+                // - 'left' in property access
+                // - 'object' in indexed access
+                // - target in rhs of import statement
+                let ok =
+                    (node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).expression === node) ||
+                    (node.parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>node.parent).expression === node) ||
+                    ((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(<Identifier>node));
+
+                if (!ok) {
+                    error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment);
+                }
+            }
+            return type;
+        }
+
+        function checkNumericLiteral(node: LiteralExpression): Type {
+            // Grammar checking
+            checkGrammarNumericLiteral(node);
+            return numberType;
+        }
+
+        function checkExpressionWorker(node: Expression, contextualMapper: TypeMapper): Type {
+            switch (node.kind) {
+                case SyntaxKind.Identifier:
+                    return checkIdentifier(<Identifier>node);
+                case SyntaxKind.ThisKeyword:
+                    return checkThisExpression(node);
+                case SyntaxKind.SuperKeyword:
+                    return checkSuperExpression(node);
+                case SyntaxKind.NullKeyword:
+                    return nullType;
+                case SyntaxKind.TrueKeyword:
+                case SyntaxKind.FalseKeyword:
+                    return booleanType;
+                case SyntaxKind.NumericLiteral:
+                    return checkNumericLiteral(<LiteralExpression>node);
+                case SyntaxKind.TemplateExpression:
+                    return checkTemplateExpression(<TemplateExpression>node);
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.NoSubstitutionTemplateLiteral:
+                    return stringType;
+                case SyntaxKind.RegularExpressionLiteral:
+                    return globalRegExpType;
+                case SyntaxKind.ArrayLiteralExpression:
+                    return checkArrayLiteral(<ArrayLiteralExpression>node, contextualMapper);
+                case SyntaxKind.ObjectLiteralExpression:
+                    return checkObjectLiteral(<ObjectLiteralExpression>node, contextualMapper);
+                case SyntaxKind.PropertyAccessExpression:
+                    return checkPropertyAccessExpression(<PropertyAccessExpression>node);
+                case SyntaxKind.ElementAccessExpression:
+                    return checkIndexedAccess(<ElementAccessExpression>node);
+                case SyntaxKind.CallExpression:
+                case SyntaxKind.NewExpression:
+                    return checkCallExpression(<CallExpression>node);
+                case SyntaxKind.TaggedTemplateExpression:
+                    return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
+                case SyntaxKind.TypeAssertionExpression:
+                    return checkTypeAssertion(<TypeAssertion>node);
+                case SyntaxKind.ParenthesizedExpression:
+                    return checkExpression((<ParenthesizedExpression>node).expression, contextualMapper);
+                case SyntaxKind.ClassExpression:
+                    return checkClassExpression(<ClassExpression>node);
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                    return checkFunctionExpressionOrObjectLiteralMethod(<FunctionExpression>node, contextualMapper);
+                case SyntaxKind.TypeOfExpression:
+                    return checkTypeOfExpression(<TypeOfExpression>node);
+                case SyntaxKind.DeleteExpression:
+                    return checkDeleteExpression(<DeleteExpression>node);
+                case SyntaxKind.VoidExpression:
+                    return checkVoidExpression(<VoidExpression>node);
+                case SyntaxKind.PrefixUnaryExpression:
+                    return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
+                case SyntaxKind.PostfixUnaryExpression:
+                    return checkPostfixUnaryExpression(<PostfixUnaryExpression>node);
+                case SyntaxKind.BinaryExpression:
+                    return checkBinaryExpression(<BinaryExpression>node, contextualMapper);
+                case SyntaxKind.ConditionalExpression:
+                    return checkConditionalExpression(<ConditionalExpression>node, contextualMapper);
+                case SyntaxKind.SpreadElementExpression:
+                    return checkSpreadElementExpression(<SpreadElementExpression>node, contextualMapper);
+                case SyntaxKind.OmittedExpression:
+                    return undefinedType;
+                case SyntaxKind.YieldExpression:
+                    checkYieldExpression(<YieldExpression>node);
+                    return unknownType;
+            }
+            return unknownType;
+        }
+
+        // DECLARATION AND STATEMENT TYPE CHECKING
+
+        function checkTypeParameter(node: TypeParameterDeclaration) {
+            checkGrammarDeclarationNameInStrictMode(node);
+
+            // Grammar Checking
+            if (node.expression) {
+                grammarErrorOnFirstToken(node.expression, Diagnostics.Type_expected);
+            }
+
+            checkSourceElement(node.constraint);
+            if (produceDiagnostics) {
+                checkTypeParameterHasIllegalReferencesInConstraint(node);
+                checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
+            }
+            // TODO: Check multiple declarations are identical
+        }
+
+        function checkParameter(node: ParameterDeclaration) {
+            // Grammar checking
+            // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
+            // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code
+            // or if its FunctionBody is strict code(11.1.5).
+            // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
+            // strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
+
+            // Grammar checking
+            checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
+
+            checkVariableLikeDeclaration(node);
+            let func = getContainingFunction(node);
+            if (node.flags & NodeFlags.AccessibilityModifier) {
+                func = getContainingFunction(node);
+                if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
+                    error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
+                }
+            }
+            if (node.questionToken && isBindingPattern(node.name) && func.body) {
+                error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
+            }
+            
+            // Only check rest parameter type if it's not a binding pattern. Since binding patterns are
+            // not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
+            if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) {
+                error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
+            }
+        }
+
+        function checkSignatureDeclaration(node: SignatureDeclaration) {
+            // Grammar checking
+            if (node.kind === SyntaxKind.IndexSignature) {
+                checkGrammarIndexSignature(<SignatureDeclaration>node);
+            }
+            // TODO (yuisu): Remove this check in else-if when SyntaxKind.Construct is moved and ambient context is handled
+            else if (node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.ConstructorType ||
+                node.kind === SyntaxKind.CallSignature || node.kind === SyntaxKind.Constructor ||
+                node.kind === SyntaxKind.ConstructSignature) {
+                checkGrammarFunctionLikeDeclaration(<FunctionLikeDeclaration>node);
+            }
+
+            checkTypeParameters(node.typeParameters);
+
+            forEach(node.parameters, checkParameter);
+
+            if (node.type) {
+                checkSourceElement(node.type);
+            }
+
+            if (produceDiagnostics) {
+                checkCollisionWithArgumentsInGeneratedCode(node);
+                if (compilerOptions.noImplicitAny && !node.type) {
+                    switch (node.kind) {
+                        case SyntaxKind.ConstructSignature:
+                            error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
+                            break;
+                        case SyntaxKind.CallSignature:
+                            error(node, Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
+                            break;
+                    }
+                }
+            }
+
+            checkSpecializedSignatureDeclaration(node);
+        }
+
+        function checkTypeForDuplicateIndexSignatures(node: Node) {
+            if (node.kind === SyntaxKind.InterfaceDeclaration) {
+                let nodeSymbol = getSymbolOfNode(node);
+                // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration
+                // to prevent this run check only for the first declaration of a given kind
+                if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) {
+                    return;
+                }
+            }
+
+            // TypeScript 1.0 spec (April 2014)
+            // 3.7.4: An object type can contain at most one string index signature and one numeric index signature.
+            // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration
+            let indexSymbol = getIndexSymbol(getSymbolOfNode(node));
+            if (indexSymbol) {
+                let seenNumericIndexer = false;
+                let seenStringIndexer = false;
+                for (let decl of indexSymbol.declarations) {
+                    let declaration = <SignatureDeclaration>decl;
+                    if (declaration.parameters.length === 1 && declaration.parameters[0].type) {
+                        switch (declaration.parameters[0].type.kind) {
+                            case SyntaxKind.StringKeyword:
+                                if (!seenStringIndexer) {
+                                    seenStringIndexer = true;
+                                }
+                                else {
+                                    error(declaration, Diagnostics.Duplicate_string_index_signature);
+                                }
+                                break;
+                            case SyntaxKind.NumberKeyword:
+                                if (!seenNumericIndexer) {
+                                    seenNumericIndexer = true;
+                                }
+                                else {
+                                    error(declaration, Diagnostics.Duplicate_number_index_signature);
+                                }
+                                break;
+                        }
+                    }
+                }
+            }
+        }
+
+        function checkPropertyDeclaration(node: PropertyDeclaration) {
+            // Grammar checking
+            checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name);
+
+            checkVariableLikeDeclaration(node);
+        }
+
+        function checkMethodDeclaration(node: MethodDeclaration) {
+            // Grammar checking
+            checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name);
+
+            // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
+            checkFunctionLikeDeclaration(node);
+        }
+
+        function checkConstructorDeclaration(node: ConstructorDeclaration) {
+            // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function.
+            checkSignatureDeclaration(node);
+            // Grammar check for checking only related to constructoDeclaration
+            checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node);
+
+            checkSourceElement(node.body);
+
+            let symbol = getSymbolOfNode(node);
+            let firstDeclaration = getDeclarationOfKind(symbol, node.kind);
+            // Only type check the symbol once
+            if (node === firstDeclaration) {
+                checkFunctionOrConstructorSymbol(symbol);
+            }
+
+            // exit early in the case of signature - super checks are not relevant to them
+            if (nodeIsMissing(node.body)) {
+                return;
+            }
+
+            if (!produceDiagnostics) {
+                return;
+            }
+
+            function isSuperCallExpression(n: Node): boolean {
+                return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.SuperKeyword;
+            }
+
+            function containsSuperCall(n: Node): boolean {
+                if (isSuperCallExpression(n)) {
+                    return true;
+                }
+                switch (n.kind) {
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.ArrowFunction:
+                    case SyntaxKind.ObjectLiteralExpression: return false;
+                    default: return forEachChild(n, containsSuperCall);
+                }
+            }
+
+            function markThisReferencesAsErrors(n: Node): void {
+                if (n.kind === SyntaxKind.ThisKeyword) {
+                    error(n, Diagnostics.this_cannot_be_referenced_in_current_location);
+                }
+                else if (n.kind !== SyntaxKind.FunctionExpression && n.kind !== SyntaxKind.FunctionDeclaration) {
+                    forEachChild(n, markThisReferencesAsErrors);
+                }
+            }
+
+            function isInstancePropertyWithInitializer(n: Node): boolean {
+                return n.kind === SyntaxKind.PropertyDeclaration &&
+                    !(n.flags & NodeFlags.Static) &&
+                    !!(<PropertyDeclaration>n).initializer;
+            }
+
+            // TS 1.0 spec (April 2014): 8.3.2
+            // Constructors of classes with no extends clause may not contain super calls, whereas
+            // constructors of derived classes must contain at least one super call somewhere in their function body.
+            if (getClassExtendsHeritageClauseElement(<ClassDeclaration>node.parent)) {
+
+                if (containsSuperCall(node.body)) {
+                    // The first statement in the body of a constructor must be a super call if both of the following are true:
+                    // - The containing class is a derived class.
+                    // - The constructor declares parameter properties
+                    //   or the containing class declares instance member variables with initializers.
+                    let superCallShouldBeFirst =
+                        forEach((<ClassDeclaration>node.parent).members, isInstancePropertyWithInitializer) ||
+                        forEach(node.parameters, p => p.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected));
+
+                    if (superCallShouldBeFirst) {
+                        let statements = (<Block>node.body).statements;
+                        if (!statements.length || statements[0].kind !== SyntaxKind.ExpressionStatement || !isSuperCallExpression((<ExpressionStatement>statements[0]).expression)) {
+                            error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties);
+                        }
+                        else {
+                            // In such a required super call, it is a compile-time error for argument expressions to reference this.
+                            markThisReferencesAsErrors((<ExpressionStatement>statements[0]).expression);
+                        }
+                    }
+                }
+                else {
+                    error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call);
+                }
+            }
+        }
+
+        function checkAccessorDeclaration(node: AccessorDeclaration) {
+            if (produceDiagnostics) {
+                // Grammar checking accessors
+                checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name);
+
+                if (node.kind === SyntaxKind.GetAccessor) {
+                    if (!isInAmbientContext(node) && nodeIsPresent(node.body) && !(bodyContainsAReturnStatement(<Block>node.body) || bodyContainsSingleThrowStatement(<Block>node.body))) {
+                        error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
+                    }
+                }
+
+                if (!hasDynamicName(node)) {
+                    // TypeScript 1.0 spec (April 2014): 8.4.3
+                    // Accessors for the same member name must specify the same accessibility.
+                    let otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
+                    let otherAccessor = <AccessorDeclaration>getDeclarationOfKind(node.symbol, otherKind);
+                    if (otherAccessor) {
+                        if (((node.flags & NodeFlags.AccessibilityModifier) !== (otherAccessor.flags & NodeFlags.AccessibilityModifier))) {
+                            error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility);
+                        }
+
+                        let currentAccessorType = getAnnotatedAccessorType(node);
+                        let otherAccessorType = getAnnotatedAccessorType(otherAccessor);
+                        // TypeScript 1.0 spec (April 2014): 4.5
+                        // If both accessors include type annotations, the specified types must be identical.
+                        if (currentAccessorType && otherAccessorType) {
+                            if (!isTypeIdenticalTo(currentAccessorType, otherAccessorType)) {
+                                error(node, Diagnostics.get_and_set_accessor_must_have_the_same_type);
+                            }
+                        }
+                    }
+                }
+
+                checkAndStoreTypeOfAccessors(getSymbolOfNode(node));
+            }
+
+            checkFunctionLikeDeclaration(node);
+        }
+
+        function checkMissingDeclaration(node: Node) {
+            checkDecorators(node);
+        }
+
+        function checkTypeReferenceNode(node: TypeReferenceNode) {
+            checkGrammarTypeReferenceInStrictMode(node.typeName);
+            return checkTypeReferenceOrHeritageClauseElement(node);
+        }
+
+        function checkHeritageClauseElement(node: HeritageClauseElement) {
+            checkGrammarHeritageClauseElementInStrictMode(<PropertyAccessExpression>node.expression);
+
+            return checkTypeReferenceOrHeritageClauseElement(node);
+        }
+
+        function checkTypeReferenceOrHeritageClauseElement(node: TypeReferenceNode | HeritageClauseElement) {
+            // Grammar checking
+            checkGrammarTypeArguments(node, node.typeArguments);
+
+            let type = getTypeFromTypeReferenceOrHeritageClauseElement(node);
+            if (type !== unknownType && node.typeArguments) {
+                // Do type argument local checks only if referenced type is successfully resolved
+                let len = node.typeArguments.length;
+                for (let i = 0; i < len; i++) {
+                    checkSourceElement(node.typeArguments[i]);
+                    let constraint = getConstraintOfTypeParameter((<TypeReference>type).target.typeParameters[i]);
+                    if (produceDiagnostics && constraint) {
+                        let typeArgument = (<TypeReference>type).typeArguments[i];
+                        checkTypeAssignableTo(typeArgument, constraint, node, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
+                    }
+                }
+            }
+        }
+
+        function checkTypeQuery(node: TypeQueryNode) {
+            getTypeFromTypeQueryNode(node);
+        }
+
+        function checkTypeLiteral(node: TypeLiteralNode) {
+            forEach(node.members, checkSourceElement);
+            if (produceDiagnostics) {
+                let type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
+                checkIndexConstraints(type);
+                checkTypeForDuplicateIndexSignatures(node);
+            }
+        }
+
+        function checkArrayType(node: ArrayTypeNode) {
+            checkSourceElement(node.elementType);
+        }
+
+        function checkTupleType(node: TupleTypeNode) {
+            // Grammar checking
+            let hasErrorFromDisallowedTrailingComma = checkGrammarForDisallowedTrailingComma(node.elementTypes);
+            if (!hasErrorFromDisallowedTrailingComma && node.elementTypes.length === 0) {
+                grammarErrorOnNode(node, Diagnostics.A_tuple_type_element_list_cannot_be_empty);
+            }
+
+            forEach(node.elementTypes, checkSourceElement);
+        }
+
+        function checkUnionType(node: UnionTypeNode) {
+            forEach(node.types, checkSourceElement);
+        }
+
+        function isPrivateWithinAmbient(node: Node): boolean {
+            return (node.flags & NodeFlags.Private) && isInAmbientContext(node);
+        }
+
+        function checkSpecializedSignatureDeclaration(signatureDeclarationNode: SignatureDeclaration): void {
+            if (!produceDiagnostics) {
+                return;
+            }
+            let signature = getSignatureFromDeclaration(signatureDeclarationNode);
+            if (!signature.hasStringLiterals) {
+                return;
+            }
+
+            // TypeScript 1.0 spec (April 2014): 3.7.2.2
+            // Specialized signatures are not permitted in conjunction with a function body
+            if (nodeIsPresent((<FunctionLikeDeclaration>signatureDeclarationNode).body)) {
+                error(signatureDeclarationNode, Diagnostics.A_signature_with_an_implementation_cannot_use_a_string_literal_type);
+                return;
+            }
+
+            // TypeScript 1.0 spec (April 2014): 3.7.2.4
+            // Every specialized call or construct signature in an object type must be assignable
+            // to at least one non-specialized call or construct signature in the same object type
+            let signaturesToCheck: Signature[];
+            // Unnamed (call\construct) signatures in interfaces are inherited and not shadowed so examining just node symbol won't give complete answer.
+            // Use declaring type to obtain full list of signatures.
+            if (!signatureDeclarationNode.name && signatureDeclarationNode.parent && signatureDeclarationNode.parent.kind === SyntaxKind.InterfaceDeclaration) {
+                Debug.assert(signatureDeclarationNode.kind === SyntaxKind.CallSignature || signatureDeclarationNode.kind === SyntaxKind.ConstructSignature);
+                let signatureKind = signatureDeclarationNode.kind === SyntaxKind.CallSignature ? SignatureKind.Call : SignatureKind.Construct;
+                let containingSymbol = getSymbolOfNode(signatureDeclarationNode.parent);
+                let containingType = getDeclaredTypeOfSymbol(containingSymbol);
+                signaturesToCheck = getSignaturesOfType(containingType, signatureKind);
+            }
+            else {
+                signaturesToCheck = getSignaturesOfSymbol(getSymbolOfNode(signatureDeclarationNode));
+            }
+
+            for (let otherSignature of signaturesToCheck) {
+                if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) {
+                    return;
+                }
+            }
+
+            error(signatureDeclarationNode, Diagnostics.Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature);
+        }
+
+        function getEffectiveDeclarationFlags(n: Node, flagsToCheck: NodeFlags) {
+            let flags = getCombinedNodeFlags(n);
+            if (n.parent.kind !== SyntaxKind.InterfaceDeclaration && isInAmbientContext(n)) {
+                if (!(flags & NodeFlags.Ambient)) {
+                    // It is nested in an ambient context, which means it is automatically exported
+                    flags |= NodeFlags.Export;
+                }
+                flags |= NodeFlags.Ambient;
+            }
+
+            return flags & flagsToCheck;
+        }
+
+        function checkFunctionOrConstructorSymbol(symbol: Symbol): void {
+            if (!produceDiagnostics) {
+                return;
+            }
+
+            function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration) {
+                // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration
+                // Error on all deviations from this canonical set of flags
+                // The caveat is that if some overloads are defined in lib.d.ts, we don't want to
+                // report the errors on those. To achieve this, we will say that the implementation is
+                // the canonical signature only if it is in the same container as the first overload
+                let implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
+                return implementationSharesContainerWithFirstOverload ? implementation : overloads[0];
+            }
+
+            function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void {
+                // Error if some overloads have a flag that is not shared by all overloads. To find the
+                // deviations, we XOR someOverloadFlags with allOverloadFlags
+                let someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
+                if (someButNotAllOverloadFlags !== 0) {
+                    let canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck);
+
+                    forEach(overloads, o => {
+                        let deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
+                        if (deviation & NodeFlags.Export) {
+                            error(o.name, Diagnostics.Overload_signatures_must_all_be_exported_or_not_exported);
+                        }
+                        else if (deviation & NodeFlags.Ambient) {
+                            error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
+                        }
+                        else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) {
+                            error(o.name, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
+                        }
+                    });
+                }
+            }
+
+            function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void {
+                if (someHaveQuestionToken !== allHaveQuestionToken) {
+                    let canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation));
+                    forEach(overloads, o => {
+                        let deviation = hasQuestionToken(o) !== canonicalHasQuestionToken;
+                        if (deviation) {
+                            error(o.name, Diagnostics.Overload_signatures_must_all_be_optional_or_required);
+                        }
+                    });
+                }
+            }
+
+            let flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected;
+            let someNodeFlags: NodeFlags = 0;
+            let allNodeFlags = flagsToCheck;
+            let someHaveQuestionToken = false;
+            let allHaveQuestionToken = true;
+            let hasOverloads = false;
+            let bodyDeclaration: FunctionLikeDeclaration;
+            let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration;
+            let previousDeclaration: FunctionLikeDeclaration;
+
+            let declarations = symbol.declarations;
+            let isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0;
+
+            function reportImplementationExpectedError(node: FunctionLikeDeclaration): void {
+                if (node.name && nodeIsMissing(node.name)) {
+                    return;
+                }
+
+                let seen = false;
+                let subsequentNode = forEachChild(node.parent, c => {
+                    if (seen) {
+                        return c;
+                    }
+                    else {
+                        seen = c === node;
+                    }
+                });
+                if (subsequentNode) {
+                    if (subsequentNode.kind === node.kind) {
+                        let errorNode: Node = (<FunctionLikeDeclaration>subsequentNode).name || subsequentNode;
+                        // TODO(jfreeman): These are methods, so handle computed name case
+                        if (node.name && (<FunctionLikeDeclaration>subsequentNode).name && (<Identifier>node.name).text === (<Identifier>(<FunctionLikeDeclaration>subsequentNode).name).text) {
+                            // the only situation when this is possible (same kind\same name but different symbol) - mixed static and instance class members
+                            Debug.assert(node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature);
+                            Debug.assert((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static));
+                            let diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static;
+                            error(errorNode, diagnostic);
+                            return;
+                        }
+                        else if (nodeIsPresent((<FunctionLikeDeclaration>subsequentNode).body)) {
+                            error(errorNode, Diagnostics.Function_implementation_name_must_be_0, declarationNameToString(node.name));
+                            return;
+                        }
+                    }
+                }
+                let errorNode: Node = node.name || node;
+                if (isConstructor) {
+                    error(errorNode, Diagnostics.Constructor_implementation_is_missing);
+                }
+                else {
+                    error(errorNode, Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration);
+                }
+            }
+
+            // when checking exported function declarations across modules check only duplicate implementations
+            // names and consistency of modifiers are verified when we check local symbol
+            let isExportSymbolInsideModule = symbol.parent && symbol.parent.flags & SymbolFlags.Module;
+            let duplicateFunctionDeclaration = false;
+            let multipleConstructorImplementation = false;
+            for (let current of declarations) {
+                let node = <FunctionLikeDeclaration>current;
+                let inAmbientContext = isInAmbientContext(node);
+                let inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext;
+                if (inAmbientContextOrInterface) {
+                    // check if declarations are consecutive only if they are non-ambient
+                    // 1. ambient declarations can be interleaved
+                    // i.e. this is legal
+                    //     declare function foo();
+                    //     declare function bar();
+                    //     declare function foo();
+                    // 2. mixing ambient and non-ambient declarations is a separate error that will be reported - do not want to report an extra one
+                    previousDeclaration = undefined;
+                }
+
+                if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.Constructor) {
+                    let currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
+                    someNodeFlags |= currentNodeFlags;
+                    allNodeFlags &= currentNodeFlags;
+                    someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node);
+                    allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node);
+
+                    if (nodeIsPresent(node.body) && bodyDeclaration) {
+                        if (isConstructor) {
+                            multipleConstructorImplementation = true;
+                        }
+                        else {
+                            duplicateFunctionDeclaration = true;
+                        }
+                    }
+                    else if (!isExportSymbolInsideModule && previousDeclaration && previousDeclaration.parent === node.parent && previousDeclaration.end !== node.pos) {
+                        reportImplementationExpectedError(previousDeclaration);
+                    }
+
+                    if (nodeIsPresent(node.body)) {
+                        if (!bodyDeclaration) {
+                            bodyDeclaration = node;
+                        }
+                    }
+                    else {
+                        hasOverloads = true;
+                    }
+
+                    previousDeclaration = node;
+
+                    if (!inAmbientContextOrInterface) {
+                        lastSeenNonAmbientDeclaration = node;
+                    }
+                }
+            }
+
+            if (multipleConstructorImplementation) {
+                forEach(declarations, declaration => {
+                    error(declaration, Diagnostics.Multiple_constructor_implementations_are_not_allowed);
+                });
+            }
+
+            if (duplicateFunctionDeclaration) {
+                forEach(declarations, declaration => {
+                    error(declaration.name, Diagnostics.Duplicate_function_implementation);
+                });
+            }
+
+            if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body) {
+                reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
+            }
+
+            if (hasOverloads) {
+                checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags);
+                checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken);
+
+                if (bodyDeclaration) {
+                    let signatures = getSignaturesOfSymbol(symbol);
+                    let bodySignature = getSignatureFromDeclaration(bodyDeclaration);
+                    // If the implementation signature has string literals, we will have reported an error in
+                    // checkSpecializedSignatureDeclaration
+                    if (!bodySignature.hasStringLiterals) {
+                        // TypeScript 1.0 spec (April 2014): 6.1
+                        // If a function declaration includes overloads, the overloads determine the call
+                        // signatures of the type given to the function object
+                        // and the function implementation signature must be assignable to that type
+                        //
+                        // TypeScript 1.0 spec (April 2014): 3.8.4
+                        // Note that specialized call and construct signatures (section 3.7.2.4) are not significant when determining assignment compatibility
+                        // Consider checking against specialized signatures too. Not doing so creates a type hole:
+                        //
+                        // function g(x: "hi", y: boolean);
+                        // function g(x: string, y: {});
+                        // function g(x: string, y: string) { }
+                        //
+                        // The implementation is completely unrelated to the specialized signature, yet we do not check this.
+                        for (let signature of signatures) {
+                            if (!signature.hasStringLiterals && !isSignatureAssignableTo(bodySignature, signature)) {
+                                error(signature.declaration, Diagnostics.Overload_signature_is_not_compatible_with_function_implementation);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        function checkExportsOnMergedDeclarations(node: Node): void {
+            if (!produceDiagnostics) {
+                return;
+            }
+
+            // Exports should be checked only if enclosing module contains both exported and non exported declarations.
+            // In case if all declarations are non-exported check is unnecessary.
+
+            // if localSymbol is defined on node then node itself is exported - check is required
+            let symbol = node.localSymbol;
+            if (!symbol) {
+                // local symbol is undefined => this declaration is non-exported.
+                // however symbol might contain other declarations that are exported
+                symbol = getSymbolOfNode(node);
+                if (!(symbol.flags & SymbolFlags.Export)) {
+                    // this is a pure local symbol (all declarations are non-exported) - no need to check anything
+                    return;
+                }
+            }
+
+            // run the check only for the first declaration in the list
+            if (getDeclarationOfKind(symbol, node.kind) !== node) {
+                return;
+            }
+
+            // we use SymbolFlags.ExportValue, SymbolFlags.ExportType and SymbolFlags.ExportNamespace
+            // to denote disjoint declarationSpaces (without making new enum type).
+            let exportedDeclarationSpaces: SymbolFlags = 0;
+            let nonExportedDeclarationSpaces: SymbolFlags = 0;
+            forEach(symbol.declarations, d => {
+                let declarationSpaces = getDeclarationSpaces(d);
+                if (getEffectiveDeclarationFlags(d, NodeFlags.Export)) {
+                    exportedDeclarationSpaces |= declarationSpaces;
+                }
+                else {
+                    nonExportedDeclarationSpaces |= declarationSpaces;
+                }
+            });
+
+            let commonDeclarationSpace = exportedDeclarationSpaces & nonExportedDeclarationSpaces;
+
+            if (commonDeclarationSpace) {
+                // declaration spaces for exported and non-exported declarations intersect
+                forEach(symbol.declarations, d => {
+                    if (getDeclarationSpaces(d) & commonDeclarationSpace) {
+                        error(d.name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(d.name));
+                    }
+                });
+            }
+
+            function getDeclarationSpaces(d: Declaration): SymbolFlags {
+                switch (d.kind) {
+                    case SyntaxKind.InterfaceDeclaration:
+                        return SymbolFlags.ExportType;
+                    case SyntaxKind.ModuleDeclaration:
+                        return (<ModuleDeclaration>d).name.kind === SyntaxKind.StringLiteral || getModuleInstanceState(d) !== ModuleInstanceState.NonInstantiated
+                            ? SymbolFlags.ExportNamespace | SymbolFlags.ExportValue
+                            : SymbolFlags.ExportNamespace;
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                        return SymbolFlags.ExportType | SymbolFlags.ExportValue;
+                    case SyntaxKind.ImportEqualsDeclaration:
+                        let result: SymbolFlags = 0;
+                        let target = resolveAlias(getSymbolOfNode(d));
+                        forEach(target.declarations, d => { result |= getDeclarationSpaces(d); });
+                        return result;
+                    default:
+                        return SymbolFlags.ExportValue;
+                }
+            }
+        }
+
+        /** Check a decorator */
+        function checkDecorator(node: Decorator): void {
+            let expression: Expression = node.expression;
+            let exprType = checkExpression(expression);
+
+            switch (node.parent.kind) {
+                case SyntaxKind.ClassDeclaration:
+                    let classSymbol = getSymbolOfNode(node.parent);
+                    let classConstructorType = getTypeOfSymbol(classSymbol);
+                    let classDecoratorType = instantiateSingleCallFunctionType(getGlobalClassDecoratorType(), [classConstructorType]);
+                    checkTypeAssignableTo(exprType, classDecoratorType, node);
+                    break;
+
+                case SyntaxKind.PropertyDeclaration:
+                    checkTypeAssignableTo(exprType, getGlobalPropertyDecoratorType(), node);
+                    break;
+
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                    let methodType = getTypeOfNode(node.parent);
+                    let methodDecoratorType = instantiateSingleCallFunctionType(getGlobalMethodDecoratorType(), [methodType]);
+                    checkTypeAssignableTo(exprType, methodDecoratorType, node);
+                    break;
+
+                case SyntaxKind.Parameter:
+                    checkTypeAssignableTo(exprType, getGlobalParameterDecoratorType(), node);
+                    break;
+            }
+        }
+
+        /** Checks a type reference node as an expression. */
+        function checkTypeNodeAsExpression(node: TypeNode) {
+            // When we are emitting type metadata for decorators, we need to try to check the type
+            // as if it were an expression so that we can emit the type in a value position when we 
+            // serialize the type metadata.
+            if (node && node.kind === SyntaxKind.TypeReference) {
+                let type = getTypeFromTypeNode(node);
+                let shouldCheckIfUnknownType = type === unknownType && compilerOptions.separateCompilation;
+                if (!type || (!shouldCheckIfUnknownType && type.flags & (TypeFlags.Intrinsic | TypeFlags.NumberLike | TypeFlags.StringLike))) {
+                    return;
+                }
+                if (shouldCheckIfUnknownType || type.symbol.valueDeclaration) {
+                    checkExpressionOrQualifiedName((<TypeReferenceNode>node).typeName);
+                }
+            }
+        }
+
+        /**
+          * Checks the type annotation of an accessor declaration or property declaration as 
+          * an expression if it is a type reference to a type with a value declaration.
+          */
+        function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) {
+            switch (node.kind) {
+                case SyntaxKind.PropertyDeclaration:
+                    checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
+                    break;
+                case SyntaxKind.Parameter:
+                    checkTypeNodeAsExpression((<ParameterDeclaration>node).type);
+                    break;
+                case SyntaxKind.MethodDeclaration:
+                    checkTypeNodeAsExpression((<MethodDeclaration>node).type);
+                    break;
+                case SyntaxKind.GetAccessor:
+                    checkTypeNodeAsExpression((<AccessorDeclaration>node).type);
+                    break;
+                case SyntaxKind.SetAccessor:
+                    checkTypeNodeAsExpression(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
+                    break;
+            }
+        }
+        
+        /** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
+        function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) {
+            // ensure all type annotations with a value declaration are checked as an expression
+            for (let parameter of node.parameters) {
+                checkTypeAnnotationAsExpression(parameter);
+            }
+        }
+
+        /** Check the decorators of a node */
+        function checkDecorators(node: Node): void {
+            if (!node.decorators) {
+                return;
+            }
+
+            // skip this check for nodes that cannot have decorators. These should have already had an error reported by
+            // checkGrammarDecorators.
+            if (!nodeCanBeDecorated(node)) {
+                return;
+            }
+
+            if (compilerOptions.emitDecoratorMetadata) {
+                // we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator.
+                switch (node.kind) {
+                    case SyntaxKind.ClassDeclaration:
+                        var constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
+                        if (constructor) {
+                            checkParameterTypeAnnotationsAsExpressions(constructor);
+                        }
+                        break;
+
+                    case SyntaxKind.MethodDeclaration:
+                        checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
+                        // fall-through
+
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.Parameter:
+                        checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
+                        break;
+                }
+            }
+
+            emitDecorate = true;
+            if (node.kind === SyntaxKind.Parameter) {
+                emitParam = true;
+            }
+
+            forEach(node.decorators, checkDecorator);
+        }
+
+        function checkFunctionDeclaration(node: FunctionDeclaration): void {
+            if (produceDiagnostics) {
+                checkFunctionLikeDeclaration(node) ||
+                checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) ||
+                checkGrammarFunctionName(node.name) ||
+                checkGrammarForGenerator(node);
+
+                checkCollisionWithCapturedSuperVariable(node, node.name);
+                checkCollisionWithCapturedThisVariable(node, node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            }
+        }
+
+        function checkFunctionLikeDeclaration(node: FunctionLikeDeclaration): void {
+            checkGrammarDeclarationNameInStrictMode(node);
+            checkDecorators(node);
+            checkSignatureDeclaration(node);
+
+            // Do not use hasDynamicName here, because that returns false for well known symbols.
+            // We want to perform checkComputedPropertyName for all computed properties, including
+            // well known symbols.
+            if (node.name && node.name.kind === SyntaxKind.ComputedPropertyName) {
+                // This check will account for methods in class/interface declarations,
+                // as well as accessors in classes/object literals
+                checkComputedPropertyName(<ComputedPropertyName>node.name);
+            }
+
+            if (!hasDynamicName(node)) {
+                // first we want to check the local symbol that contain this declaration
+                // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol
+                // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode
+                let symbol = getSymbolOfNode(node);
+                let localSymbol = node.localSymbol || symbol;
+
+                let firstDeclaration = getDeclarationOfKind(localSymbol, node.kind);
+                // Only type check the symbol once
+                if (node === firstDeclaration) {
+                    checkFunctionOrConstructorSymbol(localSymbol);
+                }
+
+                if (symbol.parent) {
+                    // run check once for the first declaration
+                    if (getDeclarationOfKind(symbol, node.kind) === node) {
+                        // run check on export symbol to check that modifiers agree across all exported declarations
+                        checkFunctionOrConstructorSymbol(symbol);
+                    }
+                }
+            }
+
+            checkSourceElement(node.body);
+            if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
+                checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
+            }
+
+            // Report an implicit any error if there is no body, no explicit return type, and node is not a private method
+            // in an ambient context
+            if (compilerOptions.noImplicitAny && nodeIsMissing(node.body) && !node.type && !isPrivateWithinAmbient(node)) {
+                reportImplicitAnyError(node, anyType);
+            }
+        }
+
+        function checkBlock(node: Block) {
+            // Grammar checking for SyntaxKind.Block
+            if (node.kind === SyntaxKind.Block) {
+                checkGrammarStatementInAmbientContext(node);
+            }
+
+            forEach(node.statements, checkSourceElement);
+            if (isFunctionBlock(node) || node.kind === SyntaxKind.ModuleBlock) {
+                checkFunctionExpressionBodies(node);
+            }
+        }
+
+        function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) {
+            // no rest parameters \ declaration context \ overload - no codegen impact
+            if (!hasRestParameters(node) || isInAmbientContext(node) || nodeIsMissing((<FunctionLikeDeclaration>node).body)) {
+                return;
+            }
+
+            forEach(node.parameters, p => {
+                if (p.name && !isBindingPattern(p.name) && (<Identifier>p.name).text === argumentsSymbol.name) {
+                    error(p, Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters);
+                }
+            });
+        }
+
+        function needCollisionCheckForIdentifier(node: Node, identifier: Identifier, name: string): boolean {
+            if (!(identifier && identifier.text === name)) {
+                return false;
+            }
+
+            if (node.kind === SyntaxKind.PropertyDeclaration ||
+                node.kind === SyntaxKind.PropertySignature ||
+                node.kind === SyntaxKind.MethodDeclaration ||
+                node.kind === SyntaxKind.MethodSignature ||
+                node.kind === SyntaxKind.GetAccessor ||
+                node.kind === SyntaxKind.SetAccessor) {
+                // it is ok to have member named '_super' or '_this' - member access is always qualified
+                return false;
+            }
+
+            if (isInAmbientContext(node)) {
+                // ambient context - no codegen impact
+                return false;
+            }
+
+            let root = getRootDeclaration(node);
+            if (root.kind === SyntaxKind.Parameter && nodeIsMissing((<FunctionLikeDeclaration>root.parent).body)) {
+                // just an overload - no codegen impact
+                return false;
+            }
+
+            return true;
+        }
+
+        function checkCollisionWithCapturedThisVariable(node: Node, name: Identifier): void {
+            if (needCollisionCheckForIdentifier(node, name, "_this")) {
+                potentialThisCollisions.push(node);
+            }
+        }
+
+        // this function will run after checking the source file so 'CaptureThis' is correct for all nodes
+        function checkIfThisIsCapturedInEnclosingScope(node: Node): void {
+            let current = node;
+            while (current) {
+                if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureThis) {
+                    let isDeclaration = node.kind !== SyntaxKind.Identifier;
+                    if (isDeclaration) {
+                        error((<Declaration>node).name, Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference);
+                    }
+                    else {
+                        error(node, Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference);
+                    }
+                    return;
+                }
+                current = current.parent;
+            }
+        }
+
+        function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) {
+            if (!needCollisionCheckForIdentifier(node, name, "_super")) {
+                return;
+            }
+
+            // bubble up and find containing type
+            let enclosingClass = <ClassDeclaration>getAncestor(node, SyntaxKind.ClassDeclaration);
+            // if containing type was not found or it is ambient - exit (no codegen)
+            if (!enclosingClass || isInAmbientContext(enclosingClass)) {
+                return;
+            }
+
+            if (getClassExtendsHeritageClauseElement(enclosingClass)) {
+                let isDeclaration = node.kind !== SyntaxKind.Identifier;
+                if (isDeclaration) {
+                    error(node, Diagnostics.Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference);
+                }
+                else {
+                    error(node, Diagnostics.Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference);
+                }
+            }
+        }
+
+        function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) {
+            if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
+                return;
+            }
+
+            // Uninstantiated modules shouldnt do this check
+            if (node.kind === SyntaxKind.ModuleDeclaration && getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) {
+                return;
+            }
+
+            // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
+            let parent = getDeclarationContainer(node);
+            if (parent.kind === SyntaxKind.SourceFile && isExternalModule(<SourceFile>parent)) {
+                // If the declaration happens to be in external module, report error that require and exports are reserved keywords
+                error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module,
+                    declarationNameToString(name), declarationNameToString(name));
+            }
+        }
+
+        function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) {
+            // - ScriptBody : StatementList
+            // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
+            // also occurs in the VarDeclaredNames of StatementList.
+
+            // - Block : { StatementList }
+            // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
+            // also occurs in the VarDeclaredNames of StatementList.
+
+            // Variable declarations are hoisted to the top of their function scope. They can shadow
+            // block scoped declarations, which bind tighter. this will not be flagged as duplicate definition
+            // by the binder as the declaration scope is different.
+            // A non-initialized declaration is a no-op as the block declaration will resolve before the var
+            // declaration. the problem is if the declaration has an initializer. this will act as a write to the
+            // block declared value. this is fine for let, but not const.
+            // Only consider declarations with initializers, uninitialized let declarations will not
+            // step on a let/const variable.
+            // Do not consider let and const declarations, as duplicate block-scoped declarations
+            // are handled by the binder.
+            // We are only looking for let declarations that step on let\const declarations from a
+            // different scope. e.g.:
+            //      {
+            //          const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration
+            //          let x = 0; // symbol for this declaration will be 'symbol'
+            //      }
+
+            // skip block-scoped variables and parameters
+            if ((getCombinedNodeFlags(node) & NodeFlags.BlockScoped) !== 0 || isParameterDeclaration(node)) {
+                return;
+            }
+
+            // skip variable declarations that don't have initializers
+            // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern
+            // so we'll always treat binding elements as initialized
+            if (node.kind === SyntaxKind.VariableDeclaration && !node.initializer) {
+                return;
+            }
+
+            var symbol = getSymbolOfNode(node);
+            if (symbol.flags & SymbolFlags.FunctionScopedVariable) {
+                let localDeclarationSymbol = resolveName(node, (<Identifier>node.name).text, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
+                if (localDeclarationSymbol &&
+                    localDeclarationSymbol !== symbol &&
+                    localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) {
+                    if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) {
+                        let varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList);
+                        let container =
+                            varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent
+                                ? varDeclList.parent.parent
+                                : undefined;
+
+                        // names of block-scoped and function scoped variables can collide only
+                        // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting)
+                        let namesShareScope =
+                            container &&
+                            (container.kind === SyntaxKind.Block && isFunctionLike(container.parent) ||
+                                container.kind === SyntaxKind.ModuleBlock ||
+                                container.kind === SyntaxKind.ModuleDeclaration ||
+                                container.kind === SyntaxKind.SourceFile);
+
+                        // here we know that function scoped variable is shadowed by block scoped one
+                        // if they are defined in the same scope - binder has already reported redeclaration error
+                        // otherwise if variable has an initializer - show error that initialization will fail
+                        // since LHS will be block scoped name instead of function scoped
+                        if (!namesShareScope) {
+                            let name = symbolToString(localDeclarationSymbol);
+                            error(node, Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name);
+                        }
+                    }
+                }
+            }
+        }
+
+        function isParameterDeclaration(node: VariableLikeDeclaration) {
+            while (node.kind === SyntaxKind.BindingElement) {
+                node = <VariableLikeDeclaration>node.parent.parent;
+            }
+            return node.kind === SyntaxKind.Parameter;
+        }
+
+        // Check that a parameter initializer contains no references to parameters declared to the right of itself
+        function checkParameterInitializer(node: VariableLikeDeclaration): void {
+            if (getRootDeclaration(node).kind !== SyntaxKind.Parameter) {
+                return;
+            }
+
+            let func = getContainingFunction(node);
+            visit(node.initializer);
+
+            function visit(n: Node) {
+                if (n.kind === SyntaxKind.Identifier) {
+                    let referencedSymbol = getNodeLinks(n).resolvedSymbol;
+                    // check FunctionLikeDeclaration.locals (stores parameters\function local variable)
+                    // if it contains entry with a specified name and if this entry matches the resolved symbol
+                    if (referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol(func.locals, referencedSymbol.name, SymbolFlags.Value) === referencedSymbol) {
+                        if (referencedSymbol.valueDeclaration.kind === SyntaxKind.Parameter) {
+                            if (referencedSymbol.valueDeclaration === node) {
+                                error(n, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, declarationNameToString(node.name));
+                                return;
+                            }
+                            if (referencedSymbol.valueDeclaration.pos < node.pos) {
+                                // legal case - parameter initializer references some parameter strictly on left of current parameter declaration
+                                return;
+                            }
+                            // fall through to error reporting
+                        }
+                        error(n, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(node.name), declarationNameToString(<Identifier>n));
+                    }
+                }
+                else {
+                    forEachChild(n, visit);
+                }
+            }
+        }
+
+        // Check variable, parameter, or property declaration
+        function checkVariableLikeDeclaration(node: VariableLikeDeclaration) {
+            checkGrammarDeclarationNameInStrictMode(node);
+            checkDecorators(node);
+            checkSourceElement(node.type);
+            // For a computed property, just check the initializer and exit
+            // Do not use hasDynamicName here, because that returns false for well known symbols.
+            // We want to perform checkComputedPropertyName for all computed properties, including
+            // well known symbols.
+            if (node.name.kind === SyntaxKind.ComputedPropertyName) {
+                checkComputedPropertyName(<ComputedPropertyName>node.name);
+                if (node.initializer) {
+                    checkExpressionCached(node.initializer);
+                }
+            }
+            // For a binding pattern, check contained binding elements
+            if (isBindingPattern(node.name)) {
+                forEach((<BindingPattern>node.name).elements, checkSourceElement);
+            }
+            // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body
+            if (node.initializer && getRootDeclaration(node).kind === SyntaxKind.Parameter && nodeIsMissing(getContainingFunction(node).body)) {
+                error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
+                return;
+            }
+            // For a binding pattern, validate the initializer and exit
+            if (isBindingPattern(node.name)) {
+                if (node.initializer) {
+                    checkTypeAssignableTo(checkExpressionCached(node.initializer), getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined);
+                    checkParameterInitializer(node);
+                }
+                return;
+            }
+            let symbol = getSymbolOfNode(node);
+            let type = getTypeOfVariableOrParameterOrProperty(symbol);
+            if (node === symbol.valueDeclaration) {
+                // Node is the primary declaration of the symbol, just validate the initializer
+                if (node.initializer) {
+                    checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, /*headMessage*/ undefined);
+                    checkParameterInitializer(node);
+                }
+            }
+            else {
+                // Node is a secondary declaration, check that type is identical to primary declaration and check that
+                // initializer is consistent with type associated with the node
+                let declarationType = getWidenedTypeForVariableLikeDeclaration(node);
+                if (type !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(type, declarationType)) {
+                    error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, declarationNameToString(node.name), typeToString(type), typeToString(declarationType));
+                }
+                if (node.initializer) {
+                    checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined);
+                }
+            }
+            if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature) {
+                // We know we don't have a binding pattern or computed name here
+                checkExportsOnMergedDeclarations(node);
+                if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
+                    checkVarDeclaredNamesNotShadowed(<VariableDeclaration | BindingElement>node);
+                }
+                checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
+                checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
+            }
+        }
+
+        function checkVariableDeclaration(node: VariableDeclaration) {
+            checkGrammarVariableDeclaration(node);
+            return checkVariableLikeDeclaration(node);
+        }
+
+        function checkBindingElement(node: BindingElement) {
+            checkGrammarBindingElement(<BindingElement>node);
+            return checkVariableLikeDeclaration(node);
+        }
+
+        function checkVariableStatement(node: VariableStatement) {
+            // Grammar checking
+            checkGrammarDecorators(node) || checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node);
+
+            forEach(node.declarationList.declarations, checkSourceElement);
+        }
+
+        function checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node: Node) {
+            if (node.modifiers) {
+                if (inBlockOrObjectLiteralExpression(node)) {
+                    return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
+                }
+            }
+        }
+
+        function inBlockOrObjectLiteralExpression(node: Node) {
+            while (node) {
+                if (node.kind === SyntaxKind.Block || node.kind === SyntaxKind.ObjectLiteralExpression) {
+                    return true;
+                }
+
+                node = node.parent;
+            }
+        }
+
+        function checkExpressionStatement(node: ExpressionStatement) {
+            // Grammar checking
+            checkGrammarStatementInAmbientContext(node)
+
+            checkExpression(node.expression);
+        }
+
+        function checkIfStatement(node: IfStatement) {
+            // Grammar checking
+            checkGrammarStatementInAmbientContext(node);
+
+            checkExpression(node.expression);
+            checkSourceElement(node.thenStatement);
+            checkSourceElement(node.elseStatement);
+        }
+
+        function checkDoStatement(node: DoStatement) {
+            // Grammar checking
+            checkGrammarStatementInAmbientContext(node);
+
+            checkSourceElement(node.statement);
+            checkExpression(node.expression);
+        }
+
+        function checkWhileStatement(node: WhileStatement) {
+            // Grammar checking
+            checkGrammarStatementInAmbientContext(node);
+
+            checkExpression(node.expression);
+            checkSourceElement(node.statement);
+        }
+
+        function checkForStatement(node: ForStatement) {
+            // Grammar checking
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                if (node.initializer && node.initializer.kind == SyntaxKind.VariableDeclarationList) {
+                    checkGrammarVariableDeclarationList(<VariableDeclarationList>node.initializer);
+                }
+            }
+
+            if (node.initializer) {
+                if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                    forEach((<VariableDeclarationList>node.initializer).declarations, checkVariableDeclaration)
+                }
+                else {
+                    checkExpression(<Expression>node.initializer)
+                }
+            }
+
+            if (node.condition) checkExpression(node.condition);
+            if (node.incrementor) checkExpression(node.incrementor);
+            checkSourceElement(node.statement);
+        }
+
+        function checkForOfStatement(node: ForOfStatement): void {
+            checkGrammarForInOrForOfStatement(node)
+
+            // Check the LHS and RHS
+            // If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS
+            // via checkRightHandSideOfForOf.
+            // If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference.
+            // Then check that the RHS is assignable to it.
+            if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                checkForInOrForOfVariableDeclaration(node);
+            }
+            else {
+                let varExpr = <Expression>node.initializer;
+                let iteratedType = checkRightHandSideOfForOf(node.expression);
+
+                // There may be a destructuring assignment on the left side
+                if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
+                    // iteratedType may be undefined. In this case, we still want to check the structure of
+                    // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like
+                    // to short circuit the type relation checking as much as possible, so we pass the unknownType.
+                    checkDestructuringAssignment(varExpr, iteratedType || unknownType);
+                }
+                else {
+                    let leftType = checkExpression(varExpr);
+                    checkReferenceExpression(varExpr, /*invalidReferenceMessage*/ Diagnostics.Invalid_left_hand_side_in_for_of_statement,
+                        /*constantVariableMessage*/ Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant);
+
+                    // iteratedType will be undefined if the rightType was missing properties/signatures
+                    // required to get its iteratedType (like [Symbol.iterator] or next). This may be
+                    // because we accessed properties from anyType, or it may have led to an error inside
+                    // getIteratedType.
+                    if (iteratedType) {
+                        checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined);
+                    }
+                }
+            }
+
+            checkSourceElement(node.statement);
+        }
+
+        function checkForInStatement(node: ForInStatement) {
+            // Grammar checking
+            checkGrammarForInOrForOfStatement(node);
+
+            // TypeScript 1.0 spec  (April 2014): 5.4
+            // In a 'for-in' statement of the form
+            // for (let VarDecl in Expr) Statement
+            //   VarDecl must be a variable declaration without a type annotation that declares a variable of type Any,
+            //   and Expr must be an expression of type Any, an object type, or a type parameter type.
+            if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                let variable = (<VariableDeclarationList>node.initializer).declarations[0];
+                if (variable && isBindingPattern(variable.name)) {
+                    error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
+                }
+
+                checkForInOrForOfVariableDeclaration(node);
+            }
+            else {
+                // In a 'for-in' statement of the form
+                // for (Var in Expr) Statement
+                //   Var must be an expression classified as a reference of type Any or the String primitive type,
+                //   and Expr must be an expression of type Any, an object type, or a type parameter type.
+                let varExpr = <Expression>node.initializer;
+                let leftType = checkExpression(varExpr);
+                if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
+                    error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
+                }
+                else if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike)) {
+                    error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
+                }
+                else {
+                    // run check only former check succeeded to avoid cascading errors
+                    checkReferenceExpression(varExpr, Diagnostics.Invalid_left_hand_side_in_for_in_statement, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant);
+                }
+            }
+
+            let rightType = checkExpression(node.expression);
+            // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
+            // in this case error about missing name is already reported - do not report extra one
+            if (!allConstituentTypesHaveKind(rightType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
+                error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter);
+            }
+
+            checkSourceElement(node.statement);
+        }
+
+        function checkForInOrForOfVariableDeclaration(iterationStatement: ForInStatement | ForOfStatement): void {
+            let variableDeclarationList = <VariableDeclarationList>iterationStatement.initializer;
+            // checkGrammarForInOrForOfStatement will check that there is exactly one declaration.
+            if (variableDeclarationList.declarations.length >= 1) {
+                let decl = variableDeclarationList.declarations[0];
+                checkVariableDeclaration(decl);
+            }
+        }
+
+        function checkRightHandSideOfForOf(rhsExpression: Expression): Type {
+            let expressionType = getTypeOfExpression(rhsExpression);
+            return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true);
+        }
+
+        function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean): Type {
+            if (inputType.flags & TypeFlags.Any) {
+                return inputType;
+            }
+
+            if (languageVersion >= ScriptTarget.ES6) {
+                return checkIteratedType(inputType, errorNode) || anyType;
+            }
+
+            if (allowStringInput) {
+                return checkElementTypeOfArrayOrString(inputType, errorNode);
+            }
+            
+            if (isArrayLikeType(inputType)) {
+                let indexType = getIndexTypeOfType(inputType, IndexKind.Number);
+                if (indexType) {
+                    return indexType;
+                }
+            }
+
+            error(errorNode, Diagnostics.Type_0_is_not_an_array_type, typeToString(inputType));
+            return unknownType;
+        }
+
+        /**
+         * When errorNode is undefined, it means we should not report any errors.
+         */
+        function checkIteratedType(iterable: Type, errorNode: Node): Type {
+            Debug.assert(languageVersion >= ScriptTarget.ES6);
+            let iteratedType = getIteratedType(iterable, errorNode);
+            // Now even though we have extracted the iteratedType, we will have to validate that the type
+            // passed in is actually an Iterable.
+            if (errorNode && iteratedType) {
+                checkTypeAssignableTo(iterable, createIterableType(iteratedType), errorNode);
+            }
+
+            return iteratedType;
+
+            function getIteratedType(iterable: Type, errorNode: Node) {
+                // We want to treat type as an iterable, and get the type it is an iterable of. The iterable
+                // must have the following structure (annotated with the names of the variables below):
+                //
+                // { // iterable
+                //     [Symbol.iterator]: { // iteratorFunction
+                //         (): { // iterator
+                //             next: { // iteratorNextFunction
+                //                 (): { // iteratorNextResult
+                //                     value: T // iteratorNextValue
+                //                 }
+                //             }
+                //         }
+                //     }
+                // }
+                //
+                // T is the type we are after. At every level that involves analyzing return types
+                // of signatures, we union the return types of all the signatures.
+                //
+                // Another thing to note is that at any step of this process, we could run into a dead end,
+                // meaning either the property is missing, or we run into the anyType. If either of these things
+                // happens, we return undefined to signal that we could not find the iterated type. If a property
+                // is missing, and the previous step did not result in 'any', then we also give an error if the
+                // caller requested it. Then the caller can decide what to do in the case where there is no iterated
+                // type. This is different from returning anyType, because that would signify that we have matched the
+                // whole pattern and that T (above) is 'any'.
+
+                if (allConstituentTypesHaveKind(iterable, TypeFlags.Any)) {
+                    return undefined;
+                }
+
+                // As an optimization, if the type is instantiated directly using the globalIterableType (Iterable<number>),
+                // then just grab its type argument.
+                if ((iterable.flags & TypeFlags.Reference) && (<GenericType>iterable).target === globalIterableType) {
+                    return (<GenericType>iterable).typeArguments[0];
+                }
+
+                let iteratorFunction = getTypeOfPropertyOfType(iterable, getPropertyNameForKnownSymbolName("iterator"));
+                if (iteratorFunction && allConstituentTypesHaveKind(iteratorFunction, TypeFlags.Any)) {
+                    return undefined;
+                }
+
+                let iteratorFunctionSignatures = iteratorFunction ? getSignaturesOfType(iteratorFunction, SignatureKind.Call) : emptyArray;
+                if (iteratorFunctionSignatures.length === 0) {
+                    if (errorNode) {
+                        error(errorNode, Diagnostics.Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator);
+                    }
+                    return undefined;
+                }
+
+                let iterator = getUnionType(map(iteratorFunctionSignatures, getReturnTypeOfSignature));
+                if (allConstituentTypesHaveKind(iterator, TypeFlags.Any)) {
+                    return undefined;
+                }
+
+                let iteratorNextFunction = getTypeOfPropertyOfType(iterator, "next");
+                if (iteratorNextFunction && allConstituentTypesHaveKind(iteratorNextFunction, TypeFlags.Any)) {
+                    return undefined;
+                }
+
+                let iteratorNextFunctionSignatures = iteratorNextFunction ? getSignaturesOfType(iteratorNextFunction, SignatureKind.Call) : emptyArray;
+                if (iteratorNextFunctionSignatures.length === 0) {
+                    if (errorNode) {
+                        error(errorNode, Diagnostics.An_iterator_must_have_a_next_method);
+                    }
+                    return undefined;
+                }
+
+                let iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature));
+                if (allConstituentTypesHaveKind(iteratorNextResult, TypeFlags.Any)) {
+                    return undefined;
+                }
+
+                let iteratorNextValue = getTypeOfPropertyOfType(iteratorNextResult, "value");
+                if (!iteratorNextValue) {
+                    if (errorNode) {
+                        error(errorNode, Diagnostics.The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property);
+                    }
+                    return undefined;
+                }
+
+                return iteratorNextValue;
+            }
+        }
+
+        /**
+         * This function does the following steps:
+         *   1. Break up arrayOrStringType (possibly a union) into its string constituents and array constituents.
+         *   2. Take the element types of the array constituents.
+         *   3. Return the union of the element types, and string if there was a string constitutent.
+         *
+         * For example:
+         *     string -> string
+         *     number[] -> number
+         *     string[] | number[] -> string | number
+         *     string | number[] -> string | number
+         *     string | string[] | number[] -> string | number
+         *
+         * It also errors if:
+         *   1. Some constituent is neither a string nor an array.
+         *   2. Some constituent is a string and target is less than ES5 (because in ES3 string is not indexable).
+         */
+        function checkElementTypeOfArrayOrString(arrayOrStringType: Type, errorNode: Node): Type {
+            Debug.assert(languageVersion < ScriptTarget.ES6);
+
+            // After we remove all types that are StringLike, we will know if there was a string constituent
+            // based on whether the remaining type is the same as the initial type.
+            let arrayType = removeTypesFromUnionType(arrayOrStringType, TypeFlags.StringLike, /*isTypeOfKind*/ true, /*allowEmptyUnionResult*/ true);
+            let hasStringConstituent = arrayOrStringType !== arrayType;
+
+            let reportedError = false;
+            if (hasStringConstituent) {
+                if (languageVersion < ScriptTarget.ES5) {
+                    error(errorNode, Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher);
+                    reportedError = true;
+                }
+
+                // Now that we've removed all the StringLike types, if no constituents remain, then the entire
+                // arrayOrStringType was a string.
+                if (arrayType === emptyObjectType) {
+                    return stringType;
+                }
+            }
+
+            if (!isArrayLikeType(arrayType)) {
+                if (!reportedError) {
+                    // Which error we report depends on whether there was a string constituent. For example,
+                    // if the input type is number | string, we want to say that number is not an array type.
+                    // But if the input was just number, we want to say that number is not an array type
+                    // or a string type.
+                    let diagnostic = hasStringConstituent
+                        ? Diagnostics.Type_0_is_not_an_array_type
+                        : Diagnostics.Type_0_is_not_an_array_type_or_a_string_type;
+                    error(errorNode, diagnostic, typeToString(arrayType));
+                }
+                return hasStringConstituent ? stringType : unknownType;
+            }
+
+            let arrayElementType = getIndexTypeOfType(arrayType, IndexKind.Number) || unknownType;
+            if (hasStringConstituent) {
+                // This is just an optimization for the case where arrayOrStringType is string | string[]
+                if (arrayElementType.flags & TypeFlags.StringLike) {
+                    return stringType;
+                }
+
+                return getUnionType([arrayElementType, stringType]);
+            }
+
+            return arrayElementType;
+        }
+
+        function checkBreakOrContinueStatement(node: BreakOrContinueStatement) {
+            // Grammar checking
+            checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node);
+
+            // TODO: Check that target label is valid
+        }
+
+        function isGetAccessorWithAnnotatatedSetAccessor(node: FunctionLikeDeclaration) {
+            return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(<AccessorDeclaration>getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor)));
+        }
+
+        function checkReturnStatement(node: ReturnStatement) {
+            // Grammar checking
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                let functionBlock = getContainingFunction(node);
+                if (!functionBlock) {
+                    grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_can_only_be_used_within_a_function_body);
+                }
+            }
+
+            if (node.expression) {
+                let func = getContainingFunction(node);
+                if (func) {
+                    let returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func));
+                    let exprType = checkExpressionCached(node.expression);
+                    if (func.kind === SyntaxKind.SetAccessor) {
+                        error(node.expression, Diagnostics.Setters_cannot_return_a_value);
+                    }
+                    else {
+                        if (func.kind === SyntaxKind.Constructor) {
+                            if (!isTypeAssignableTo(exprType, returnType)) {
+                                error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
+                            }
+                        }
+                        else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func)) {
+                            checkTypeAssignableTo(exprType, returnType, node.expression, /*headMessage*/ undefined);
+                        }
+                    }
+                }
+            }
+        }
+
+        function checkWithStatement(node: WithStatement) {
+            // Grammar checking for withStatement
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                if (node.parserContextFlags & ParserContextFlags.StrictMode) {
+                    grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode);
+                }
+            }
+
+            checkExpression(node.expression);
+            error(node.expression, Diagnostics.All_symbols_within_a_with_block_will_be_resolved_to_any);
+        }
+
+        function checkSwitchStatement(node: SwitchStatement) {
+            // Grammar checking
+            checkGrammarStatementInAmbientContext(node);
+
+            let firstDefaultClause: CaseOrDefaultClause;
+            let hasDuplicateDefaultClause = false;
+
+            let expressionType = checkExpression(node.expression);
+            forEach(node.caseBlock.clauses, clause => {
+                // Grammar check for duplicate default clauses, skip if we already report duplicate default clause
+                if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) {
+                    if (firstDefaultClause === undefined) {
+                        firstDefaultClause = clause;
+                    }
+                    else {
+                        let sourceFile = getSourceFileOfNode(node);
+                        let start = skipTrivia(sourceFile.text, clause.pos);
+                        let end = clause.statements.length > 0 ? clause.statements[0].pos : clause.end;
+                        grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement);
+                        hasDuplicateDefaultClause = true;
+                    }
+                }
+
+                if (produceDiagnostics && clause.kind === SyntaxKind.CaseClause) {
+                    let caseClause = <CaseClause>clause;
+                    // TypeScript 1.0 spec (April 2014):5.9
+                    // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression.
+                    let caseType = checkExpression(caseClause.expression);
+                    if (!isTypeAssignableTo(expressionType, caseType)) {
+                        // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails
+                        checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
+                    }
+                }
+                forEach(clause.statements, checkSourceElement);
+            });
+        }
+
+        function checkLabeledStatement(node: LabeledStatement) {
+            // Grammar checking
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                let current = node.parent;
+                while (current) {
+                    if (isFunctionLike(current)) {
+                        break;
+                    }
+                    if (current.kind === SyntaxKind.LabeledStatement && (<LabeledStatement>current).label.text === node.label.text) {
+                        let sourceFile = getSourceFileOfNode(node);
+                        grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNodeFromSourceText(sourceFile.text, node.label));
+                        break;
+                    }
+                    current = current.parent;
+                }
+            }
+
+            // ensure that label is unique
+            checkSourceElement(node.statement);
+        }
+
+        function checkThrowStatement(node: ThrowStatement) {
+            // Grammar checking
+            if (!checkGrammarStatementInAmbientContext(node)) {
+                if (node.expression === undefined) {
+                    grammarErrorAfterFirstToken(node, Diagnostics.Line_break_not_permitted_here);
+                }
+            }
+
+            if (node.expression) {
+                checkExpression(node.expression);
+            }
+        }
+
+        function checkTryStatement(node: TryStatement) {
+            // Grammar checking
+            checkGrammarStatementInAmbientContext(node);
+
+            checkBlock(node.tryBlock);
+            let catchClause = node.catchClause;
+            if (catchClause) {
+                // Grammar checking
+                if (catchClause.variableDeclaration) {
+                    if (catchClause.variableDeclaration.name.kind !== SyntaxKind.Identifier) {
+                        grammarErrorOnFirstToken(catchClause.variableDeclaration.name, Diagnostics.Catch_clause_variable_name_must_be_an_identifier);
+                    }
+                    else if (catchClause.variableDeclaration.type) {
+                        grammarErrorOnFirstToken(catchClause.variableDeclaration.type, Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation);
+                    }
+                    else if (catchClause.variableDeclaration.initializer) {
+                        grammarErrorOnFirstToken(catchClause.variableDeclaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
+                    }
+                    else {
+                        let identifierName = (<Identifier>catchClause.variableDeclaration.name).text;
+                        let locals = catchClause.block.locals;
+                        if (locals && hasProperty(locals, identifierName)) {
+                            let localSymbol = locals[identifierName]
+                            if (localSymbol && (localSymbol.flags & SymbolFlags.BlockScopedVariable) !== 0) {
+                                grammarErrorOnNode(localSymbol.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, identifierName);
+                            }
+                        }
+
+                        // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
+                        // Catch production is eval or arguments
+                        checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>catchClause.variableDeclaration.name);
+                    }
+                }
+
+                checkBlock(catchClause.block);
+            }
+
+            if (node.finallyBlock) {
+                checkBlock(node.finallyBlock);
+            }
+        }
+
+        function checkIndexConstraints(type: Type) {
+            let declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.Number);
+            let declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, IndexKind.String);
+
+            let stringIndexType = getIndexTypeOfType(type, IndexKind.String);
+            let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
+
+            if (stringIndexType || numberIndexType) {
+                forEach(getPropertiesOfObjectType(type), prop => {
+                    let propType = getTypeOfSymbol(prop);
+                    checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String);
+                    checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number);
+                });
+
+                if (type.flags & TypeFlags.Class && type.symbol.valueDeclaration.kind === SyntaxKind.ClassDeclaration) {
+                    let classDeclaration = <ClassDeclaration>type.symbol.valueDeclaration;
+                    for (let member of classDeclaration.members) {
+                        // Only process instance properties with computed names here.
+                        // Static properties cannot be in conflict with indexers,
+                        // and properties with literal names were already checked.
+                        if (!(member.flags & NodeFlags.Static) && hasDynamicName(member)) {
+                            let propType = getTypeOfSymbol(member.symbol);
+                            checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String);
+                            checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number);
+                        }
+                    }
+                }
+            }
+
+            let errorNode: Node;
+            if (stringIndexType && numberIndexType) {
+                errorNode = declaredNumberIndexer || declaredStringIndexer;
+                // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer
+                if (!errorNode && (type.flags & TypeFlags.Interface)) {
+                    let someBaseTypeHasBothIndexers = forEach(getBaseTypes(<InterfaceType>type), base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number));
+                    errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0];
+                }
+            }
+
+            if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) {
+                error(errorNode, Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1,
+                    typeToString(numberIndexType), typeToString(stringIndexType));
+            }
+
+            function checkIndexConstraintForProperty(
+                prop: Symbol,
+                propertyType: Type,
+                containingType: Type,
+                indexDeclaration: Declaration,
+                indexType: Type,
+                indexKind: IndexKind): void {
+
+                if (!indexType) {
+                    return;
+                }
+
+                // index is numeric and property name is not valid numeric literal
+                if (indexKind === IndexKind.Number && !isNumericName(prop.valueDeclaration.name)) {
+                    return;
+                }
+
+                // perform property check if property or indexer is declared in 'type'
+                // this allows to rule out cases when both property and indexer are inherited from the base class
+                let errorNode: Node;
+                if (prop.valueDeclaration.name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol) {
+                    errorNode = prop.valueDeclaration;
+                }
+                else if (indexDeclaration) {
+                    errorNode = indexDeclaration;
+                }
+                else if (containingType.flags & TypeFlags.Interface) {
+                    // for interfaces property and indexer might be inherited from different bases
+                    // check if any base class already has both property and indexer.
+                    // check should be performed only if 'type' is the first type that brings property\indexer together
+                    let someBaseClassHasBothPropertyAndIndexer = forEach(getBaseTypes(<InterfaceType>containingType), base => getPropertyOfObjectType(base, prop.name) && getIndexTypeOfType(base, indexKind));
+                    errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0];
+                }
+
+                if (errorNode && !isTypeAssignableTo(propertyType, indexType)) {
+                    let errorMessage =
+                        indexKind === IndexKind.String
+                            ? Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2
+                            : Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2;
+                    error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType));
+                }
+            }
+        }
+
+        function checkTypeNameIsReserved(name: DeclarationName, message: DiagnosticMessage): void {
+            // TS 1.0 spec (April 2014): 3.6.1
+            // The predefined type keywords are reserved and cannot be used as names of user defined types.
+            switch ((<Identifier>name).text) {
+                case "any":
+                case "number":
+                case "boolean":
+                case "string":
+                case "symbol":
+                case "void":
+                    error(name, message, (<Identifier>name).text);
+            }
+        }
+
+        // Check each type parameter and check that list has no duplicate type parameter declarations
+        function checkTypeParameters(typeParameterDeclarations: TypeParameterDeclaration[]) {
+            if (typeParameterDeclarations) {
+                for (let i = 0, n = typeParameterDeclarations.length; i < n; i++) {
+                    let node = typeParameterDeclarations[i];
+                    checkTypeParameter(node);
+
+                    if (produceDiagnostics) {
+                        for (let j = 0; j < i; j++) {
+                            if (typeParameterDeclarations[j].symbol === node.symbol) {
+                                error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        function checkClassExpression(node: ClassExpression): Type {
+            grammarErrorOnNode(node, Diagnostics.class_expressions_are_not_currently_supported);
+            forEach(node.members, checkSourceElement);
+            return unknownType;
+        }
+
+        function checkClassDeclaration(node: ClassDeclaration) {
+            checkGrammarDeclarationNameInStrictMode(node);
+            // Grammar checking
+            if (node.parent.kind !== SyntaxKind.ModuleBlock && node.parent.kind !== SyntaxKind.SourceFile) {
+                grammarErrorOnNode(node, Diagnostics.class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration);
+            }
+
+            if (!node.name && !(node.flags & NodeFlags.Default)) {
+                grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
+            }
+
+            checkGrammarClassDeclarationHeritageClauses(node);
+            checkDecorators(node);
+            if (node.name) {
+                checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
+                checkCollisionWithCapturedThisVariable(node, node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            }
+            checkTypeParameters(node.typeParameters);
+            checkExportsOnMergedDeclarations(node);
+            let symbol = getSymbolOfNode(node);
+            let type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
+            let staticType = <ObjectType>getTypeOfSymbol(symbol);
+            let baseTypeNode = getClassExtendsHeritageClauseElement(node);
+            if (baseTypeNode) {
+                if (!isSupportedHeritageClauseElement(baseTypeNode)) {
+                    error(baseTypeNode.expression, Diagnostics.Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses);
+                }
+
+                emitExtends = emitExtends || !isInAmbientContext(node);
+                checkHeritageClauseElement(baseTypeNode);
+            }
+            let baseTypes = getBaseTypes(type);
+            if (baseTypes.length) {
+                if (produceDiagnostics) {
+                    let baseType = baseTypes[0];
+                    checkTypeAssignableTo(type, baseType, node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
+                    let staticBaseType = getTypeOfSymbol(baseType.symbol);
+                    checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name || node,
+                        Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
+
+                    if (baseType.symbol !== resolveEntityName(baseTypeNode.expression, SymbolFlags.Value)) {
+                        error(baseTypeNode, Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
+                    }
+
+                    checkKindsOfPropertyMemberOverrides(type, baseType);
+                }
+            }
+
+            if (baseTypes.length || (baseTypeNode && compilerOptions.separateCompilation)) {
+                // Check that base type can be evaluated as expression
+                checkExpressionOrQualifiedName(baseTypeNode.expression);
+            }
+
+            let implementedTypeNodes = getClassImplementsHeritageClauseElements(node);
+            if (implementedTypeNodes) {
+                forEach(implementedTypeNodes, typeRefNode => {
+                    if (!isSupportedHeritageClauseElement(typeRefNode)) {
+                        error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments);
+                    }
+
+                    checkHeritageClauseElement(typeRefNode);
+                    if (produceDiagnostics) {
+                        let t = getTypeFromHeritageClauseElement(typeRefNode);
+                        if (t !== unknownType) {
+                            let declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
+                            if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
+                                checkTypeAssignableTo(type, t, node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1);
+                            }
+                            else {
+                                error(typeRefNode, Diagnostics.A_class_may_only_implement_another_class_or_interface);
+                            }
+                        }
+                    }
+                });
+            }
+
+            forEach(node.members, checkSourceElement);
+            if (produceDiagnostics) {
+                checkIndexConstraints(type);
+                checkTypeForDuplicateIndexSignatures(node);
+            }
+        }
+
+        function getTargetSymbol(s: Symbol) {
+            // if symbol is instantiated its flags are not copied from the 'target'
+            // so we'll need to get back original 'target' symbol to work with correct set of flags
+            return s.flags & SymbolFlags.Instantiated ? getSymbolLinks(s).target : s;
+        }
+
+        function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: ObjectType): void {
+
+            // TypeScript 1.0 spec (April 2014): 8.2.3
+            // A derived class inherits all members from its base class it doesn't override.
+            // Inheritance means that a derived class implicitly contains all non - overridden members of the base class.
+            // Both public and private property members are inherited, but only public property members can be overridden.
+            // A property member in a derived class is said to override a property member in a base class
+            // when the derived class property member has the same name and kind(instance or static)
+            // as the base class property member.
+            // The type of an overriding property member must be assignable(section 3.8.4)
+            // to the type of the overridden property member, or otherwise a compile - time error occurs.
+            // Base class instance member functions can be overridden by derived class instance member functions,
+            // but not by other kinds of members.
+            // Base class instance member variables and accessors can be overridden by
+            // derived class instance member variables and accessors, but not by other kinds of members.
+
+            // NOTE: assignability is checked in checkClassDeclaration
+            let baseProperties = getPropertiesOfObjectType(baseType);
+            for (let baseProperty of baseProperties) {
+                let base = getTargetSymbol(baseProperty);
+
+                if (base.flags & SymbolFlags.Prototype) {
+                    continue;
+                }
+
+                let derived = getTargetSymbol(getPropertyOfObjectType(type, base.name));
+                if (derived) {
+                    let baseDeclarationFlags = getDeclarationFlagsFromSymbol(base);
+                    let derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
+                    if ((baseDeclarationFlags & NodeFlags.Private) || (derivedDeclarationFlags & NodeFlags.Private)) {
+                        // either base or derived property is private - not override, skip it
+                        continue;
+                    }
+
+                    if ((baseDeclarationFlags & NodeFlags.Static) !== (derivedDeclarationFlags & NodeFlags.Static)) {
+                        // value of 'static' is not the same for properties - not override, skip it
+                        continue;
+                    }
+
+                    if ((base.flags & derived.flags & SymbolFlags.Method) || ((base.flags & SymbolFlags.PropertyOrAccessor) && (derived.flags & SymbolFlags.PropertyOrAccessor))) {
+                        // method is overridden with method or property/accessor is overridden with property/accessor - correct case
+                        continue;
+                    }
+
+                    let errorMessage: DiagnosticMessage;
+                    if (base.flags & SymbolFlags.Method) {
+                        if (derived.flags & SymbolFlags.Accessor) {
+                            errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
+                        }
+                        else {
+                            Debug.assert((derived.flags & SymbolFlags.Property) !== 0);
+                            errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property;
+                        }
+                    }
+                    else if (base.flags & SymbolFlags.Property) {
+                        Debug.assert((derived.flags & SymbolFlags.Method) !== 0);
+                        errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
+                    }
+                    else {
+                        Debug.assert((base.flags & SymbolFlags.Accessor) !== 0);
+                        Debug.assert((derived.flags & SymbolFlags.Method) !== 0);
+                        errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
+                    }
+
+                    error(derived.valueDeclaration.name, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
+                }
+            }
+        }
+
+        function isAccessor(kind: SyntaxKind): boolean {
+            return kind === SyntaxKind.GetAccessor || kind === SyntaxKind.SetAccessor;
+        }
+
+        function areTypeParametersIdentical(list1: TypeParameterDeclaration[], list2: TypeParameterDeclaration[]) {
+            if (!list1 && !list2) {
+                return true;
+            }
+            if (!list1 || !list2 || list1.length !== list2.length) {
+                return false;
+            }
+            // TypeScript 1.0 spec (April 2014):
+            // When a generic interface has multiple declarations,  all declarations must have identical type parameter
+            // lists, i.e. identical type parameter names with identical constraints in identical order.
+            for (let i = 0, len = list1.length; i < len; i++) {
+                let tp1 = list1[i];
+                let tp2 = list2[i];
+                if (tp1.name.text !== tp2.name.text) {
+                    return false;
+                }
+                if (!tp1.constraint && !tp2.constraint) {
+                    continue;
+                }
+                if (!tp1.constraint || !tp2.constraint) {
+                    return false;
+                }
+                if (!isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean {
+            let baseTypes = getBaseTypes(type);
+            if (baseTypes.length < 2) {
+                return true;
+            }
+
+            let seen: Map<{ prop: Symbol; containingType: Type }> = {};
+            forEach(resolveDeclaredMembers(type).declaredProperties, p => { seen[p.name] = { prop: p, containingType: type }; });
+            let ok = true;
+
+            for (let base of baseTypes) {
+                let properties = getPropertiesOfObjectType(base);
+                for (let prop of properties) {
+                    if (!hasProperty(seen, prop.name)) {
+                        seen[prop.name] = { prop: prop, containingType: base };
+                    }
+                    else {
+                        let existing = seen[prop.name];
+                        let isInheritedProperty = existing.containingType !== type;
+                        if (isInheritedProperty && !isPropertyIdenticalTo(existing.prop, prop)) {
+                            ok = false;
+
+                            let typeName1 = typeToString(existing.containingType);
+                            let typeName2 = typeToString(base);
+
+                            let errorInfo = chainDiagnosticMessages(undefined, Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2);
+                            errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
+                            diagnostics.add(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo));
+                        }
+                    }
+                }
+            }
+
+            return ok;
+        }
+
+        function checkInterfaceDeclaration(node: InterfaceDeclaration) {
+            // Grammar checking
+            checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node);
+
+            checkTypeParameters(node.typeParameters);
+            if (produceDiagnostics) {
+                checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0);
+
+                checkExportsOnMergedDeclarations(node);
+                let symbol = getSymbolOfNode(node);
+                let firstInterfaceDecl = <InterfaceDeclaration>getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration);
+                if (symbol.declarations.length > 1) {
+                    if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) {
+                        error(node.name, Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters);
+                    }
+                }
+
+                // Only check this symbol once
+                if (node === firstInterfaceDecl) {
+                    let type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
+                    // run subsequent checks only if first set succeeded
+                    if (checkInheritedPropertiesAreIdentical(type, node.name)) {
+                        forEach(getBaseTypes(type), baseType => {
+                            checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1);
+                        });
+                        checkIndexConstraints(type);
+                    }
+                }
+            }
+            forEach(getInterfaceBaseTypeNodes(node), heritageElement => {
+                if (!isSupportedHeritageClauseElement(heritageElement)) {
+                    error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments);
+                }
+
+                checkHeritageClauseElement(heritageElement);
+            });
+            forEach(node.members, checkSourceElement);
+
+            if (produceDiagnostics) {
+                checkTypeForDuplicateIndexSignatures(node);
+            }
+        }
+
+        function checkTypeAliasDeclaration(node: TypeAliasDeclaration) {
+            // Grammar checking
+            checkGrammarDecorators(node) || checkGrammarModifiers(node);
+
+            checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0);
+            checkSourceElement(node.type);
+        }
+
+        function computeEnumMemberValues(node: EnumDeclaration) {
+            let nodeLinks = getNodeLinks(node);
+
+            if (!(nodeLinks.flags & NodeCheckFlags.EnumValuesComputed)) {
+                let enumSymbol = getSymbolOfNode(node);
+                let enumType = getDeclaredTypeOfSymbol(enumSymbol);
+                let autoValue = 0;
+                let ambient = isInAmbientContext(node);
+                let enumIsConst = isConst(node);
+
+                forEach(node.members, member => {
+                    if (member.name.kind !== SyntaxKind.ComputedPropertyName && isNumericLiteralName((<Identifier>member.name).text)) {
+                        error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name);
+                    }
+                    let initializer = member.initializer;
+                    if (initializer) {
+                        autoValue = getConstantValueForEnumMemberInitializer(initializer);
+                        if (autoValue === undefined) {
+                            if (enumIsConst) {
+                                error(initializer, Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression);
+                            }
+                            else if (!ambient) {
+                                // Only here do we need to check that the initializer is assignable to the enum type.
+                                // If it is a constant value (not undefined), it is syntactically constrained to be a number.
+                                // Also, we do not need to check this for ambients because there is already
+                                // a syntax error if it is not a constant.
+                                checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*headMessage*/ undefined);
+                            }
+                        }
+                        else if (enumIsConst) {
+                            if (isNaN(autoValue)) {
+                                error(initializer, Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN);
+                            }
+                            else if (!isFinite(autoValue)) {
+                                error(initializer, Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value);
+                            }
+                        }
+
+                    }
+                    else if (ambient && !enumIsConst) {
+                        autoValue = undefined;
+                    }
+
+                    if (autoValue !== undefined) {
+                        getNodeLinks(member).enumMemberValue = autoValue++;
+                    }
+                });
+
+                nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed;
+            }
+
+            function getConstantValueForEnumMemberInitializer(initializer: Expression): number {
+                return evalConstant(initializer);
+
+                function evalConstant(e: Node): number {
+                    switch (e.kind) {
+                        case SyntaxKind.PrefixUnaryExpression:
+                            let value = evalConstant((<PrefixUnaryExpression>e).operand);
+                            if (value === undefined) {
+                                return undefined;
+                            }
+                            switch ((<PrefixUnaryExpression>e).operator) {
+                                case SyntaxKind.PlusToken: return value;
+                                case SyntaxKind.MinusToken: return -value;
+                                case SyntaxKind.TildeToken: return ~value;
+                            }
+                            return undefined;
+                        case SyntaxKind.BinaryExpression:
+                            let left = evalConstant((<BinaryExpression>e).left);
+                            if (left === undefined) {
+                                return undefined;
+                            }
+                            let right = evalConstant((<BinaryExpression>e).right);
+                            if (right === undefined) {
+                                return undefined;
+                            }
+                            switch ((<BinaryExpression>e).operatorToken.kind) {
+                                case SyntaxKind.BarToken: return left | right;
+                                case SyntaxKind.AmpersandToken: return left & right;
+                                case SyntaxKind.GreaterThanGreaterThanToken: return left >> right;
+                                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: return left >>> right;
+                                case SyntaxKind.LessThanLessThanToken: return left << right;
+                                case SyntaxKind.CaretToken: return left ^ right;
+                                case SyntaxKind.AsteriskToken: return left * right;
+                                case SyntaxKind.SlashToken: return left / right;
+                                case SyntaxKind.PlusToken: return left + right;
+                                case SyntaxKind.MinusToken: return left - right;
+                                case SyntaxKind.PercentToken: return left % right;
+                            }
+                            return undefined;
+                        case SyntaxKind.NumericLiteral:
+                            return +(<LiteralExpression>e).text;
+                        case SyntaxKind.ParenthesizedExpression:
+                            return evalConstant((<ParenthesizedExpression>e).expression);
+                        case SyntaxKind.Identifier:
+                        case SyntaxKind.ElementAccessExpression:
+                        case SyntaxKind.PropertyAccessExpression:
+                            let member = initializer.parent;
+                            let currentType = getTypeOfSymbol(getSymbolOfNode(member.parent));
+                            let enumType: Type;
+                            let propertyName: string;
+
+                            if (e.kind === SyntaxKind.Identifier) {
+                                // unqualified names can refer to member that reside in different declaration of the enum so just doing name resolution won't work.
+                                // instead pick current enum type and later try to fetch member from the type
+                                enumType = currentType;
+                                propertyName = (<Identifier>e).text;
+                            }
+                            else {
+                                let expression: Expression;
+                                if (e.kind === SyntaxKind.ElementAccessExpression) {
+                                    if ((<ElementAccessExpression>e).argumentExpression === undefined ||
+                                        (<ElementAccessExpression>e).argumentExpression.kind !== SyntaxKind.StringLiteral) {
+                                        return undefined;
+                                    }
+                                    expression = (<ElementAccessExpression>e).expression;
+                                    propertyName = (<LiteralExpression>(<ElementAccessExpression>e).argumentExpression).text;
+                                }
+                                else {
+                                    expression = (<PropertyAccessExpression>e).expression;
+                                    propertyName = (<PropertyAccessExpression>e).name.text;
+                                }
+
+                                // expression part in ElementAccess\PropertyAccess should be either identifier or dottedName
+                                var current = expression;
+                                while (current) {
+                                    if (current.kind === SyntaxKind.Identifier) {
+                                        break;
+                                    }
+                                    else if (current.kind === SyntaxKind.PropertyAccessExpression) {
+                                        current = (<ElementAccessExpression>current).expression;
+                                    }
+                                    else {
+                                        return undefined;
+                                    }
+                                }
+
+                                enumType = checkExpression(expression);
+                                // allow references to constant members of other enums
+                                if (!(enumType.symbol && (enumType.symbol.flags & SymbolFlags.Enum))) {
+                                    return undefined;
+                                }
+                            }
+
+                            if (propertyName === undefined) {
+                                return undefined;
+                            }
+
+                            let property = getPropertyOfObjectType(enumType, propertyName);
+                            if (!property || !(property.flags & SymbolFlags.EnumMember)) {
+                                return undefined;
+                            }
+
+                            let propertyDecl = property.valueDeclaration;
+                            // self references are illegal
+                            if (member === propertyDecl) {
+                                return undefined;
+                            }
+
+                            // illegal case: forward reference
+                            if (!isDefinedBefore(propertyDecl, member)) {
+                                return undefined;
+                            }
+
+                            return <number>getNodeLinks(propertyDecl).enumMemberValue;
+                    }
+                }
+            }
+        }
+
+        function checkEnumDeclaration(node: EnumDeclaration) {
+            if (!produceDiagnostics) {
+                return;
+            }
+
+            // Grammar checking
+            checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarEnumDeclaration(node);
+
+            checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
+            checkCollisionWithCapturedThisVariable(node, node.name);
+            checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            checkExportsOnMergedDeclarations(node);
+
+            computeEnumMemberValues(node);
+
+            let enumIsConst = isConst(node);
+            if (compilerOptions.separateCompilation && enumIsConst && isInAmbientContext(node)) {
+                error(node.name, Diagnostics.Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided);
+            }
+
+            // Spec 2014 - Section 9.3:
+            // It isn't possible for one enum declaration to continue the automatic numbering sequence of another,
+            // and when an enum type has multiple declarations, only one declaration is permitted to omit a value
+            // for the first member.
+            //
+            // Only perform this check once per symbol
+            let enumSymbol = getSymbolOfNode(node);
+            let firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind);
+            if (node === firstDeclaration) {
+                if (enumSymbol.declarations.length > 1) {
+                    // check that const is placed\omitted on all enum declarations
+                    forEach(enumSymbol.declarations, decl => {
+                        if (isConstEnumDeclaration(decl) !== enumIsConst) {
+                            error(decl.name, Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
+                        }
+                    });
+                }
+
+                let seenEnumMissingInitialInitializer = false;
+                forEach(enumSymbol.declarations, declaration => {
+                    // return true if we hit a violation of the rule, false otherwise
+                    if (declaration.kind !== SyntaxKind.EnumDeclaration) {
+                        return false;
+                    }
+
+                    let enumDeclaration = <EnumDeclaration>declaration;
+                    if (!enumDeclaration.members.length) {
+                        return false;
+                    }
+
+                    let firstEnumMember = enumDeclaration.members[0];
+                    if (!firstEnumMember.initializer) {
+                        if (seenEnumMissingInitialInitializer) {
+                            error(firstEnumMember.name, Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element);
+                        }
+                        else {
+                            seenEnumMissingInitialInitializer = true;
+                        }
+                    }
+                });
+            }
+        }
+
+        function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration {
+            let declarations = symbol.declarations;
+            for (let declaration of declarations) {
+                if ((declaration.kind === SyntaxKind.ClassDeclaration ||
+                    (declaration.kind === SyntaxKind.FunctionDeclaration && nodeIsPresent((<FunctionLikeDeclaration>declaration).body))) &&
+                    !isInAmbientContext(declaration)) {
+                    return declaration;
+                }
+            }
+            return undefined;
+        }
+
+        function inSameLexicalScope(node1: Node, node2: Node) {
+            let container1 = getEnclosingBlockScopeContainer(node1);
+            let container2 = getEnclosingBlockScopeContainer(node2);
+            if (isGlobalSourceFile(container1)) {
+                return isGlobalSourceFile(container2);
+            }
+            else if (isGlobalSourceFile(container2)) {
+                return false;
+            }
+            else {
+                return container1 === container2;
+            }
+        }
+
+        function checkModuleDeclaration(node: ModuleDeclaration) {
+            if (produceDiagnostics) {
+                // Grammar checking
+                if (!checkGrammarDeclarationNameInStrictMode(node) && !checkGrammarDecorators(node) && !checkGrammarModifiers(node)) {
+                    if (!isInAmbientContext(node) && node.name.kind === SyntaxKind.StringLiteral) {
+                        grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names);
+                    }
+                }
+
+                checkCollisionWithCapturedThisVariable(node, node.name);
+                checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+                checkExportsOnMergedDeclarations(node);
+                let symbol = getSymbolOfNode(node);
+
+                // The following checks only apply on a non-ambient instantiated module declaration.
+                if (symbol.flags & SymbolFlags.ValueModule
+                    && symbol.declarations.length > 1
+                    && !isInAmbientContext(node)
+                    && isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.separateCompilation)) {
+                    let firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
+                    if (firstNonAmbientClassOrFunc) {
+                        if (getSourceFileOfNode(node) !== getSourceFileOfNode(firstNonAmbientClassOrFunc)) {
+                            error(node.name, Diagnostics.A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged);
+                        }
+                        else if (node.pos < firstNonAmbientClassOrFunc.pos) {
+                            error(node.name, Diagnostics.A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged);
+                        }
+                    }
+
+                    // if the module merges with a class declaration in the same lexical scope, 
+                    // we need to track this to ensure the correct emit.
+                    let mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration);                    
+                    if (mergedClass &&
+                        inSameLexicalScope(node, mergedClass)) {
+                        getNodeLinks(node).flags |= NodeCheckFlags.LexicalModuleMergesWithClass;
+                    }
+                }
+
+                // Checks for ambient external modules.
+                if (node.name.kind === SyntaxKind.StringLiteral) {
+                    if (!isGlobalSourceFile(node.parent)) {
+                        error(node.name, Diagnostics.Ambient_external_modules_cannot_be_nested_in_other_modules);
+                    }
+                    if (isExternalModuleNameRelative(node.name.text)) {
+                        error(node.name, Diagnostics.Ambient_external_module_declaration_cannot_specify_relative_module_name);
+                    }
+                }
+            }
+            checkSourceElement(node.body);
+        }
+
+        function getFirstIdentifier(node: EntityName | Expression): Identifier {
+            while (true) {
+                if (node.kind === SyntaxKind.QualifiedName) {
+                    node = (<QualifiedName>node).left;
+                }
+                else if (node.kind === SyntaxKind.PropertyAccessExpression) {
+                    node = (<PropertyAccessExpression>node).expression;
+                }
+                else {
+                    break;
+                }
+            }
+            Debug.assert(node.kind === SyntaxKind.Identifier);
+            return <Identifier>node;
+        }
+
+        function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
+            let moduleName = getExternalModuleName(node);
+            if (!nodeIsMissing(moduleName) && moduleName.kind !== SyntaxKind.StringLiteral) {
+                error(moduleName, Diagnostics.String_literal_expected);
+                return false;
+            }
+            let inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && (<ModuleDeclaration>node.parent.parent).name.kind === SyntaxKind.StringLiteral;
+            if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule) {
+                error(moduleName, node.kind === SyntaxKind.ExportDeclaration ?
+                    Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module :
+                    Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
+                return false;
+            }
+            if (inAmbientExternalModule && isExternalModuleNameRelative((<LiteralExpression>moduleName).text)) {
+                // TypeScript 1.0 spec (April 2013): 12.1.6
+                // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference
+                // other external modules only through top - level external module names.
+                // Relative external module names are not permitted.
+                error(node, Diagnostics.Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name);
+                return false;
+            }
+            return true;
+        }
+
+        function checkAliasSymbol(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier) {
+            let symbol = getSymbolOfNode(node);
+            let target = resolveAlias(symbol);
+            if (target !== unknownSymbol) {
+                let excludedMeanings =
+                    (symbol.flags & SymbolFlags.Value ? SymbolFlags.Value : 0) |
+                    (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) |
+                    (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0);
+                if (target.flags & excludedMeanings) {
+                    let message = node.kind === SyntaxKind.ExportSpecifier ?
+                        Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 :
+                        Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0;
+                    error(node, message, symbolToString(symbol));
+                }
+            }
+        }
+
+        function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
+            checkCollisionWithCapturedThisVariable(node, node.name);
+            checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
+            checkAliasSymbol(node);
+        }
+
+        function checkImportDeclaration(node: ImportDeclaration) {
+            if (!checkGrammarImportDeclarationNameInStrictMode(node) && !checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
+                grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
+            }
+            if (checkExternalImportOrExportDeclaration(node)) {
+                let importClause = node.importClause;
+                if (importClause) {
+                    if (importClause.name) {
+                        checkImportBinding(importClause);
+                    }
+                    if (importClause.namedBindings) {
+                        if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
+                            checkImportBinding(<NamespaceImport>importClause.namedBindings);
+                        }
+                        else {
+                            forEach((<NamedImports>importClause.namedBindings).elements, checkImportBinding);
+                        }
+                    }
+                }
+            }
+        }
+
+        function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
+            checkGrammarDeclarationNameInStrictMode(node) || checkGrammarDecorators(node) || checkGrammarModifiers(node);
+            if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
+                checkImportBinding(node);
+                if (node.flags & NodeFlags.Export) {
+                    markExportAsReferenced(node);
+                }
+                if (isInternalModuleImportEqualsDeclaration(node)) {
+                    let target = resolveAlias(getSymbolOfNode(node));
+                    if (target !== unknownSymbol) {
+                        if (target.flags & SymbolFlags.Value) {
+                            // Target is a value symbol, check that it is not hidden by a local declaration with the same name
+                            let moduleName = getFirstIdentifier(<EntityName>node.moduleReference);
+                            if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace).flags & SymbolFlags.Namespace)) {
+                                error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName));
+                            }
+                        }
+                        if (target.flags & SymbolFlags.Type) {
+                            checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0);
+                        }
+                    }
+                }
+                else {
+                    if (languageVersion >= ScriptTarget.ES6) {
+                        // Import equals declaration is deprecated in es6 or above
+                        grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead);
+                    }
+                }
+            }
+        }
+
+        function checkExportDeclaration(node: ExportDeclaration) {
+            if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
+                grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers);
+            }
+            if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
+                if (node.exportClause) {
+                    // export { x, y }
+                    // export { x, y } from "foo"
+                    forEach(node.exportClause.elements, checkExportSpecifier);
+
+                    let inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && (<ModuleDeclaration>node.parent.parent).name.kind === SyntaxKind.StringLiteral;
+                    if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule) {
+                        error(node, Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module);
+                    }
+                }
+                else {
+                    // export * from "foo"
+                    let moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier);
+                    if (moduleSymbol && moduleSymbol.exports["export="]) {
+                        error(node.moduleSpecifier, Diagnostics.External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
+                    }
+                }
+            }
+        }
+
+        function checkExportSpecifier(node: ExportSpecifier) {
+            checkAliasSymbol(node);
+            if (!(<ExportDeclaration>node.parent.parent).moduleSpecifier) {
+                markExportAsReferenced(node);
+            }
+        }
+
+        function checkExportAssignment(node: ExportAssignment) {
+            let container = node.parent.kind === SyntaxKind.SourceFile ? <SourceFile>node.parent : <ModuleDeclaration>node.parent.parent;
+            if (container.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>container).name.kind === SyntaxKind.Identifier) {
+                error(node, Diagnostics.An_export_assignment_cannot_be_used_in_an_internal_module);
+                return;
+            }
+            // Grammar checking
+            if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
+                grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
+            }
+            if (node.expression.kind === SyntaxKind.Identifier) {
+                markExportAsReferenced(node);
+            }
+            else {
+                checkExpressionCached(node.expression);
+            }
+            checkExternalModuleExports(container);
+
+            if (node.isExportEquals && languageVersion >= ScriptTarget.ES6) {
+                // export assignment is deprecated in es6 or above
+                grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead);
+            }
+        }
+
+        function getModuleStatements(node: Declaration): ModuleElement[] {
+            if (node.kind === SyntaxKind.SourceFile) {
+                return (<SourceFile>node).statements;
+            }
+            if (node.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node).body.kind === SyntaxKind.ModuleBlock) {
+                return (<ModuleBlock>(<ModuleDeclaration>node).body).statements;
+            }
+            return emptyArray;
+        }
+
+        function hasExportedMembers(moduleSymbol: Symbol) {
+            for (var id in moduleSymbol.exports) {
+                if (id !== "export=") {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        function checkExternalModuleExports(node: SourceFile | ModuleDeclaration) {
+            let moduleSymbol = getSymbolOfNode(node);
+            let links = getSymbolLinks(moduleSymbol);
+            if (!links.exportsChecked) {
+                let exportEqualsSymbol = moduleSymbol.exports["export="];
+                if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) {
+                    let declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
+                    error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
+                }
+                links.exportsChecked = true;
+            }
+        }
+
+        function checkSourceElement(node: Node): void {
+            if (!node) return;
+            switch (node.kind) {
+                case SyntaxKind.TypeParameter:
+                    return checkTypeParameter(<TypeParameterDeclaration>node);
+                case SyntaxKind.Parameter:
+                    return checkParameter(<ParameterDeclaration>node);
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    return checkPropertyDeclaration(<PropertyDeclaration>node);
+                case SyntaxKind.FunctionType:
+                case SyntaxKind.ConstructorType:
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.ConstructSignature:
+                    return checkSignatureDeclaration(<SignatureDeclaration>node);
+                case SyntaxKind.IndexSignature:
+                    return checkSignatureDeclaration(<SignatureDeclaration>node);
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                    return checkMethodDeclaration(<MethodDeclaration>node);
+                case SyntaxKind.Constructor:
+                    return checkConstructorDeclaration(<ConstructorDeclaration>node);
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                    return checkAccessorDeclaration(<AccessorDeclaration>node);
+                case SyntaxKind.TypeReference:
+                    return checkTypeReferenceNode(<TypeReferenceNode>node);
+                case SyntaxKind.TypeQuery:
+                    return checkTypeQuery(<TypeQueryNode>node);
+                case SyntaxKind.TypeLiteral:
+                    return checkTypeLiteral(<TypeLiteralNode>node);
+                case SyntaxKind.ArrayType:
+                    return checkArrayType(<ArrayTypeNode>node);
+                case SyntaxKind.TupleType:
+                    return checkTupleType(<TupleTypeNode>node);
+                case SyntaxKind.UnionType:
+                    return checkUnionType(<UnionTypeNode>node);
+                case SyntaxKind.ParenthesizedType:
+                    return checkSourceElement((<ParenthesizedTypeNode>node).type);
+                case SyntaxKind.FunctionDeclaration:
+                    return checkFunctionDeclaration(<FunctionDeclaration>node);
+                case SyntaxKind.Block:
+                case SyntaxKind.ModuleBlock:
+                    return checkBlock(<Block>node);
+                case SyntaxKind.VariableStatement:
+                    return checkVariableStatement(<VariableStatement>node);
+                case SyntaxKind.ExpressionStatement:
+                    return checkExpressionStatement(<ExpressionStatement>node);
+                case SyntaxKind.IfStatement:
+                    return checkIfStatement(<IfStatement>node);
+                case SyntaxKind.DoStatement:
+                    return checkDoStatement(<DoStatement>node);
+                case SyntaxKind.WhileStatement:
+                    return checkWhileStatement(<WhileStatement>node);
+                case SyntaxKind.ForStatement:
+                    return checkForStatement(<ForStatement>node);
+                case SyntaxKind.ForInStatement:
+                    return checkForInStatement(<ForInStatement>node);
+                case SyntaxKind.ForOfStatement:
+                    return checkForOfStatement(<ForOfStatement>node);
+                case SyntaxKind.ContinueStatement:
+                case SyntaxKind.BreakStatement:
+                    return checkBreakOrContinueStatement(<BreakOrContinueStatement>node);
+                case SyntaxKind.ReturnStatement:
+                    return checkReturnStatement(<ReturnStatement>node);
+                case SyntaxKind.WithStatement:
+                    return checkWithStatement(<WithStatement>node);
+                case SyntaxKind.SwitchStatement:
+                    return checkSwitchStatement(<SwitchStatement>node);
+                case SyntaxKind.LabeledStatement:
+                    return checkLabeledStatement(<LabeledStatement>node);
+                case SyntaxKind.ThrowStatement:
+                    return checkThrowStatement(<ThrowStatement>node);
+                case SyntaxKind.TryStatement:
+                    return checkTryStatement(<TryStatement>node);
+                case SyntaxKind.VariableDeclaration:
+                    return checkVariableDeclaration(<VariableDeclaration>node);
+                case SyntaxKind.BindingElement:
+                    return checkBindingElement(<BindingElement>node);
+                case SyntaxKind.ClassDeclaration:
+                    return checkClassDeclaration(<ClassDeclaration>node);
+                case SyntaxKind.InterfaceDeclaration:
+                    return checkInterfaceDeclaration(<InterfaceDeclaration>node);
+                case SyntaxKind.TypeAliasDeclaration:
+                    return checkTypeAliasDeclaration(<TypeAliasDeclaration>node);
+                case SyntaxKind.EnumDeclaration:
+                    return checkEnumDeclaration(<EnumDeclaration>node);
+                case SyntaxKind.ModuleDeclaration:
+                    return checkModuleDeclaration(<ModuleDeclaration>node);
+                case SyntaxKind.ImportDeclaration:
+                    return checkImportDeclaration(<ImportDeclaration>node);
+                case SyntaxKind.ImportEqualsDeclaration:
+                    return checkImportEqualsDeclaration(<ImportEqualsDeclaration>node);
+                case SyntaxKind.ExportDeclaration:
+                    return checkExportDeclaration(<ExportDeclaration>node);
+                case SyntaxKind.ExportAssignment:
+                    return checkExportAssignment(<ExportAssignment>node);
+                case SyntaxKind.EmptyStatement:
+                    checkGrammarStatementInAmbientContext(node);
+                    return;
+                case SyntaxKind.DebuggerStatement:
+                    checkGrammarStatementInAmbientContext(node);
+                    return;
+                case SyntaxKind.MissingDeclaration:
+                    return checkMissingDeclaration(node);
+            }
+        }
+
+        // Function expression bodies are checked after all statements in the enclosing body. This is to ensure
+        // constructs like the following are permitted:
+        //     let foo = function () {
+        //        let s = foo();
+        //        return "hello";
+        //     }
+        // Here, performing a full type check of the body of the function expression whilst in the process of
+        // determining the type of foo would cause foo to be given type any because of the recursive reference.
+        // Delaying the type check of the body ensures foo has been assigned a type.
+        function checkFunctionExpressionBodies(node: Node): void {
+            switch (node.kind) {
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                    forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionExpressionBodies);
+                    checkFunctionExpressionOrObjectLiteralMethodBody(<FunctionExpression>node);
+                    break;
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                    forEach((<MethodDeclaration>node).parameters, checkFunctionExpressionBodies);
+                    if (isObjectLiteralMethod(node)) {
+                        checkFunctionExpressionOrObjectLiteralMethodBody(<MethodDeclaration>node);
+                    }
+                    break;
+                case SyntaxKind.Constructor:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.FunctionDeclaration:
+                    forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionExpressionBodies);
+                    break;
+                case SyntaxKind.WithStatement:
+                    checkFunctionExpressionBodies((<WithStatement>node).expression);
+                    break;
+                case SyntaxKind.Parameter:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.ObjectBindingPattern:
+                case SyntaxKind.ArrayBindingPattern:
+                case SyntaxKind.BindingElement:
+                case SyntaxKind.ArrayLiteralExpression:
+                case SyntaxKind.ObjectLiteralExpression:
+                case SyntaxKind.PropertyAssignment:
+                case SyntaxKind.PropertyAccessExpression:
+                case SyntaxKind.ElementAccessExpression:
+                case SyntaxKind.CallExpression:
+                case SyntaxKind.NewExpression:
+                case SyntaxKind.TaggedTemplateExpression:
+                case SyntaxKind.TemplateExpression:
+                case SyntaxKind.TemplateSpan:
+                case SyntaxKind.TypeAssertionExpression:
+                case SyntaxKind.ParenthesizedExpression:
+                case SyntaxKind.TypeOfExpression:
+                case SyntaxKind.VoidExpression:
+                case SyntaxKind.DeleteExpression:
+                case SyntaxKind.PrefixUnaryExpression:
+                case SyntaxKind.PostfixUnaryExpression:
+                case SyntaxKind.BinaryExpression:
+                case SyntaxKind.ConditionalExpression:
+                case SyntaxKind.SpreadElementExpression:
+                case SyntaxKind.Block:
+                case SyntaxKind.ModuleBlock:
+                case SyntaxKind.VariableStatement:
+                case SyntaxKind.ExpressionStatement:
+                case SyntaxKind.IfStatement:
+                case SyntaxKind.DoStatement:
+                case SyntaxKind.WhileStatement:
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                case SyntaxKind.ContinueStatement:
+                case SyntaxKind.BreakStatement:
+                case SyntaxKind.ReturnStatement:
+                case SyntaxKind.SwitchStatement:
+                case SyntaxKind.CaseBlock:
+                case SyntaxKind.CaseClause:
+                case SyntaxKind.DefaultClause:
+                case SyntaxKind.LabeledStatement:
+                case SyntaxKind.ThrowStatement:
+                case SyntaxKind.TryStatement:
+                case SyntaxKind.CatchClause:
+                case SyntaxKind.VariableDeclaration:
+                case SyntaxKind.VariableDeclarationList:
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                case SyntaxKind.EnumMember:
+                case SyntaxKind.ExportAssignment:
+                case SyntaxKind.SourceFile:
+                    forEachChild(node, checkFunctionExpressionBodies);
+                    break;
+            }
+        }
+
+        function checkSourceFile(node: SourceFile) {
+            let start = new Date().getTime();
+            checkSourceFileWorker(node);
+            checkTime += new Date().getTime() - start;
+        }
+
+        // Fully type check a source file and collect the relevant diagnostics.
+        function checkSourceFileWorker(node: SourceFile) {
+            let links = getNodeLinks(node);
+            if (!(links.flags & NodeCheckFlags.TypeChecked)) {
+                // Grammar checking
+                checkGrammarSourceFile(node);
+
+                emitExtends = false;
+                emitDecorate = false;
+                emitParam = false;
+                potentialThisCollisions.length = 0;
+
+                forEach(node.statements, checkSourceElement);
+                checkFunctionExpressionBodies(node);
+
+                if (isExternalModule(node)) {
+                    checkExternalModuleExports(node);
+                }
+
+                if (potentialThisCollisions.length) {
+                    forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
+                    potentialThisCollisions.length = 0;
+                }
+
+                if (emitExtends) {
+                    links.flags |= NodeCheckFlags.EmitExtends;
+                }
+
+                if (emitDecorate) {
+                    links.flags |= NodeCheckFlags.EmitDecorate;
+                }
+
+                if (emitParam) {
+                    links.flags |= NodeCheckFlags.EmitParam;
+                }
+
+                links.flags |= NodeCheckFlags.TypeChecked;
+            }
+        }
+
+        function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
+            throwIfNonDiagnosticsProducing();
+            if (sourceFile) {
+                checkSourceFile(sourceFile);
+                return diagnostics.getDiagnostics(sourceFile.fileName);
+            }
+            forEach(host.getSourceFiles(), checkSourceFile);
+            return diagnostics.getDiagnostics();
+        }
+
+        function getGlobalDiagnostics(): Diagnostic[] {
+            throwIfNonDiagnosticsProducing();
+            return diagnostics.getGlobalDiagnostics();
+        }
+
+        function throwIfNonDiagnosticsProducing() {
+            if (!produceDiagnostics) {
+                throw new Error("Trying to get diagnostics from a type checker that does not produce them.");
+            }
+        }
+
+        // Language service support
+
+        function isInsideWithStatementBody(node: Node): boolean {
+            if (node) {
+                while (node.parent) {
+                    if (node.parent.kind === SyntaxKind.WithStatement && (<WithStatement>node.parent).statement === node) {
+                        return true;
+                    }
+                    node = node.parent;
+                }
+            }
+
+            return false;
+        }
+
+        function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] {
+            let symbols: SymbolTable = {};
+            let memberFlags: NodeFlags = 0;
+
+            if (isInsideWithStatementBody(location)) {
+                // We cannot answer semantic questions within a with block, do not proceed any further
+                return [];
+            }
+
+            populateSymbols();
+
+            return symbolsToArray(symbols);
+
+            function populateSymbols() {
+                while (location) {
+                    if (location.locals && !isGlobalSourceFile(location)) {
+                        copySymbols(location.locals, meaning);
+                    }
+
+                    switch (location.kind) {
+                        case SyntaxKind.SourceFile:
+                            if (!isExternalModule(<SourceFile>location)) {
+                                break;
+                            }
+                        case SyntaxKind.ModuleDeclaration:
+                            copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.ModuleMember);
+                            break;
+                        case SyntaxKind.EnumDeclaration:
+                            copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.EnumMember);
+                            break;
+                        case SyntaxKind.ClassDeclaration:
+                        case SyntaxKind.InterfaceDeclaration:
+                            if (!(memberFlags & NodeFlags.Static)) {
+                                copySymbols(getSymbolOfNode(location).members, meaning & SymbolFlags.Type);
+                            }
+                            break;
+                        case SyntaxKind.FunctionExpression:
+                            if ((<FunctionExpression>location).name) {
+                                copySymbol(location.symbol, meaning);
+                            }
+                            break;
+                    }
+
+                    memberFlags = location.flags;
+                    location = location.parent;
+                }
+
+                copySymbols(globals, meaning);
+            }
+
+            // Returns 'true' if we should stop processing symbols.
+            function copySymbol(symbol: Symbol, meaning: SymbolFlags): void {
+                if (symbol.flags & meaning) {
+                    let id = symbol.name;
+                    if (!isReservedMemberName(id) && !hasProperty(symbols, id)) {
+                        symbols[id] = symbol;
+                    }
+                }
+            }
+
+            function copySymbols(source: SymbolTable, meaning: SymbolFlags): void {
+                if (meaning) {
+                    for (let id in source) {
+                        if (hasProperty(source, id)) {
+                            copySymbol(source[id], meaning);
+                        }
+                    }
+                }
+            }
+
+            if (isInsideWithStatementBody(location)) {
+                // We cannot answer semantic questions within a with block, do not proceed any further
+                return [];
+            }
+
+            while (location) {
+                if (location.locals && !isGlobalSourceFile(location)) {
+                    copySymbols(location.locals, meaning);
+                }
+                switch (location.kind) {
+                    case SyntaxKind.SourceFile:
+                        if (!isExternalModule(<SourceFile>location)) break;
+                    case SyntaxKind.ModuleDeclaration:
+                        copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.ModuleMember);
+                        break;
+                    case SyntaxKind.EnumDeclaration:
+                        copySymbols(getSymbolOfNode(location).exports, meaning & SymbolFlags.EnumMember);
+                        break;
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                        if (!(memberFlags & NodeFlags.Static)) {
+                            copySymbols(getSymbolOfNode(location).members, meaning & SymbolFlags.Type);
+                        }
+                        break;
+                    case SyntaxKind.FunctionExpression:
+                        if ((<FunctionExpression>location).name) {
+                            copySymbol(location.symbol, meaning);
+                        }
+                        break;
+                }
+                memberFlags = location.flags;
+                location = location.parent;
+            }
+            copySymbols(globals, meaning);
+            return symbolsToArray(symbols);
+        }
+
+        function isTypeDeclarationName(name: Node): boolean {
+            return name.kind == SyntaxKind.Identifier &&
+                isTypeDeclaration(name.parent) &&
+                (<Declaration>name.parent).name === name;
+        }
+
+        function isTypeDeclaration(node: Node): boolean {
+            switch (node.kind) {
+                case SyntaxKind.TypeParameter:
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.TypeAliasDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                    return true;
+            }
+        }
+
+        // True if the given identifier is part of a type reference
+        function isTypeReferenceIdentifier(entityName: EntityName): boolean {
+            let node: Node = entityName;
+            while (node.parent && node.parent.kind === SyntaxKind.QualifiedName) {
+                node = node.parent;
+            }
+
+            return node.parent && node.parent.kind === SyntaxKind.TypeReference;
+        }
+
+        function isHeritageClauseElementIdentifier(entityName: Node): boolean {
+            let node = entityName;
+            while (node.parent && node.parent.kind === SyntaxKind.PropertyAccessExpression) {
+                node = node.parent;
+            }
+
+            return node.parent && node.parent.kind === SyntaxKind.HeritageClauseElement;
+        }
+
+        function isTypeNode(node: Node): boolean {
+            if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) {
+                return true;
+            }
+
+            switch (node.kind) {
+                case SyntaxKind.AnyKeyword:
+                case SyntaxKind.NumberKeyword:
+                case SyntaxKind.StringKeyword:
+                case SyntaxKind.BooleanKeyword:
+                case SyntaxKind.SymbolKeyword:
+                    return true;
+                case SyntaxKind.VoidKeyword:
+                    return node.parent.kind !== SyntaxKind.VoidExpression;
+                case SyntaxKind.StringLiteral:
+                    // Specialized signatures can have string literals as their parameters' type names
+                    return node.parent.kind === SyntaxKind.Parameter;
+                case SyntaxKind.HeritageClauseElement:
+                    return true;
+
+                // Identifiers and qualified names may be type nodes, depending on their context. Climb
+                // above them to find the lowest container
+                case SyntaxKind.Identifier:
+                    // If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
+                    if (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node) {
+                        node = node.parent;
+                    }
+                    else if (node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node) {
+                        node = node.parent;
+                    }
+                    // fall through
+                case SyntaxKind.QualifiedName:
+                case SyntaxKind.PropertyAccessExpression:
+                    // At this point, node is either a qualified name or an identifier
+                    Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression,
+                        "'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'.");
+
+                    let parent = node.parent;
+                    if (parent.kind === SyntaxKind.TypeQuery) {
+                        return false;
+                    }
+                    // Do not recursively call isTypeNode on the parent. In the example:
+                    //
+                    //     let a: A.B.C;
+                    //
+                    // Calling isTypeNode would consider the qualified name A.B a type node. Only C or
+                    // A.B.C is a type node.
+                    if (SyntaxKind.FirstTypeNode <= parent.kind && parent.kind <= SyntaxKind.LastTypeNode) {
+                        return true;
+                    }
+                    switch (parent.kind) {
+                        case SyntaxKind.HeritageClauseElement:
+                            return true;
+                        case SyntaxKind.TypeParameter:
+                            return node === (<TypeParameterDeclaration>parent).constraint;
+                        case SyntaxKind.PropertyDeclaration:
+                        case SyntaxKind.PropertySignature:
+                        case SyntaxKind.Parameter:
+                        case SyntaxKind.VariableDeclaration:
+                            return node === (<VariableLikeDeclaration>parent).type;
+                        case SyntaxKind.FunctionDeclaration:
+                        case SyntaxKind.FunctionExpression:
+                        case SyntaxKind.ArrowFunction:
+                        case SyntaxKind.Constructor:
+                        case SyntaxKind.MethodDeclaration:
+                        case SyntaxKind.MethodSignature:
+                        case SyntaxKind.GetAccessor:
+                        case SyntaxKind.SetAccessor:
+                            return node === (<FunctionLikeDeclaration>parent).type;
+                        case SyntaxKind.CallSignature:
+                        case SyntaxKind.ConstructSignature:
+                        case SyntaxKind.IndexSignature:
+                            return node === (<SignatureDeclaration>parent).type;
+                        case SyntaxKind.TypeAssertionExpression:
+                            return node === (<TypeAssertion>parent).type;
+                        case SyntaxKind.CallExpression:
+                        case SyntaxKind.NewExpression:
+                            return (<CallExpression>parent).typeArguments && indexOf((<CallExpression>parent).typeArguments, node) >= 0;
+                        case SyntaxKind.TaggedTemplateExpression:
+                            // TODO (drosen): TaggedTemplateExpressions may eventually support type arguments.
+                            return false;
+                    }
+            }
+
+            return false;
+        }
+
+        function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment {
+            while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) {
+                nodeOnRightSide = <QualifiedName>nodeOnRightSide.parent;
+            }
+
+            if (nodeOnRightSide.parent.kind === SyntaxKind.ImportEqualsDeclaration) {
+                return (<ImportEqualsDeclaration>nodeOnRightSide.parent).moduleReference === nodeOnRightSide && <ImportEqualsDeclaration>nodeOnRightSide.parent;
+            }
+
+            if (nodeOnRightSide.parent.kind === SyntaxKind.ExportAssignment) {
+                return (<ExportAssignment>nodeOnRightSide.parent).expression === <Node>nodeOnRightSide && <ExportAssignment>nodeOnRightSide.parent;
+            }
+
+            return undefined;
+        }
+
+        function isInRightSideOfImportOrExportAssignment(node: EntityName) {
+            return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
+        }
+
+        function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
+            if (isDeclarationName(entityName)) {
+                return getSymbolOfNode(entityName.parent);
+            }
+
+            if (entityName.parent.kind === SyntaxKind.ExportAssignment) {
+                return resolveEntityName(<Identifier>entityName,
+                    /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
+            }
+
+            if (entityName.kind !== SyntaxKind.PropertyAccessExpression) {
+                if (isInRightSideOfImportOrExportAssignment(<EntityName>entityName)) {
+                    // Since we already checked for ExportAssignment, this really could only be an Import
+                    return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>entityName);
+                }
+            }
+
+            if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
+                entityName = <QualifiedName | PropertyAccessExpression>entityName.parent;
+            }
+
+            if (isHeritageClauseElementIdentifier(<EntityName>entityName)) {
+                let meaning = entityName.parent.kind === SyntaxKind.HeritageClauseElement ? SymbolFlags.Type : SymbolFlags.Namespace;
+                meaning |= SymbolFlags.Alias;
+                return resolveEntityName(<EntityName>entityName, meaning);
+            }
+            else if (isExpression(entityName)) {
+                if (nodeIsMissing(entityName)) {
+                    // Missing entity name.
+                    return undefined;
+                }
+
+                if (entityName.kind === SyntaxKind.Identifier) {
+                    // Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead
+                    // return the alias symbol.
+                    let meaning: SymbolFlags = SymbolFlags.Value | SymbolFlags.Alias;
+                    return resolveEntityName(<Identifier>entityName, meaning);
+                }
+                else if (entityName.kind === SyntaxKind.PropertyAccessExpression) {
+                    let symbol = getNodeLinks(entityName).resolvedSymbol;
+                    if (!symbol) {
+                        checkPropertyAccessExpression(<PropertyAccessExpression>entityName);
+                    }
+                    return getNodeLinks(entityName).resolvedSymbol;
+                }
+                else if (entityName.kind === SyntaxKind.QualifiedName) {
+                    let symbol = getNodeLinks(entityName).resolvedSymbol;
+                    if (!symbol) {
+                        checkQualifiedName(<QualifiedName>entityName);
+                    }
+                    return getNodeLinks(entityName).resolvedSymbol;
+                }
+            }
+            else if (isTypeReferenceIdentifier(<EntityName>entityName)) {
+                let meaning = entityName.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
+                // Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead
+                // return the alias symbol.
+                meaning |= SymbolFlags.Alias;
+                return resolveEntityName(<EntityName>entityName, meaning);
+            }
+
+            // Do we want to return undefined here?
+            return undefined;
+        }
+
+        function getSymbolInfo(node: Node) {
+            if (isInsideWithStatementBody(node)) {
+                // We cannot answer semantic questions within a with block, do not proceed any further
+                return undefined;
+            }
+
+            if (isDeclarationName(node)) {
+                // This is a declaration, call getSymbolOfNode
+                return getSymbolOfNode(node.parent);
+            }
+
+            if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
+                return node.parent.kind === SyntaxKind.ExportAssignment
+                    ? getSymbolOfEntityNameOrPropertyAccessExpression(<Identifier>node)
+                    : getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
+            }
+
+            switch (node.kind) {
+                case SyntaxKind.Identifier:
+                case SyntaxKind.PropertyAccessExpression:
+                case SyntaxKind.QualifiedName:
+                    return getSymbolOfEntityNameOrPropertyAccessExpression(<EntityName | PropertyAccessExpression>node);
+
+                case SyntaxKind.ThisKeyword:
+                case SyntaxKind.SuperKeyword:
+                    let type = checkExpression(<Expression>node);
+                    return type.symbol;
+
+                case SyntaxKind.ConstructorKeyword:
+                    // constructor keyword for an overload, should take us to the definition if it exist
+                    let constructorDeclaration = node.parent;
+                    if (constructorDeclaration && constructorDeclaration.kind === SyntaxKind.Constructor) {
+                        return (<ClassDeclaration>constructorDeclaration.parent).symbol;
+                    }
+                    return undefined;
+
+                case SyntaxKind.StringLiteral:
+                    // External module name in an import declaration
+                    let moduleName: Expression;
+                    if ((isExternalModuleImportEqualsDeclaration(node.parent.parent) &&
+                        getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) ||
+                        ((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) &&
+                            (<ImportDeclaration>node.parent).moduleSpecifier === node)) {
+                        return resolveExternalModuleName(node, <LiteralExpression>node);
+                    }
+
+                // Intentional fall-through
+                case SyntaxKind.NumericLiteral:
+                    // index access
+                    if (node.parent.kind == SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>node.parent).argumentExpression === node) {
+                        let objectType = checkExpression((<ElementAccessExpression>node.parent).expression);
+                        if (objectType === unknownType) return undefined;
+                        let apparentType = getApparentType(objectType);
+                        if (apparentType === unknownType) return undefined;
+                        return getPropertyOfType(apparentType, (<LiteralExpression>node).text);
+                    }
+                    break;
+            }
+            return undefined;
+        }
+
+        function getShorthandAssignmentValueSymbol(location: Node): Symbol {
+            // The function returns a value symbol of an identifier in the short-hand property assignment.
+            // This is necessary as an identifier in short-hand property assignment can contains two meaning:
+            // property name and property value.
+            if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) {
+                return resolveEntityName((<ShorthandPropertyAssignment>location).name, SymbolFlags.Value);
+            }
+            return undefined;
+        }
+
+        function getTypeOfNode(node: Node): Type {
+            if (isInsideWithStatementBody(node)) {
+                // We cannot answer semantic questions within a with block, do not proceed any further
+                return unknownType;
+            }
+
+            if (isTypeNode(node)) {
+                return getTypeFromTypeNode(<TypeNode>node);
+            }
+
+            if (isExpression(node)) {
+                return getTypeOfExpression(<Expression>node);
+            }
+
+            if (isTypeDeclaration(node)) {
+                // In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
+                let symbol = getSymbolOfNode(node);
+                return getDeclaredTypeOfSymbol(symbol);
+            }
+
+            if (isTypeDeclarationName(node)) {
+                let symbol = getSymbolInfo(node);
+                return symbol && getDeclaredTypeOfSymbol(symbol);
+            }
+
+            if (isDeclaration(node)) {
+                // In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
+                let symbol = getSymbolOfNode(node);
+                return getTypeOfSymbol(symbol);
+            }
+
+            if (isDeclarationName(node)) {
+                let symbol = getSymbolInfo(node);
+                return symbol && getTypeOfSymbol(symbol);
+            }
+
+            if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
+                let symbol = getSymbolInfo(node);
+                let declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
+                return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
+            }
+
+            return unknownType;
+        }
+
+        function getTypeOfExpression(expr: Expression): Type {
+            if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
+                expr = <Expression>expr.parent;
+            }
+            return checkExpression(expr);
+        }
+
+        // Return the list of properties of the given type, augmented with properties from Function
+        // if the type has call or construct signatures
+        function getAugmentedPropertiesOfType(type: Type): Symbol[] {
+            type = getApparentType(type);
+            let propsByName = createSymbolTable(getPropertiesOfType(type));
+            if (getSignaturesOfType(type, SignatureKind.Call).length || getSignaturesOfType(type, SignatureKind.Construct).length) {
+                forEach(getPropertiesOfType(globalFunctionType), p => {
+                    if (!hasProperty(propsByName, p.name)) {
+                        propsByName[p.name] = p;
+                    }
+                });
+            }
+            return getNamedMembers(propsByName);
+        }
+
+        function getRootSymbols(symbol: Symbol): Symbol[] {
+            if (symbol.flags & SymbolFlags.UnionProperty) {
+                let symbols: Symbol[] = [];
+                let name = symbol.name;
+                forEach(getSymbolLinks(symbol).unionType.types, t => {
+                    symbols.push(getPropertyOfType(t, name));
+                });
+                return symbols;
+            }
+            else if (symbol.flags & SymbolFlags.Transient) {
+                let target = getSymbolLinks(symbol).target;
+                if (target) {
+                    return [target];
+                }
+            }
+            return [symbol];
+        }
+
+        // Emitter support
+
+        function isExternalModuleSymbol(symbol: Symbol): boolean {
+            return symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length === 1 && symbol.declarations[0].kind === SyntaxKind.SourceFile;
+        }
+
+        function getAliasNameSubstitution(symbol: Symbol, getGeneratedNameForNode: (node: Node) => string): string {
+            // If this is es6 or higher, just use the name of the export
+            // no need to qualify it.
+            if (languageVersion >= ScriptTarget.ES6) {
+                return undefined;
+            }
+
+            let node = getDeclarationOfAliasSymbol(symbol);
+            if (node) {
+                if (node.kind === SyntaxKind.ImportClause) {
+                    let defaultKeyword: string;
+
+                    if (languageVersion === ScriptTarget.ES3) {
+                        defaultKeyword = "[\"default\"]";
+                    } else {
+                        defaultKeyword = ".default";
+                    }
+                    return getGeneratedNameForNode(<ImportDeclaration>node.parent) + defaultKeyword;
+                }
+                if (node.kind === SyntaxKind.ImportSpecifier) {
+                    let moduleName = getGeneratedNameForNode(<ImportDeclaration>node.parent.parent.parent);
+                    let propertyName = (<ImportSpecifier>node).propertyName || (<ImportSpecifier>node).name;
+                    return moduleName + "." + unescapeIdentifier(propertyName.text);
+                }
+            }
+        }
+
+        function getExportNameSubstitution(symbol: Symbol, location: Node, getGeneratedNameForNode: (Node: Node) => string): string {
+            if (isExternalModuleSymbol(symbol.parent)) {
+                // If this is es6 or higher, just use the name of the export
+                // no need to qualify it.
+                if (languageVersion >= ScriptTarget.ES6) {
+                    return undefined;
+                }
+                return "exports." + unescapeIdentifier(symbol.name);
+            }
+            let node = location;
+            let containerSymbol = getParentOfSymbol(symbol);
+            while (node) {
+                if ((node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(node) === containerSymbol) {
+                    return getGeneratedNameForNode(<ModuleDeclaration | EnumDeclaration>node) + "." + unescapeIdentifier(symbol.name);
+                }
+                node = node.parent;
+            }
+        }
+
+        function getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (Node: Node) => string): string {
+            let symbol = getNodeLinks(node).resolvedSymbol || (isDeclarationName(node) ? getSymbolOfNode(node.parent) : undefined);
+            if (symbol) {
+                // Whan an identifier resolves to a parented symbol, it references an exported entity from
+                // another declaration of the same internal module.
+                if (symbol.parent) {
+                    return getExportNameSubstitution(symbol, node.parent, getGeneratedNameForNode);
+                }
+                // If we reference an exported entity within the same module declaration, then whether
+                // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the
+                // kinds that we do NOT prefix.
+                let exportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
+                if (symbol !== exportSymbol && !(exportSymbol.flags & SymbolFlags.ExportHasLocal)) {
+                    return getExportNameSubstitution(exportSymbol, node.parent, getGeneratedNameForNode);
+                }
+                // Named imports from ES6 import declarations are rewritten
+                if (symbol.flags & SymbolFlags.Alias) {
+                    return getAliasNameSubstitution(symbol, getGeneratedNameForNode);
+                }
+            }
+        }
+
+        function isValueAliasDeclaration(node: Node): boolean {
+            switch (node.kind) {
+                case SyntaxKind.ImportEqualsDeclaration:
+                case SyntaxKind.ImportClause:
+                case SyntaxKind.NamespaceImport:
+                case SyntaxKind.ImportSpecifier:
+                case SyntaxKind.ExportSpecifier:
+                    return isAliasResolvedToValue(getSymbolOfNode(node));
+                case SyntaxKind.ExportDeclaration:
+                    let exportClause = (<ExportDeclaration>node).exportClause;
+                    return exportClause && forEach(exportClause.elements, isValueAliasDeclaration);
+                case SyntaxKind.ExportAssignment:
+                    return (<ExportAssignment>node).expression && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node)) : true;
+            }
+            return false;
+        }
+
+        function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean {
+            if (node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) {
+                // parent is not source file or it is not reference to internal module
+                return false;
+            }
+
+            var isValue = isAliasResolvedToValue(getSymbolOfNode(node));
+            return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference);
+        }
+
+        function isAliasResolvedToValue(symbol: Symbol): boolean {
+            let target = resolveAlias(symbol);
+            if (target === unknownSymbol && compilerOptions.separateCompilation) {
+                return true;
+            }
+            // const enums and modules that contain only const enums are not considered values from the emit perespective
+            return target !== unknownSymbol && target && target.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(target);
+        }
+
+        function isConstEnumOrConstEnumOnlyModule(s: Symbol): boolean {
+            return isConstEnumSymbol(s) || s.constEnumOnlyModule;
+        }
+
+        function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean {
+            if (isAliasSymbolDeclaration(node)) {
+                let symbol = getSymbolOfNode(node);
+                if (getSymbolLinks(symbol).referenced) {
+                    return true;
+                }
+            }
+
+            if (checkChildren) {
+                return forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren));
+            }
+            return false;
+        }
+
+        function isImplementationOfOverload(node: FunctionLikeDeclaration) {
+            if (nodeIsPresent(node.body)) {
+                let symbol = getSymbolOfNode(node);
+                let signaturesOfSymbol = getSignaturesOfSymbol(symbol);
+                // If this function body corresponds to function with multiple signature, it is implementation of overload
+                // e.g.: function foo(a: string): string;
+                //       function foo(a: number): number;
+                //       function foo(a: any) { // This is implementation of the overloads
+                //           return a;
+                //       }
+                return signaturesOfSymbol.length > 1 ||
+                    // If there is single signature for the symbol, it is overload if that signature isn't coming from the node
+                    // e.g.: function foo(a: string): string;
+                    //       function foo(a: any) { // This is implementation of the overloads
+                    //           return a;
+                    //       }
+                    (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node);
+            }
+            return false;
+        }
+
+        function getNodeCheckFlags(node: Node): NodeCheckFlags {
+            return getNodeLinks(node).flags;
+        }
+
+        function getEnumMemberValue(node: EnumMember): number {
+            computeEnumMemberValues(<EnumDeclaration>node.parent);
+            return getNodeLinks(node).enumMemberValue;
+        }
+
+        function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number {
+            if (node.kind === SyntaxKind.EnumMember) {
+                return getEnumMemberValue(<EnumMember>node);
+            }
+
+            let symbol = getNodeLinks(node).resolvedSymbol;
+            if (symbol && (symbol.flags & SymbolFlags.EnumMember)) {
+                // inline property\index accesses only for const enums
+                if (isConstEnumDeclaration(symbol.valueDeclaration.parent)) {
+                    return getEnumMemberValue(<EnumMember>symbol.valueDeclaration);
+                }
+            }
+
+            return undefined;
+        }
+
+        /** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */
+        function serializeEntityName(node: EntityName, getGeneratedNameForNode: (Node: Node) => string, fallbackPath?: string[]): string {
+            if (node.kind === SyntaxKind.Identifier) {
+                var substitution = getExpressionNameSubstitution(<Identifier>node, getGeneratedNameForNode);
+                var text = substitution || (<Identifier>node).text;
+                if (fallbackPath) {
+                    fallbackPath.push(text);
+                }
+                else {
+                    return text;
+                }
+            }
+            else {
+                var left = serializeEntityName((<QualifiedName>node).left, getGeneratedNameForNode, fallbackPath);
+                var right = serializeEntityName((<QualifiedName>node).right, getGeneratedNameForNode, fallbackPath);
+                if (!fallbackPath) {
+                    return left + "." + right;
+                }
+            }
+        }
+
+        /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
+        function serializeTypeReferenceNode(node: TypeReferenceNode, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
+            // serialization of a TypeReferenceNode uses the following rules:
+            //
+            // * The serialized type of a TypeReference that is `void` is "void 0".
+            // * The serialized type of a TypeReference that is a `boolean` is "Boolean".
+            // * The serialized type of a TypeReference that is an enum or `number` is "Number".
+            // * The serialized type of a TypeReference that is a string literal or `string` is "String".
+            // * The serialized type of a TypeReference that is a tuple is "Array".
+            // * The serialized type of a TypeReference that is a `symbol` is "Symbol".
+            // * The serialized type of a TypeReference with a value declaration is its entity name.
+            // * The serialized type of a TypeReference with a call or construct signature is "Function".
+            // * The serialized type of any other type is "Object".
+            let type = getTypeFromTypeReference(node);
+            if (type.flags & TypeFlags.Void) {
+                return "void 0";
+            }
+            else if (type.flags & TypeFlags.Boolean) {
+                return "Boolean";
+            }
+            else if (type.flags & TypeFlags.NumberLike) {
+                return "Number";
+            }
+            else if (type.flags & TypeFlags.StringLike) {
+                return "String";
+            }
+            else if (type.flags & TypeFlags.Tuple) {
+                return "Array";
+            }
+            else if (type.flags & TypeFlags.ESSymbol) {
+                return "Symbol";
+            }
+            else if (type === unknownType) {
+                var fallbackPath: string[] = [];
+                serializeEntityName(node.typeName, getGeneratedNameForNode, fallbackPath);
+                return fallbackPath;
+            }
+            else if (type.symbol && type.symbol.valueDeclaration) {
+                return serializeEntityName(node.typeName, getGeneratedNameForNode);
+            }
+            else if (typeHasCallOrConstructSignatures(type)) {
+                return "Function";
+            }
+
+            return "Object";
+        }
+
+        /** Serializes a TypeNode to an appropriate JS constructor value. Used by the __metadata decorator. */
+        function serializeTypeNode(node: TypeNode | LiteralExpression, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
+            // serialization of a TypeNode uses the following rules:
+            //
+            // * The serialized type of `void` is "void 0" (undefined).
+            // * The serialized type of a parenthesized type is the serialized type of its nested type.
+            // * The serialized type of a Function or Constructor type is "Function".
+            // * The serialized type of an Array or Tuple type is "Array".
+            // * The serialized type of `boolean` is "Boolean".
+            // * The serialized type of `string` or a string-literal type is "String".
+            // * The serialized type of a type reference is handled by `serializeTypeReferenceNode`.
+            // * The serialized type of any other type node is "Object".
+            if (node) {
+                switch (node.kind) {
+                    case SyntaxKind.VoidKeyword:
+                        return "void 0";
+                    case SyntaxKind.ParenthesizedType:
+                        return serializeTypeNode((<ParenthesizedTypeNode>node).type, getGeneratedNameForNode);
+                    case SyntaxKind.FunctionType:
+                    case SyntaxKind.ConstructorType:
+                        return "Function";
+                    case SyntaxKind.ArrayType:
+                    case SyntaxKind.TupleType:
+                        return "Array";
+                    case SyntaxKind.BooleanKeyword:
+                        return "Boolean";
+                    case SyntaxKind.StringKeyword:
+                    case SyntaxKind.StringLiteral:
+                        return "String";
+                    case SyntaxKind.NumberKeyword:
+                        return "Number";
+                    case SyntaxKind.TypeReference:
+                        return serializeTypeReferenceNode(<TypeReferenceNode>node, getGeneratedNameForNode);
+                    case SyntaxKind.TypeQuery:
+                    case SyntaxKind.TypeLiteral:
+                    case SyntaxKind.UnionType:
+                    case SyntaxKind.AnyKeyword:
+                        break;
+                    default:
+                        Debug.fail("Cannot serialize unexpected type node.");
+                        break;
+                }
+            }
+             
+            return "Object";
+        }
+
+        /** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */
+        function serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
+            // serialization of the type of a declaration uses the following rules:
+            //
+            // * The serialized type of a ClassDeclaration is "Function"
+            // * The serialized type of a ParameterDeclaration is the serialized type of its type annotation.
+            // * The serialized type of a PropertyDeclaration is the serialized type of its type annotation.
+            // * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter.
+            // * The serialized type of any other FunctionLikeDeclaration is "Function".
+            // * The serialized type of any other node is "void 0".
+            // 
+            // For rules on serializing type annotations, see `serializeTypeNode`.
+            switch (node.kind) {
+                case SyntaxKind.ClassDeclaration:       return "Function";
+                case SyntaxKind.PropertyDeclaration:    return serializeTypeNode((<PropertyDeclaration>node).type, getGeneratedNameForNode);
+                case SyntaxKind.Parameter:              return serializeTypeNode((<ParameterDeclaration>node).type, getGeneratedNameForNode);
+                case SyntaxKind.GetAccessor:            return serializeTypeNode((<AccessorDeclaration>node).type, getGeneratedNameForNode);
+                case SyntaxKind.SetAccessor:            return serializeTypeNode(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node), getGeneratedNameForNode);
+            }
+            if (isFunctionLike(node)) {
+                return "Function";
+            }
+            return "void 0";
+        }
+        
+        /** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
+        function serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[] {
+            // serialization of parameter types uses the following rules:
+            //
+            // * If the declaration is a class, the parameters of the first constructor with a body are used.
+            // * If the declaration is function-like and has a body, the parameters of the function are used.
+            // 
+            // For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
+            if (node) {
+                var valueDeclaration: FunctionLikeDeclaration;
+                if (node.kind === SyntaxKind.ClassDeclaration) {
+                    valueDeclaration = getFirstConstructorWithBody(<ClassDeclaration>node);
+                }
+                else if (isFunctionLike(node) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
+                    valueDeclaration = <FunctionLikeDeclaration>node;
+                }
+                if (valueDeclaration) {
+                    var result: (string | string[])[];
+                    var parameters = valueDeclaration.parameters;
+                    var parameterCount = parameters.length;
+                    if (parameterCount > 0) {
+                        result = new Array<string>(parameterCount);
+                        for (var i = 0; i < parameterCount; i++) {
+                            if (parameters[i].dotDotDotToken) {
+                                var parameterType = parameters[i].type;
+                                if (parameterType.kind === SyntaxKind.ArrayType) {
+                                    parameterType = (<ArrayTypeNode>parameterType).elementType;
+                                }
+                                else if (parameterType.kind === SyntaxKind.TypeReference && (<TypeReferenceNode>parameterType).typeArguments && (<TypeReferenceNode>parameterType).typeArguments.length === 1) {
+                                    parameterType = (<TypeReferenceNode>parameterType).typeArguments[0];
+                                }
+                                else {
+                                    parameterType = undefined;
+                                }
+                                result[i] = serializeTypeNode(parameterType, getGeneratedNameForNode);
+                            }
+                            else {
+                                result[i] = serializeTypeOfNode(parameters[i], getGeneratedNameForNode);
+                            }
+                        }
+                        return result;
+                    }
+                }
+            }
+            return emptyArray;
+        }
+
+        /** Serializes the return type of function. Used by the __metadata decorator for a method. */
+        function serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
+            if (node && isFunctionLike(node)) {
+                return serializeTypeNode((<FunctionLikeDeclaration>node).type, getGeneratedNameForNode);
+            }
+            return "void 0";
+        }
+
+        function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
+            // Get type of the symbol if this is the valid symbol otherwise get type at location
+            let symbol = getSymbolOfNode(declaration);
+            let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
+                ? getTypeOfSymbol(symbol)
+                : unknownType;
+
+            getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+        }
+
+        function writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
+            let signature = getSignatureFromDeclaration(signatureDeclaration);
+            getSymbolDisplayBuilder().buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags);
+        }
+
+        function writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
+            var type = getTypeOfExpression(expr);
+            getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+        }
+
+        function hasGlobalName(name: string): boolean {
+            return hasProperty(globals, name);
+        }
+
+        function resolvesToSomeValue(location: Node, name: string): boolean {
+            Debug.assert(!nodeIsSynthesized(location), "resolvesToSomeValue called with a synthesized location");
+            return !!resolveName(location, name, SymbolFlags.Value, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);
+        }
+
+        function getBlockScopedVariableId(n: Identifier): number {
+            Debug.assert(!nodeIsSynthesized(n));
+
+            let isVariableDeclarationOrBindingElement =
+                n.parent.kind === SyntaxKind.BindingElement || (n.parent.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>n.parent).name === n);
+
+            let symbol = 
+                (isVariableDeclarationOrBindingElement ? getSymbolOfNode(n.parent) : undefined) ||
+                getNodeLinks(n).resolvedSymbol ||
+                resolveName(n, n.text, SymbolFlags.Value | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);
+
+            let isLetOrConst =
+                symbol &&
+                (symbol.flags & SymbolFlags.BlockScopedVariable) &&
+                symbol.valueDeclaration.parent.kind !== SyntaxKind.CatchClause;
+
+            if (isLetOrConst) {
+                // side-effect of calling this method:
+                //   assign id to symbol if it was not yet set
+                getSymbolLinks(symbol);
+                return symbol.id;
+            }
+            return undefined;
+        }
+
+        function instantiateSingleCallFunctionType(functionType: Type, typeArguments: Type[]): Type {
+            if (functionType === unknownType) {
+                return unknownType;
+            }
+
+            let signature = getSingleCallSignature(functionType);
+            if (!signature) {
+                return unknownType;
+            }
+            
+            let instantiatedSignature = getSignatureInstantiation(signature, typeArguments);
+            return getOrCreateTypeFromSignature(instantiatedSignature);
+        }
+
+        function createResolver(): EmitResolver {
+            return {
+                getExpressionNameSubstitution,
+                isValueAliasDeclaration,
+                hasGlobalName,
+                isReferencedAliasDeclaration,
+                getNodeCheckFlags,
+                isTopLevelValueImportEqualsWithEntityName,
+                isDeclarationVisible,
+                isImplementationOfOverload,
+                writeTypeOfDeclaration,
+                writeReturnTypeOfSignatureDeclaration,
+                writeTypeOfExpression,
+                isSymbolAccessible,
+                isEntityNameVisible,
+                getConstantValue,
+                resolvesToSomeValue,
+                collectLinkedAliases,
+                getBlockScopedVariableId,
+                serializeTypeOfNode,
+                serializeParameterTypesOfNode,
+                serializeReturnTypeOfNode,
+            };
+        }
+
+        function initializeTypeChecker() {
+            // Bind all source files and propagate errors
+            forEach(host.getSourceFiles(), file => {
+                bindSourceFile(file);
+            });
+
+            // Initialize global symbol table
+            forEach(host.getSourceFiles(), file => {
+                if (!isExternalModule(file)) {
+                    mergeSymbolTable(globals, file.locals);
+                }
+            });
+
+            // Initialize special symbols
+            getSymbolLinks(undefinedSymbol).type = undefinedType;
+            getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
+            getSymbolLinks(unknownSymbol).type = unknownType;
+            globals[undefinedSymbol.name] = undefinedSymbol;
+            // Initialize special types
+            globalArraySymbol = getGlobalTypeSymbol("Array");
+            globalArrayType = getTypeOfGlobalSymbol(globalArraySymbol, /*arity*/ 1);
+            globalObjectType = getGlobalType("Object");
+            globalFunctionType = getGlobalType("Function");
+            globalStringType = getGlobalType("String");
+            globalNumberType = getGlobalType("Number");
+            globalBooleanType = getGlobalType("Boolean");
+            globalRegExpType = getGlobalType("RegExp");
+            getGlobalClassDecoratorType = memoize(() => getGlobalType("ClassDecorator"));
+            getGlobalPropertyDecoratorType = memoize(() => getGlobalType("PropertyDecorator"));
+            getGlobalMethodDecoratorType = memoize(() => getGlobalType("MethodDecorator"));
+            getGlobalParameterDecoratorType = memoize(() => getGlobalType("ParameterDecorator"));
+
+            // If we're in ES6 mode, load the TemplateStringsArray.
+            // Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios.
+            if (languageVersion >= ScriptTarget.ES6) {
+                globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray");
+                globalESSymbolType = getGlobalType("Symbol");
+                globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol");
+                globalIterableType = getGlobalType("Iterable", /*arity*/ 1);
+            }
+            else {
+                globalTemplateStringsArrayType = unknownType;
+
+                // Consider putting Symbol interface in lib.d.ts. On the plus side, putting it in lib.d.ts would make it
+                // extensible for Polyfilling Symbols. But putting it into lib.d.ts could also break users that have
+                // a global Symbol already, particularly if it is a class.
+                globalESSymbolType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
+                globalESSymbolConstructorSymbol = undefined;
+            }
+
+            anyArrayType = createArrayType(anyType);
+        }
+
+        // GRAMMAR CHECKING
+        function isReservedWordInStrictMode(node: Identifier): boolean {
+            // Check that originalKeywordKind is less than LastFutureReservedWord to see if an Identifier is a strict-mode reserved word
+            return (node.parserContextFlags & ParserContextFlags.StrictMode) &&
+                (SyntaxKind.FirstFutureReservedWord <= node.originalKeywordKind && node.originalKeywordKind <= SyntaxKind.LastFutureReservedWord);
+        }
+
+        function reportStrictModeGrammarErrorInClassDeclaration(identifier: Identifier, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
+            // We are checking if this name is inside class declaration or class expression (which are under class definitions inside ES6 spec.)
+            // if so, we would like to give more explicit invalid usage error.
+            if (getAncestor(identifier, SyntaxKind.ClassDeclaration) || getAncestor(identifier, SyntaxKind.ClassExpression)) {
+                return grammarErrorOnNode(identifier, message, arg0);
+            }
+            return false;
+        }
+
+        function checkGrammarImportDeclarationNameInStrictMode(node: ImportDeclaration): boolean {
+            // Check if the import declaration used strict-mode reserved word in its names bindings
+            if (node.importClause) {
+                let impotClause = node.importClause;
+                if (impotClause.namedBindings) {
+                    let nameBindings = impotClause.namedBindings;
+                    if (nameBindings.kind === SyntaxKind.NamespaceImport) {
+                        let name = <Identifier>(<NamespaceImport>nameBindings).name;
+                        if (isReservedWordInStrictMode(name)) {
+                            let nameText = declarationNameToString(name);
+                            return grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                        }
+                    }
+                    else if (nameBindings.kind === SyntaxKind.NamedImports) {
+                        let reportError = false;
+                        for (let element of (<NamedImports>nameBindings).elements) {
+                            let name = element.name;
+                            if (isReservedWordInStrictMode(name)) {
+                                let nameText = declarationNameToString(name);
+                                reportError = reportError || grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                            }
+                        }
+                        return reportError;
+                    }
+                }
+            }
+            return false;
+        }
+
+        function checkGrammarDeclarationNameInStrictMode(node: Declaration): boolean {
+            let name = node.name;
+            if (name && name.kind === SyntaxKind.Identifier && isReservedWordInStrictMode(<Identifier>name)) {
+                let nameText = declarationNameToString(name);
+                switch (node.kind) {
+                    case SyntaxKind.Parameter:
+                    case SyntaxKind.VariableDeclaration:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.TypeParameter:
+                    case SyntaxKind.BindingElement:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.TypeAliasDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                        return checkGrammarIdentifierInStrictMode(<Identifier>name);
+
+                    case SyntaxKind.ClassDeclaration:
+                        // Report an error if the class declaration uses strict-mode reserved word.
+                        return grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText);
+
+                    case SyntaxKind.ModuleDeclaration:
+                        // Report an error if the module declaration uses strict-mode reserved word.
+                        // TODO(yuisu): fix this when having external module in strict mode
+                        return grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+
+                    case SyntaxKind.ImportEqualsDeclaration:
+                        // TODO(yuisu): fix this when having external module in strict mode
+                        return grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                }
+            }
+            return false;
+        }
+
+        function checkGrammarTypeReferenceInStrictMode(typeName: Identifier | QualifiedName) {
+            // Check if the type reference is using strict mode keyword
+            // Example:
+            //      class C {
+            //          foo(x: public){}  // Error.
+            //      }
+            if (typeName.kind === SyntaxKind.Identifier) {
+                checkGrammarTypeNameInStrictMode(<Identifier>typeName);
+            }
+            // Report an error for each identifier in QualifiedName
+            // Example:
+            //      foo (x: B.private.bar)      // error at private
+            //      foo (x: public.private.package)  // error at public, private, and package
+            else if (typeName.kind === SyntaxKind.QualifiedName) {
+                // Walk from right to left and report a possible error at each Identifier in QualifiedName
+                // Example:
+                //      x1: public.private.package  // error at public and private
+                checkGrammarTypeNameInStrictMode((<QualifiedName>typeName).right);
+                checkGrammarTypeReferenceInStrictMode((<QualifiedName>typeName).left);
+            }
+        }
+
+        // This function will report an error for every identifier in property access expression
+        // whether it violates strict mode reserved words.
+        // Example:
+        //      public                  // error at public
+        //      public.private.package  // error at public
+        //      B.private.B             // no error
+        function checkGrammarHeritageClauseElementInStrictMode(expression: Expression) {
+            // Example:
+            //      class C extends public // error at public
+            if (expression && expression.kind === SyntaxKind.Identifier) {
+                return checkGrammarIdentifierInStrictMode(expression);
+            }
+            else if (expression && expression.kind === SyntaxKind.PropertyAccessExpression) {
+                // Walk from left to right in PropertyAccessExpression until we are at the left most expression
+                // in PropertyAccessExpression. According to grammar production of MemberExpression,
+                // the left component expression is a PrimaryExpression (i.e. Identifier) while the other
+                // component after dots can be IdentifierName.
+                checkGrammarHeritageClauseElementInStrictMode((<PropertyAccessExpression>expression).expression);
+            }
+
+        }
+
+        // The function takes an identifier itself or an expression which has SyntaxKind.Identifier.
+        function checkGrammarIdentifierInStrictMode(node: Expression | Identifier, nameText?: string): boolean {
+            if (node && node.kind === SyntaxKind.Identifier && isReservedWordInStrictMode(<Identifier>node)) {
+                if (!nameText) {
+                    nameText = declarationNameToString(<Identifier>node);
+                }
+
+                // TODO (yuisu): Fix when module is a strict mode
+                let errorReport = reportStrictModeGrammarErrorInClassDeclaration(<Identifier>node, Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText)||
+                    grammarErrorOnNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                return errorReport;
+            }
+            return false;
+        }
+
+        // The function takes an identifier when uses as a typeName in TypeReferenceNode
+        function checkGrammarTypeNameInStrictMode(node: Identifier): boolean {
+            if (node && node.kind === SyntaxKind.Identifier && isReservedWordInStrictMode(<Identifier>node)) {
+                let nameText = declarationNameToString(<Identifier>node);
+
+                // TODO (yuisu): Fix when module is a strict mode
+                let errorReport = reportStrictModeGrammarErrorInClassDeclaration(<Identifier>node, Diagnostics.Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode, nameText) ||
+                    grammarErrorOnNode(node, Diagnostics.Type_expected_0_is_a_reserved_word_in_strict_mode, nameText);
+                return errorReport;
+            }
+            return false;
+        }
+
+        function checkGrammarDecorators(node: Node): boolean {
+            if (!node.decorators) {
+                return false;
+            }
+            if (!nodeCanBeDecorated(node)) {
+                return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here);
+            }
+            else if (languageVersion < ScriptTarget.ES5) {
+                return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
+            }
+            else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
+                let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, <AccessorDeclaration>node);
+                if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) {
+                    return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name);
+                }
+            }
+            return false;
+        }
+
+        function checkGrammarModifiers(node: Node): boolean {
+            switch (node.kind) {
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.Constructor:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.IndexSignature:
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.ModuleDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                case SyntaxKind.VariableStatement:
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.TypeAliasDeclaration:
+                case SyntaxKind.ImportDeclaration:
+                case SyntaxKind.ImportEqualsDeclaration:
+                case SyntaxKind.ExportDeclaration:
+                case SyntaxKind.ExportAssignment:
+                case SyntaxKind.Parameter:
+                    break;
+                default:
+                    return false;
+            }
+
+            if (!node.modifiers) {
+                return;
+            }
+
+            let lastStatic: Node, lastPrivate: Node, lastProtected: Node, lastDeclare: Node;
+            let flags = 0;
+            for (let modifier of node.modifiers) {
+                switch (modifier.kind) {
+                    case SyntaxKind.PublicKeyword:
+                    case SyntaxKind.ProtectedKeyword:
+                    case SyntaxKind.PrivateKeyword:
+                        let text: string;
+                        if (modifier.kind === SyntaxKind.PublicKeyword) {
+                            text = "public";
+                        }
+                        else if (modifier.kind === SyntaxKind.ProtectedKeyword) {
+                            text = "protected";
+                            lastProtected = modifier;
+                        }
+                        else {
+                            text = "private";
+                            lastPrivate = modifier;
+                        }
+
+                        if (flags & NodeFlags.AccessibilityModifier) {
+                            return grammarErrorOnNode(modifier, Diagnostics.Accessibility_modifier_already_seen);
+                        }
+                        else if (flags & NodeFlags.Static) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
+                        }
+                        else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_element, text);
+                        }
+                        flags |= modifierToFlag(modifier.kind);
+                        break;
+
+                    case SyntaxKind.StaticKeyword:
+                        if (flags & NodeFlags.Static) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static");
+                        }
+                        else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_element, "static");
+                        }
+                        else if (node.kind === SyntaxKind.Parameter) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static");
+                        }
+                        flags |= NodeFlags.Static;
+                        lastStatic = modifier;
+                        break;
+
+                    case SyntaxKind.ExportKeyword:
+                        if (flags & NodeFlags.Export) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "export");
+                        }
+                        else if (flags & NodeFlags.Ambient) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
+                        }
+                        else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export");
+                        }
+                        else if (node.kind === SyntaxKind.Parameter) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export");
+                        }
+                        flags |= NodeFlags.Export;
+                        break;
+
+                    case SyntaxKind.DeclareKeyword:
+                        if (flags & NodeFlags.Ambient) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare");
+                        }
+                        else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare");
+                        }
+                        else if (node.kind === SyntaxKind.Parameter) {
+                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare");
+                        }
+                        else if (isInAmbientContext(node.parent) && node.parent.kind === SyntaxKind.ModuleBlock) {
+                            return grammarErrorOnNode(modifier, Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
+                        }
+                        flags |= NodeFlags.Ambient;
+                        lastDeclare = modifier
+                        break;
+                }
+            }
+
+            if (node.kind === SyntaxKind.Constructor) {
+                if (flags & NodeFlags.Static) {
+                    return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static");
+                }
+                else if (flags & NodeFlags.Protected) {
+                    return grammarErrorOnNode(lastProtected, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
+                }
+                else if (flags & NodeFlags.Private) {
+                    return grammarErrorOnNode(lastPrivate, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
+                }
+            }
+            else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & NodeFlags.Ambient) {
+                return grammarErrorOnNode(lastDeclare, Diagnostics.A_declare_modifier_cannot_be_used_with_an_import_declaration, "declare");
+            }
+            else if (node.kind === SyntaxKind.InterfaceDeclaration && flags & NodeFlags.Ambient) {
+                return grammarErrorOnNode(lastDeclare, Diagnostics.A_declare_modifier_cannot_be_used_with_an_interface_declaration, "declare");
+            }
+            else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.AccessibilityModifier) && isBindingPattern((<ParameterDeclaration>node).name)) {
+                return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_a_binding_pattern);
+            }
+        }
+
+        function checkGrammarForDisallowedTrailingComma(list: NodeArray<Node>): boolean {
+            if (list && list.hasTrailingComma) {
+                let start = list.end - ",".length;
+                let end = list.end;
+                let sourceFile = getSourceFileOfNode(list[0]);
+                return grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.Trailing_comma_not_allowed);
+            }
+        }
+
+        function checkGrammarTypeParameterList(node: FunctionLikeDeclaration, typeParameters: NodeArray<TypeParameterDeclaration>, file: SourceFile): boolean {
+            if (checkGrammarForDisallowedTrailingComma(typeParameters)) {
+                return true;
+            }
+
+            if (typeParameters && typeParameters.length === 0) {
+                let start = typeParameters.pos - "<".length;
+                let end = skipTrivia(file.text, typeParameters.end) + ">".length;
+                return grammarErrorAtPos(file, start, end - start, Diagnostics.Type_parameter_list_cannot_be_empty);
+            }
+        }
+
+        function checkGrammarParameterList(parameters: NodeArray<ParameterDeclaration>) {
+            if (checkGrammarForDisallowedTrailingComma(parameters)) {
+                return true;
+            }
+
+            let seenOptionalParameter = false;
+            let parameterCount = parameters.length;
+
+            for (let i = 0; i < parameterCount; i++) {
+                let parameter = parameters[i];
+                if (parameter.dotDotDotToken) {
+                    if (i !== (parameterCount - 1)) {
+                        return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
+                    }
+
+                    if (isBindingPattern(parameter.name)) {
+                        return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
+                    }
+
+                    if (parameter.questionToken) {
+                        return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_rest_parameter_cannot_be_optional);
+                    }
+
+                    if (parameter.initializer) {
+                        return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_have_an_initializer);
+                    }
+                }
+                else if (parameter.questionToken || parameter.initializer) {
+                    seenOptionalParameter = true;
+
+                    if (parameter.questionToken && parameter.initializer) {
+                        return grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer);
+                    }
+                }
+                else {
+                    if (seenOptionalParameter) {
+                        return grammarErrorOnNode(parameter.name, Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter);
+                    }
+                }
+            }
+        }
+
+        function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
+            // Prevent cascading error by short-circuit
+            let file = getSourceFileOfNode(node);
+            return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters, file) ||
+                checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
+        }
+
+        function checkGrammarArrowFunction(node: FunctionLikeDeclaration, file: SourceFile): boolean {
+            if (node.kind === SyntaxKind.ArrowFunction) {
+                let arrowFunction = <ArrowFunction>node;
+                let startLine = getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.pos).line;
+                let endLine = getLineAndCharacterOfPosition(file, arrowFunction.equalsGreaterThanToken.end).line;
+                if (startLine !== endLine) {
+                    return grammarErrorOnNode(arrowFunction.equalsGreaterThanToken, Diagnostics.Line_terminator_not_permitted_before_arrow);
+                }
+            }
+            return false;
+        }
+
+        function checkGrammarIndexSignatureParameters(node: SignatureDeclaration): boolean {
+            let parameter = node.parameters[0];
+            if (node.parameters.length !== 1) {
+                if (parameter) {
+                    return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_must_have_exactly_one_parameter);
+                }
+                else {
+                    return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_exactly_one_parameter);
+                }
+            }
+            if (parameter.dotDotDotToken) {
+                return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter);
+            }
+            if (parameter.flags & NodeFlags.Modifier) {
+                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier);
+            }
+            if (parameter.questionToken) {
+                return grammarErrorOnNode(parameter.questionToken, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark);
+            }
+            if (parameter.initializer) {
+                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_initializer);
+            }
+            if (!parameter.type) {
+                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_must_have_a_type_annotation);
+            }
+            if (parameter.type.kind !== SyntaxKind.StringKeyword && parameter.type.kind !== SyntaxKind.NumberKeyword) {
+                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_must_be_string_or_number);
+            }
+            if (!node.type) {
+                return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_a_type_annotation);
+            }
+        }
+
+        function checkGrammarForIndexSignatureModifier(node: SignatureDeclaration): void {
+            if (node.flags & NodeFlags.Modifier) {
+                grammarErrorOnFirstToken(node, Diagnostics.Modifiers_not_permitted_on_index_signature_members);
+            }
+        }
+
+        function checkGrammarIndexSignature(node: SignatureDeclaration) {
+            // Prevent cascading error by short-circuit
+            return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node) || checkGrammarForIndexSignatureModifier(node);
+        }
+
+        function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray<TypeNode>): boolean {
+            if (typeArguments && typeArguments.length === 0) {
+                let sourceFile = getSourceFileOfNode(node);
+                let start = typeArguments.pos - "<".length;
+                let end = skipTrivia(sourceFile.text, typeArguments.end) + ">".length;
+                return grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.Type_argument_list_cannot_be_empty);
+            }
+        }
+
+        function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray<TypeNode>): boolean {
+            return checkGrammarForDisallowedTrailingComma(typeArguments) ||
+                checkGrammarForAtLeastOneTypeArgument(node, typeArguments);
+        }
+
+        function checkGrammarForOmittedArgument(node: CallExpression, arguments: NodeArray<Expression>): boolean {
+            if (arguments) {
+                let sourceFile = getSourceFileOfNode(node);
+                for (let arg of arguments) {
+                    if (arg.kind === SyntaxKind.OmittedExpression) {
+                        return grammarErrorAtPos(sourceFile, arg.pos, 0, Diagnostics.Argument_expression_expected);
+                    }
+                }
+            }
+        }
+
+        function checkGrammarArguments(node: CallExpression, arguments: NodeArray<Expression>): boolean {
+            return checkGrammarForDisallowedTrailingComma(arguments) ||
+                checkGrammarForOmittedArgument(node, arguments);
+        }
+
+        function checkGrammarHeritageClause(node: HeritageClause): boolean {
+            let types = node.types;
+            if (checkGrammarForDisallowedTrailingComma(types)) {
+                return true;
+            }
+            if (types && types.length === 0) {
+                let listType = tokenToString(node.token);
+                let sourceFile = getSourceFileOfNode(node);
+                return grammarErrorAtPos(sourceFile, types.pos, 0, Diagnostics._0_list_cannot_be_empty, listType)
+            }
+        }
+
+        function checkGrammarClassDeclarationHeritageClauses(node: ClassDeclaration) {
+            let seenExtendsClause = false;
+            let seenImplementsClause = false;
+
+            if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && node.heritageClauses) {
+                for (let heritageClause of node.heritageClauses) {
+                    if (heritageClause.token === SyntaxKind.ExtendsKeyword) {
+                        if (seenExtendsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_already_seen)
+                        }
+
+                        if (seenImplementsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_must_precede_implements_clause);
+                        }
+
+                        if (heritageClause.types.length > 1) {
+                            return grammarErrorOnFirstToken(heritageClause.types[1], Diagnostics.Classes_can_only_extend_a_single_class);
+                        }
+
+                        seenExtendsClause = true;
+                    }
+                    else {
+                        Debug.assert(heritageClause.token === SyntaxKind.ImplementsKeyword);
+                        if (seenImplementsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.implements_clause_already_seen);
+                        }
+
+                        seenImplementsClause = true;
+                    }
+
+                    // Grammar checking heritageClause inside class declaration
+                    checkGrammarHeritageClause(heritageClause);
+                }
+            }
+        }
+
+        function checkGrammarInterfaceDeclaration(node: InterfaceDeclaration) {
+            let seenExtendsClause = false;
+
+            if (node.heritageClauses) {
+                for (let heritageClause of node.heritageClauses) {
+                    if (heritageClause.token === SyntaxKind.ExtendsKeyword) {
+                        if (seenExtendsClause) {
+                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_already_seen);
+                        }
+
+                        seenExtendsClause = true;
+                    }
+                    else {
+                        Debug.assert(heritageClause.token === SyntaxKind.ImplementsKeyword);
+                        return grammarErrorOnFirstToken(heritageClause, Diagnostics.Interface_declaration_cannot_have_implements_clause);
+                    }
+
+                    // Grammar checking heritageClause inside class declaration
+                    checkGrammarHeritageClause(heritageClause);
+                }
+            }
+
+            return false;
+        }
+
+        function checkGrammarComputedPropertyName(node: Node): boolean {
+            // If node is not a computedPropertyName, just skip the grammar checking
+            if (node.kind !== SyntaxKind.ComputedPropertyName) {
+                return false;
+            }
+
+            let computedPropertyName = <ComputedPropertyName>node;
+            if (computedPropertyName.expression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>computedPropertyName.expression).operatorToken.kind === SyntaxKind.CommaToken) {
+                return grammarErrorOnNode(computedPropertyName.expression, Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name);
+            }
+        }
+
+        function checkGrammarForGenerator(node: FunctionLikeDeclaration) {
+            if (node.asteriskToken) {
+                return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_not_currently_supported);
+            }
+        }
+
+        function checkGrammarFunctionName(name: Node) {
+            // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1))
+            return checkGrammarEvalOrArgumentsInStrictMode(name, <Identifier>name);
+        }
+
+        function checkGrammarForInvalidQuestionMark(node: Declaration, questionToken: Node, message: DiagnosticMessage): boolean {
+            if (questionToken) {
+                return grammarErrorOnNode(questionToken, message);
+            }
+        }
+
+        function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression) {
+            let seen: Map<SymbolFlags> = {};
+            let Property = 1;
+            let GetAccessor = 2;
+            let SetAccesor = 4;
+            let GetOrSetAccessor = GetAccessor | SetAccesor;
+            let inStrictMode = (node.parserContextFlags & ParserContextFlags.StrictMode) !== 0;
+
+            for (let prop of node.properties) {
+                let name = prop.name;
+                if (prop.kind === SyntaxKind.OmittedExpression ||
+                    name.kind === SyntaxKind.ComputedPropertyName) {
+                    // If the name is not a ComputedPropertyName, the grammar checking will skip it
+                    checkGrammarComputedPropertyName(<ComputedPropertyName>name);
+                    continue;
+                }
+
+                // ECMA-262 11.1.5 Object Initialiser
+                // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true
+                // a.This production is contained in strict code and IsDataDescriptor(previous) is true and
+                // IsDataDescriptor(propId.descriptor) is true.
+                //    b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true.
+                //    c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true.
+                //    d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true
+                // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields
+                let currentKind: number;
+                if (prop.kind === SyntaxKind.PropertyAssignment || prop.kind === SyntaxKind.ShorthandPropertyAssignment) {
+                    // Grammar checking for computedPropertName and shorthandPropertyAssignment
+                    checkGrammarForInvalidQuestionMark(prop,(<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
+                    if (name.kind === SyntaxKind.NumericLiteral) {
+                        checkGrammarNumericLiteral(<Identifier>name);
+                    }
+                    currentKind = Property;
+                }
+                else if ( prop.kind === SyntaxKind.MethodDeclaration) {
+                    currentKind = Property;
+                }
+                else if (prop.kind === SyntaxKind.GetAccessor) {
+                    currentKind = GetAccessor;
+                }
+                else if (prop.kind === SyntaxKind.SetAccessor) {
+                    currentKind = SetAccesor;
+                }
+                else {
+                    Debug.fail("Unexpected syntax kind:" + prop.kind);
+                }
+
+                if (!hasProperty(seen, (<Identifier>name).text)) {
+                    seen[(<Identifier>name).text] = currentKind;
+                }
+                else {
+                    let existingKind = seen[(<Identifier>name).text];
+                    if (currentKind === Property && existingKind === Property) {
+                        if (inStrictMode) {
+                            grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode);
+                        }
+                    }
+                    else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) {
+                        if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) {
+                            seen[(<Identifier>name).text] = currentKind | existingKind;
+                        }
+                        else {
+                            return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
+                        }
+                    }
+                    else {
+                        return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
+                    }
+                }
+            }
+        }
+
+        function checkGrammarForInOrForOfStatement(forInOrOfStatement: ForInStatement | ForOfStatement): boolean {
+            if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) {
+                return true;
+            }
+
+            if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                let variableList = <VariableDeclarationList>forInOrOfStatement.initializer;
+                if (!checkGrammarVariableDeclarationList(variableList)) {
+                    if (variableList.declarations.length > 1) {
+                        let diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
+                            ? Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
+                            : Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
+                        return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
+                    }
+                    let firstDeclaration = variableList.declarations[0];
+                    if (firstDeclaration.initializer) {
+                        let diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
+                            ? Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
+                            : Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer;
+                        return grammarErrorOnNode(firstDeclaration.name, diagnostic);
+                    }
+                    if (firstDeclaration.type) {
+                        let diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
+                            ? Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation
+                            : Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation;
+                        return grammarErrorOnNode(firstDeclaration, diagnostic);
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        function checkGrammarAccessor(accessor: MethodDeclaration): boolean {
+            let kind = accessor.kind;
+            if (languageVersion < ScriptTarget.ES5) {
+                return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
+            }
+            else if (isInAmbientContext(accessor)) {
+                return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context);
+            }
+            else if (accessor.body === undefined) {
+                return grammarErrorAtPos(getSourceFileOfNode(accessor), accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
+            }
+            else if (accessor.typeParameters) {
+                return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_have_type_parameters);
+            }
+            else if (kind === SyntaxKind.GetAccessor && accessor.parameters.length) {
+                return grammarErrorOnNode(accessor.name, Diagnostics.A_get_accessor_cannot_have_parameters);
+            }
+            else if (kind === SyntaxKind.SetAccessor) {
+                if (accessor.type) {
+                    return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation);
+                }
+                else if (accessor.parameters.length !== 1) {
+                    return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_must_have_exactly_one_parameter);
+                }
+                else {
+                    let parameter = accessor.parameters[0];
+                    if (parameter.dotDotDotToken) {
+                        return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter);
+                    }
+                    else if (parameter.flags & NodeFlags.Modifier) {
+                        return grammarErrorOnNode(accessor.name, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
+                    }
+                    else if (parameter.questionToken) {
+                        return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter);
+                    }
+                    else if (parameter.initializer) {
+                        return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer);
+                    }
+                }
+            }
+        }
+
+        function checkGrammarForNonSymbolComputedProperty(node: DeclarationName, message: DiagnosticMessage) {
+            if (node.kind === SyntaxKind.ComputedPropertyName && !isWellKnownSymbolSyntactically((<ComputedPropertyName>node).expression)) {
+                return grammarErrorOnNode(node, message);
+            }
+        }
+
+        function checkGrammarMethod(node: MethodDeclaration) {
+            if (checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node) ||
+                checkGrammarFunctionLikeDeclaration(node) ||
+                checkGrammarForGenerator(node)) {
+                return true;
+            }
+
+            if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
+                if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) {
+                    return true;
+                }
+                else if (node.body === undefined) {
+                    return grammarErrorAtPos(getSourceFile(node), node.end - 1, ";".length, Diagnostics._0_expected, "{");
+                }
+            }
+
+            if (node.parent.kind === SyntaxKind.ClassDeclaration) {
+                if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) {
+                    return true;
+                }
+                // Technically, computed properties in ambient contexts is disallowed
+                // for property declarations and accessors too, not just methods.
+                // However, property declarations disallow computed names in general,
+                // and accessors are not allowed in ambient contexts in general,
+                // so this error only really matters for methods.
+                if (isInAmbientContext(node)) {
+                    return checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol);
+                }
+                else if (!node.body) {
+                    return checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol);
+                }
+            }
+            else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) {
+                return checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol);
+            }
+            else if (node.parent.kind === SyntaxKind.TypeLiteral) {
+                return checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol);
+            }
+        }
+
+        function isIterationStatement(node: Node, lookInLabeledStatements: boolean): boolean {
+            switch (node.kind) {
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                case SyntaxKind.DoStatement:
+                case SyntaxKind.WhileStatement:
+                    return true;
+                case SyntaxKind.LabeledStatement:
+                    return lookInLabeledStatements && isIterationStatement((<LabeledStatement>node).statement, lookInLabeledStatements);
+            }
+
+            return false;
+        }
+
+        function checkGrammarBreakOrContinueStatement(node: BreakOrContinueStatement): boolean {
+            let current: Node = node;
+            while (current) {
+                if (isFunctionLike(current)) {
+                    return grammarErrorOnNode(node, Diagnostics.Jump_target_cannot_cross_function_boundary);
+                }
+
+                switch (current.kind) {
+                    case SyntaxKind.LabeledStatement:
+                        if (node.label && (<LabeledStatement>current).label.text === node.label.text) {
+                            // found matching label - verify that label usage is correct
+                            // continue can only target labels that are on iteration statements
+                            let isMisplacedContinueLabel = node.kind === SyntaxKind.ContinueStatement
+                                && !isIterationStatement((<LabeledStatement>current).statement, /*lookInLabeledStatement*/ true);
+
+                            if (isMisplacedContinueLabel) {
+                                return grammarErrorOnNode(node, Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement);
+                            }
+
+                            return false;
+                        }
+                        break;
+                    case SyntaxKind.SwitchStatement:
+                        if (node.kind === SyntaxKind.BreakStatement && !node.label) {
+                            // unlabeled break within switch statement - ok
+                            return false;
+                        }
+                        break;
+                    default:
+                        if (isIterationStatement(current, /*lookInLabeledStatement*/ false) && !node.label) {
+                            // unlabeled break or continue within iteration statement - ok
+                            return false;
+                        }
+                        break;
+                }
+
+                current = current.parent;
+            }
+
+            if (node.label) {
+                let message = node.kind === SyntaxKind.BreakStatement
+                    ? Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement
+                    : Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement;
+
+                return grammarErrorOnNode(node, message)
+            }
+            else {
+                let message = node.kind === SyntaxKind.BreakStatement
+                    ? Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement
+                    : Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement;
+                return grammarErrorOnNode(node, message)
+            }
+        }
+
+        function checkGrammarBindingElement(node: BindingElement) {
+            if (node.dotDotDotToken) {
+                let elements = (<BindingPattern>node.parent).elements;
+                if (node !== elements[elements.length - 1]) {
+                    return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
+                }
+
+                if (node.name.kind === SyntaxKind.ArrayBindingPattern || node.name.kind === SyntaxKind.ObjectBindingPattern) {
+                    return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
+                }
+
+                if (node.initializer) {
+                    // Error on equals token which immediate precedes the initializer
+                    return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
+                }
+            }
+            // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
+            // and its Identifier is eval or arguments
+            return checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
+        }
+
+        function checkGrammarVariableDeclaration(node: VariableDeclaration) {
+            if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) {
+                if (isInAmbientContext(node)) {
+                    if (node.initializer) {
+                        // Error on equals token which immediate precedes the initializer
+                        let equalsTokenLength = "=".length;
+                        return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength,
+                            equalsTokenLength, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
+                    }
+                }
+                else if (!node.initializer) {
+                    if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) {
+                        return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer);
+                    }
+                    if (isConst(node)) {
+                        return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized);
+                    }
+                }
+            }
+
+            let checkLetConstNames =  languageVersion >= ScriptTarget.ES6 && (isLet(node) || isConst(node));
+
+            // 1. LexicalDeclaration : LetOrConst BindingList ;
+            // It is a Syntax Error if the BoundNames of BindingList contains "let".
+            // 2. ForDeclaration: ForDeclaration : LetOrConst ForBinding
+            // It is a Syntax Error if the BoundNames of ForDeclaration contains "let".
+
+            // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
+            // and its Identifier is eval or arguments
+            return (checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name)) ||
+                checkGrammarEvalOrArgumentsInStrictMode(node, <Identifier>node.name);
+        }
+
+        function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
+            if (name.kind === SyntaxKind.Identifier) {
+                if ((<Identifier>name).text === "let") {
+                    return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
+                }
+            }
+            else {
+                let elements = (<BindingPattern>name).elements;
+                for (let element of elements) {
+                    if (element.kind !== SyntaxKind.OmittedExpression) {
+                        checkGrammarNameInLetOrConstDeclarations(element.name);
+                    }
+                }
+            }
+        }
+
+        function checkGrammarVariableDeclarationList(declarationList: VariableDeclarationList): boolean {
+            let declarations = declarationList.declarations;
+            if (checkGrammarForDisallowedTrailingComma(declarationList.declarations)) {
+                return true;
+            }
+
+            if (!declarationList.declarations.length) {
+                return grammarErrorAtPos(getSourceFileOfNode(declarationList), declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty);
+            }
+        }
+
+        function allowLetAndConstDeclarations(parent: Node): boolean {
+            switch (parent.kind) {
+                case SyntaxKind.IfStatement:
+                case SyntaxKind.DoStatement:
+                case SyntaxKind.WhileStatement:
+                case SyntaxKind.WithStatement:
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                    return false;
+                case SyntaxKind.LabeledStatement:
+                    return allowLetAndConstDeclarations(parent.parent);
+            }
+
+            return true;
+        }
+
+        function checkGrammarForDisallowedLetOrConstStatement(node: VariableStatement) {
+            if (!allowLetAndConstDeclarations(node.parent)) {
+                if (isLet(node.declarationList)) {
+                    return grammarErrorOnNode(node, Diagnostics.let_declarations_can_only_be_declared_inside_a_block);
+                }
+                else if (isConst(node.declarationList)) {
+                    return grammarErrorOnNode(node, Diagnostics.const_declarations_can_only_be_declared_inside_a_block);
+                }
+            }
+        }
+
+        function isIntegerLiteral(expression: Expression): boolean {
+            if (expression.kind === SyntaxKind.PrefixUnaryExpression) {
+                let unaryExpression = <PrefixUnaryExpression>expression;
+                if (unaryExpression.operator === SyntaxKind.PlusToken || unaryExpression.operator === SyntaxKind.MinusToken) {
+                    expression = unaryExpression.operand;
+                }
+            }
+            if (expression.kind === SyntaxKind.NumericLiteral) {
+                // Allows for scientific notation since literalExpression.text was formed by
+                // coercing a number to a string. Sometimes this coercion can yield a string
+                // in scientific notation.
+                // We also don't need special logic for hex because a hex integer is converted
+                // to decimal when it is coerced.
+                return /^[0-9]+([eE]\+?[0-9]+)?$/.test((<LiteralExpression>expression).text);
+            }
+
+            return false;
+        }
+
+        function checkGrammarEnumDeclaration(enumDecl: EnumDeclaration): boolean {
+            let enumIsConst = (enumDecl.flags & NodeFlags.Const) !== 0;
+
+            let hasError = false;
+
+            // skip checks below for const enums  - they allow arbitrary initializers as long as they can be evaluated to constant expressions.
+            // since all values are known in compile time - it is not necessary to check that constant enum section precedes computed enum members.
+            if (!enumIsConst) {
+                let inConstantEnumMemberSection = true;
+                let inAmbientContext = isInAmbientContext(enumDecl);
+                for (let node of enumDecl.members) {
+                    // Do not use hasDynamicName here, because that returns false for well known symbols.
+                    // We want to perform checkComputedPropertyName for all computed properties, including
+                    // well known symbols.
+                    if (node.name.kind === SyntaxKind.ComputedPropertyName) {
+                        hasError = grammarErrorOnNode(node.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums);
+                    }
+                    else if (inAmbientContext) {
+                        if (node.initializer && !isIntegerLiteral(node.initializer)) {
+                            hasError = grammarErrorOnNode(node.name, Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers) || hasError;
+                        }
+                    }
+                    else if (node.initializer) {
+                        inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
+                    }
+                    else if (!inConstantEnumMemberSection) {
+                        hasError = grammarErrorOnNode(node.name, Diagnostics.Enum_member_must_have_initializer) || hasError;
+                    }
+                }
+            }
+
+            return hasError;
+        }
+
+        function hasParseDiagnostics(sourceFile: SourceFile): boolean {
+            return sourceFile.parseDiagnostics.length > 0;
+        }
+
+        function grammarErrorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
+            let sourceFile = getSourceFileOfNode(node);
+            if (!hasParseDiagnostics(sourceFile)) {
+                let span = getSpanOfTokenAtPosition(sourceFile, node.pos);
+                diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+
+        function grammarErrorAtPos(sourceFile: SourceFile, start: number, length: number, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
+            if (!hasParseDiagnostics(sourceFile)) {
+                diagnostics.add(createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+
+        function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
+            let sourceFile = getSourceFileOfNode(node);
+            if (!hasParseDiagnostics(sourceFile)) {
+                diagnostics.add(createDiagnosticForNode(node, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+
+        function checkGrammarEvalOrArgumentsInStrictMode(contextNode: Node, name: Node): boolean {
+            if (name && name.kind === SyntaxKind.Identifier) {
+                let identifier = <Identifier>name;
+                if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
+                    let nameText = declarationNameToString(identifier);
+
+                    // We check first if the name is inside class declaration or class expression; if so give explicit message
+                    // otherwise report generic error message.
+                    // reportGrammarErrorInClassDeclaration only return true if grammar error is successfully reported and false otherwise
+                    let reportErrorInClassDeclaration = reportStrictModeGrammarErrorInClassDeclaration(identifier, Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode, nameText);
+                    if (!reportErrorInClassDeclaration){
+                        return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
+                    }
+                    return reportErrorInClassDeclaration;
+                }
+            }
+        }
+
+        function isEvalOrArgumentsIdentifier(node: Node): boolean {
+            return node.kind === SyntaxKind.Identifier &&
+                ((<Identifier>node).text === "eval" || (<Identifier>node).text === "arguments");
+        }
+
+        function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) {
+            if (node.typeParameters) {
+                return grammarErrorAtPos(getSourceFileOfNode(node), node.typeParameters.pos, node.typeParameters.end - node.typeParameters.pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration);
+            }
+        }
+
+        function checkGrammarConstructorTypeAnnotation(node: ConstructorDeclaration) {
+            if (node.type) {
+                return grammarErrorOnNode(node.type, Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration);
+            }
+        }
+
+        function checkGrammarProperty(node: PropertyDeclaration) {
+            if (node.parent.kind === SyntaxKind.ClassDeclaration) {
+                if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional) ||
+                    checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol)) {
+                    return true;
+                }
+            }
+            else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) {
+                if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol)) {
+                    return true;
+                }
+            }
+            else if (node.parent.kind === SyntaxKind.TypeLiteral) {
+                if (checkGrammarForNonSymbolComputedProperty(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol)) {
+                    return true;
+                }
+            }
+
+            if (isInAmbientContext(node) && node.initializer) {
+                return grammarErrorOnFirstToken(node.initializer, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
+            }
+        }
+
+        function checkGrammarTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
+            // A declare modifier is required for any top level .d.ts declaration except export=, export default,
+            // interfaces and imports categories:
+            //
+            //  DeclarationElement:
+            //     ExportAssignment
+            //     export_opt   InterfaceDeclaration
+            //     export_opt   ImportDeclaration
+            //     export_opt   ExternalImportDeclaration
+            //     export_opt   AmbientDeclaration
+            //
+            if (node.kind === SyntaxKind.InterfaceDeclaration ||
+                node.kind === SyntaxKind.ImportDeclaration ||
+                node.kind === SyntaxKind.ImportEqualsDeclaration ||
+                node.kind === SyntaxKind.ExportDeclaration ||
+                node.kind === SyntaxKind.ExportAssignment ||
+                (node.flags & NodeFlags.Ambient) ||
+                (node.flags & (NodeFlags.Export | NodeFlags.Default))) {
+
+                return false;
+            }
+
+            return grammarErrorOnFirstToken(node, Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file);
+        }
+
+        function checkGrammarTopLevelElementsForRequiredDeclareModifier(file: SourceFile): boolean {
+            for (let decl of file.statements) {
+                if (isDeclaration(decl) || decl.kind === SyntaxKind.VariableStatement) {
+                    if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        function checkGrammarSourceFile(node: SourceFile): boolean {
+            return isInAmbientContext(node) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node);
+        }
+
+        function checkGrammarStatementInAmbientContext(node: Node): boolean {
+            if (isInAmbientContext(node)) {
+                // An accessors is already reported about the ambient context
+                if (isAccessor(node.parent.kind)) {
+                    return getNodeLinks(node).hasReportedStatementInAmbientContext = true;
+                }
+
+                // Find containing block which is either Block, ModuleBlock, SourceFile
+                let links = getNodeLinks(node);
+                if (!links.hasReportedStatementInAmbientContext && isFunctionLike(node.parent)) {
+                    return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts)
+                }
+
+                // We are either parented by another statement, or some sort of block.
+                // If we're in a block, we only want to really report an error once
+                // to prevent noisyness.  So use a bit on the block to indicate if
+                // this has already been reported, and don't report if it has.
+                //
+                if (node.parent.kind === SyntaxKind.Block || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
+                    let links = getNodeLinks(node.parent);
+                    // Check if the containing block ever report this error
+                    if (!links.hasReportedStatementInAmbientContext) {
+                        return links.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
+                    }
+                }
+                else {
+                    // We must be parented by a statement.  If so, there's no need
+                    // to report the error as our parent will have already done it.
+                    // Debug.assert(isStatement(node.parent));
+                }
+            }
+        }
+
+        function checkGrammarNumericLiteral(node: Identifier): boolean {
+            // Grammar checking
+            if (node.flags & NodeFlags.OctalLiteral) {
+                if (node.parserContextFlags & ParserContextFlags.StrictMode) {
+                    return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode);
+                }
+                else if (languageVersion >= ScriptTarget.ES5) {
+                    return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);
+                }
+            }
+        }
+
+        function grammarErrorAfterFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
+            let sourceFile = getSourceFileOfNode(node);
+            if (!hasParseDiagnostics(sourceFile)) {
+                let span = getSpanOfTokenAtPosition(sourceFile, node.pos);
+                diagnostics.add(createFileDiagnostic(sourceFile, textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2));
+                return true;
+            }
+        }
+
+        initializeTypeChecker();
+
+        return checker;
+    }
+}
diff --git a/lib/typescript/compiler/commandLineParser.ts b/lib/typescript/compiler/commandLineParser.ts
new file mode 100644
index 000000000..db2fb55d1
--- /dev/null
+++ b/lib/typescript/compiler/commandLineParser.ts
@@ -0,0 +1,388 @@
+/// <reference path="sys.ts"/>
+/// <reference path="types.ts"/>
+/// <reference path="core.ts"/>
+/// <reference path="scanner.ts"/>
+
+module ts {
+    /* @internal */
+    export var optionDeclarations: CommandLineOption[] = [
+        {
+            name: "charset",
+            type: "string",
+        },
+        {
+            name: "declaration",
+            shortName: "d",
+            type: "boolean",
+            description: Diagnostics.Generates_corresponding_d_ts_file,
+        },
+        {
+            name: "diagnostics",
+            type: "boolean",
+        },
+        {
+            name: "emitBOM",
+            type: "boolean"
+        },
+        {
+            name: "help",
+            shortName: "h",
+            type: "boolean",
+            description: Diagnostics.Print_this_message,
+        },
+        {
+            name: "listFiles",
+            type: "boolean",
+        },
+        {
+            name: "locale",
+            type: "string",
+        },
+        {
+            name: "mapRoot",
+            type: "string",
+            isFilePath: true,
+            description: Diagnostics.Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
+            paramType: Diagnostics.LOCATION,
+        },
+        {
+            name: "module",
+            shortName: "m",
+            type: {
+                "commonjs": ModuleKind.CommonJS,
+                "amd": ModuleKind.AMD,
+                "umd": ModuleKind.UMD
+            },
+            description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_or_umd,
+            paramType: Diagnostics.KIND,
+            error: Diagnostics.Argument_for_module_option_must_be_commonjs_amd_or_umd
+        },
+        {
+            name: "noEmit",
+            type: "boolean",
+            description: Diagnostics.Do_not_emit_outputs,
+        },
+        {
+            name: "noEmitOnError",
+            type: "boolean",
+            description: Diagnostics.Do_not_emit_outputs_if_any_type_checking_errors_were_reported,
+        },
+        {
+            name: "noImplicitAny",
+            type: "boolean",
+            description: Diagnostics.Raise_error_on_expressions_and_declarations_with_an_implied_any_type,
+        },
+        {
+            name: "noLib",
+            type: "boolean",
+        },
+        {
+            name: "noResolve",
+            type: "boolean",
+        },
+        {
+            name: "out",
+            type: "string",
+            description: Diagnostics.Concatenate_and_emit_output_to_single_file,
+            paramType: Diagnostics.FILE,
+        },
+        {
+            name: "outDir",
+            type: "string",
+            isFilePath: true,
+            description: Diagnostics.Redirect_output_structure_to_the_directory,
+            paramType: Diagnostics.DIRECTORY,
+        },
+        {
+            name: "preserveConstEnums",
+            type: "boolean",
+            description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
+        },
+        {
+            name: "project",
+            shortName: "p",
+            type: "string",
+            isFilePath: true,
+            description: Diagnostics.Compile_the_project_in_the_given_directory,
+            paramType: Diagnostics.DIRECTORY
+        },
+        {
+            name: "removeComments",
+            type: "boolean",
+            description: Diagnostics.Do_not_emit_comments_to_output,
+        },
+        {
+            name: "rootDir",
+            type: "string",
+            isFilePath: true,
+            description: Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir,
+            paramType: Diagnostics.LOCATION,
+        },
+        {
+            name: "separateCompilation",
+            type: "boolean",
+        },
+        {
+            name: "sourceMap",
+            type: "boolean",
+            description: Diagnostics.Generates_corresponding_map_file,
+        },
+        {
+            name: "sourceRoot",
+            type: "string",
+            isFilePath: true,
+            description: Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations,
+            paramType: Diagnostics.LOCATION,
+        },
+        {
+            name: "suppressImplicitAnyIndexErrors",
+            type: "boolean",
+            description: Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures,
+        },
+        {
+            name: "stripInternal",
+            type: "boolean",
+            description: Diagnostics.Do_not_emit_declarations_for_code_that_has_an_internal_annotation,
+            experimental: true
+        },
+        {
+            name: "target",
+            shortName: "t",
+            type: { "es3": ScriptTarget.ES3, "es5": ScriptTarget.ES5, "es6": ScriptTarget.ES6 },
+            description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
+            paramType: Diagnostics.VERSION,
+            error: Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES6
+        },
+        {
+            name: "version",
+            shortName: "v",
+            type: "boolean",
+            description: Diagnostics.Print_the_compiler_s_version,
+        },
+        {
+            name: "watch",
+            shortName: "w",
+            type: "boolean",
+            description: Diagnostics.Watch_input_files,
+        },
+        {
+            name: "emitDecoratorMetadata",
+            type: "boolean",
+            experimental: true
+        }
+    ];
+
+    export function parseCommandLine(commandLine: string[]): ParsedCommandLine {
+        var options: CompilerOptions = {};
+        var fileNames: string[] = [];
+        var errors: Diagnostic[] = [];
+        var shortOptionNames: Map<string> = {};
+        var optionNameMap: Map<CommandLineOption> = {};
+
+        forEach(optionDeclarations, option => {
+            optionNameMap[option.name.toLowerCase()] = option;
+            if (option.shortName) {
+                shortOptionNames[option.shortName] = option.name;
+            }
+        });
+        parseStrings(commandLine);
+        return {
+            options,
+            fileNames,
+            errors
+        };
+
+        function parseStrings(args: string[]) {
+            var i = 0;
+            while (i < args.length) {
+                var s = args[i++];
+                if (s.charCodeAt(0) === CharacterCodes.at) {
+                    parseResponseFile(s.slice(1));
+                }
+                else if (s.charCodeAt(0) === CharacterCodes.minus) {
+                    s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
+
+                    // Try to translate short option names to their full equivalents.
+                    if (hasProperty(shortOptionNames, s)) {
+                        s = shortOptionNames[s];
+                    }
+
+                    if (hasProperty(optionNameMap, s)) {
+                        var opt = optionNameMap[s];
+
+                        // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
+                        if (!args[i] && opt.type !== "boolean") {
+                            errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
+                        }
+
+                        switch (opt.type) {
+                            case "number":
+                                options[opt.name] = parseInt(args[i++]);
+                                break;
+                            case "boolean":
+                                options[opt.name] = true;
+                                break;
+                            case "string":
+                                options[opt.name] = args[i++] || "";
+                                break;
+                            // If not a primitive, the possible types are specified in what is effectively a map of options.
+                            default:
+                                var map = <Map<number>>opt.type;
+                                var key = (args[i++] || "").toLowerCase();
+                                if (hasProperty(map, key)) {
+                                    options[opt.name] = map[key];
+                                }
+                                else {
+                                    errors.push(createCompilerDiagnostic(opt.error));
+                                }
+                        }
+                    }
+                    else {
+                        errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, s));
+                    }
+                }
+                else {
+                    fileNames.push(s);
+                }
+            }
+        }
+
+        function parseResponseFile(fileName: string) {
+            var text = sys.readFile(fileName);
+
+            if (!text) {
+                errors.push(createCompilerDiagnostic(Diagnostics.File_0_not_found, fileName));
+                return;
+            }
+
+            var args: string[] = [];
+            var pos = 0;
+            while (true) {
+                while (pos < text.length && text.charCodeAt(pos) <= CharacterCodes.space) pos++;
+                if (pos >= text.length) break;
+                var start = pos;
+                if (text.charCodeAt(start) === CharacterCodes.doubleQuote) {
+                    pos++;
+                    while (pos < text.length && text.charCodeAt(pos) !== CharacterCodes.doubleQuote) pos++;
+                    if (pos < text.length) {
+                        args.push(text.substring(start + 1, pos));
+                        pos++;
+                    }
+                    else {
+                        errors.push(createCompilerDiagnostic(Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName));
+                    }
+                }
+                else {
+                    while (text.charCodeAt(pos) > CharacterCodes.space) pos++;
+                    args.push(text.substring(start, pos));
+                }
+            }
+            parseStrings(args);
+        }
+    }
+
+    /**
+      * Read tsconfig.json file
+      * @param fileName The path to the config file
+      */
+    export function readConfigFile(fileName: string): { config?: any; error?: Diagnostic }  {
+        try {
+            var text = sys.readFile(fileName);
+        }
+        catch (e) {
+            return { error: createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message) };
+        }
+        return parseConfigFileText(fileName, text);
+    }
+
+    /**
+      * Parse the text of the tsconfig.json file
+      * @param fileName The path to the config file
+      * @param jsonText The text of the config file
+      */
+    export function parseConfigFileText(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
+        try {
+            return { config: /\S/.test(jsonText) ? JSON.parse(jsonText) : {} };
+        }
+        catch (e) {
+            return { error: createCompilerDiagnostic(Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) };
+        }
+    }
+
+    /**
+      * Parse the contents of a config file (tsconfig.json).
+      * @param json The contents of the config file to parse
+      * @param basePath A root directory to resolve relative path entries in the config
+      *    file to. e.g. outDir 
+      */
+    export function parseConfigFile(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine {
+        var errors: Diagnostic[] = [];
+
+        return {
+            options: getCompilerOptions(),
+            fileNames: getFiles(),
+            errors
+        };
+
+        function getCompilerOptions(): CompilerOptions {
+            var options: CompilerOptions = {};
+            var optionNameMap: Map<CommandLineOption> = {};
+            forEach(optionDeclarations, option => {
+                optionNameMap[option.name] = option;
+            });
+            var jsonOptions = json["compilerOptions"];
+            if (jsonOptions) {
+                for (var id in jsonOptions) {
+                    if (hasProperty(optionNameMap, id)) {
+                        var opt = optionNameMap[id];
+                        var optType = opt.type;
+                        var value = jsonOptions[id];
+                        var expectedType = typeof optType === "string" ? optType : "string";
+                        if (typeof value === expectedType) {
+                            if (typeof optType !== "string") {
+                                var key = value.toLowerCase();
+                                if (hasProperty(optType, key)) {
+                                    value = optType[key];
+                                }
+                                else {
+                                    errors.push(createCompilerDiagnostic(opt.error));
+                                    value = 0;
+                                }
+                            }
+                            if (opt.isFilePath) {
+                                value = normalizePath(combinePaths(basePath, value));
+                            }
+                            options[opt.name] = value;
+                        }
+                        else {
+                            errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
+                        }
+                    }
+                    else {
+                        errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));
+                    }
+                }
+            }
+            return options;
+        }
+
+        function getFiles(): string[] {
+            var files: string[] = [];
+            if (hasProperty(json, "files")) {
+                if (json["files"] instanceof Array) {
+                    var files = map(<string[]>json["files"], s => combinePaths(basePath, s));
+                }
+            }
+            else {
+                var sysFiles = host.readDirectory(basePath, ".ts");
+                for (var i = 0; i < sysFiles.length; i++) {
+                    var name = sysFiles[i];
+                    if (!fileExtensionIs(name, ".d.ts") || !contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
+                        files.push(name);
+                    }
+                }
+            }
+            return files;
+        }
+    }
+}
diff --git a/lib/typescript/compiler/core.ts b/lib/typescript/compiler/core.ts
new file mode 100644
index 000000000..5f4cf64f1
--- /dev/null
+++ b/lib/typescript/compiler/core.ts
@@ -0,0 +1,740 @@
+/// <reference path="types.ts"/>
+
+/* @internal */
+module ts {
+    // Ternary values are defined such that
+    // x & y is False if either x or y is False.
+    // x & y is Maybe if either x or y is Maybe, but neither x or y is False.
+    // x & y is True if both x and y are True.
+    // x | y is False if both x and y are False.
+    // x | y is Maybe if either x or y is Maybe, but neither x or y is True.
+    // x | y is True if either x or y is True.
+    export const enum Ternary {
+        False = 0,
+        Maybe = 1,
+        True  = -1
+    }
+
+    export const enum Comparison {
+        LessThan    = -1,
+        EqualTo     = 0,
+        GreaterThan = 1
+    }
+
+    export interface StringSet extends Map<any> { }
+
+    export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
+        if (array) {
+            for (let i = 0, len = array.length; i < len; i++) {
+                let result = callback(array[i], i);
+                if (result) {
+                    return result;
+                }
+            }
+        }
+        return undefined;
+    }
+
+    export function contains<T>(array: T[], value: T): boolean {
+        if (array) {
+            for (let v of array) {
+                if (v === value) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    export function indexOf<T>(array: T[], value: T): number {
+        if (array) {
+            for (let i = 0, len = array.length; i < len; i++) {
+                if (array[i] === value) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
+        let count = 0;
+        if (array) {
+            for (let v of array) {
+                if (predicate(v)) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
+    export function filter<T>(array: T[], f: (x: T) => boolean): T[]{
+        let result: T[];
+        if (array) {
+            result = [];
+            for (let item of array) {
+                if (f(item)) {
+                    result.push(item);
+                }
+            }
+        }
+        return result;
+    }
+
+    export function map<T, U>(array: T[], f: (x: T) => U): U[]{
+        let result: U[];
+        if (array) {
+            result = [];
+            for (let v of array) {
+                result.push(f(v));
+            }
+        }
+        return result;
+    }
+
+    export function concatenate<T>(array1: T[], array2: T[]): T[] {
+        if (!array2 || !array2.length) return array1;
+        if (!array1 || !array1.length) return array2;
+
+        return array1.concat(array2);
+    }
+
+    export function deduplicate<T>(array: T[]): T[]{
+        let result: T[];
+        if (array) {
+            result = [];
+            for (let item of array) {
+                if (!contains(result, item)) {
+                    result.push(item);
+                }
+            }
+        }
+        return result;
+    }
+
+    export function sum(array: any[], prop: string): number {
+        let result = 0;
+        for (let v of array) {
+            result += v[prop];
+        }
+        return result;
+    }
+
+    export function addRange<T>(to: T[], from: T[]): void {
+        if (to && from) {
+            for (let v of from) {
+                to.push(v);
+            }
+        }
+    } 
+
+    /**
+     * Returns the last element of an array if non-empty, undefined otherwise.
+     */
+    export function lastOrUndefined<T>(array: T[]): T {
+        if (array.length === 0) {
+            return undefined;
+        }
+
+        return array[array.length - 1];
+    }
+
+    export function binarySearch(array: number[], value: number): number {
+        let low = 0;
+        let high = array.length - 1;
+
+        while (low <= high) {
+            let middle = low + ((high - low) >> 1);
+            let midValue = array[middle];
+
+            if (midValue === value) {
+                return middle;
+            }
+            else if (midValue > value) {
+                high = middle - 1;
+            }
+            else {
+                low = middle + 1;
+            }
+        }
+
+        return ~low;
+    }
+
+    export function reduceLeft<T>(array: T[], f: (a: T, x: T) => T): T;
+    export function reduceLeft<T, U>(array: T[], f: (a: U, x: T) => U, initial: U): U;
+    export function reduceLeft<T, U>(array: T[], f: (a: U, x: T) => U, initial?: U): U {
+        if (array) {
+            var count = array.length;
+            if (count > 0) {
+                var pos = 0;
+                var result = arguments.length <= 2 ? array[pos++] : initial;
+                while (pos < count) {
+                    result = f(<U>result, array[pos++]);
+                }
+                return <U>result;
+            }
+        }
+        return initial;
+    }
+
+    export function reduceRight<T>(array: T[], f: (a: T, x: T) => T): T;
+    export function reduceRight<T, U>(array: T[], f: (a: U, x: T) => U, initial: U): U;
+    export function reduceRight<T, U>(array: T[], f: (a: U, x: T) => U, initial?: U): U {
+        if (array) {
+            var pos = array.length - 1;
+            if (pos >= 0) {
+                var result = arguments.length <= 2 ? array[pos--] : initial;
+                while (pos >= 0) {
+                    result = f(<U>result, array[pos--]);
+                }
+                return <U>result;
+            }
+        }
+        return initial;
+    }
+
+    let hasOwnProperty = Object.prototype.hasOwnProperty;
+
+    export function hasProperty<T>(map: Map<T>, key: string): boolean {
+        return hasOwnProperty.call(map, key);
+    }
+
+    export function getProperty<T>(map: Map<T>, key: string): T {
+        return hasOwnProperty.call(map, key) ? map[key] : undefined;
+    }
+
+    export function isEmpty<T>(map: Map<T>) {
+        for (let id in map) {
+            if (hasProperty(map, id)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    export function clone<T>(object: T): T {
+        let result: any = {};
+        for (let id in object) {
+            result[id] = (<any>object)[id];
+        }
+        return <T>result;
+    }
+
+    export function extend<T>(first: Map<T>, second: Map<T>): Map<T> {
+        let result: Map<T> = {};
+        for (let id in first) {
+            result[id] = first[id];
+        }
+        for (let id in second) {
+            if (!hasProperty(result, id)) {
+                result[id] = second[id];
+            }
+        }
+        return result;
+    }
+
+    export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
+        let result: U;
+        for (let id in map) {
+            if (result = callback(map[id])) break;
+        }
+        return result;
+    }
+
+    export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
+        let result: U;
+        for (let id in map) {
+            if (result = callback(id)) break;
+        }
+        return result;
+    }
+
+    export function lookUp<T>(map: Map<T>, key: string): T {
+        return hasProperty(map, key) ? map[key] : undefined;
+    }
+
+    export function copyMap<T>(source: Map<T>, target: Map<T>): void {
+        for (let p in source) {
+            target[p] = source[p];
+        }
+    }
+
+    /**
+     * Creates a map from the elements of an array.
+     *
+     * @param array the array of input elements.
+     * @param makeKey a function that produces a key for a given element.
+     *
+     * This function makes no effort to avoid collisions; if any two elements produce
+     * the same key with the given 'makeKey' function, then the element with the higher
+     * index in the array will be the one associated with the produced key.
+     */
+    export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
+        let result: Map<T> = {};
+
+        forEach(array, value => {
+            result[makeKey(value)] = value;
+        });
+
+        return result;
+    }
+
+    export function memoize<T>(callback: () => T): () => T {
+        let value: T;
+        return () => {
+            if (callback) {
+                value = callback();
+                callback = undefined;
+            }
+            return value;
+        };
+    }
+
+    function formatStringFromArgs(text: string, args: { [index: number]: any; }, baseIndex?: number): string {
+        baseIndex = baseIndex || 0;
+
+        return text.replace(/{(\d+)}/g, (match, index?) => args[+index + baseIndex]);
+    }
+
+    export let localizedDiagnosticMessages: Map<string> = undefined;
+
+    export function getLocaleSpecificMessage(message: string) {
+        return localizedDiagnosticMessages && localizedDiagnosticMessages[message]
+            ? localizedDiagnosticMessages[message]
+            : message;
+    }
+
+    export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
+    export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
+        let end = start + length;
+
+        Debug.assert(start >= 0, "start must be non-negative, is " + start);
+        Debug.assert(length >= 0, "length must be non-negative, is " + length);
+        Debug.assert(start <= file.text.length, `start must be within the bounds of the file. ${ start } > ${ file.text.length }`);
+        Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`);
+
+        let text = getLocaleSpecificMessage(message.key);
+        
+        if (arguments.length > 4) {
+            text = formatStringFromArgs(text, arguments, 4);
+        }
+
+        return {
+            file,
+            start,
+            length,
+
+            messageText: text,
+            category: message.category,
+            code: message.code,
+        };
+    }
+
+    export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: any[]): Diagnostic;
+    export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic {
+        let text = getLocaleSpecificMessage(message.key);
+
+        if (arguments.length > 1) {
+            text = formatStringFromArgs(text, arguments, 1);
+        }
+
+        return {
+            file: undefined,
+            start: undefined,
+            length: undefined,
+
+            messageText: text,
+            category: message.category,
+            code: message.code
+        };
+    }
+
+    export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: any[]): DiagnosticMessageChain;
+    export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain {
+        let text = getLocaleSpecificMessage(message.key);
+
+        if (arguments.length > 2) {
+            text = formatStringFromArgs(text, arguments, 2);
+        }
+
+        return {
+            messageText: text,
+            category: message.category,
+            code: message.code,
+
+            next: details
+        };
+    }
+
+    export function concatenateDiagnosticMessageChains(headChain: DiagnosticMessageChain, tailChain: DiagnosticMessageChain): DiagnosticMessageChain {
+        Debug.assert(!headChain.next);
+        headChain.next = tailChain;
+        return headChain;
+    }
+
+    export function compareValues<T>(a: T, b: T): Comparison {
+        if (a === b) return Comparison.EqualTo;
+        if (a === undefined) return Comparison.LessThan;
+        if (b === undefined) return Comparison.GreaterThan;
+        return a < b ? Comparison.LessThan : Comparison.GreaterThan;
+    }
+
+    function getDiagnosticFileName(diagnostic: Diagnostic): string {
+        return diagnostic.file ? diagnostic.file.fileName : undefined;
+    }
+
+    export function compareDiagnostics(d1: Diagnostic, d2: Diagnostic): Comparison {
+        return compareValues(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) ||
+            compareValues(d1.start, d2.start) ||
+            compareValues(d1.length, d2.length) ||
+            compareValues(d1.code, d2.code) ||
+            compareMessageText(d1.messageText, d2.messageText) ||
+            Comparison.EqualTo;
+    }
+
+    function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison {
+        while (text1 && text2) {
+            // We still have both chains.
+            let string1 = typeof text1 === "string" ? text1 : text1.messageText;
+            let string2 = typeof text2 === "string" ? text2 : text2.messageText;
+
+            let res = compareValues(string1, string2);
+            if (res) {
+                return res;
+            }
+
+            text1 = typeof text1 === "string" ? undefined : text1.next;
+            text2 = typeof text2 === "string" ? undefined : text2.next;
+        }
+
+        if (!text1 && !text2) {
+            // if the chains are done, then these messages are the same.
+            return Comparison.EqualTo;
+        }
+
+        // We still have one chain remaining.  The shorter chain should come first.
+        return text1 ? Comparison.GreaterThan : Comparison.LessThan;
+    }
+
+    export function sortAndDeduplicateDiagnostics(diagnostics: Diagnostic[]): Diagnostic[]{
+        return deduplicateSortedDiagnostics(diagnostics.sort(compareDiagnostics));
+    }
+
+    export function deduplicateSortedDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] {
+        if (diagnostics.length < 2) {
+            return diagnostics;
+        }
+
+        let newDiagnostics = [diagnostics[0]];
+        let previousDiagnostic = diagnostics[0];
+        for (let i = 1; i < diagnostics.length; i++) {
+            let currentDiagnostic = diagnostics[i];
+            let isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
+            if (!isDupe) {
+                newDiagnostics.push(currentDiagnostic);
+                previousDiagnostic = currentDiagnostic;
+            }
+        }
+
+        return newDiagnostics;
+    }
+
+    export function normalizeSlashes(path: string): string {
+        return path.replace(/\\/g, "/");
+    }
+
+    // Returns length of path root (i.e. length of "/", "x:/", "//server/share/, file:///user/files")
+    export function getRootLength(path: string): number {
+        if (path.charCodeAt(0) === CharacterCodes.slash) {
+            if (path.charCodeAt(1) !== CharacterCodes.slash) return 1;
+            let p1 = path.indexOf("/", 2);
+            if (p1 < 0) return 2;
+            let p2 = path.indexOf("/", p1 + 1);
+            if (p2 < 0) return p1 + 1;
+            return p2 + 1;
+        }
+        if (path.charCodeAt(1) === CharacterCodes.colon) {
+            if (path.charCodeAt(2) === CharacterCodes.slash) return 3;
+            return 2;
+        }
+        let idx = path.indexOf('://');
+        if (idx !== -1) return idx + 3
+        return 0;
+    }
+
+    export let directorySeparator = "/";
+    function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) {
+        let parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
+        let normalized: string[] = [];
+        for (let part of parts) {
+            if (part !== ".") {
+                if (part === ".." && normalized.length > 0 && normalized[normalized.length - 1] !== "..") {
+                    normalized.pop();
+                }
+                else {
+                    // A part may be an empty string (which is 'falsy') if the path had consecutive slashes,
+                    // e.g. "path//file.ts".  Drop these before re-joining the parts.
+                    if(part) {
+                        normalized.push(part);
+                    }
+                }
+            }
+        }
+
+        return normalized;
+    }
+
+    export function normalizePath(path: string): string {
+        path = normalizeSlashes(path);
+        let rootLength = getRootLength(path);
+        let normalized = getNormalizedParts(path, rootLength);
+        return path.substr(0, rootLength) + normalized.join(directorySeparator);
+    }
+
+    export function getDirectoryPath(path: string) {
+        return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(directorySeparator)));
+    }
+
+    export function isUrl(path: string) {
+        return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1;
+    }
+
+    export function isRootedDiskPath(path: string) {
+        return getRootLength(path) !== 0;
+    }
+
+    function normalizedPathComponents(path: string, rootLength: number) {
+        let normalizedParts = getNormalizedParts(path, rootLength);
+        return [path.substr(0, rootLength)].concat(normalizedParts);
+    }
+
+    export function getNormalizedPathComponents(path: string, currentDirectory: string) {
+        path = normalizeSlashes(path);
+        let rootLength = getRootLength(path);
+        if (rootLength == 0) {
+            // If the path is not rooted it is relative to current directory
+            path = combinePaths(normalizeSlashes(currentDirectory), path);
+            rootLength = getRootLength(path);
+        }
+
+        return normalizedPathComponents(path, rootLength);
+    }
+
+    export function getNormalizedAbsolutePath(fileName: string, currentDirectory: string) {
+        return getNormalizedPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory));
+    }
+
+    export function getNormalizedPathFromPathComponents(pathComponents: string[]) {
+        if (pathComponents && pathComponents.length) {
+            return pathComponents[0] + pathComponents.slice(1).join(directorySeparator);
+        }
+    }
+
+    function getNormalizedPathComponentsOfUrl(url: string) {
+        // Get root length of http://www.website.com/folder1/foler2/
+        // In this example the root is:  http://www.website.com/ 
+        // normalized path components should be ["http://www.website.com/", "folder1", "folder2"]
+
+        let urlLength = url.length;
+        // Initial root length is http:// part
+        let rootLength = url.indexOf("://") + "://".length;
+        while (rootLength < urlLength) {
+            // Consume all immediate slashes in the protocol 
+            // eg.initial rootlength is just file:// but it needs to consume another "/" in file:///
+            if (url.charCodeAt(rootLength) === CharacterCodes.slash) {
+                rootLength++;
+            }
+            else {
+                // non slash character means we continue proceeding to next component of root search 
+                break;
+            }
+        }
+
+        // there are no parts after http:// just return current string as the pathComponent
+        if (rootLength === urlLength) {
+            return [url];
+        }
+
+        // Find the index of "/" after website.com so the root can be http://www.website.com/ (from existing http://)
+        let indexOfNextSlash = url.indexOf(directorySeparator, rootLength);
+        if (indexOfNextSlash !== -1) {
+            // Found the "/" after the website.com so the root is length of http://www.website.com/ 
+            // and get components afetr the root normally like any other folder components
+            rootLength = indexOfNextSlash + 1;
+            return normalizedPathComponents(url, rootLength);
+        }
+        else {
+            // Can't find the host assume the rest of the string as component 
+            // but make sure we append "/"  to it as root is not joined using "/"
+            // eg. if url passed in was http://website.com we want to use root as [http://website.com/] 
+            // so that other path manipulations will be correct and it can be merged with relative paths correctly
+            return [url + directorySeparator];
+        }
+    }
+
+    function getNormalizedPathOrUrlComponents(pathOrUrl: string, currentDirectory: string) {
+        if (isUrl(pathOrUrl)) {
+            return getNormalizedPathComponentsOfUrl(pathOrUrl);
+        }
+        else {
+            return getNormalizedPathComponents(pathOrUrl, currentDirectory);
+        }
+    }
+
+    export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: (fileName: string) => string, isAbsolutePathAnUrl: boolean) {
+        let pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
+        let directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
+        if (directoryComponents.length > 1 && directoryComponents[directoryComponents.length - 1] === "") {
+            // If the directory path given was of type test/cases/ then we really need components of directory to be only till its name
+            // that is  ["test", "cases", ""] needs to be actually ["test", "cases"]
+            directoryComponents.length--;
+        }
+
+        // Find the component that differs
+        for (var joinStartIndex = 0; joinStartIndex < pathComponents.length && joinStartIndex < directoryComponents.length; joinStartIndex++) {
+            if (getCanonicalFileName(directoryComponents[joinStartIndex]) !== getCanonicalFileName(pathComponents[joinStartIndex])) {
+                break;
+            }
+        }
+
+        // Get the relative path
+        if (joinStartIndex) {
+            let relativePath = "";
+            let relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
+            for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
+                if (directoryComponents[joinStartIndex] !== "") {
+                    relativePath = relativePath + ".." + directorySeparator;
+                }
+            }
+
+            return relativePath + relativePathComponents.join(directorySeparator);
+        }
+
+        // Cant find the relative path, get the absolute path
+        let absolutePath = getNormalizedPathFromPathComponents(pathComponents);
+        if (isAbsolutePathAnUrl && isRootedDiskPath(absolutePath)) {
+            absolutePath = "file:///" + absolutePath;
+        }
+
+        return absolutePath;
+    }
+
+    export function getBaseFileName(path: string) {
+        let i = path.lastIndexOf(directorySeparator);
+        return i < 0 ? path : path.substring(i + 1);
+    }
+
+    export function combinePaths(path1: string, path2: string) {
+        if (!(path1 && path1.length)) return path2;
+        if (!(path2 && path2.length)) return path1;
+        if (getRootLength(path2) !== 0) return path2;
+        if (path1.charAt(path1.length - 1) === directorySeparator) return path1 + path2;
+        return path1 + directorySeparator + path2;
+    }
+
+    export function fileExtensionIs(path: string, extension: string): boolean {
+        let pathLen = path.length;
+        let extLen = extension.length;
+        return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
+    }
+
+    let supportedExtensions = [".d.ts", ".ts", ".js"];
+
+    export function removeFileExtension(path: string): string {
+        for (let ext of supportedExtensions) {
+
+            if (fileExtensionIs(path, ext)) {
+                return path.substr(0, path.length - ext.length);
+            }
+        }
+
+        return path;
+    }
+
+    let backslashOrDoubleQuote = /[\"\\]/g;
+    let escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
+    let escapedCharsMap: Map<string> = {
+        "\0": "\\0",
+        "\t": "\\t",
+        "\v": "\\v",
+        "\f": "\\f",
+        "\b": "\\b",
+        "\r": "\\r",
+        "\n": "\\n",
+        "\\": "\\\\",
+        "\"": "\\\"",
+        "\u2028": "\\u2028", // lineSeparator
+        "\u2029": "\\u2029", // paragraphSeparator
+        "\u0085": "\\u0085"  // nextLine
+    };
+
+    export interface ObjectAllocator {
+        getNodeConstructor(kind: SyntaxKind): new () => Node;
+        getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
+        getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
+        getSignatureConstructor(): new (checker: TypeChecker) => Signature;
+    }
+
+    function Symbol(flags: SymbolFlags, name: string) {
+        this.flags = flags;
+        this.name = name;
+        this.declarations = undefined;
+    }
+
+    function Type(checker: TypeChecker, flags: TypeFlags) {
+        this.flags = flags;
+    }
+
+    function Signature(checker: TypeChecker) {
+    }
+
+    export let objectAllocator: ObjectAllocator = {
+        getNodeConstructor: kind => {
+            function Node() {
+            }
+            Node.prototype = {
+                kind: kind,
+                pos: 0,
+                end: 0,
+                flags: 0,
+                parent: undefined,
+            };
+            return <any>Node;
+        },
+        getSymbolConstructor: () => <any>Symbol,
+        getTypeConstructor: () => <any>Type,
+        getSignatureConstructor: () => <any>Signature
+    }
+
+    export const enum AssertionLevel {
+        None = 0,
+        Normal = 1,
+        Aggressive = 2,
+        VeryAggressive = 3,
+    }
+
+    export module Debug {
+        let currentAssertionLevel = AssertionLevel.None;
+
+        export function shouldAssert(level: AssertionLevel): boolean {
+            return currentAssertionLevel >= level;
+        }
+
+        export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void {
+            if (!expression) {
+                let verboseDebugString = "";
+                if (verboseDebugInfo) {
+                    verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
+                }
+
+                throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString);
+            }
+        }
+
+        export function fail(message?: string): void {
+            Debug.assert(false, message);
+        }
+    }
+}
diff --git a/lib/typescript/compiler/declarationEmitter.ts b/lib/typescript/compiler/declarationEmitter.ts
new file mode 100644
index 000000000..d2399e5d0
--- /dev/null
+++ b/lib/typescript/compiler/declarationEmitter.ts
@@ -0,0 +1,1590 @@
+/// <reference path="checker.ts"/>
+
+/* @internal */
+module ts {
+    interface ModuleElementDeclarationEmitInfo {
+        node: Node;
+        outputPos: number;
+        indent: number;
+        asynchronousOutput?: string; // If the output for alias was written asynchronously, the corresponding output
+        subModuleElementDeclarationEmitInfo?: ModuleElementDeclarationEmitInfo[];
+        isVisible?: boolean;
+    }
+
+    interface DeclarationEmit {
+        reportedDeclarationError: boolean;
+        moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[];
+        synchronousDeclarationOutput: string;
+        referencePathsOutput: string;
+    }
+
+    type GetSymbolAccessibilityDiagnostic = (symbolAccesibilityResult: SymbolAccessiblityResult) => SymbolAccessibilityDiagnostic;
+
+    interface EmitTextWriterWithSymbolWriter extends EmitTextWriter, SymbolWriter {
+        getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic;
+    }
+
+    interface SymbolAccessibilityDiagnostic {
+        errorNode: Node;
+        diagnosticMessage: DiagnosticMessage;
+        typeName?: DeclarationName;
+    }
+
+    export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
+        let diagnostics: Diagnostic[] = [];
+        let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
+        emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
+        return diagnostics;
+    }
+
+    function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit {
+        let newLine = host.getNewLine();
+        let compilerOptions = host.getCompilerOptions();
+        let languageVersion = compilerOptions.target || ScriptTarget.ES3;
+
+        let write: (s: string) => void;
+        let writeLine: () => void;
+        let increaseIndent: () => void;
+        let decreaseIndent: () => void;
+        let writeTextOfNode: (sourceFile: SourceFile, node: Node) => void;
+
+        let writer = createAndSetNewTextWriterWithSymbolWriter();
+
+        let enclosingDeclaration: Node;
+        let currentSourceFile: SourceFile;
+        let reportedDeclarationError = false;
+        let emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
+        let emit = compilerOptions.stripInternal ? stripInternal : emitNode;
+
+        let moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = [];
+        let asynchronousSubModuleDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[];
+
+        // Contains the reference paths that needs to go in the declaration file.
+        // Collecting this separately because reference paths need to be first thing in the declaration file
+        // and we could be collecting these paths from multiple files into single one with --out option
+        let referencePathsOutput = "";
+
+        if (root) {
+            // Emitting just a single file, so emit references in this file only
+            if (!compilerOptions.noResolve) {
+                let addedGlobalFileReference = false;
+                forEach(root.referencedFiles, fileReference => {
+                    let referencedFile = tryResolveScriptReference(host, root, fileReference);
+
+                    // All the references that are not going to be part of same file
+                    if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
+                        shouldEmitToOwnFile(referencedFile, compilerOptions) || // This is referenced file is emitting its own js file
+                        !addedGlobalFileReference)) { // Or the global out file corresponding to this reference was not added
+
+                        writeReferencePath(referencedFile);
+                        if (!isExternalModuleOrDeclarationFile(referencedFile)) {
+                            addedGlobalFileReference = true;
+                        }
+                    }
+                });
+            }
+
+            emitSourceFile(root);
+
+            // create asynchronous output for the importDeclarations
+            if (moduleElementDeclarationEmitInfo.length) {
+                let oldWriter = writer;
+                forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
+                    if (aliasEmitInfo.isVisible) {
+                        Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
+                        createAndSetNewTextWriterWithSymbolWriter();
+                        Debug.assert(aliasEmitInfo.indent === 0);
+                        writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
+                        aliasEmitInfo.asynchronousOutput = writer.getText();
+                    }
+                });
+                setWriter(oldWriter);
+            }
+        }
+        else {
+            // Emit references corresponding to this file
+            let emittedReferencedFiles: SourceFile[] = [];
+            forEach(host.getSourceFiles(), sourceFile => {
+                if (!isExternalModuleOrDeclarationFile(sourceFile)) {
+                    // Check what references need to be added
+                    if (!compilerOptions.noResolve) {
+                        forEach(sourceFile.referencedFiles, fileReference => {
+                            let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
+
+                            // If the reference file is a declaration file or an external module, emit that reference
+                            if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) &&
+                                !contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted
+
+                                writeReferencePath(referencedFile);
+                                emittedReferencedFiles.push(referencedFile);
+                            }
+                        });
+                    }
+
+                    emitSourceFile(sourceFile);
+                }
+            });
+        }
+
+        return {
+            reportedDeclarationError,
+            moduleElementDeclarationEmitInfo,
+            synchronousDeclarationOutput: writer.getText(),
+            referencePathsOutput,
+        }
+
+        function hasInternalAnnotation(range: CommentRange) {
+            let text = currentSourceFile.text;
+            let comment = text.substring(range.pos, range.end);
+            return comment.indexOf("@internal") >= 0;
+        }
+
+        function stripInternal(node: Node) {
+            if (node) {
+                let leadingCommentRanges = getLeadingCommentRanges(currentSourceFile.text, node.pos);
+                if (forEach(leadingCommentRanges, hasInternalAnnotation)) {
+                    return;
+                }
+
+                emitNode(node);
+            }
+        }
+
+        function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter {
+            let writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
+            writer.trackSymbol = trackSymbol;
+            writer.writeKeyword = writer.write;
+            writer.writeOperator = writer.write;
+            writer.writePunctuation = writer.write;
+            writer.writeSpace = writer.write;
+            writer.writeStringLiteral = writer.writeLiteral;
+            writer.writeParameter = writer.write;
+            writer.writeSymbol = writer.write;
+            setWriter(writer);
+            return writer;
+        }
+
+        function setWriter(newWriter: EmitTextWriterWithSymbolWriter) {
+            writer = newWriter;
+            write = newWriter.write;
+            writeTextOfNode = newWriter.writeTextOfNode;
+            writeLine = newWriter.writeLine;
+            increaseIndent = newWriter.increaseIndent;
+            decreaseIndent = newWriter.decreaseIndent;
+        }
+
+        function writeAsynchronousModuleElements(nodes: Node[]) {
+            let oldWriter = writer;
+            forEach(nodes, declaration => {
+                let nodeToCheck: Node;
+                if (declaration.kind === SyntaxKind.VariableDeclaration) {
+                    nodeToCheck = declaration.parent.parent;
+                } else if (declaration.kind === SyntaxKind.NamedImports || declaration.kind === SyntaxKind.ImportSpecifier || declaration.kind === SyntaxKind.ImportClause) {
+                    Debug.fail("We should be getting ImportDeclaration instead to write");
+                } else {
+                    nodeToCheck = declaration;
+                }
+
+                let moduleElementEmitInfo = forEach(moduleElementDeclarationEmitInfo, declEmitInfo => declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined);
+                if (!moduleElementEmitInfo && asynchronousSubModuleDeclarationEmitInfo) {
+                    moduleElementEmitInfo = forEach(asynchronousSubModuleDeclarationEmitInfo, declEmitInfo => declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined);
+                }
+                                
+                // If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration
+                // then we don't need to write it at this point. We will write it when we actually see its declaration
+                // Eg.
+                // export function bar(a: foo.Foo) { }
+                // import foo = require("foo");
+                // Writing of function bar would mark alias declaration foo as visible but we haven't yet visited that declaration so do nothing,
+                // we would write alias foo declaration when we visit it since it would now be marked as visible
+                if (moduleElementEmitInfo) {
+                    if (moduleElementEmitInfo.node.kind === SyntaxKind.ImportDeclaration) {
+                        // we have to create asynchronous output only after we have collected complete information 
+                        // because it is possible to enable multiple bindings as asynchronously visible
+                        moduleElementEmitInfo.isVisible = true;
+                    }
+                    else {
+                        createAndSetNewTextWriterWithSymbolWriter();
+                        for (let declarationIndent = moduleElementEmitInfo.indent; declarationIndent; declarationIndent--) {
+                            increaseIndent();
+                        }
+
+                        if (nodeToCheck.kind === SyntaxKind.ModuleDeclaration) {
+                            Debug.assert(asynchronousSubModuleDeclarationEmitInfo === undefined);
+                            asynchronousSubModuleDeclarationEmitInfo = [];
+                        }
+                        writeModuleElement(nodeToCheck);
+                        if (nodeToCheck.kind === SyntaxKind.ModuleDeclaration) {
+                            moduleElementEmitInfo.subModuleElementDeclarationEmitInfo = asynchronousSubModuleDeclarationEmitInfo;
+                            asynchronousSubModuleDeclarationEmitInfo = undefined;
+                        }
+                        moduleElementEmitInfo.asynchronousOutput = writer.getText();
+                    }
+                }
+            });
+            setWriter(oldWriter);
+        }
+
+        function handleSymbolAccessibilityError(symbolAccesibilityResult: SymbolAccessiblityResult) {
+            if (symbolAccesibilityResult.accessibility === SymbolAccessibility.Accessible) {
+                // write the aliases
+                if (symbolAccesibilityResult && symbolAccesibilityResult.aliasesToMakeVisible) {
+                    writeAsynchronousModuleElements(symbolAccesibilityResult.aliasesToMakeVisible);
+                }
+            }
+            else {
+                // Report error
+                reportedDeclarationError = true;
+                let errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult);
+                if (errorInfo) {
+                    if (errorInfo.typeName) {
+                        diagnostics.push(createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode,
+                            errorInfo.diagnosticMessage,
+                            getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName),
+                            symbolAccesibilityResult.errorSymbolName,
+                            symbolAccesibilityResult.errorModuleName));
+                    }
+                    else {
+                        diagnostics.push(createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode,
+                            errorInfo.diagnosticMessage,
+                            symbolAccesibilityResult.errorSymbolName,
+                            symbolAccesibilityResult.errorModuleName));
+                    }
+                }
+            }
+        }
+
+        function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
+            handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning));
+        }
+
+        function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
+            writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
+            write(": ");
+            if (type) {
+                // Write the type
+                emitType(type);
+            }
+            else {
+                resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
+            }
+        }
+
+        function writeReturnTypeAtSignature(signature: SignatureDeclaration, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
+            writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
+            write(": ");
+            if (signature.type) {
+                // Write the type
+                emitType(signature.type);
+            }
+            else {
+                resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
+            }
+        }
+
+        function emitLines(nodes: Node[]) {
+            for (let node of nodes) {
+                emit(node);
+            }
+        }
+
+        function emitSeparatedList(nodes: Node[], separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
+            let currentWriterPos = writer.getTextPos();
+            for (let node of nodes) {
+                if (!canEmitFn || canEmitFn(node)) {
+                    if (currentWriterPos !== writer.getTextPos()) {
+                        write(separator);
+                    }
+                    currentWriterPos = writer.getTextPos();
+                    eachNodeEmitFn(node);
+                }
+            }
+        }
+
+        function emitCommaList(nodes: Node[], eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
+            emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn);
+        }
+
+        function writeJsDocComments(declaration: Node) {
+            if (declaration) {
+                let jsDocComments = getJsDocComments(declaration, currentSourceFile);
+                emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments);
+                // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
+                emitComments(currentSourceFile, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
+            }
+        }
+
+        function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type: TypeNode | EntityName, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
+            writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
+            emitType(type);
+        }
+
+        function emitType(type: TypeNode | Identifier | QualifiedName) {
+            switch (type.kind) {
+                case SyntaxKind.AnyKeyword:
+                case SyntaxKind.StringKeyword:
+                case SyntaxKind.NumberKeyword:
+                case SyntaxKind.BooleanKeyword:
+                case SyntaxKind.SymbolKeyword:
+                case SyntaxKind.VoidKeyword:
+                case SyntaxKind.StringLiteral:
+                    return writeTextOfNode(currentSourceFile, type);
+                case SyntaxKind.HeritageClauseElement:
+                    return emitHeritageClauseElement(<HeritageClauseElement>type);
+                case SyntaxKind.TypeReference:
+                    return emitTypeReference(<TypeReferenceNode>type);
+                case SyntaxKind.TypeQuery:
+                    return emitTypeQuery(<TypeQueryNode>type);
+                case SyntaxKind.ArrayType:
+                    return emitArrayType(<ArrayTypeNode>type);
+                case SyntaxKind.TupleType:
+                    return emitTupleType(<TupleTypeNode>type);
+                case SyntaxKind.UnionType:
+                    return emitUnionType(<UnionTypeNode>type);
+                case SyntaxKind.ParenthesizedType:
+                    return emitParenType(<ParenthesizedTypeNode>type);
+                case SyntaxKind.FunctionType:
+                case SyntaxKind.ConstructorType:
+                    return emitSignatureDeclarationWithJsDocComments(<FunctionOrConstructorTypeNode>type);
+                case SyntaxKind.TypeLiteral:
+                    return emitTypeLiteral(<TypeLiteralNode>type);
+                case SyntaxKind.Identifier:
+                    return emitEntityName(<Identifier>type);
+                case SyntaxKind.QualifiedName:
+                    return emitEntityName(<QualifiedName>type);
+            }
+
+            function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
+                let visibilityResult = resolver.isEntityNameVisible(entityName,
+                    // Aliases can be written asynchronously so use correct enclosing declaration
+                    entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
+
+                handleSymbolAccessibilityError(visibilityResult);
+                writeEntityName(entityName);
+
+                function writeEntityName(entityName: EntityName | Expression) {
+                    if (entityName.kind === SyntaxKind.Identifier) {
+                        writeTextOfNode(currentSourceFile, entityName);
+                    }
+                    else {
+                        let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
+                        let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
+                        writeEntityName(left);
+                        write(".");
+                        writeTextOfNode(currentSourceFile, right);
+                    }
+                }
+            }
+
+            function emitHeritageClauseElement(node: HeritageClauseElement) {
+                if (isSupportedHeritageClauseElement(node)) {
+                    Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression);
+                    emitEntityName(<Identifier | PropertyAccessExpression>node.expression);
+                    if (node.typeArguments) {
+                        write("<");
+                        emitCommaList(node.typeArguments, emitType);
+                        write(">");
+                    }
+                }
+            }
+
+            function emitTypeReference(type: TypeReferenceNode) {
+                emitEntityName(type.typeName);
+                if (type.typeArguments) {
+                    write("<");
+                    emitCommaList(type.typeArguments, emitType);
+                    write(">");
+                }
+            }
+
+            function emitTypeQuery(type: TypeQueryNode) {
+                write("typeof ");
+                emitEntityName(type.exprName);
+            }
+
+            function emitArrayType(type: ArrayTypeNode) {
+                emitType(type.elementType);
+                write("[]");
+            }
+
+            function emitTupleType(type: TupleTypeNode) {
+                write("[");
+                emitCommaList(type.elementTypes, emitType);
+                write("]");
+            }
+
+            function emitUnionType(type: UnionTypeNode) {
+                emitSeparatedList(type.types, " | ", emitType);
+            }
+
+            function emitParenType(type: ParenthesizedTypeNode) {
+                write("(");
+                emitType(type.type);
+                write(")");
+            }
+
+            function emitTypeLiteral(type: TypeLiteralNode) {
+                write("{");
+                if (type.members.length) {
+                    writeLine();
+                    increaseIndent();
+                    // write members
+                    emitLines(type.members);
+                    decreaseIndent();
+                }
+                write("}");
+            }
+        }
+
+        function emitSourceFile(node: SourceFile) {
+            currentSourceFile = node;
+            enclosingDeclaration = node;
+            emitLines(node.statements);
+        }
+
+        // Return a temp variable name to be used in `export default` statements.
+        // The temp name will be of the form _default_counter.
+        // Note that export default is only allowed at most once in a module, so we
+        // do not need to keep track of created temp names.
+        function getExportDefaultTempVariableName(): string {
+            let baseName = "_default";
+            if (!hasProperty(currentSourceFile.identifiers, baseName)) {
+                return baseName;
+            }
+            let count = 0;
+            while (true) {
+                let name = baseName + "_" + (++count);
+                if (!hasProperty(currentSourceFile.identifiers, name)) {
+                    return name;
+                }
+            }
+        }
+
+        function emitExportAssignment(node: ExportAssignment) {
+            if (node.expression.kind === SyntaxKind.Identifier) {
+                write(node.isExportEquals ? "export = " : "export default ");
+                writeTextOfNode(currentSourceFile, node.expression);
+            }
+            else {
+                // Expression
+                let tempVarName = getExportDefaultTempVariableName();
+                write("declare var ");
+                write(tempVarName);
+                write(": ");
+                writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic;
+                resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
+                write(";");
+                writeLine();
+                write(node.isExportEquals ? "export = " : "export default ");
+                write(tempVarName);
+            }
+            write(";");
+            writeLine();
+
+            // Make all the declarations visible for the export name
+            if (node.expression.kind === SyntaxKind.Identifier) {
+                let nodes = resolver.collectLinkedAliases(<Identifier>node.expression);
+
+                // write each of these declarations asynchronously
+                writeAsynchronousModuleElements(nodes);
+            }
+
+            function getDefaultExportAccessibilityDiagnostic(diagnostic: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                return {
+                    diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
+                    errorNode: node
+                };
+            }
+        }
+
+        function isModuleElementVisible(node: Declaration) {
+            return resolver.isDeclarationVisible(node);
+        }
+
+        function emitModuleElement(node: Node, isModuleElementVisible: boolean) {
+            if (isModuleElementVisible) {
+                writeModuleElement(node);
+            }
+            // Import equals declaration in internal module can become visible as part of any emit so lets make sure we add these irrespective
+            else if (node.kind === SyntaxKind.ImportEqualsDeclaration ||
+                (node.parent.kind === SyntaxKind.SourceFile && isExternalModule(currentSourceFile))) {
+                let isVisible: boolean;
+                if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) {
+                    // Import declaration of another module that is visited async so lets put it in right spot
+                    asynchronousSubModuleDeclarationEmitInfo.push({
+                        node,
+                        outputPos: writer.getTextPos(),
+                        indent: writer.getIndent(),
+                        isVisible
+                    });
+                }
+                else {
+                    if (node.kind === SyntaxKind.ImportDeclaration) {
+                        let importDeclaration = <ImportDeclaration>node;
+                        if (importDeclaration.importClause) {
+                            isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) ||
+                            isVisibleNamedBinding(importDeclaration.importClause.namedBindings);
+                        }
+                    }
+                    moduleElementDeclarationEmitInfo.push({
+                        node,
+                        outputPos: writer.getTextPos(),
+                        indent: writer.getIndent(),
+                        isVisible
+                    });
+                }
+            }
+        }
+
+        function writeModuleElement(node: Node) {
+            switch (node.kind) {
+                case SyntaxKind.FunctionDeclaration:
+                    return writeFunctionDeclaration(<FunctionLikeDeclaration>node);
+                case SyntaxKind.VariableStatement:
+                    return writeVariableStatement(<VariableStatement>node);
+                case SyntaxKind.InterfaceDeclaration:
+                    return writeInterfaceDeclaration(<InterfaceDeclaration>node);
+                case SyntaxKind.ClassDeclaration:
+                    return writeClassDeclaration(<ClassDeclaration>node);
+                case SyntaxKind.TypeAliasDeclaration:
+                    return writeTypeAliasDeclaration(<TypeAliasDeclaration>node);
+                case SyntaxKind.EnumDeclaration:
+                    return writeEnumDeclaration(<EnumDeclaration>node);
+                case SyntaxKind.ModuleDeclaration:
+                    return writeModuleDeclaration(<ModuleDeclaration>node);
+                case SyntaxKind.ImportEqualsDeclaration:
+                    return writeImportEqualsDeclaration(<ImportEqualsDeclaration>node);
+                case SyntaxKind.ImportDeclaration:
+                    return writeImportDeclaration(<ImportDeclaration>node);
+                default:
+                    Debug.fail("Unknown symbol kind");
+            }
+        }
+
+        function emitModuleElementDeclarationFlags(node: Node) {
+            // If the node is parented in the current source file we need to emit export declare or just export
+            if (node.parent === currentSourceFile) {
+                // If the node is exported
+                if (node.flags & NodeFlags.Export) {
+                    write("export ");
+                }
+
+                if (node.flags & NodeFlags.Default) {
+                    write("default ");
+                }
+                else if (node.kind !== SyntaxKind.InterfaceDeclaration) {
+                    write("declare ");
+                }
+            }
+        }
+
+        function emitClassMemberDeclarationFlags(node: Declaration) {
+            if (node.flags & NodeFlags.Private) {
+                write("private ");
+            }
+            else if (node.flags & NodeFlags.Protected) {
+                write("protected ");
+            }
+
+            if (node.flags & NodeFlags.Static) {
+                write("static ");
+            }
+        }
+
+        function writeImportEqualsDeclaration(node: ImportEqualsDeclaration) {
+            // note usage of writer. methods instead of aliases created, just to make sure we are using 
+            // correct writer especially to handle asynchronous alias writing
+            emitJsDocComments(node);
+            if (node.flags & NodeFlags.Export) {
+                write("export ");
+            }
+            write("import ");
+            writeTextOfNode(currentSourceFile, node.name);
+            write(" = ");
+            if (isInternalModuleImportEqualsDeclaration(node)) {
+                emitTypeWithNewGetSymbolAccessibilityDiagnostic(<EntityName>node.moduleReference, getImportEntityNameVisibilityError);
+                write(";");
+            }
+            else {
+                write("require(");
+                writeTextOfNode(currentSourceFile, getExternalModuleImportEqualsDeclarationExpression(node));
+                write(");");
+            }
+            writer.writeLine();
+
+            function getImportEntityNameVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                return {
+                    diagnosticMessage: Diagnostics.Import_declaration_0_is_using_private_name_1,
+                    errorNode: node,
+                    typeName: node.name
+                };
+            }
+        }
+
+        function isVisibleNamedBinding(namedBindings: NamespaceImport | NamedImports): boolean {
+            if (namedBindings) {
+                if (namedBindings.kind === SyntaxKind.NamespaceImport) {
+                    return resolver.isDeclarationVisible(<NamespaceImport>namedBindings);
+                }
+                else {
+                    return forEach((<NamedImports>namedBindings).elements, namedImport => resolver.isDeclarationVisible(namedImport));
+                }
+            }
+        }
+
+        function writeImportDeclaration(node: ImportDeclaration) {
+            if (!node.importClause && !(node.flags & NodeFlags.Export)) {
+                // do not write non-exported import declarations that don't have import clauses 
+                return;
+            }
+            emitJsDocComments(node);
+            if (node.flags & NodeFlags.Export) {
+                write("export ");
+            }
+            write("import ");
+            if (node.importClause) {
+                let currentWriterPos = writer.getTextPos();
+                if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) {
+                    writeTextOfNode(currentSourceFile, node.importClause.name);
+                }
+                if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) {
+                    if (currentWriterPos !== writer.getTextPos()) {
+                        // If the default binding was emitted, write the separated
+                        write(", ");
+                    }
+                    if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
+                        write("* as ");
+                        writeTextOfNode(currentSourceFile, (<NamespaceImport>node.importClause.namedBindings).name);
+                    }
+                    else {
+                        write("{ ");
+                        emitCommaList((<NamedImports>node.importClause.namedBindings).elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible);
+                        write(" }");
+                    }
+                }
+                write(" from ");
+            }
+            writeTextOfNode(currentSourceFile, node.moduleSpecifier);
+            write(";");
+            writer.writeLine();
+        }
+
+        function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) {
+            if (node.propertyName) {
+                writeTextOfNode(currentSourceFile, node.propertyName);
+                write(" as ");
+            }
+            writeTextOfNode(currentSourceFile, node.name);
+        }
+
+        function emitExportSpecifier(node: ExportSpecifier) {
+            emitImportOrExportSpecifier(node);
+
+            // Make all the declarations visible for the export name
+            let nodes = resolver.collectLinkedAliases(node.propertyName || node.name);
+
+            // write each of these declarations asynchronously
+            writeAsynchronousModuleElements(nodes);
+        }
+
+        function emitExportDeclaration(node: ExportDeclaration) {
+            emitJsDocComments(node);
+            write("export ");
+            if (node.exportClause) {
+                write("{ ");
+                emitCommaList(node.exportClause.elements, emitExportSpecifier);
+                write(" }");
+            }
+            else {
+                write("*");
+            }
+            if (node.moduleSpecifier) {
+                write(" from ");
+                writeTextOfNode(currentSourceFile, node.moduleSpecifier);
+            }
+            write(";");
+            writer.writeLine();
+        }
+
+        function writeModuleDeclaration(node: ModuleDeclaration) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("module ");
+            writeTextOfNode(currentSourceFile, node.name);
+            while (node.body.kind !== SyntaxKind.ModuleBlock) {
+                node = <ModuleDeclaration>node.body;
+                write(".");
+                writeTextOfNode(currentSourceFile, node.name);
+            }
+            let prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitLines((<ModuleBlock>node.body).statements);
+            decreaseIndent();
+            write("}");
+            writeLine();
+            enclosingDeclaration = prevEnclosingDeclaration;
+        }
+
+        function writeTypeAliasDeclaration(node: TypeAliasDeclaration) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("type ");
+            writeTextOfNode(currentSourceFile, node.name);
+            write(" = ");
+            emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
+            write(";");
+            writeLine();
+
+            function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                return {
+                    diagnosticMessage: Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
+                    errorNode: node.type,
+                    typeName: node.name
+                };
+            }
+        }
+
+        function writeEnumDeclaration(node: EnumDeclaration) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            if (isConst(node)) {
+                write("const ")
+            }
+            write("enum ");
+            writeTextOfNode(currentSourceFile, node.name);
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitLines(node.members);
+            decreaseIndent();
+            write("}");
+            writeLine();
+        }
+
+        function emitEnumMemberDeclaration(node: EnumMember) {
+            emitJsDocComments(node);
+            writeTextOfNode(currentSourceFile, node.name);
+            let enumMemberValue = resolver.getConstantValue(node);
+            if (enumMemberValue !== undefined) {
+                write(" = ");
+                write(enumMemberValue.toString());
+            }
+            write(",");
+            writeLine();
+        }
+
+        function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) {
+            return node.parent.kind === SyntaxKind.MethodDeclaration && (node.parent.flags & NodeFlags.Private);
+        }
+
+        function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) {
+            function emitTypeParameter(node: TypeParameterDeclaration) {
+                increaseIndent();
+                emitJsDocComments(node);
+                decreaseIndent();
+                writeTextOfNode(currentSourceFile, node.name);
+                // If there is constraint present and this is not a type parameter of the private method emit the constraint
+                if (node.constraint && !isPrivateMethodTypeParameter(node)) {
+                    write(" extends ");
+                    if (node.parent.kind === SyntaxKind.FunctionType ||
+                        node.parent.kind === SyntaxKind.ConstructorType ||
+                        (node.parent.parent && node.parent.parent.kind === SyntaxKind.TypeLiteral)) {
+                        Debug.assert(node.parent.kind === SyntaxKind.MethodDeclaration ||
+                            node.parent.kind === SyntaxKind.MethodSignature ||
+                            node.parent.kind === SyntaxKind.FunctionType ||
+                            node.parent.kind === SyntaxKind.ConstructorType ||
+                            node.parent.kind === SyntaxKind.CallSignature ||
+                            node.parent.kind === SyntaxKind.ConstructSignature);
+                        emitType(node.constraint);
+                    }
+                    else {
+                        emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError);
+                    }
+                }
+
+                function getTypeParameterConstraintVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                    // Type parameter constraints are named by user so we should always be able to name it
+                    let diagnosticMessage: DiagnosticMessage;
+                    switch (node.parent.kind) {
+                        case SyntaxKind.ClassDeclaration:
+                            diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1;
+                            break;
+
+                        case SyntaxKind.InterfaceDeclaration:
+                            diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1;
+                            break;
+
+                        case SyntaxKind.ConstructSignature:
+                            diagnosticMessage = Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
+                            break;
+
+                        case SyntaxKind.CallSignature:
+                            diagnosticMessage = Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
+                            break;
+
+                        case SyntaxKind.MethodDeclaration:
+                        case SyntaxKind.MethodSignature:
+                            if (node.parent.flags & NodeFlags.Static) {
+                                diagnosticMessage = Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
+                            }
+                            else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
+                                diagnosticMessage = Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
+                            }
+                            else {
+                                diagnosticMessage = Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
+                            }
+                            break;
+
+                        case SyntaxKind.FunctionDeclaration:
+                            diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1;
+                            break;
+
+                        default:
+                            Debug.fail("This is unknown parent for type parameter: " + node.parent.kind);
+                    }
+
+                    return {
+                        diagnosticMessage,
+                        errorNode: node,
+                        typeName: node.name
+                    };
+                }
+            }
+
+            if (typeParameters) {
+                write("<");
+                emitCommaList(typeParameters, emitTypeParameter);
+                write(">");
+            }
+        }
+
+        function emitHeritageClause(typeReferences: HeritageClauseElement[], isImplementsList: boolean) {
+            if (typeReferences) {
+                write(isImplementsList ? " implements " : " extends ");
+                emitCommaList(typeReferences, emitTypeOfTypeReference);
+            }
+
+            function emitTypeOfTypeReference(node: HeritageClauseElement) {
+                if (isSupportedHeritageClauseElement(node)) {
+                    emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
+                }
+
+                function getHeritageClauseVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                    let diagnosticMessage: DiagnosticMessage;
+                    // Heritage clause is written by user so it can always be named
+                    if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
+                        // Class or Interface implemented/extended is inaccessible
+                        diagnosticMessage = isImplementsList ?
+                            Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 :
+                            Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
+                    }
+                    else {
+                        // interface is inaccessible
+                        diagnosticMessage = Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1;
+                    }
+
+                    return {
+                        diagnosticMessage,
+                        errorNode: node,
+                        typeName: (<Declaration>node.parent.parent).name
+                    };
+                }
+            }
+        }
+
+        function writeClassDeclaration(node: ClassDeclaration) {
+            function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
+                if (constructorDeclaration) {
+                    forEach(constructorDeclaration.parameters, param => {
+                        if (param.flags & NodeFlags.AccessibilityModifier) {
+                            emitPropertyDeclaration(param);
+                        }
+                    });
+                }
+            }
+
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("class ");
+            writeTextOfNode(currentSourceFile, node.name);
+            let prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+            emitTypeParameters(node.typeParameters);
+            let baseTypeNode = getClassExtendsHeritageClauseElement(node);
+            if (baseTypeNode) {
+                emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
+            }
+            emitHeritageClause(getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitParameterProperties(getFirstConstructorWithBody(node));
+            emitLines(node.members);
+            decreaseIndent();
+            write("}");
+            writeLine();
+            enclosingDeclaration = prevEnclosingDeclaration;
+        }
+
+        function writeInterfaceDeclaration(node: InterfaceDeclaration) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            write("interface ");
+            writeTextOfNode(currentSourceFile, node.name);
+            let prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+            emitTypeParameters(node.typeParameters);
+            emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false);
+            write(" {");
+            writeLine();
+            increaseIndent();
+            emitLines(node.members);
+            decreaseIndent();
+            write("}");
+            writeLine();
+            enclosingDeclaration = prevEnclosingDeclaration;
+        }
+
+        function emitPropertyDeclaration(node: Declaration) {
+            if (hasDynamicName(node)) {
+                return;
+            }
+
+            emitJsDocComments(node);
+            emitClassMemberDeclarationFlags(node);
+            emitVariableDeclaration(<VariableDeclaration>node);
+            write(";");
+            writeLine();
+        }
+
+        function emitVariableDeclaration(node: VariableDeclaration) {
+            // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted
+            // so there is no check needed to see if declaration is visible
+            if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) {
+                if (isBindingPattern(node.name)) {
+                    emitBindingPattern(<BindingPattern>node.name);
+                }
+                else {
+                    // If this node is a computed name, it can only be a symbol, because we've already skipped
+                    // it if it's not a well known symbol. In that case, the text of the name will be exactly
+                    // what we want, namely the name expression enclosed in brackets.
+                    writeTextOfNode(currentSourceFile, node.name);
+                    // If optional property emit ?
+                    if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) {
+                        write("?");
+                    }
+                    if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
+                        emitTypeOfVariableDeclarationFromTypeLiteral(node);
+                    }
+                    else if (!(node.flags & NodeFlags.Private)) {
+                        writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError);
+                    }
+                }
+            }
+
+            function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult: SymbolAccessiblityResult) {
+                if (node.kind === SyntaxKind.VariableDeclaration) {
+                    return symbolAccesibilityResult.errorModuleName ?
+                        symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                            Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                            Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 :
+                        Diagnostics.Exported_variable_0_has_or_is_using_private_name_1;
+                }
+                // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit
+                else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) {
+                    // TODO(jfreeman): Deal with computed properties in error reporting.
+                    if (node.flags & NodeFlags.Static) {
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1;
+                    }
+                    else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1;
+                    }
+                    else {
+                        // Interfaces cannot have types that cannot be named
+                        return symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1;
+                    }
+                }
+            }
+
+            function getVariableDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                let diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                return diagnosticMessage !== undefined ? {
+                    diagnosticMessage,
+                    errorNode: node,
+                    typeName: node.name
+                } : undefined;
+            }
+
+            function emitBindingPattern(bindingPattern: BindingPattern) {
+                // Only select non-omitted expression from the bindingPattern's elements.
+                // We have to do this to avoid emitting trailing commas.
+                // For example:
+                //      original: var [, c,,] = [ 2,3,4]
+                //      emitted: declare var c: number; // instead of declare var c:number, ;
+                let elements: Node[] = [];
+                for (let element of bindingPattern.elements) {
+                    if (element.kind !== SyntaxKind.OmittedExpression){
+                        elements.push(element);
+                    }
+                }
+                emitCommaList(elements, emitBindingElement);
+            }
+
+            function emitBindingElement(bindingElement: BindingElement) {
+                function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                    let diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                    return diagnosticMessage !== undefined ? {
+                        diagnosticMessage,
+                        errorNode: bindingElement,
+                        typeName: bindingElement.name
+                    } : undefined;
+                }
+
+                if (bindingElement.name) {
+                    if (isBindingPattern(bindingElement.name)) {
+                        emitBindingPattern(<BindingPattern>bindingElement.name);
+                    }
+                    else {
+                        writeTextOfNode(currentSourceFile, bindingElement.name);
+                        writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError);
+                    }
+                }
+            }
+        }
+
+        function emitTypeOfVariableDeclarationFromTypeLiteral(node: VariableLikeDeclaration) {
+            // if this is property of type literal,
+            // or is parameter of method/call/construct/index signature of type literal
+            // emit only if type is specified
+            if (node.type) {
+                write(": ");
+                emitType(node.type);
+            }
+        }
+
+        function isVariableStatementVisible(node: VariableStatement) {
+            return forEach(node.declarationList.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
+        }
+
+        function writeVariableStatement(node: VariableStatement) {
+            emitJsDocComments(node);
+            emitModuleElementDeclarationFlags(node);
+            if (isLet(node.declarationList)) {
+                write("let ");
+            }
+            else if (isConst(node.declarationList)) {
+                write("const ");
+            }
+            else {
+                write("var ");
+            }
+            emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
+            write(";");
+            writeLine();
+        }
+
+        function emitAccessorDeclaration(node: AccessorDeclaration) {
+            if (hasDynamicName(node)) {
+                return;
+            }
+
+            let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, node);
+            let accessorWithTypeAnnotation: AccessorDeclaration;
+
+            if (node === accessors.firstAccessor) {
+                emitJsDocComments(accessors.getAccessor);
+                emitJsDocComments(accessors.setAccessor);
+                emitClassMemberDeclarationFlags(node);
+                writeTextOfNode(currentSourceFile, node.name);
+                if (!(node.flags & NodeFlags.Private)) {
+                    accessorWithTypeAnnotation = node;
+                    let type = getTypeAnnotationFromAccessor(node);
+                    if (!type) {
+                        // couldn't get type for the first accessor, try the another one
+                        let anotherAccessor = node.kind === SyntaxKind.GetAccessor ? accessors.setAccessor : accessors.getAccessor;
+                        type = getTypeAnnotationFromAccessor(anotherAccessor);
+                        if (type) {
+                            accessorWithTypeAnnotation = anotherAccessor;
+                        }
+                    }
+                    writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError);
+                }
+                write(";");
+                writeLine();
+            }
+
+            function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode {
+                if (accessor) {
+                    return accessor.kind === SyntaxKind.GetAccessor
+                        ? accessor.type // Getter - return type
+                        : accessor.parameters.length > 0
+                            ? accessor.parameters[0].type // Setter parameter type
+                            : undefined;
+                }
+            }
+
+            function getAccessorDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                let diagnosticMessage: DiagnosticMessage;
+                if (accessorWithTypeAnnotation.kind === SyntaxKind.SetAccessor) {
+                    // Setters have to have type named and cannot infer it so, the type should always be named
+                    if (accessorWithTypeAnnotation.parent.flags & NodeFlags.Static) {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1;
+                    }
+                    else {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1;
+                    }
+                    return {
+                        diagnosticMessage,
+                        errorNode: <Node>accessorWithTypeAnnotation.parameters[0],
+                        // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name
+                        typeName: accessorWithTypeAnnotation.name
+                    };
+                }
+                else {
+                    if (accessorWithTypeAnnotation.flags & NodeFlags.Static) {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                            Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0;
+                    }
+                    else {
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                            Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0;
+                    }
+                    return {
+                        diagnosticMessage,
+                        errorNode: <Node>accessorWithTypeAnnotation.name,
+                        typeName: undefined
+                    };
+                }
+            }
+        }
+
+        function writeFunctionDeclaration(node: FunctionLikeDeclaration) {
+            if (hasDynamicName(node)) {
+                return;
+            }
+
+            // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting
+            // so no need to verify if the declaration is visible
+            if (!resolver.isImplementationOfOverload(node)) {
+                emitJsDocComments(node);
+                if (node.kind === SyntaxKind.FunctionDeclaration) {
+                    emitModuleElementDeclarationFlags(node);
+                }
+                else if (node.kind === SyntaxKind.MethodDeclaration) {
+                    emitClassMemberDeclarationFlags(node);
+                }
+                if (node.kind === SyntaxKind.FunctionDeclaration) {
+                    write("function ");
+                    writeTextOfNode(currentSourceFile, node.name);
+                }
+                else if (node.kind === SyntaxKind.Constructor) {
+                    write("constructor");
+                }
+                else {
+                    writeTextOfNode(currentSourceFile, node.name);
+                    if (hasQuestionToken(node)) {
+                        write("?");
+                    }
+                }
+                emitSignatureDeclaration(node);
+            }
+        }
+
+        function emitSignatureDeclarationWithJsDocComments(node: SignatureDeclaration) {
+            emitJsDocComments(node);
+            emitSignatureDeclaration(node);
+        }
+
+        function emitSignatureDeclaration(node: SignatureDeclaration) {
+            // Construct signature or constructor type write new Signature
+            if (node.kind === SyntaxKind.ConstructSignature || node.kind === SyntaxKind.ConstructorType) {
+                write("new ");
+            }
+            emitTypeParameters(node.typeParameters);
+            if (node.kind === SyntaxKind.IndexSignature) {
+                write("[");
+            }
+            else {
+                write("(");
+            }
+
+            let prevEnclosingDeclaration = enclosingDeclaration;
+            enclosingDeclaration = node;
+
+            // Parameters
+            emitCommaList(node.parameters, emitParameterDeclaration);
+
+            if (node.kind === SyntaxKind.IndexSignature) {
+                write("]");
+            }
+            else {
+                write(")");
+            }
+
+            // If this is not a constructor and is not private, emit the return type
+            let isFunctionTypeOrConstructorType = node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.ConstructorType;
+            if (isFunctionTypeOrConstructorType || node.parent.kind === SyntaxKind.TypeLiteral) {
+                // Emit type literal signature return type only if specified
+                if (node.type) {
+                    write(isFunctionTypeOrConstructorType ? " => " : ": ");
+                    emitType(node.type);
+                }
+            }
+            else if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) {
+                writeReturnTypeAtSignature(node, getReturnTypeVisibilityError);
+            }
+
+            enclosingDeclaration = prevEnclosingDeclaration;
+
+            if (!isFunctionTypeOrConstructorType) {
+                write(";");
+                writeLine();
+            }
+
+            function getReturnTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                let diagnosticMessage: DiagnosticMessage;
+                switch (node.kind) {
+                    case SyntaxKind.ConstructSignature:
+                        // Interfaces cannot have return types that cannot be named
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                            Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0;
+                        break;
+
+                    case SyntaxKind.CallSignature:
+                        // Interfaces cannot have return types that cannot be named
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                            Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0;
+                        break;
+
+                    case SyntaxKind.IndexSignature:
+                        // Interfaces cannot have return types that cannot be named
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                            Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0;
+                        break;
+
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                        if (node.flags & NodeFlags.Static) {
+                            diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                    Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                    Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                                Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0;
+                        }
+                        else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
+                            diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                    Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                    Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 :
+                                Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0;
+                        }
+                        else {
+                            // Interfaces cannot have return types that cannot be named
+                            diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                                Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 :
+                                Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0;
+                        }
+                        break;
+
+                    case SyntaxKind.FunctionDeclaration:
+                        diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
+                                Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 :
+                            Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0;
+                        break;
+
+                    default:
+                        Debug.fail("This is unknown kind for signature: " + node.kind);
+                }
+
+                return {
+                    diagnosticMessage,
+                    errorNode: <Node>node.name || node,
+                };
+            }
+        }
+
+        function emitParameterDeclaration(node: ParameterDeclaration) {
+            increaseIndent();
+            emitJsDocComments(node);
+            if (node.dotDotDotToken) {
+                write("...");
+            }
+            if (isBindingPattern(node.name)) {
+                // For bindingPattern, we can't simply writeTextOfNode from the source file
+                // because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted.
+                // Therefore, we will have to recursively emit each element in the bindingPattern.
+                emitBindingPattern(<BindingPattern>node.name);
+            }
+            else {
+                writeTextOfNode(currentSourceFile, node.name);
+            }
+            if (node.initializer || hasQuestionToken(node)) {
+                write("?");
+            }
+            decreaseIndent();
+
+            if (node.parent.kind === SyntaxKind.FunctionType ||
+                node.parent.kind === SyntaxKind.ConstructorType ||
+                node.parent.parent.kind === SyntaxKind.TypeLiteral) {
+                emitTypeOfVariableDeclarationFromTypeLiteral(node);
+            }
+            else if (!(node.parent.flags & NodeFlags.Private)) {
+                writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError);
+            }
+
+            function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                let diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                return diagnosticMessage !== undefined ? {
+                    diagnosticMessage,
+                    errorNode: node,
+                    typeName: node.name
+                } : undefined;
+            }
+
+            function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult: SymbolAccessiblityResult): DiagnosticMessage {
+                switch (node.parent.kind) {
+                    case SyntaxKind.Constructor:
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1;
+
+                    case SyntaxKind.ConstructSignature:
+                        // Interfaces cannot have parameter types that cannot be named
+                        return symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1;
+
+                    case SyntaxKind.CallSignature:
+                        // Interfaces cannot have parameter types that cannot be named
+                        return symbolAccesibilityResult.errorModuleName ?
+                            Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1;
+
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                        if (node.parent.flags & NodeFlags.Static) {
+                            return symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                    Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                    Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                                Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
+                        }
+                        else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
+                             return symbolAccesibilityResult.errorModuleName ?
+                                symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                    Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                    Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
+                                Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1;
+                        }
+                        else {
+                            // Interfaces cannot have parameter types that cannot be named
+                            return symbolAccesibilityResult.errorModuleName ?
+                                Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 :
+                                Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1;
+                        }
+
+                    case SyntaxKind.FunctionDeclaration:
+                        return symbolAccesibilityResult.errorModuleName ?
+                            symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
+                                Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+                                Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 :
+                            Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1;
+
+                    default:
+                        Debug.fail("This is unknown parent for parameter: " + node.parent.kind);
+                }
+            }
+
+            function emitBindingPattern(bindingPattern: BindingPattern) {
+                // We have to explicitly emit square bracket and bracket because these tokens are not store inside the node.
+                if (bindingPattern.kind === SyntaxKind.ObjectBindingPattern) {
+                    write("{");
+                    emitCommaList(bindingPattern.elements, emitBindingElement);
+                    write("}");
+                }
+                else if (bindingPattern.kind === SyntaxKind.ArrayBindingPattern) {
+                    write("[");
+                    let elements = bindingPattern.elements;
+                    emitCommaList(elements, emitBindingElement);
+                    if (elements && elements.hasTrailingComma) {
+                        write(", ");
+                    }
+                    write("]");
+                }
+            }
+
+            function emitBindingElement(bindingElement: BindingElement) {
+                function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
+                    let diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
+                    return diagnosticMessage !== undefined ? {
+                        diagnosticMessage,
+                        errorNode: bindingElement,
+                        typeName: bindingElement.name
+                    } : undefined;
+                }
+
+                if (bindingElement.kind === SyntaxKind.OmittedExpression) {
+                    // If bindingElement is an omittedExpression (i.e. containing elision),
+                    // we will emit blank space (although this may differ from users' original code,
+                    // it allows emitSeparatedList to write separator appropriately)
+                    // Example:
+                    //      original: function foo([, x, ,]) {}
+                    //      emit    : function foo([ , x,  , ]) {}
+                    write(" ");
+                }
+                else if (bindingElement.kind === SyntaxKind.BindingElement) {
+                    if (bindingElement.propertyName) {
+                        // bindingElement has propertyName property in the following case:
+                        //      { y: [a,b,c] ...} -> bindingPattern will have a property called propertyName for "y"
+                        // We have to explicitly emit the propertyName before descending into its binding elements.
+                        // Example:
+                        //      original: function foo({y: [a,b,c]}) {}
+                        //      emit    : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void;
+                        writeTextOfNode(currentSourceFile, bindingElement.propertyName);
+                        write(": ");
+
+                        // If bindingElement has propertyName property, then its name must be another bindingPattern of SyntaxKind.ObjectBindingPattern
+                        emitBindingPattern(<BindingPattern>bindingElement.name);
+                    }
+                    else if (bindingElement.name) {
+                        if (isBindingPattern(bindingElement.name)) {
+                            // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately.
+                            // In the case of rest element, we will omit rest element.
+                            // Example:
+                            //      original: function foo([a, [[b]], c] = [1,[["string"]], 3]) {}
+                            //      emit    : declare function foo([a, [[b]], c]: [number, [[string]], number]): void;
+                            //      original with rest: function foo([a, ...c]) {}
+                            //      emit              : declare function foo([a, ...c]): void;
+                            emitBindingPattern(<BindingPattern>bindingElement.name);
+                        }
+                        else {
+                            Debug.assert(bindingElement.name.kind === SyntaxKind.Identifier);
+                            // If the node is just an identifier, we will simply emit the text associated with the node's name
+                            // Example:
+                            //      original: function foo({y = 10, x}) {}
+                            //      emit    : declare function foo({y, x}: {number, any}): void;
+                            if (bindingElement.dotDotDotToken) {
+                                write("...");
+                            }
+                            writeTextOfNode(currentSourceFile, bindingElement.name);
+                        }
+                    }
+                }
+            } 
+        }
+
+        function emitNode(node: Node) {
+            switch (node.kind) {
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.ModuleDeclaration:
+                case SyntaxKind.ImportEqualsDeclaration:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.TypeAliasDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                    return emitModuleElement(node, isModuleElementVisible(<Declaration>node));
+                case SyntaxKind.VariableStatement:
+                    return emitModuleElement(node, isVariableStatementVisible(<VariableStatement>node));
+                case SyntaxKind.ImportDeclaration:
+                    // Import declaration without import clause is visible, otherwise it is not visible
+                    return emitModuleElement(node, /*isModuleElementVisible*/!(<ImportDeclaration>node).importClause);
+                case SyntaxKind.ExportDeclaration:
+                    return emitExportDeclaration(<ExportDeclaration>node);
+                case SyntaxKind.Constructor:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                    return writeFunctionDeclaration(<FunctionLikeDeclaration>node);
+                case SyntaxKind.ConstructSignature:
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.IndexSignature:
+                    return emitSignatureDeclarationWithJsDocComments(<SignatureDeclaration>node);
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                    return emitAccessorDeclaration(<AccessorDeclaration>node);
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    return emitPropertyDeclaration(<PropertyDeclaration>node);
+                case SyntaxKind.EnumMember:
+                    return emitEnumMemberDeclaration(<EnumMember>node);
+                case SyntaxKind.ExportAssignment:
+                    return emitExportAssignment(<ExportAssignment>node);
+                case SyntaxKind.SourceFile:
+                    return emitSourceFile(<SourceFile>node);
+            }
+        }
+
+        function writeReferencePath(referencedFile: SourceFile) {
+            let declFileName = referencedFile.flags & NodeFlags.DeclarationFile
+                ? referencedFile.fileName // Declaration file, use declaration file name
+                : shouldEmitToOwnFile(referencedFile, compilerOptions)
+                    ? getOwnEmitOutputFilePath(referencedFile, host, ".d.ts") // Own output file so get the .d.ts file
+                    : removeFileExtension(compilerOptions.out) + ".d.ts";// Global out file
+
+            declFileName = getRelativePathToDirectoryOrUrl(
+                getDirectoryPath(normalizeSlashes(jsFilePath)),
+                declFileName,
+                host.getCurrentDirectory(),
+                host.getCanonicalFileName,
+            /*isAbsolutePathAnUrl*/ false);
+
+            referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
+        }
+    }
+    
+    /* @internal */
+    export function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) {
+        let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile);
+        // TODO(shkamat): Should we not write any declaration file if any of them can produce error,
+        // or should we just not write this file like we are doing now
+        if (!emitDeclarationResult.reportedDeclarationError) {
+            let declarationOutput = emitDeclarationResult.referencePathsOutput
+                + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
+            writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM);
+        }
+
+        function getDeclarationOutput(synchronousDeclarationOutput: string, moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[]) {
+            let appliedSyncOutputPos = 0;
+            let declarationOutput = "";
+            // apply asynchronous additions to the synchronous output
+            forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
+                if (aliasEmitInfo.asynchronousOutput) {
+                    declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos);
+                    declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo);
+                    appliedSyncOutputPos = aliasEmitInfo.outputPos;
+                }
+            });
+            declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos);
+            return declarationOutput;
+        }
+    }
+}
diff --git a/lib/typescript/compiler/diagnosticInformationMap.generated.ts b/lib/typescript/compiler/diagnosticInformationMap.generated.ts
new file mode 100644
index 000000000..20ffe2628
--- /dev/null
+++ b/lib/typescript/compiler/diagnosticInformationMap.generated.ts
@@ -0,0 +1,542 @@
+// <auto-generated />
+/// <reference path="types.ts" />
+/* @internal */
+module ts {
+    export var Diagnostics = {
+        Unterminated_string_literal: { code: 1002, category: DiagnosticCategory.Error, key: "Unterminated string literal." },
+        Identifier_expected: { code: 1003, category: DiagnosticCategory.Error, key: "Identifier expected." },
+        _0_expected: { code: 1005, category: DiagnosticCategory.Error, key: "'{0}' expected." },
+        A_file_cannot_have_a_reference_to_itself: { code: 1006, category: DiagnosticCategory.Error, key: "A file cannot have a reference to itself." },
+        Trailing_comma_not_allowed: { code: 1009, category: DiagnosticCategory.Error, key: "Trailing comma not allowed." },
+        Asterisk_Slash_expected: { code: 1010, category: DiagnosticCategory.Error, key: "'*/' expected." },
+        Unexpected_token: { code: 1012, category: DiagnosticCategory.Error, key: "Unexpected token." },
+        A_rest_parameter_must_be_last_in_a_parameter_list: { code: 1014, category: DiagnosticCategory.Error, key: "A rest parameter must be last in a parameter list." },
+        Parameter_cannot_have_question_mark_and_initializer: { code: 1015, category: DiagnosticCategory.Error, key: "Parameter cannot have question mark and initializer." },
+        A_required_parameter_cannot_follow_an_optional_parameter: { code: 1016, category: DiagnosticCategory.Error, key: "A required parameter cannot follow an optional parameter." },
+        An_index_signature_cannot_have_a_rest_parameter: { code: 1017, category: DiagnosticCategory.Error, key: "An index signature cannot have a rest parameter." },
+        An_index_signature_parameter_cannot_have_an_accessibility_modifier: { code: 1018, category: DiagnosticCategory.Error, key: "An index signature parameter cannot have an accessibility modifier." },
+        An_index_signature_parameter_cannot_have_a_question_mark: { code: 1019, category: DiagnosticCategory.Error, key: "An index signature parameter cannot have a question mark." },
+        An_index_signature_parameter_cannot_have_an_initializer: { code: 1020, category: DiagnosticCategory.Error, key: "An index signature parameter cannot have an initializer." },
+        An_index_signature_must_have_a_type_annotation: { code: 1021, category: DiagnosticCategory.Error, key: "An index signature must have a type annotation." },
+        An_index_signature_parameter_must_have_a_type_annotation: { code: 1022, category: DiagnosticCategory.Error, key: "An index signature parameter must have a type annotation." },
+        An_index_signature_parameter_type_must_be_string_or_number: { code: 1023, category: DiagnosticCategory.Error, key: "An index signature parameter type must be 'string' or 'number'." },
+        A_class_or_interface_declaration_can_only_have_one_extends_clause: { code: 1024, category: DiagnosticCategory.Error, key: "A class or interface declaration can only have one 'extends' clause." },
+        An_extends_clause_must_precede_an_implements_clause: { code: 1025, category: DiagnosticCategory.Error, key: "An 'extends' clause must precede an 'implements' clause." },
+        A_class_can_only_extend_a_single_class: { code: 1026, category: DiagnosticCategory.Error, key: "A class can only extend a single class." },
+        A_class_declaration_can_only_have_one_implements_clause: { code: 1027, category: DiagnosticCategory.Error, key: "A class declaration can only have one 'implements' clause." },
+        Accessibility_modifier_already_seen: { code: 1028, category: DiagnosticCategory.Error, key: "Accessibility modifier already seen." },
+        _0_modifier_must_precede_1_modifier: { code: 1029, category: DiagnosticCategory.Error, key: "'{0}' modifier must precede '{1}' modifier." },
+        _0_modifier_already_seen: { code: 1030, category: DiagnosticCategory.Error, key: "'{0}' modifier already seen." },
+        _0_modifier_cannot_appear_on_a_class_element: { code: 1031, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a class element." },
+        An_interface_declaration_cannot_have_an_implements_clause: { code: 1032, category: DiagnosticCategory.Error, key: "An interface declaration cannot have an 'implements' clause." },
+        super_must_be_followed_by_an_argument_list_or_member_access: { code: 1034, category: DiagnosticCategory.Error, key: "'super' must be followed by an argument list or member access." },
+        Only_ambient_modules_can_use_quoted_names: { code: 1035, category: DiagnosticCategory.Error, key: "Only ambient modules can use quoted names." },
+        Statements_are_not_allowed_in_ambient_contexts: { code: 1036, category: DiagnosticCategory.Error, key: "Statements are not allowed in ambient contexts." },
+        A_declare_modifier_cannot_be_used_in_an_already_ambient_context: { code: 1038, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used in an already ambient context." },
+        Initializers_are_not_allowed_in_ambient_contexts: { code: 1039, category: DiagnosticCategory.Error, key: "Initializers are not allowed in ambient contexts." },
+        _0_modifier_cannot_appear_on_a_module_element: { code: 1044, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a module element." },
+        A_declare_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an interface declaration." },
+        A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: { code: 1046, category: DiagnosticCategory.Error, key: "A 'declare' modifier is required for a top level declaration in a .d.ts file." },
+        A_rest_parameter_cannot_be_optional: { code: 1047, category: DiagnosticCategory.Error, key: "A rest parameter cannot be optional." },
+        A_rest_parameter_cannot_have_an_initializer: { code: 1048, category: DiagnosticCategory.Error, key: "A rest parameter cannot have an initializer." },
+        A_set_accessor_must_have_exactly_one_parameter: { code: 1049, category: DiagnosticCategory.Error, key: "A 'set' accessor must have exactly one parameter." },
+        A_set_accessor_cannot_have_an_optional_parameter: { code: 1051, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have an optional parameter." },
+        A_set_accessor_parameter_cannot_have_an_initializer: { code: 1052, category: DiagnosticCategory.Error, key: "A 'set' accessor parameter cannot have an initializer." },
+        A_set_accessor_cannot_have_rest_parameter: { code: 1053, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have rest parameter." },
+        A_get_accessor_cannot_have_parameters: { code: 1054, category: DiagnosticCategory.Error, key: "A 'get' accessor cannot have parameters." },
+        Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1056, category: DiagnosticCategory.Error, key: "Accessors are only available when targeting ECMAScript 5 and higher." },
+        Enum_member_must_have_initializer: { code: 1061, category: DiagnosticCategory.Error, key: "Enum member must have initializer." },
+        An_export_assignment_cannot_be_used_in_an_internal_module: { code: 1063, category: DiagnosticCategory.Error, key: "An export assignment cannot be used in an internal module." },
+        Ambient_enum_elements_can_only_have_integer_literal_initializers: { code: 1066, category: DiagnosticCategory.Error, key: "Ambient enum elements can only have integer literal initializers." },
+        Unexpected_token_A_constructor_method_accessor_or_property_was_expected: { code: 1068, category: DiagnosticCategory.Error, key: "Unexpected token. A constructor, method, accessor, or property was expected." },
+        A_declare_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an import declaration." },
+        Invalid_reference_directive_syntax: { code: 1084, category: DiagnosticCategory.Error, key: "Invalid 'reference' directive syntax." },
+        Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: { code: 1085, category: DiagnosticCategory.Error, key: "Octal literals are not available when targeting ECMAScript 5 and higher." },
+        An_accessor_cannot_be_declared_in_an_ambient_context: { code: 1086, category: DiagnosticCategory.Error, key: "An accessor cannot be declared in an ambient context." },
+        _0_modifier_cannot_appear_on_a_constructor_declaration: { code: 1089, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a constructor declaration." },
+        _0_modifier_cannot_appear_on_a_parameter: { code: 1090, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a parameter." },
+        Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement: { code: 1091, category: DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...in' statement." },
+        Type_parameters_cannot_appear_on_a_constructor_declaration: { code: 1092, category: DiagnosticCategory.Error, key: "Type parameters cannot appear on a constructor declaration." },
+        Type_annotation_cannot_appear_on_a_constructor_declaration: { code: 1093, category: DiagnosticCategory.Error, key: "Type annotation cannot appear on a constructor declaration." },
+        An_accessor_cannot_have_type_parameters: { code: 1094, category: DiagnosticCategory.Error, key: "An accessor cannot have type parameters." },
+        A_set_accessor_cannot_have_a_return_type_annotation: { code: 1095, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have a return type annotation." },
+        An_index_signature_must_have_exactly_one_parameter: { code: 1096, category: DiagnosticCategory.Error, key: "An index signature must have exactly one parameter." },
+        _0_list_cannot_be_empty: { code: 1097, category: DiagnosticCategory.Error, key: "'{0}' list cannot be empty." },
+        Type_parameter_list_cannot_be_empty: { code: 1098, category: DiagnosticCategory.Error, key: "Type parameter list cannot be empty." },
+        Type_argument_list_cannot_be_empty: { code: 1099, category: DiagnosticCategory.Error, key: "Type argument list cannot be empty." },
+        Invalid_use_of_0_in_strict_mode: { code: 1100, category: DiagnosticCategory.Error, key: "Invalid use of '{0}' in strict mode." },
+        with_statements_are_not_allowed_in_strict_mode: { code: 1101, category: DiagnosticCategory.Error, key: "'with' statements are not allowed in strict mode." },
+        delete_cannot_be_called_on_an_identifier_in_strict_mode: { code: 1102, category: DiagnosticCategory.Error, key: "'delete' cannot be called on an identifier in strict mode." },
+        A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement: { code: 1104, category: DiagnosticCategory.Error, key: "A 'continue' statement can only be used within an enclosing iteration statement." },
+        A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement: { code: 1105, category: DiagnosticCategory.Error, key: "A 'break' statement can only be used within an enclosing iteration or switch statement." },
+        Jump_target_cannot_cross_function_boundary: { code: 1107, category: DiagnosticCategory.Error, key: "Jump target cannot cross function boundary." },
+        A_return_statement_can_only_be_used_within_a_function_body: { code: 1108, category: DiagnosticCategory.Error, key: "A 'return' statement can only be used within a function body." },
+        Expression_expected: { code: 1109, category: DiagnosticCategory.Error, key: "Expression expected." },
+        Type_expected: { code: 1110, category: DiagnosticCategory.Error, key: "Type expected." },
+        A_class_member_cannot_be_declared_optional: { code: 1112, category: DiagnosticCategory.Error, key: "A class member cannot be declared optional." },
+        A_default_clause_cannot_appear_more_than_once_in_a_switch_statement: { code: 1113, category: DiagnosticCategory.Error, key: "A 'default' clause cannot appear more than once in a 'switch' statement." },
+        Duplicate_label_0: { code: 1114, category: DiagnosticCategory.Error, key: "Duplicate label '{0}'" },
+        A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement: { code: 1115, category: DiagnosticCategory.Error, key: "A 'continue' statement can only jump to a label of an enclosing iteration statement." },
+        A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement: { code: 1116, category: DiagnosticCategory.Error, key: "A 'break' statement can only jump to a label of an enclosing statement." },
+        An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode: { code: 1117, category: DiagnosticCategory.Error, key: "An object literal cannot have multiple properties with the same name in strict mode." },
+        An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name: { code: 1118, category: DiagnosticCategory.Error, key: "An object literal cannot have multiple get/set accessors with the same name." },
+        An_object_literal_cannot_have_property_and_accessor_with_the_same_name: { code: 1119, category: DiagnosticCategory.Error, key: "An object literal cannot have property and accessor with the same name." },
+        An_export_assignment_cannot_have_modifiers: { code: 1120, category: DiagnosticCategory.Error, key: "An export assignment cannot have modifiers." },
+        Octal_literals_are_not_allowed_in_strict_mode: { code: 1121, category: DiagnosticCategory.Error, key: "Octal literals are not allowed in strict mode." },
+        A_tuple_type_element_list_cannot_be_empty: { code: 1122, category: DiagnosticCategory.Error, key: "A tuple type element list cannot be empty." },
+        Variable_declaration_list_cannot_be_empty: { code: 1123, category: DiagnosticCategory.Error, key: "Variable declaration list cannot be empty." },
+        Digit_expected: { code: 1124, category: DiagnosticCategory.Error, key: "Digit expected." },
+        Hexadecimal_digit_expected: { code: 1125, category: DiagnosticCategory.Error, key: "Hexadecimal digit expected." },
+        Unexpected_end_of_text: { code: 1126, category: DiagnosticCategory.Error, key: "Unexpected end of text." },
+        Invalid_character: { code: 1127, category: DiagnosticCategory.Error, key: "Invalid character." },
+        Declaration_or_statement_expected: { code: 1128, category: DiagnosticCategory.Error, key: "Declaration or statement expected." },
+        Statement_expected: { code: 1129, category: DiagnosticCategory.Error, key: "Statement expected." },
+        case_or_default_expected: { code: 1130, category: DiagnosticCategory.Error, key: "'case' or 'default' expected." },
+        Property_or_signature_expected: { code: 1131, category: DiagnosticCategory.Error, key: "Property or signature expected." },
+        Enum_member_expected: { code: 1132, category: DiagnosticCategory.Error, key: "Enum member expected." },
+        Type_reference_expected: { code: 1133, category: DiagnosticCategory.Error, key: "Type reference expected." },
+        Variable_declaration_expected: { code: 1134, category: DiagnosticCategory.Error, key: "Variable declaration expected." },
+        Argument_expression_expected: { code: 1135, category: DiagnosticCategory.Error, key: "Argument expression expected." },
+        Property_assignment_expected: { code: 1136, category: DiagnosticCategory.Error, key: "Property assignment expected." },
+        Expression_or_comma_expected: { code: 1137, category: DiagnosticCategory.Error, key: "Expression or comma expected." },
+        Parameter_declaration_expected: { code: 1138, category: DiagnosticCategory.Error, key: "Parameter declaration expected." },
+        Type_parameter_declaration_expected: { code: 1139, category: DiagnosticCategory.Error, key: "Type parameter declaration expected." },
+        Type_argument_expected: { code: 1140, category: DiagnosticCategory.Error, key: "Type argument expected." },
+        String_literal_expected: { code: 1141, category: DiagnosticCategory.Error, key: "String literal expected." },
+        Line_break_not_permitted_here: { code: 1142, category: DiagnosticCategory.Error, key: "Line break not permitted here." },
+        or_expected: { code: 1144, category: DiagnosticCategory.Error, key: "'{' or ';' expected." },
+        Modifiers_not_permitted_on_index_signature_members: { code: 1145, category: DiagnosticCategory.Error, key: "Modifiers not permitted on index signature members." },
+        Declaration_expected: { code: 1146, category: DiagnosticCategory.Error, key: "Declaration expected." },
+        Import_declarations_in_an_internal_module_cannot_reference_an_external_module: { code: 1147, category: DiagnosticCategory.Error, key: "Import declarations in an internal module cannot reference an external module." },
+        Cannot_compile_external_modules_unless_the_module_flag_is_provided: { code: 1148, category: DiagnosticCategory.Error, key: "Cannot compile external modules unless the '--module' flag is provided." },
+        File_name_0_differs_from_already_included_file_name_1_only_in_casing: { code: 1149, category: DiagnosticCategory.Error, key: "File name '{0}' differs from already included file name '{1}' only in casing" },
+        new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 1150, category: DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
+        var_let_or_const_expected: { code: 1152, category: DiagnosticCategory.Error, key: "'var', 'let' or 'const' expected." },
+        let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1153, category: DiagnosticCategory.Error, key: "'let' declarations are only available when targeting ECMAScript 6 and higher." },
+        const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1154, category: DiagnosticCategory.Error, key: "'const' declarations are only available when targeting ECMAScript 6 and higher." },
+        const_declarations_must_be_initialized: { code: 1155, category: DiagnosticCategory.Error, key: "'const' declarations must be initialized" },
+        const_declarations_can_only_be_declared_inside_a_block: { code: 1156, category: DiagnosticCategory.Error, key: "'const' declarations can only be declared inside a block." },
+        let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
+        Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." },
+        Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
+        An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
+        yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
+        Computed_property_names_are_not_allowed_in_enums: { code: 1164, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in enums." },
+        A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol: { code: 1165, category: DiagnosticCategory.Error, key: "A computed property name in an ambient context must directly refer to a built-in symbol." },
+        A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol: { code: 1166, category: DiagnosticCategory.Error, key: "A computed property name in a class property declaration must directly refer to a built-in symbol." },
+        Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1167, category: DiagnosticCategory.Error, key: "Computed property names are only available when targeting ECMAScript 6 and higher." },
+        A_computed_property_name_in_a_method_overload_must_directly_refer_to_a_built_in_symbol: { code: 1168, category: DiagnosticCategory.Error, key: "A computed property name in a method overload must directly refer to a built-in symbol." },
+        A_computed_property_name_in_an_interface_must_directly_refer_to_a_built_in_symbol: { code: 1169, category: DiagnosticCategory.Error, key: "A computed property name in an interface must directly refer to a built-in symbol." },
+        A_computed_property_name_in_a_type_literal_must_directly_refer_to_a_built_in_symbol: { code: 1170, category: DiagnosticCategory.Error, key: "A computed property name in a type literal must directly refer to a built-in symbol." },
+        A_comma_expression_is_not_allowed_in_a_computed_property_name: { code: 1171, category: DiagnosticCategory.Error, key: "A comma expression is not allowed in a computed property name." },
+        extends_clause_already_seen: { code: 1172, category: DiagnosticCategory.Error, key: "'extends' clause already seen." },
+        extends_clause_must_precede_implements_clause: { code: 1173, category: DiagnosticCategory.Error, key: "'extends' clause must precede 'implements' clause." },
+        Classes_can_only_extend_a_single_class: { code: 1174, category: DiagnosticCategory.Error, key: "Classes can only extend a single class." },
+        implements_clause_already_seen: { code: 1175, category: DiagnosticCategory.Error, key: "'implements' clause already seen." },
+        Interface_declaration_cannot_have_implements_clause: { code: 1176, category: DiagnosticCategory.Error, key: "Interface declaration cannot have 'implements' clause." },
+        Binary_digit_expected: { code: 1177, category: DiagnosticCategory.Error, key: "Binary digit expected." },
+        Octal_digit_expected: { code: 1178, category: DiagnosticCategory.Error, key: "Octal digit expected." },
+        Unexpected_token_expected: { code: 1179, category: DiagnosticCategory.Error, key: "Unexpected token. '{' expected." },
+        Property_destructuring_pattern_expected: { code: 1180, category: DiagnosticCategory.Error, key: "Property destructuring pattern expected." },
+        Array_element_destructuring_pattern_expected: { code: 1181, category: DiagnosticCategory.Error, key: "Array element destructuring pattern expected." },
+        A_destructuring_declaration_must_have_an_initializer: { code: 1182, category: DiagnosticCategory.Error, key: "A destructuring declaration must have an initializer." },
+        Destructuring_declarations_are_not_allowed_in_ambient_contexts: { code: 1183, category: DiagnosticCategory.Error, key: "Destructuring declarations are not allowed in ambient contexts." },
+        An_implementation_cannot_be_declared_in_ambient_contexts: { code: 1184, category: DiagnosticCategory.Error, key: "An implementation cannot be declared in ambient contexts." },
+        Modifiers_cannot_appear_here: { code: 1184, category: DiagnosticCategory.Error, key: "Modifiers cannot appear here." },
+        Merge_conflict_marker_encountered: { code: 1185, category: DiagnosticCategory.Error, key: "Merge conflict marker encountered." },
+        A_rest_element_cannot_have_an_initializer: { code: 1186, category: DiagnosticCategory.Error, key: "A rest element cannot have an initializer." },
+        A_parameter_property_may_not_be_a_binding_pattern: { code: 1187, category: DiagnosticCategory.Error, key: "A parameter property may not be a binding pattern." },
+        Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement: { code: 1188, category: DiagnosticCategory.Error, key: "Only a single variable declaration is allowed in a 'for...of' statement." },
+        The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer: { code: 1189, category: DiagnosticCategory.Error, key: "The variable declaration of a 'for...in' statement cannot have an initializer." },
+        The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer: { code: 1190, category: DiagnosticCategory.Error, key: "The variable declaration of a 'for...of' statement cannot have an initializer." },
+        An_import_declaration_cannot_have_modifiers: { code: 1191, category: DiagnosticCategory.Error, key: "An import declaration cannot have modifiers." },
+        External_module_0_has_no_default_export: { code: 1192, category: DiagnosticCategory.Error, key: "External module '{0}' has no default export." },
+        An_export_declaration_cannot_have_modifiers: { code: 1193, category: DiagnosticCategory.Error, key: "An export declaration cannot have modifiers." },
+        Export_declarations_are_not_permitted_in_an_internal_module: { code: 1194, category: DiagnosticCategory.Error, key: "Export declarations are not permitted in an internal module." },
+        Catch_clause_variable_name_must_be_an_identifier: { code: 1195, category: DiagnosticCategory.Error, key: "Catch clause variable name must be an identifier." },
+        Catch_clause_variable_cannot_have_a_type_annotation: { code: 1196, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have a type annotation." },
+        Catch_clause_variable_cannot_have_an_initializer: { code: 1197, category: DiagnosticCategory.Error, key: "Catch clause variable cannot have an initializer." },
+        An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
+        Unterminated_Unicode_escape_sequence: { code: 1199, category: DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
+        Line_terminator_not_permitted_before_arrow: { code: 1200, category: DiagnosticCategory.Error, key: "Line terminator not permitted before arrow." },
+        Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
+        Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
+        Cannot_compile_external_modules_into_amd_commonjs_or_umd_when_targeting_ES6_or_higher: { code: 1204, category: DiagnosticCategory.Error, key: "Cannot compile external modules into 'amd', 'commonjs' or 'umd' when targeting 'ES6' or higher." },
+        Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1205, category: DiagnosticCategory.Error, key: "Decorators are only available when targeting ECMAScript 5 and higher." },
+        Decorators_are_not_valid_here: { code: 1206, category: DiagnosticCategory.Error, key: "Decorators are not valid here." },
+        Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name: { code: 1207, category: DiagnosticCategory.Error, key: "Decorators cannot be applied to multiple get/set accessors of the same name." },
+        Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided: { code: 1208, category: DiagnosticCategory.Error, key: "Cannot compile non-external modules when the '--separateCompilation' flag is provided." },
+        Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided: { code: 1209, category: DiagnosticCategory.Error, key: "Ambient const enums are not allowed when the '--separateCompilation' flag is provided." },
+        Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode: { code: 1210, category: DiagnosticCategory.Error, key: "Invalid use of '{0}'. Class definitions are automatically in strict mode." },
+        A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
+        Identifier_expected_0_is_a_reserved_word_in_strict_mode: { code: 1212, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode" },
+        Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1213, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
+        Identifier_expected_0_is_a_reserved_word_in_strict_mode_External_Module_is_automatically_in_strict_mode: { code: 1214, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. External Module is automatically in strict mode." },
+        Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
+        Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
+        Type_expected_0_is_a_reserved_word_in_strict_mode_Module_is_automatically_in_strict_mode: { code: 1217, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode." },
+        Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
+        Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
+        Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
+        Circular_definition_of_import_alias_0: { code: 2303, category: DiagnosticCategory.Error, key: "Circular definition of import alias '{0}'." },
+        Cannot_find_name_0: { code: 2304, category: DiagnosticCategory.Error, key: "Cannot find name '{0}'." },
+        Module_0_has_no_exported_member_1: { code: 2305, category: DiagnosticCategory.Error, key: "Module '{0}' has no exported member '{1}'." },
+        File_0_is_not_an_external_module: { code: 2306, category: DiagnosticCategory.Error, key: "File '{0}' is not an external module." },
+        Cannot_find_external_module_0: { code: 2307, category: DiagnosticCategory.Error, key: "Cannot find external module '{0}'." },
+        A_module_cannot_have_more_than_one_export_assignment: { code: 2308, category: DiagnosticCategory.Error, key: "A module cannot have more than one export assignment." },
+        An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements: { code: 2309, category: DiagnosticCategory.Error, key: "An export assignment cannot be used in a module with other exported elements." },
+        Type_0_recursively_references_itself_as_a_base_type: { code: 2310, category: DiagnosticCategory.Error, key: "Type '{0}' recursively references itself as a base type." },
+        A_class_may_only_extend_another_class: { code: 2311, category: DiagnosticCategory.Error, key: "A class may only extend another class." },
+        An_interface_may_only_extend_a_class_or_another_interface: { code: 2312, category: DiagnosticCategory.Error, key: "An interface may only extend a class or another interface." },
+        Constraint_of_a_type_parameter_cannot_reference_any_type_parameter_from_the_same_type_parameter_list: { code: 2313, category: DiagnosticCategory.Error, key: "Constraint of a type parameter cannot reference any type parameter from the same type parameter list." },
+        Generic_type_0_requires_1_type_argument_s: { code: 2314, category: DiagnosticCategory.Error, key: "Generic type '{0}' requires {1} type argument(s)." },
+        Type_0_is_not_generic: { code: 2315, category: DiagnosticCategory.Error, key: "Type '{0}' is not generic." },
+        Global_type_0_must_be_a_class_or_interface_type: { code: 2316, category: DiagnosticCategory.Error, key: "Global type '{0}' must be a class or interface type." },
+        Global_type_0_must_have_1_type_parameter_s: { code: 2317, category: DiagnosticCategory.Error, key: "Global type '{0}' must have {1} type parameter(s)." },
+        Cannot_find_global_type_0: { code: 2318, category: DiagnosticCategory.Error, key: "Cannot find global type '{0}'." },
+        Named_property_0_of_types_1_and_2_are_not_identical: { code: 2319, category: DiagnosticCategory.Error, key: "Named property '{0}' of types '{1}' and '{2}' are not identical." },
+        Interface_0_cannot_simultaneously_extend_types_1_and_2: { code: 2320, category: DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'." },
+        Excessive_stack_depth_comparing_types_0_and_1: { code: 2321, category: DiagnosticCategory.Error, key: "Excessive stack depth comparing types '{0}' and '{1}'." },
+        Type_0_is_not_assignable_to_type_1: { code: 2322, category: DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}'." },
+        Property_0_is_missing_in_type_1: { code: 2324, category: DiagnosticCategory.Error, key: "Property '{0}' is missing in type '{1}'." },
+        Property_0_is_private_in_type_1_but_not_in_type_2: { code: 2325, category: DiagnosticCategory.Error, key: "Property '{0}' is private in type '{1}' but not in type '{2}'." },
+        Types_of_property_0_are_incompatible: { code: 2326, category: DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible." },
+        Property_0_is_optional_in_type_1_but_required_in_type_2: { code: 2327, category: DiagnosticCategory.Error, key: "Property '{0}' is optional in type '{1}' but required in type '{2}'." },
+        Types_of_parameters_0_and_1_are_incompatible: { code: 2328, category: DiagnosticCategory.Error, key: "Types of parameters '{0}' and '{1}' are incompatible." },
+        Index_signature_is_missing_in_type_0: { code: 2329, category: DiagnosticCategory.Error, key: "Index signature is missing in type '{0}'." },
+        Index_signatures_are_incompatible: { code: 2330, category: DiagnosticCategory.Error, key: "Index signatures are incompatible." },
+        this_cannot_be_referenced_in_a_module_body: { code: 2331, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a module body." },
+        this_cannot_be_referenced_in_current_location: { code: 2332, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in current location." },
+        this_cannot_be_referenced_in_constructor_arguments: { code: 2333, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in constructor arguments." },
+        this_cannot_be_referenced_in_a_static_property_initializer: { code: 2334, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a static property initializer." },
+        super_can_only_be_referenced_in_a_derived_class: { code: 2335, category: DiagnosticCategory.Error, key: "'super' can only be referenced in a derived class." },
+        super_cannot_be_referenced_in_constructor_arguments: { code: 2336, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in constructor arguments." },
+        Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors: { code: 2337, category: DiagnosticCategory.Error, key: "Super calls are not permitted outside constructors or in nested functions inside constructors" },
+        super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class: { code: 2338, category: DiagnosticCategory.Error, key: "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class" },
+        Property_0_does_not_exist_on_type_1: { code: 2339, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on type '{1}'." },
+        Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword: { code: 2340, category: DiagnosticCategory.Error, key: "Only public and protected methods of the base class are accessible via the 'super' keyword" },
+        Property_0_is_private_and_only_accessible_within_class_1: { code: 2341, category: DiagnosticCategory.Error, key: "Property '{0}' is private and only accessible within class '{1}'." },
+        An_index_expression_argument_must_be_of_type_string_number_symbol_or_any: { code: 2342, category: DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', 'symbol, or 'any'." },
+        Type_0_does_not_satisfy_the_constraint_1: { code: 2344, category: DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}'." },
+        Argument_of_type_0_is_not_assignable_to_parameter_of_type_1: { code: 2345, category: DiagnosticCategory.Error, key: "Argument of type '{0}' is not assignable to parameter of type '{1}'." },
+        Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: DiagnosticCategory.Error, key: "Supplied parameters do not match any signature of call target." },
+        Untyped_function_calls_may_not_accept_type_arguments: { code: 2347, category: DiagnosticCategory.Error, key: "Untyped function calls may not accept type arguments." },
+        Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: { code: 2348, category: DiagnosticCategory.Error, key: "Value of type '{0}' is not callable. Did you mean to include 'new'?" },
+        Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { code: 2349, category: DiagnosticCategory.Error, key: "Cannot invoke an expression whose type lacks a call signature." },
+        Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
+        Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
+        Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
+        No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
+        A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
+        An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
+        The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: { code: 2357, category: DiagnosticCategory.Error, key: "The operand of an increment or decrement operator must be a variable, property or indexer." },
+        The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2358, category: DiagnosticCategory.Error, key: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter." },
+        The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: { code: 2359, category: DiagnosticCategory.Error, key: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type." },
+        The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol: { code: 2360, category: DiagnosticCategory.Error, key: "The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'." },
+        The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2361, category: DiagnosticCategory.Error, key: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter" },
+        The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2362, category: DiagnosticCategory.Error, key: "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
+        The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2363, category: DiagnosticCategory.Error, key: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
+        Invalid_left_hand_side_of_assignment_expression: { code: 2364, category: DiagnosticCategory.Error, key: "Invalid left-hand side of assignment expression." },
+        Operator_0_cannot_be_applied_to_types_1_and_2: { code: 2365, category: DiagnosticCategory.Error, key: "Operator '{0}' cannot be applied to types '{1}' and '{2}'." },
+        Type_parameter_name_cannot_be_0: { code: 2368, category: DiagnosticCategory.Error, key: "Type parameter name cannot be '{0}'" },
+        A_parameter_property_is_only_allowed_in_a_constructor_implementation: { code: 2369, category: DiagnosticCategory.Error, key: "A parameter property is only allowed in a constructor implementation." },
+        A_rest_parameter_must_be_of_an_array_type: { code: 2370, category: DiagnosticCategory.Error, key: "A rest parameter must be of an array type." },
+        A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation: { code: 2371, category: DiagnosticCategory.Error, key: "A parameter initializer is only allowed in a function or constructor implementation." },
+        Parameter_0_cannot_be_referenced_in_its_initializer: { code: 2372, category: DiagnosticCategory.Error, key: "Parameter '{0}' cannot be referenced in its initializer." },
+        Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: { code: 2373, category: DiagnosticCategory.Error, key: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it." },
+        Duplicate_string_index_signature: { code: 2374, category: DiagnosticCategory.Error, key: "Duplicate string index signature." },
+        Duplicate_number_index_signature: { code: 2375, category: DiagnosticCategory.Error, key: "Duplicate number index signature." },
+        A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties: { code: 2376, category: DiagnosticCategory.Error, key: "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties." },
+        Constructors_for_derived_classes_must_contain_a_super_call: { code: 2377, category: DiagnosticCategory.Error, key: "Constructors for derived classes must contain a 'super' call." },
+        A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2378, category: DiagnosticCategory.Error, key: "A 'get' accessor must return a value or consist of a single 'throw' statement." },
+        Getter_and_setter_accessors_do_not_agree_in_visibility: { code: 2379, category: DiagnosticCategory.Error, key: "Getter and setter accessors do not agree in visibility." },
+        get_and_set_accessor_must_have_the_same_type: { code: 2380, category: DiagnosticCategory.Error, key: "'get' and 'set' accessor must have the same type." },
+        A_signature_with_an_implementation_cannot_use_a_string_literal_type: { code: 2381, category: DiagnosticCategory.Error, key: "A signature with an implementation cannot use a string literal type." },
+        Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature: { code: 2382, category: DiagnosticCategory.Error, key: "Specialized overload signature is not assignable to any non-specialized signature." },
+        Overload_signatures_must_all_be_exported_or_not_exported: { code: 2383, category: DiagnosticCategory.Error, key: "Overload signatures must all be exported or not exported." },
+        Overload_signatures_must_all_be_ambient_or_non_ambient: { code: 2384, category: DiagnosticCategory.Error, key: "Overload signatures must all be ambient or non-ambient." },
+        Overload_signatures_must_all_be_public_private_or_protected: { code: 2385, category: DiagnosticCategory.Error, key: "Overload signatures must all be public, private or protected." },
+        Overload_signatures_must_all_be_optional_or_required: { code: 2386, category: DiagnosticCategory.Error, key: "Overload signatures must all be optional or required." },
+        Function_overload_must_be_static: { code: 2387, category: DiagnosticCategory.Error, key: "Function overload must be static." },
+        Function_overload_must_not_be_static: { code: 2388, category: DiagnosticCategory.Error, key: "Function overload must not be static." },
+        Function_implementation_name_must_be_0: { code: 2389, category: DiagnosticCategory.Error, key: "Function implementation name must be '{0}'." },
+        Constructor_implementation_is_missing: { code: 2390, category: DiagnosticCategory.Error, key: "Constructor implementation is missing." },
+        Function_implementation_is_missing_or_not_immediately_following_the_declaration: { code: 2391, category: DiagnosticCategory.Error, key: "Function implementation is missing or not immediately following the declaration." },
+        Multiple_constructor_implementations_are_not_allowed: { code: 2392, category: DiagnosticCategory.Error, key: "Multiple constructor implementations are not allowed." },
+        Duplicate_function_implementation: { code: 2393, category: DiagnosticCategory.Error, key: "Duplicate function implementation." },
+        Overload_signature_is_not_compatible_with_function_implementation: { code: 2394, category: DiagnosticCategory.Error, key: "Overload signature is not compatible with function implementation." },
+        Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local: { code: 2395, category: DiagnosticCategory.Error, key: "Individual declarations in merged declaration {0} must be all exported or all local." },
+        Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters: { code: 2396, category: DiagnosticCategory.Error, key: "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters." },
+        Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference: { code: 2399, category: DiagnosticCategory.Error, key: "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference." },
+        Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference: { code: 2400, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference." },
+        Duplicate_identifier_super_Compiler_uses_super_to_capture_base_class_reference: { code: 2401, category: DiagnosticCategory.Error, key: "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference." },
+        Expression_resolves_to_super_that_compiler_uses_to_capture_base_class_reference: { code: 2402, category: DiagnosticCategory.Error, key: "Expression resolves to '_super' that compiler uses to capture base class reference." },
+        Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2: { code: 2403, category: DiagnosticCategory.Error, key: "Subsequent variable declarations must have the same type.  Variable '{0}' must be of type '{1}', but here has type '{2}'." },
+        The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation: { code: 2404, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot use a type annotation." },
+        The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any: { code: 2405, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement must be of type 'string' or 'any'." },
+        Invalid_left_hand_side_in_for_in_statement: { code: 2406, category: DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...in' statement." },
+        The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2407, category: DiagnosticCategory.Error, key: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." },
+        Setters_cannot_return_a_value: { code: 2408, category: DiagnosticCategory.Error, key: "Setters cannot return a value." },
+        Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2409, category: DiagnosticCategory.Error, key: "Return type of constructor signature must be assignable to the instance type of the class" },
+        All_symbols_within_a_with_block_will_be_resolved_to_any: { code: 2410, category: DiagnosticCategory.Error, key: "All symbols within a 'with' block will be resolved to 'any'." },
+        Property_0_of_type_1_is_not_assignable_to_string_index_type_2: { code: 2411, category: DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'." },
+        Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: { code: 2412, category: DiagnosticCategory.Error, key: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'." },
+        Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: DiagnosticCategory.Error, key: "Numeric index type '{0}' is not assignable to string index type '{1}'." },
+        Class_name_cannot_be_0: { code: 2414, category: DiagnosticCategory.Error, key: "Class name cannot be '{0}'" },
+        Class_0_incorrectly_extends_base_class_1: { code: 2415, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly extends base class '{1}'." },
+        Class_static_side_0_incorrectly_extends_base_class_static_side_1: { code: 2417, category: DiagnosticCategory.Error, key: "Class static side '{0}' incorrectly extends base class static side '{1}'." },
+        Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0: { code: 2419, category: DiagnosticCategory.Error, key: "Type name '{0}' in extends clause does not reference constructor function for '{0}'." },
+        Class_0_incorrectly_implements_interface_1: { code: 2420, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly implements interface '{1}'." },
+        A_class_may_only_implement_another_class_or_interface: { code: 2422, category: DiagnosticCategory.Error, key: "A class may only implement another class or interface." },
+        Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor: { code: 2423, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor." },
+        Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property: { code: 2424, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property." },
+        Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2425, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function." },
+        Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2426, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function." },
+        Interface_name_cannot_be_0: { code: 2427, category: DiagnosticCategory.Error, key: "Interface name cannot be '{0}'" },
+        All_declarations_of_an_interface_must_have_identical_type_parameters: { code: 2428, category: DiagnosticCategory.Error, key: "All declarations of an interface must have identical type parameters." },
+        Interface_0_incorrectly_extends_interface_1: { code: 2430, category: DiagnosticCategory.Error, key: "Interface '{0}' incorrectly extends interface '{1}'." },
+        Enum_name_cannot_be_0: { code: 2431, category: DiagnosticCategory.Error, key: "Enum name cannot be '{0}'" },
+        In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element: { code: 2432, category: DiagnosticCategory.Error, key: "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element." },
+        A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged: { code: 2433, category: DiagnosticCategory.Error, key: "A module declaration cannot be in a different file from a class or function with which it is merged" },
+        A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged: { code: 2434, category: DiagnosticCategory.Error, key: "A module declaration cannot be located prior to a class or function with which it is merged" },
+        Ambient_external_modules_cannot_be_nested_in_other_modules: { code: 2435, category: DiagnosticCategory.Error, key: "Ambient external modules cannot be nested in other modules." },
+        Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2436, category: DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." },
+        Module_0_is_hidden_by_a_local_declaration_with_the_same_name: { code: 2437, category: DiagnosticCategory.Error, key: "Module '{0}' is hidden by a local declaration with the same name" },
+        Import_name_cannot_be_0: { code: 2438, category: DiagnosticCategory.Error, key: "Import name cannot be '{0}'" },
+        Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: DiagnosticCategory.Error, key: "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name." },
+        Import_declaration_conflicts_with_local_declaration_of_0: { code: 2440, category: DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" },
+        Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: { code: 2441, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module." },
+        Types_have_separate_declarations_of_a_private_property_0: { code: 2442, category: DiagnosticCategory.Error, key: "Types have separate declarations of a private property '{0}'." },
+        Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2: { code: 2443, category: DiagnosticCategory.Error, key: "Property '{0}' is protected but type '{1}' is not a class derived from '{2}'." },
+        Property_0_is_protected_in_type_1_but_public_in_type_2: { code: 2444, category: DiagnosticCategory.Error, key: "Property '{0}' is protected in type '{1}' but public in type '{2}'." },
+        Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2445, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses." },
+        Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: { code: 2446, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible through an instance of class '{1}'." },
+        The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: { code: 2447, category: DiagnosticCategory.Error, key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead." },
+        Block_scoped_variable_0_used_before_its_declaration: { code: 2448, category: DiagnosticCategory.Error, key: "Block-scoped variable '{0}' used before its declaration." },
+        The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant: { code: 2449, category: DiagnosticCategory.Error, key: "The operand of an increment or decrement operator cannot be a constant." },
+        Left_hand_side_of_assignment_expression_cannot_be_a_constant: { code: 2450, category: DiagnosticCategory.Error, key: "Left-hand side of assignment expression cannot be a constant." },
+        Cannot_redeclare_block_scoped_variable_0: { code: 2451, category: DiagnosticCategory.Error, key: "Cannot redeclare block-scoped variable '{0}'." },
+        An_enum_member_cannot_have_a_numeric_name: { code: 2452, category: DiagnosticCategory.Error, key: "An enum member cannot have a numeric name." },
+        The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly: { code: 2453, category: DiagnosticCategory.Error, key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly." },
+        Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0: { code: 2455, category: DiagnosticCategory.Error, key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'." },
+        Type_alias_0_circularly_references_itself: { code: 2456, category: DiagnosticCategory.Error, key: "Type alias '{0}' circularly references itself." },
+        Type_alias_name_cannot_be_0: { code: 2457, category: DiagnosticCategory.Error, key: "Type alias name cannot be '{0}'" },
+        An_AMD_module_cannot_have_multiple_name_assignments: { code: 2458, category: DiagnosticCategory.Error, key: "An AMD module cannot have multiple name assignments." },
+        Type_0_has_no_property_1_and_no_string_index_signature: { code: 2459, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}' and no string index signature." },
+        Type_0_has_no_property_1: { code: 2460, category: DiagnosticCategory.Error, key: "Type '{0}' has no property '{1}'." },
+        Type_0_is_not_an_array_type: { code: 2461, category: DiagnosticCategory.Error, key: "Type '{0}' is not an array type." },
+        A_rest_element_must_be_last_in_an_array_destructuring_pattern: { code: 2462, category: DiagnosticCategory.Error, key: "A rest element must be last in an array destructuring pattern" },
+        A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature: { code: 2463, category: DiagnosticCategory.Error, key: "A binding pattern parameter cannot be optional in an implementation signature." },
+        A_computed_property_name_must_be_of_type_string_number_symbol_or_any: { code: 2464, category: DiagnosticCategory.Error, key: "A computed property name must be of type 'string', 'number', 'symbol', or 'any'." },
+        this_cannot_be_referenced_in_a_computed_property_name: { code: 2465, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a computed property name." },
+        super_cannot_be_referenced_in_a_computed_property_name: { code: 2466, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in a computed property name." },
+        A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type: { code: 2467, category: DiagnosticCategory.Error, key: "A computed property name cannot reference a type parameter from its containing type." },
+        Cannot_find_global_value_0: { code: 2468, category: DiagnosticCategory.Error, key: "Cannot find global value '{0}'." },
+        The_0_operator_cannot_be_applied_to_type_symbol: { code: 2469, category: DiagnosticCategory.Error, key: "The '{0}' operator cannot be applied to type 'symbol'." },
+        Symbol_reference_does_not_refer_to_the_global_Symbol_constructor_object: { code: 2470, category: DiagnosticCategory.Error, key: "'Symbol' reference does not refer to the global Symbol constructor object." },
+        A_computed_property_name_of_the_form_0_must_be_of_type_symbol: { code: 2471, category: DiagnosticCategory.Error, key: "A computed property name of the form '{0}' must be of type 'symbol'." },
+        Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher: { code: 2472, category: DiagnosticCategory.Error, key: "Spread operator in 'new' expressions is only available when targeting ECMAScript 6 and higher." },
+        Enum_declarations_must_all_be_const_or_non_const: { code: 2473, category: DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
+        In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 2474, category: DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression." },
+        const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment: { code: 2475, category: DiagnosticCategory.Error, key: "'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment." },
+        A_const_enum_member_can_only_be_accessed_using_a_string_literal: { code: 2476, category: DiagnosticCategory.Error, key: "A const enum member can only be accessed using a string literal." },
+        const_enum_member_initializer_was_evaluated_to_a_non_finite_value: { code: 2477, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to a non-finite value." },
+        const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: { code: 2478, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to disallowed value 'NaN'." },
+        Property_0_does_not_exist_on_const_enum_1: { code: 2479, category: DiagnosticCategory.Error, key: "Property '{0}' does not exist on 'const' enum '{1}'." },
+        let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations: { code: 2480, category: DiagnosticCategory.Error, key: "'let' is not allowed to be used as a name in 'let' or 'const' declarations." },
+        Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1: { code: 2481, category: DiagnosticCategory.Error, key: "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'." },
+        The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation: { code: 2483, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot use a type annotation." },
+        Export_declaration_conflicts_with_exported_declaration_of_0: { code: 2484, category: DiagnosticCategory.Error, key: "Export declaration conflicts with exported declaration of '{0}'" },
+        The_left_hand_side_of_a_for_of_statement_cannot_be_a_previously_defined_constant: { code: 2485, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...of' statement cannot be a previously defined constant." },
+        The_left_hand_side_of_a_for_in_statement_cannot_be_a_previously_defined_constant: { code: 2486, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a previously defined constant." },
+        Invalid_left_hand_side_in_for_of_statement: { code: 2487, category: DiagnosticCategory.Error, key: "Invalid left-hand side in 'for...of' statement." },
+        Type_must_have_a_Symbol_iterator_method_that_returns_an_iterator: { code: 2488, category: DiagnosticCategory.Error, key: "Type must have a '[Symbol.iterator]()' method that returns an iterator." },
+        An_iterator_must_have_a_next_method: { code: 2489, category: DiagnosticCategory.Error, key: "An iterator must have a 'next()' method." },
+        The_type_returned_by_the_next_method_of_an_iterator_must_have_a_value_property: { code: 2490, category: DiagnosticCategory.Error, key: "The type returned by the 'next()' method of an iterator must have a 'value' property." },
+        The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern: { code: 2491, category: DiagnosticCategory.Error, key: "The left-hand side of a 'for...in' statement cannot be a destructuring pattern." },
+        Cannot_redeclare_identifier_0_in_catch_clause: { code: 2492, category: DiagnosticCategory.Error, key: "Cannot redeclare identifier '{0}' in catch clause" },
+        Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2: { code: 2493, category: DiagnosticCategory.Error, key: "Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'." },
+        Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher: { code: 2494, category: DiagnosticCategory.Error, key: "Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher." },
+        Type_0_is_not_an_array_type_or_a_string_type: { code: 2495, category: DiagnosticCategory.Error, key: "Type '{0}' is not an array type or a string type." },
+        The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression: { code: 2496, category: DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an arrow function in ES3 and ES5. Consider using a standard function expression." },
+        External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct: { code: 2497, category: DiagnosticCategory.Error, key: "External module '{0}' resolves to a non-module entity and cannot be imported using this construct." },
+        External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk: { code: 2498, category: DiagnosticCategory.Error, key: "External module '{0}' uses 'export =' and cannot be used with 'export *'." },
+        An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2499, category: DiagnosticCategory.Error, key: "An interface can only extend an identifier/qualified-name with optional type arguments." },
+        A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2500, category: DiagnosticCategory.Error, key: "A class can only implement an identifier/qualified-name with optional type arguments." },
+        A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: DiagnosticCategory.Error, key: "A rest element cannot contain a binding pattern." },
+        Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
+        Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
+        Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4006, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4008, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4010, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
+        Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4012, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using private name '{1}'." },
+        Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4014, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using private name '{1}'." },
+        Type_parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4016, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using private name '{1}'." },
+        Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4019, category: DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using private name '{1}'." },
+        Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4020, category: DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using private name '{1}'." },
+        Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1: { code: 4022, category: DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using private name '{1}'." },
+        Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4023, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from external module {2} but cannot be named." },
+        Exported_variable_0_has_or_is_using_name_1_from_private_module_2: { code: 4024, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from private module '{2}'." },
+        Exported_variable_0_has_or_is_using_private_name_1: { code: 4025, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using private name '{1}'." },
+        Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4026, category: DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4027, category: DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
+        Public_static_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4028, category: DiagnosticCategory.Error, key: "Public static property '{0}' of exported class has or is using private name '{1}'." },
+        Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4029, category: DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4030, category: DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
+        Public_property_0_of_exported_class_has_or_is_using_private_name_1: { code: 4031, category: DiagnosticCategory.Error, key: "Public property '{0}' of exported class has or is using private name '{1}'." },
+        Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4032, category: DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using name '{1}' from private module '{2}'." },
+        Property_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4033, category: DiagnosticCategory.Error, key: "Property '{0}' of exported interface has or is using private name '{1}'." },
+        Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4034, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4035, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static property setter from exported class has or is using private name '{1}'." },
+        Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4036, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1: { code: 4037, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public property setter from exported class has or is using private name '{1}'." },
+        Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4038, category: DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4039, category: DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4040, category: DiagnosticCategory.Error, key: "Return type of public static property getter from exported class has or is using private name '{0}'." },
+        Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4041, category: DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4042, category: DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0: { code: 4043, category: DiagnosticCategory.Error, key: "Return type of public property getter from exported class has or is using private name '{0}'." },
+        Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4044, category: DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4045, category: DiagnosticCategory.Error, key: "Return type of constructor signature from exported interface has or is using private name '{0}'." },
+        Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4046, category: DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4047, category: DiagnosticCategory.Error, key: "Return type of call signature from exported interface has or is using private name '{0}'." },
+        Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4048, category: DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0: { code: 4049, category: DiagnosticCategory.Error, key: "Return type of index signature from exported interface has or is using private name '{0}'." },
+        Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4050, category: DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4051, category: DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0: { code: 4052, category: DiagnosticCategory.Error, key: "Return type of public static method from exported class has or is using private name '{0}'." },
+        Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4053, category: DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1: { code: 4054, category: DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0: { code: 4055, category: DiagnosticCategory.Error, key: "Return type of public method from exported class has or is using private name '{0}'." },
+        Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1: { code: 4056, category: DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0: { code: 4057, category: DiagnosticCategory.Error, key: "Return type of method from exported interface has or is using private name '{0}'." },
+        Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named: { code: 4058, category: DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from external module {1} but cannot be named." },
+        Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1: { code: 4059, category: DiagnosticCategory.Error, key: "Return type of exported function has or is using name '{0}' from private module '{1}'." },
+        Return_type_of_exported_function_has_or_is_using_private_name_0: { code: 4060, category: DiagnosticCategory.Error, key: "Return type of exported function has or is using private name '{0}'." },
+        Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4061, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4062, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1: { code: 4063, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor from exported class has or is using private name '{1}'." },
+        Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4064, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4065, category: DiagnosticCategory.Error, key: "Parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
+        Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4066, category: DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4067, category: DiagnosticCategory.Error, key: "Parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
+        Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4068, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4069, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4070, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
+        Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4071, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4072, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4073, category: DiagnosticCategory.Error, key: "Parameter '{0}' of public method from exported class has or is using private name '{1}'." },
+        Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4074, category: DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4075, category: DiagnosticCategory.Error, key: "Parameter '{0}' of method from exported interface has or is using private name '{1}'." },
+        Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4076, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named." },
+        Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 4077, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
+        Parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4078, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using private name '{1}'." },
+        Exported_type_alias_0_has_or_is_using_private_name_1: { code: 4081, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using private name '{1}'." },
+        Default_export_of_the_module_has_or_is_using_private_name_0: { code: 4082, category: DiagnosticCategory.Error, key: "Default export of the module has or is using private name '{0}'." },
+        Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher: { code: 4091, category: DiagnosticCategory.Error, key: "Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher." },
+        The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
+        Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
+        Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
+        Unsupported_file_encoding: { code: 5013, category: DiagnosticCategory.Error, key: "Unsupported file encoding." },
+        Failed_to_parse_file_0_Colon_1: { code: 5014, category: DiagnosticCategory.Error, key: "Failed to parse file '{0}': {1}." },
+        Unknown_compiler_option_0: { code: 5023, category: DiagnosticCategory.Error, key: "Unknown compiler option '{0}'." },
+        Compiler_option_0_requires_a_value_of_type_1: { code: 5024, category: DiagnosticCategory.Error, key: "Compiler option '{0}' requires a value of type {1}." },
+        Could_not_write_file_0_Colon_1: { code: 5033, category: DiagnosticCategory.Error, key: "Could not write file '{0}': {1}" },
+        Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5038, category: DiagnosticCategory.Error, key: "Option 'mapRoot' cannot be specified without specifying 'sourcemap' option." },
+        Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option: { code: 5039, category: DiagnosticCategory.Error, key: "Option 'sourceRoot' cannot be specified without specifying 'sourcemap' option." },
+        Option_noEmit_cannot_be_specified_with_option_out_or_outDir: { code: 5040, category: DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'out' or 'outDir'." },
+        Option_noEmit_cannot_be_specified_with_option_declaration: { code: 5041, category: DiagnosticCategory.Error, key: "Option 'noEmit' cannot be specified with option 'declaration'." },
+        Option_project_cannot_be_mixed_with_source_files_on_a_command_line: { code: 5042, category: DiagnosticCategory.Error, key: "Option 'project' cannot be mixed with source files on a command line." },
+        Option_sourceMap_cannot_be_specified_with_option_separateCompilation: { code: 5043, category: DiagnosticCategory.Error, key: "Option 'sourceMap' cannot be specified with option 'separateCompilation'." },
+        Option_declaration_cannot_be_specified_with_option_separateCompilation: { code: 5044, category: DiagnosticCategory.Error, key: "Option 'declaration' cannot be specified with option 'separateCompilation'." },
+        Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation: { code: 5045, category: DiagnosticCategory.Error, key: "Option 'noEmitOnError' cannot be specified with option 'separateCompilation'." },
+        Option_out_cannot_be_specified_with_option_separateCompilation: { code: 5046, category: DiagnosticCategory.Error, key: "Option 'out' cannot be specified with option 'separateCompilation'." },
+        Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher: { code: 5047, category: DiagnosticCategory.Error, key: "Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher." },
+        Concatenate_and_emit_output_to_single_file: { code: 6001, category: DiagnosticCategory.Message, key: "Concatenate and emit output to single file." },
+        Generates_corresponding_d_ts_file: { code: 6002, category: DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." },
+        Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." },
+        Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations: { code: 6004, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate TypeScript files instead of source locations." },
+        Watch_input_files: { code: 6005, category: DiagnosticCategory.Message, key: "Watch input files." },
+        Redirect_output_structure_to_the_directory: { code: 6006, category: DiagnosticCategory.Message, key: "Redirect output structure to the directory." },
+        Do_not_erase_const_enum_declarations_in_generated_code: { code: 6007, category: DiagnosticCategory.Message, key: "Do not erase const enum declarations in generated code." },
+        Do_not_emit_outputs_if_any_type_checking_errors_were_reported: { code: 6008, category: DiagnosticCategory.Message, key: "Do not emit outputs if any type checking errors were reported." },
+        Do_not_emit_comments_to_output: { code: 6009, category: DiagnosticCategory.Message, key: "Do not emit comments to output." },
+        Do_not_emit_outputs: { code: 6010, category: DiagnosticCategory.Message, key: "Do not emit outputs." },
+        Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental: { code: 6015, category: DiagnosticCategory.Message, key: "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)" },
+        Specify_module_code_generation_Colon_commonjs_amd_or_umd: { code: 6016, category: DiagnosticCategory.Message, key: "Specify module code generation: 'commonjs', 'amd', or 'umd'." },
+        Print_this_message: { code: 6017, category: DiagnosticCategory.Message, key: "Print this message." },
+        Print_the_compiler_s_version: { code: 6019, category: DiagnosticCategory.Message, key: "Print the compiler's version." },
+        Compile_the_project_in_the_given_directory: { code: 6020, category: DiagnosticCategory.Message, key: "Compile the project in the given directory." },
+        Syntax_Colon_0: { code: 6023, category: DiagnosticCategory.Message, key: "Syntax: {0}" },
+        options: { code: 6024, category: DiagnosticCategory.Message, key: "options" },
+        file: { code: 6025, category: DiagnosticCategory.Message, key: "file" },
+        Examples_Colon_0: { code: 6026, category: DiagnosticCategory.Message, key: "Examples: {0}" },
+        Options_Colon: { code: 6027, category: DiagnosticCategory.Message, key: "Options:" },
+        Version_0: { code: 6029, category: DiagnosticCategory.Message, key: "Version {0}" },
+        Insert_command_line_options_and_files_from_a_file: { code: 6030, category: DiagnosticCategory.Message, key: "Insert command line options and files from a file." },
+        File_change_detected_Starting_incremental_compilation: { code: 6032, category: DiagnosticCategory.Message, key: "File change detected. Starting incremental compilation..." },
+        KIND: { code: 6034, category: DiagnosticCategory.Message, key: "KIND" },
+        FILE: { code: 6035, category: DiagnosticCategory.Message, key: "FILE" },
+        VERSION: { code: 6036, category: DiagnosticCategory.Message, key: "VERSION" },
+        LOCATION: { code: 6037, category: DiagnosticCategory.Message, key: "LOCATION" },
+        DIRECTORY: { code: 6038, category: DiagnosticCategory.Message, key: "DIRECTORY" },
+        Compilation_complete_Watching_for_file_changes: { code: 6042, category: DiagnosticCategory.Message, key: "Compilation complete. Watching for file changes." },
+        Generates_corresponding_map_file: { code: 6043, category: DiagnosticCategory.Message, key: "Generates corresponding '.map' file." },
+        Compiler_option_0_expects_an_argument: { code: 6044, category: DiagnosticCategory.Error, key: "Compiler option '{0}' expects an argument." },
+        Unterminated_quoted_string_in_response_file_0: { code: 6045, category: DiagnosticCategory.Error, key: "Unterminated quoted string in response file '{0}'." },
+        Argument_for_module_option_must_be_commonjs_amd_or_umd: { code: 6046, category: DiagnosticCategory.Error, key: "Argument for '--module' option must be 'commonjs', 'amd', or 'umd'." },
+        Argument_for_target_option_must_be_ES3_ES5_or_ES6: { code: 6047, category: DiagnosticCategory.Error, key: "Argument for '--target' option must be 'ES3', 'ES5', or 'ES6'." },
+        Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1: { code: 6048, category: DiagnosticCategory.Error, key: "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'." },
+        Unsupported_locale_0: { code: 6049, category: DiagnosticCategory.Error, key: "Unsupported locale '{0}'." },
+        Unable_to_open_file_0: { code: 6050, category: DiagnosticCategory.Error, key: "Unable to open file '{0}'." },
+        Corrupted_locale_file_0: { code: 6051, category: DiagnosticCategory.Error, key: "Corrupted locale file {0}." },
+        Raise_error_on_expressions_and_declarations_with_an_implied_any_type: { code: 6052, category: DiagnosticCategory.Message, key: "Raise error on expressions and declarations with an implied 'any' type." },
+        File_0_not_found: { code: 6053, category: DiagnosticCategory.Error, key: "File '{0}' not found." },
+        File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." },
+        Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." },
+        Do_not_emit_declarations_for_code_that_has_an_internal_annotation: { code: 6056, category: DiagnosticCategory.Message, key: "Do not emit declarations for code that has an '@internal' annotation." },
+        Preserve_new_lines_when_emitting_code: { code: 6057, category: DiagnosticCategory.Message, key: "Preserve new-lines when emitting code." },
+        Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir: { code: 6058, category: DiagnosticCategory.Message, key: "Specifies the root directory of input files. Use to control the output directory structure with --outDir." },
+        File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files: { code: 6059, category: DiagnosticCategory.Error, key: "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files." },
+        Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
+        Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
+        Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },
+        new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type: { code: 7009, category: DiagnosticCategory.Error, key: "'new' expression, whose target lacks a construct signature, implicitly has an 'any' type." },
+        _0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type: { code: 7010, category: DiagnosticCategory.Error, key: "'{0}', which lacks return-type annotation, implicitly has an '{1}' return type." },
+        Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type: { code: 7011, category: DiagnosticCategory.Error, key: "Function expression, which lacks return-type annotation, implicitly has an '{0}' return type." },
+        Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7013, category: DiagnosticCategory.Error, key: "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type." },
+        Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation: { code: 7016, category: DiagnosticCategory.Error, key: "Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation." },
+        Index_signature_of_object_type_implicitly_has_an_any_type: { code: 7017, category: DiagnosticCategory.Error, key: "Index signature of object type implicitly has an 'any' type." },
+        Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
+        Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
+        Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
+        _0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 7021, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation." },
+        _0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer: { code: 7022, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer." },
+        _0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7023, category: DiagnosticCategory.Error, key: "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
+        Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
+        You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
+        You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: { code: 8001, category: DiagnosticCategory.Error, key: "You cannot rename elements that are defined in the standard TypeScript library." },
+        import_can_only_be_used_in_a_ts_file: { code: 8002, category: DiagnosticCategory.Error, key: "'import ... =' can only be used in a .ts file." },
+        export_can_only_be_used_in_a_ts_file: { code: 8003, category: DiagnosticCategory.Error, key: "'export=' can only be used in a .ts file." },
+        type_parameter_declarations_can_only_be_used_in_a_ts_file: { code: 8004, category: DiagnosticCategory.Error, key: "'type parameter declarations' can only be used in a .ts file." },
+        implements_clauses_can_only_be_used_in_a_ts_file: { code: 8005, category: DiagnosticCategory.Error, key: "'implements clauses' can only be used in a .ts file." },
+        interface_declarations_can_only_be_used_in_a_ts_file: { code: 8006, category: DiagnosticCategory.Error, key: "'interface declarations' can only be used in a .ts file." },
+        module_declarations_can_only_be_used_in_a_ts_file: { code: 8007, category: DiagnosticCategory.Error, key: "'module declarations' can only be used in a .ts file." },
+        type_aliases_can_only_be_used_in_a_ts_file: { code: 8008, category: DiagnosticCategory.Error, key: "'type aliases' can only be used in a .ts file." },
+        _0_can_only_be_used_in_a_ts_file: { code: 8009, category: DiagnosticCategory.Error, key: "'{0}' can only be used in a .ts file." },
+        types_can_only_be_used_in_a_ts_file: { code: 8010, category: DiagnosticCategory.Error, key: "'types' can only be used in a .ts file." },
+        type_arguments_can_only_be_used_in_a_ts_file: { code: 8011, category: DiagnosticCategory.Error, key: "'type arguments' can only be used in a .ts file." },
+        parameter_modifiers_can_only_be_used_in_a_ts_file: { code: 8012, category: DiagnosticCategory.Error, key: "'parameter modifiers' can only be used in a .ts file." },
+        can_only_be_used_in_a_ts_file: { code: 8013, category: DiagnosticCategory.Error, key: "'?' can only be used in a .ts file." },
+        property_declarations_can_only_be_used_in_a_ts_file: { code: 8014, category: DiagnosticCategory.Error, key: "'property declarations' can only be used in a .ts file." },
+        enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." },
+        type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." },
+        decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." },
+        yield_expressions_are_not_currently_supported: { code: 9000, category: DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
+        Generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "Generators are not currently supported." },
+        Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." },
+        class_expressions_are_not_currently_supported: { code: 9003, category: DiagnosticCategory.Error, key: "'class' expressions are not currently supported." },
+        class_declarations_are_only_supported_directly_inside_a_module_or_as_a_top_level_declaration: { code: 9004, category: DiagnosticCategory.Error, key: "'class' declarations are only supported directly inside a module or as a top level declaration." },
+    };
+}
diff --git a/lib/typescript/compiler/diagnosticMessages.json b/lib/typescript/compiler/diagnosticMessages.json
new file mode 100644
index 000000000..583b05fcc
--- /dev/null
+++ b/lib/typescript/compiler/diagnosticMessages.json
@@ -0,0 +1,2146 @@
+{
+    "Unterminated string literal.": {
+        "category": "Error",
+        "code": 1002
+    },
+    "Identifier expected.": {
+        "category": "Error",
+        "code": 1003
+    },
+    "'{0}' expected.": {
+        "category": "Error",
+        "code": 1005
+    },
+    "A file cannot have a reference to itself.": {
+        "category": "Error",
+        "code": 1006
+    },
+    "Trailing comma not allowed.": {
+        "category": "Error",
+        "code": 1009
+    },
+    "'*/' expected.": {
+        "category": "Error",
+        "code": 1010
+    },
+    "Unexpected token.": {
+        "category": "Error",
+        "code": 1012
+    },
+    "A rest parameter must be last in a parameter list.": {
+        "category": "Error",
+        "code": 1014
+    },
+    "Parameter cannot have question mark and initializer.": {
+        "category": "Error",
+        "code": 1015
+    },
+    "A required parameter cannot follow an optional parameter.": {
+        "category": "Error",
+        "code": 1016
+    },
+    "An index signature cannot have a rest parameter.": {
+        "category": "Error",
+        "code": 1017
+    },
+    "An index signature parameter cannot have an accessibility modifier.": {
+        "category": "Error",
+        "code": 1018
+    },
+    "An index signature parameter cannot have a question mark.": {
+        "category": "Error",
+        "code": 1019
+    },
+    "An index signature parameter cannot have an initializer.": {
+        "category": "Error",
+        "code": 1020
+    },
+    "An index signature must have a type annotation.": {
+        "category": "Error",
+        "code": 1021
+    },
+    "An index signature parameter must have a type annotation.": {
+        "category": "Error",
+        "code": 1022
+    },
+    "An index signature parameter type must be 'string' or 'number'.": {
+        "category": "Error",
+        "code": 1023
+    },
+    "A class or interface declaration can only have one 'extends' clause.": {
+        "category": "Error",
+        "code": 1024
+    },
+    "An 'extends' clause must precede an 'implements' clause.": {
+        "category": "Error",
+        "code": 1025
+    },
+    "A class can only extend a single class.": {
+        "category": "Error",
+        "code": 1026
+    },
+    "A class declaration can only have one 'implements' clause.": {
+        "category": "Error",
+        "code": 1027
+    },
+    "Accessibility modifier already seen.": {
+        "category": "Error",
+        "code": 1028
+    },
+    "'{0}' modifier must precede '{1}' modifier.": {
+        "category": "Error",
+        "code": 1029
+    },
+    "'{0}' modifier already seen.": {
+        "category": "Error",
+        "code": 1030
+    },
+    "'{0}' modifier cannot appear on a class element.": {
+        "category": "Error",
+        "code": 1031
+    },
+    "An interface declaration cannot have an 'implements' clause.": {
+        "category": "Error",
+        "code": 1032
+    },
+    "'super' must be followed by an argument list or member access.": {
+        "category": "Error",
+        "code": 1034
+    },
+    "Only ambient modules can use quoted names.": {
+        "category": "Error",
+        "code": 1035
+    },
+    "Statements are not allowed in ambient contexts.": {
+        "category": "Error",
+        "code": 1036
+    },
+    "A 'declare' modifier cannot be used in an already ambient context.": {
+        "category": "Error",
+        "code": 1038
+    },
+    "Initializers are not allowed in ambient contexts.": {
+        "category": "Error",
+        "code": 1039
+    },
+    "'{0}' modifier cannot appear on a module element.": {
+        "category": "Error",
+        "code": 1044
+    },
+    "A 'declare' modifier cannot be used with an interface declaration.": {
+        "category": "Error",
+        "code": 1045
+    },
+    "A 'declare' modifier is required for a top level declaration in a .d.ts file.": {
+        "category": "Error",
+        "code": 1046
+    },
+    "A rest parameter cannot be optional.": {
+        "category": "Error",
+        "code": 1047
+    },
+    "A rest parameter cannot have an initializer.": {
+        "category": "Error",
+        "code": 1048
+    },
+    "A 'set' accessor must have exactly one parameter.": {
+        "category": "Error",
+        "code": 1049
+    },
+    "A 'set' accessor cannot have an optional parameter.": {
+        "category": "Error",
+        "code": 1051
+    },
+    "A 'set' accessor parameter cannot have an initializer.": {
+        "category": "Error",
+        "code": 1052
+    },
+    "A 'set' accessor cannot have rest parameter.": {
+        "category": "Error",
+        "code": 1053
+    },
+    "A 'get' accessor cannot have parameters.": {
+        "category": "Error",
+        "code": 1054
+    },
+    "Accessors are only available when targeting ECMAScript 5 and higher.": {
+        "category": "Error",
+        "code": 1056
+    },
+    "Enum member must have initializer.": {
+        "category": "Error",
+        "code": 1061
+    },
+    "An export assignment cannot be used in an internal module.": {
+        "category": "Error",
+        "code": 1063
+    },
+    "Ambient enum elements can only have integer literal initializers.": {
+        "category": "Error",
+        "code": 1066
+    },
+    "Unexpected token. A constructor, method, accessor, or property was expected.": {
+        "category": "Error",
+        "code": 1068
+    },
+    "A 'declare' modifier cannot be used with an import declaration.": {
+        "category": "Error",
+        "code": 1079
+    },
+    "Invalid 'reference' directive syntax.": {
+        "category": "Error",
+        "code": 1084
+    },
+    "Octal literals are not available when targeting ECMAScript 5 and higher.": {
+        "category": "Error",
+        "code": 1085
+    },
+    "An accessor cannot be declared in an ambient context.": {
+        "category": "Error",
+        "code": 1086
+    },
+    "'{0}' modifier cannot appear on a constructor declaration.": {
+        "category": "Error",
+        "code": 1089
+    },
+    "'{0}' modifier cannot appear on a parameter.": {
+        "category": "Error",
+        "code": 1090
+    },
+    "Only a single variable declaration is allowed in a 'for...in' statement.": {
+        "category": "Error",
+        "code": 1091
+    },
+    "Type parameters cannot appear on a constructor declaration.": {
+        "category": "Error",
+        "code": 1092
+    },
+    "Type annotation cannot appear on a constructor declaration.": {
+        "category": "Error",
+        "code": 1093
+    },
+    "An accessor cannot have type parameters.": {
+        "category": "Error",
+        "code": 1094
+    },
+    "A 'set' accessor cannot have a return type annotation.": {
+        "category": "Error",
+        "code": 1095
+    },
+    "An index signature must have exactly one parameter.": {
+        "category": "Error",
+        "code": 1096
+    },
+    "'{0}' list cannot be empty.": {
+        "category": "Error",
+        "code": 1097
+    },
+    "Type parameter list cannot be empty.": {
+        "category": "Error",
+        "code": 1098
+    },
+    "Type argument list cannot be empty.": {
+        "category": "Error",
+        "code": 1099
+    },
+    "Invalid use of '{0}' in strict mode.": {
+        "category": "Error",
+        "code": 1100
+    },
+    "'with' statements are not allowed in strict mode.": {
+        "category": "Error",
+        "code": 1101
+    },
+    "'delete' cannot be called on an identifier in strict mode.": {
+        "category": "Error",
+        "code": 1102
+    },
+    "A 'continue' statement can only be used within an enclosing iteration statement.": {
+        "category": "Error",
+        "code": 1104
+    },
+    "A 'break' statement can only be used within an enclosing iteration or switch statement.": {
+        "category": "Error",
+        "code": 1105
+    },
+    "Jump target cannot cross function boundary.": {
+        "category": "Error",
+        "code": 1107
+    },
+    "A 'return' statement can only be used within a function body.": {
+        "category": "Error",
+        "code": 1108
+    },
+    "Expression expected.": {
+        "category": "Error",
+        "code": 1109
+    },
+    "Type expected.": {
+        "category": "Error",
+        "code": 1110
+    },
+    "A class member cannot be declared optional.": {
+        "category": "Error",
+        "code": 1112
+    },
+    "A 'default' clause cannot appear more than once in a 'switch' statement.": {
+        "category": "Error",
+        "code": 1113
+    },
+    "Duplicate label '{0}'": {
+        "category": "Error",
+        "code": 1114
+    },
+    "A 'continue' statement can only jump to a label of an enclosing iteration statement.": {
+        "category": "Error",
+        "code": 1115
+    },
+    "A 'break' statement can only jump to a label of an enclosing statement.": {
+        "category": "Error",
+        "code": 1116
+    },
+    "An object literal cannot have multiple properties with the same name in strict mode.": {
+        "category": "Error",
+        "code": 1117
+    },
+    "An object literal cannot have multiple get/set accessors with the same name.": {
+        "category": "Error",
+        "code": 1118
+    },
+    "An object literal cannot have property and accessor with the same name.": {
+        "category": "Error",
+        "code": 1119
+    },
+    "An export assignment cannot have modifiers.": {
+        "category": "Error",
+        "code": 1120
+    },
+    "Octal literals are not allowed in strict mode.": {
+        "category": "Error",
+        "code": 1121
+    },
+    "A tuple type element list cannot be empty.": {
+        "category": "Error",
+        "code": 1122
+    },
+    "Variable declaration list cannot be empty.": {
+        "category": "Error",
+        "code": 1123
+    },
+    "Digit expected.": {
+        "category": "Error",
+        "code": 1124
+    },
+    "Hexadecimal digit expected.": {
+        "category": "Error",
+        "code": 1125
+    },
+    "Unexpected end of text.": {
+        "category": "Error",
+        "code": 1126
+    },
+    "Invalid character.": {
+        "category": "Error",
+        "code": 1127
+    },
+    "Declaration or statement expected.": {
+        "category": "Error",
+        "code": 1128
+    },
+    "Statement expected.": {
+        "category": "Error",
+        "code": 1129
+    },
+    "'case' or 'default' expected.": {
+        "category": "Error",
+        "code": 1130
+    },
+    "Property or signature expected.": {
+        "category": "Error",
+        "code": 1131
+    },
+    "Enum member expected.": {
+        "category": "Error",
+        "code": 1132
+    },
+    "Type reference expected.": {
+        "category": "Error",
+        "code": 1133
+    },
+    "Variable declaration expected.": {
+        "category": "Error",
+        "code": 1134
+    },
+    "Argument expression expected.": {
+        "category": "Error",
+        "code": 1135
+    },
+    "Property assignment expected.": {
+        "category": "Error",
+        "code": 1136
+    },
+    "Expression or comma expected.": {
+        "category": "Error",
+        "code": 1137
+    },
+    "Parameter declaration expected.": {
+        "category": "Error",
+        "code": 1138
+    },
+    "Type parameter declaration expected.": {
+        "category": "Error",
+        "code": 1139
+    },
+    "Type argument expected.": {
+        "category": "Error",
+        "code": 1140
+    },
+    "String literal expected.": {
+        "category": "Error",
+        "code": 1141
+    },
+    "Line break not permitted here.": {
+        "category": "Error",
+        "code": 1142
+    },
+    "'{' or ';' expected.": {
+        "category": "Error",
+        "code": 1144
+    },
+    "Modifiers not permitted on index signature members.": {
+        "category": "Error",
+        "code": 1145
+    },
+    "Declaration expected.": {
+        "category": "Error",
+        "code": 1146
+    },
+    "Import declarations in an internal module cannot reference an external module.": {
+        "category": "Error",
+        "code": 1147
+    },
+    "Cannot compile external modules unless the '--module' flag is provided.": {
+        "category": "Error",
+        "code": 1148
+    },
+    "File name '{0}' differs from already included file name '{1}' only in casing": {
+        "category": "Error",
+        "code": 1149
+    },
+    "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead.": {
+        "category": "Error",
+        "code": 1150
+    },
+    "'var', 'let' or 'const' expected.": {
+        "category": "Error",
+        "code": 1152
+    },
+    "'let' declarations are only available when targeting ECMAScript 6 and higher.": {
+        "category": "Error",
+        "code": 1153
+    },
+    "'const' declarations are only available when targeting ECMAScript 6 and higher.": {
+        "category": "Error",
+        "code": 1154
+    },
+    "'const' declarations must be initialized": {
+        "category": "Error",
+        "code": 1155
+    },
+    "'const' declarations can only be declared inside a block.": {
+        "category": "Error",
+        "code": 1156
+    },
+    "'let' declarations can only be declared inside a block.": {
+        "category": "Error",
+        "code": 1157
+    },
+    "Unterminated template literal.": {
+        "category": "Error",
+        "code": 1160
+    },
+    "Unterminated regular expression literal.": {
+        "category": "Error",
+        "code": 1161
+    },
+    "An object member cannot be declared optional.": {
+        "category": "Error",
+        "code": 1162
+    },
+    "'yield' expression must be contained_within a generator declaration.": {
+        "category": "Error",
+        "code": 1163
+    },
+    "Computed property names are not allowed in enums.": {
+        "category": "Error",
+        "code": 1164
+    },
+    "A computed property name in an ambient context must directly refer to a built-in symbol.": {
+        "category": "Error",
+        "code": 1165
+    },
+    "A computed property name in a class property declaration must directly refer to a built-in symbol.": {
+        "category": "Error",
+        "code": 1166
+    },
+    "Computed property names are only available when targeting ECMAScript 6 and higher.": {
+        "category": "Error",
+        "code": 1167
+    },
+    "A computed property name in a method overload must directly refer to a built-in symbol.": {
+        "category": "Error",
+        "code": 1168
+    },
+    "A computed property name in an interface must directly refer to a built-in symbol.": {
+        "category": "Error",
+        "code": 1169
+    },
+    "A computed property name in a type literal must directly refer to a built-in symbol.": {
+        "category": "Error",
+        "code": 1170
+    },
+    "A comma expression is not allowed in a computed property name.": {
+        "category": "Error",
+        "code": 1171
+    },
+    "'extends' clause already seen.": {
+        "category": "Error",
+        "code": 1172
+    },
+    "'extends' clause must precede 'implements' clause.": {
+        "category": "Error",
+        "code": 1173
+    },
+    "Classes can only extend a single class.": {
+        "category": "Error",
+        "code": 1174
+    },
+    "'implements' clause already seen.": {
+        "category": "Error",
+        "code": 1175
+    },
+    "Interface declaration cannot have 'implements' clause.": {
+        "category": "Error",
+        "code": 1176
+    },
+    "Binary digit expected.": {
+        "category": "Error",
+        "code": 1177
+    },
+    "Octal digit expected.": {
+        "category": "Error",
+        "code": 1178
+    },
+    "Unexpected token. '{' expected.": {
+        "category": "Error",
+        "code": 1179
+    },
+    "Property destructuring pattern expected.": {
+        "category": "Error",
+        "code": 1180
+    },
+    "Array element destructuring pattern expected.": {
+        "category": "Error",
+        "code": 1181
+    },
+    "A destructuring declaration must have an initializer.": {
+        "category": "Error",
+        "code": 1182
+    },
+    "Destructuring declarations are not allowed in ambient contexts.": {
+        "category": "Error",
+        "code": 1183
+    },
+    "An implementation cannot be declared in ambient contexts.": {
+        "category": "Error",
+        "code": 1184
+    },
+    "Modifiers cannot appear here.": {
+        "category": "Error",
+        "code": 1184
+    },
+    "Merge conflict marker encountered.": {
+        "category": "Error",
+        "code": 1185
+    },
+    "A rest element cannot have an initializer.": {
+        "category": "Error",
+        "code": 1186
+    },
+    "A parameter property may not be a binding pattern.": {
+        "category": "Error",
+        "code": 1187
+    },
+    "Only a single variable declaration is allowed in a 'for...of' statement.": {
+        "category": "Error",
+        "code": 1188
+    },
+    "The variable declaration of a 'for...in' statement cannot have an initializer.": {
+        "category": "Error",
+        "code": 1189
+    },
+    "The variable declaration of a 'for...of' statement cannot have an initializer.": {
+        "category": "Error",
+        "code": 1190
+    },
+    "An import declaration cannot have modifiers.": {
+        "category": "Error",
+        "code": 1191
+    },
+    "External module '{0}' has no default export.": {
+        "category": "Error",
+        "code": 1192
+    },
+    "An export declaration cannot have modifiers.": {
+        "category": "Error",
+        "code": 1193
+    },
+    "Export declarations are not permitted in an internal module.": {
+        "category": "Error",
+        "code": 1194
+    },
+    "Catch clause variable name must be an identifier.": {
+        "category": "Error",
+        "code": 1195
+    },
+    "Catch clause variable cannot have a type annotation.": {
+        "category": "Error",
+        "code": 1196
+    },
+    "Catch clause variable cannot have an initializer.": {
+        "category": "Error",
+        "code": 1197
+    },
+    "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive.": {
+        "category": "Error",
+        "code": 1198
+    },
+    "Unterminated Unicode escape sequence.": {
+        "category": "Error",
+        "code": 1199
+    },
+    "Line terminator not permitted before arrow.": {
+        "category": "Error",
+        "code": 1200
+    },
+    "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead.": {
+        "category": "Error",
+        "code": 1202
+    },
+    "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead.": {
+        "category": "Error",
+        "code": 1203
+    },
+    "Cannot compile external modules into 'amd', 'commonjs' or 'umd' when targeting 'ES6' or higher.": {
+        "category": "Error",
+        "code": 1204
+    },
+    "Decorators are only available when targeting ECMAScript 5 and higher.": {
+        "category": "Error",
+        "code": 1205
+    },
+    "Decorators are not valid here.": {
+        "category": "Error",
+        "code": 1206
+    },
+    "Decorators cannot be applied to multiple get/set accessors of the same name.": {
+        "category": "Error",
+        "code": 1207
+    },
+    "Cannot compile non-external modules when the '--separateCompilation' flag is provided.": {
+        "category": "Error",
+        "code": 1208
+    },
+    "Ambient const enums are not allowed when the '--separateCompilation' flag is provided.": {
+        "category": "Error",
+        "code": 1209
+    },
+    "Invalid use of '{0}'. Class definitions are automatically in strict mode.": {
+        "category": "Error",
+        "code": 1210
+    },
+    "A class declaration without the 'default' modifier must have a name": {
+        "category": "Error",
+        "code": 1211
+    },
+    "Identifier expected. '{0}' is a reserved word in strict mode": {
+        "category": "Error",
+        "code": 1212
+    },
+    "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode.": {
+        "category": "Error",
+        "code": 1213
+    },
+    "Identifier expected. '{0}' is a reserved word in strict mode. External Module is automatically in strict mode.": {
+        "category": "Error",
+        "code": 1214
+    },
+    "Type expected. '{0}' is a reserved word in strict mode": {
+        "category": "Error",
+        "code": 1215
+    },
+    "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode.": {
+        "category": "Error",
+        "code": 1216
+    },
+    "Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode.": {
+        "category": "Error",
+        "code": 1217
+    },
+    "Duplicate identifier '{0}'.": {
+        "category": "Error",
+        "code": 2300
+    },
+    "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor.": {
+        "category": "Error",
+        "code": 2301
+    },
+    "Static members cannot reference class type parameters.": {
+        "category": "Error",
+        "code": 2302
+    },
+    "Circular definition of import alias '{0}'.": {
+        "category": "Error",
+        "code": 2303
+    },
+    "Cannot find name '{0}'.": {
+        "category": "Error",
+        "code": 2304
+    },
+    "Module '{0}' has no exported member '{1}'.": {
+        "category": "Error",
+        "code": 2305
+    },
+    "File '{0}' is not an external module.": {
+        "category": "Error",
+        "code": 2306
+    },
+    "Cannot find external module '{0}'.": {
+        "category": "Error",
+        "code": 2307
+    },
+    "A module cannot have more than one export assignment.": {
+        "category": "Error",
+        "code": 2308
+    },
+    "An export assignment cannot be used in a module with other exported elements.": {
+        "category": "Error",
+        "code": 2309
+    },
+    "Type '{0}' recursively references itself as a base type.": {
+        "category": "Error",
+        "code": 2310
+    },
+    "A class may only extend another class.": {
+        "category": "Error",
+        "code": 2311
+    },
+    "An interface may only extend a class or another interface.": {
+        "category": "Error",
+        "code": 2312
+    },
+    "Constraint of a type parameter cannot reference any type parameter from the same type parameter list.": {
+        "category": "Error",
+        "code": 2313
+    },
+    "Generic type '{0}' requires {1} type argument(s).": {
+        "category": "Error",
+        "code": 2314
+    },
+    "Type '{0}' is not generic.": {
+        "category": "Error",
+        "code": 2315
+    },
+    "Global type '{0}' must be a class or interface type.": {
+        "category": "Error",
+        "code": 2316
+    },
+    "Global type '{0}' must have {1} type parameter(s).": {
+        "category": "Error",
+        "code": 2317
+    },
+    "Cannot find global type '{0}'.": {
+        "category": "Error",
+        "code": 2318
+    },
+    "Named property '{0}' of types '{1}' and '{2}' are not identical.": {
+        "category": "Error",
+        "code": 2319
+    },
+    "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'.": {
+        "category": "Error",
+        "code": 2320
+    },
+    "Excessive stack depth comparing types '{0}' and '{1}'.": {
+        "category": "Error",
+        "code": 2321
+    },
+    "Type '{0}' is not assignable to type '{1}'.": {
+        "category": "Error",
+        "code": 2322
+    },
+    "Property '{0}' is missing in type '{1}'.": {
+        "category": "Error",
+        "code": 2324
+    },
+    "Property '{0}' is private in type '{1}' but not in type '{2}'.": {
+        "category": "Error",
+        "code": 2325
+    },
+    "Types of property '{0}' are incompatible.": {
+        "category": "Error",
+        "code": 2326
+    },
+    "Property '{0}' is optional in type '{1}' but required in type '{2}'.": {
+        "category": "Error",
+        "code": 2327
+    },
+    "Types of parameters '{0}' and '{1}' are incompatible.": {
+        "category": "Error",
+        "code": 2328
+    },
+    "Index signature is missing in type '{0}'.": {
+        "category": "Error",
+        "code": 2329
+    },
+    "Index signatures are incompatible.": {
+        "category": "Error",
+        "code": 2330
+    },
+    "'this' cannot be referenced in a module body.": {
+        "category": "Error",
+        "code": 2331
+    },
+    "'this' cannot be referenced in current location.": {
+        "category": "Error",
+        "code": 2332
+    },
+    "'this' cannot be referenced in constructor arguments.": {
+        "category": "Error",
+        "code": 2333
+    },
+    "'this' cannot be referenced in a static property initializer.": {
+        "category": "Error",
+        "code": 2334
+    },
+    "'super' can only be referenced in a derived class.": {
+        "category": "Error",
+        "code": 2335
+    },
+    "'super' cannot be referenced in constructor arguments.": {
+        "category": "Error",
+        "code": 2336
+    },
+    "Super calls are not permitted outside constructors or in nested functions inside constructors": {
+        "category": "Error",
+        "code": 2337
+    },
+    "'super' property access is permitted only in a constructor, member function, or member accessor of a derived class": {
+        "category": "Error",
+        "code": 2338
+    },
+    "Property '{0}' does not exist on type '{1}'.": {
+        "category": "Error",
+        "code": 2339
+    },
+    "Only public and protected methods of the base class are accessible via the 'super' keyword": {
+        "category": "Error",
+        "code": 2340
+    },
+    "Property '{0}' is private and only accessible within class '{1}'.": {
+        "category": "Error",
+        "code": 2341
+    },
+    "An index expression argument must be of type 'string', 'number', 'symbol, or 'any'.": {
+        "category": "Error",
+        "code": 2342
+    },
+    "Type '{0}' does not satisfy the constraint '{1}'.": {
+        "category": "Error",
+        "code": 2344
+    },
+    "Argument of type '{0}' is not assignable to parameter of type '{1}'.": {
+        "category": "Error",
+        "code": 2345
+    },
+    "Supplied parameters do not match any signature of call target.": {
+        "category": "Error",
+        "code": 2346
+    },
+    "Untyped function calls may not accept type arguments.": {
+        "category": "Error",
+        "code": 2347
+    },
+    "Value of type '{0}' is not callable. Did you mean to include 'new'?": {
+        "category": "Error",
+        "code": 2348
+    },
+    "Cannot invoke an expression whose type lacks a call signature.": {
+        "category": "Error",
+        "code": 2349
+    },
+    "Only a void function can be called with the 'new' keyword.": {
+        "category": "Error",
+        "code": 2350
+    },
+    "Cannot use 'new' with an expression whose type lacks a call or construct signature.": {
+        "category": "Error",
+        "code": 2351
+    },
+    "Neither type '{0}' nor type '{1}' is assignable to the other.": {
+        "category": "Error",
+        "code": 2352
+    },
+    "No best common type exists among return expressions.": {
+        "category": "Error",
+        "code": 2354
+    },
+    "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.": {
+        "category": "Error",
+        "code": 2355
+    },
+    "An arithmetic operand must be of type 'any', 'number' or an enum type.": {
+        "category": "Error",
+        "code": 2356
+    },
+    "The operand of an increment or decrement operator must be a variable, property or indexer.": {
+        "category": "Error",
+        "code": 2357
+    },
+    "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.": {
+        "category": "Error",
+        "code": 2358
+    },
+    "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type.": {
+        "category": "Error",
+        "code": 2359
+    },
+    "The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.": {
+        "category": "Error",
+        "code": 2360
+    },
+    "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter": {
+        "category": "Error",
+        "code": 2361
+    },
+    "The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.": {
+        "category": "Error",
+        "code": 2362
+    },
+    "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.": {
+        "category": "Error",
+        "code": 2363
+    },
+    "Invalid left-hand side of assignment expression.": {
+        "category": "Error",
+        "code": 2364
+    },
+    "Operator '{0}' cannot be applied to types '{1}' and '{2}'.": {
+        "category": "Error",
+        "code": 2365
+    },
+    "Type parameter name cannot be '{0}'": {
+        "category": "Error",
+        "code": 2368
+    },
+    "A parameter property is only allowed in a constructor implementation.": {
+        "category": "Error",
+        "code": 2369
+    },
+    "A rest parameter must be of an array type.": {
+        "category": "Error",
+        "code": 2370
+    },
+    "A parameter initializer is only allowed in a function or constructor implementation.": {
+        "category": "Error",
+        "code": 2371
+    },
+    "Parameter '{0}' cannot be referenced in its initializer.": {
+        "category": "Error",
+        "code": 2372
+    },
+    "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it.": {
+        "category": "Error",
+        "code": 2373
+    },
+    "Duplicate string index signature.": {
+        "category": "Error",
+        "code": 2374
+    },
+    "Duplicate number index signature.": {
+        "category": "Error",
+        "code": 2375
+    },
+    "A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.": {
+        "category": "Error",
+        "code": 2376
+    },
+    "Constructors for derived classes must contain a 'super' call.": {
+        "category": "Error",
+        "code": 2377
+    },
+    "A 'get' accessor must return a value or consist of a single 'throw' statement.": {
+        "category": "Error",
+        "code": 2378
+    },
+    "Getter and setter accessors do not agree in visibility.": {
+        "category": "Error",
+        "code": 2379
+    },
+    "'get' and 'set' accessor must have the same type.": {
+        "category": "Error",
+        "code": 2380
+    },
+    "A signature with an implementation cannot use a string literal type.": {
+        "category": "Error",
+        "code": 2381
+    },
+    "Specialized overload signature is not assignable to any non-specialized signature.": {
+        "category": "Error",
+        "code": 2382
+    },
+    "Overload signatures must all be exported or not exported.": {
+        "category": "Error",
+        "code": 2383
+    },
+    "Overload signatures must all be ambient or non-ambient.": {
+        "category": "Error",
+        "code": 2384
+    },
+    "Overload signatures must all be public, private or protected.": {
+        "category": "Error",
+        "code": 2385
+    },
+    "Overload signatures must all be optional or required.": {
+        "category": "Error",
+        "code": 2386
+    },
+    "Function overload must be static.": {
+        "category": "Error",
+        "code": 2387
+    },
+    "Function overload must not be static.": {
+        "category": "Error",
+        "code": 2388
+    },
+    "Function implementation name must be '{0}'.": {
+        "category": "Error",
+        "code": 2389
+    },
+    "Constructor implementation is missing.": {
+        "category": "Error",
+        "code": 2390
+    },
+    "Function implementation is missing or not immediately following the declaration.": {
+        "category": "Error",
+        "code": 2391
+    },
+    "Multiple constructor implementations are not allowed.": {
+        "category": "Error",
+        "code": 2392
+    },
+    "Duplicate function implementation.": {
+        "category": "Error",
+        "code": 2393
+    },
+    "Overload signature is not compatible with function implementation.": {
+        "category": "Error",
+        "code": 2394
+    },
+    "Individual declarations in merged declaration {0} must be all exported or all local.": {
+        "category": "Error",
+        "code": 2395
+    },
+    "Duplicate identifier 'arguments'. Compiler uses 'arguments' to initialize rest parameters.": {
+        "category": "Error",
+        "code": 2396
+    },
+    "Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.": {
+        "category": "Error",
+        "code": 2399
+    },
+    "Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference.": {
+        "category": "Error",
+        "code": 2400
+    },
+    "Duplicate identifier '_super'. Compiler uses '_super' to capture base class reference.": {
+        "category": "Error",
+        "code": 2401
+    },
+    "Expression resolves to '_super' that compiler uses to capture base class reference.": {
+        "category": "Error",
+        "code": 2402
+    },
+    "Subsequent variable declarations must have the same type.  Variable '{0}' must be of type '{1}', but here has type '{2}'.": {
+        "category": "Error",
+        "code": 2403
+    },
+    "The left-hand side of a 'for...in' statement cannot use a type annotation.": {
+        "category": "Error",
+        "code": 2404
+    },
+    "The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.": {
+        "category": "Error",
+        "code": 2405
+    },
+    "Invalid left-hand side in 'for...in' statement.": {
+        "category": "Error",
+        "code": 2406
+    },
+    "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter.": {
+        "category": "Error",
+        "code": 2407
+    },
+    "Setters cannot return a value.": {
+        "category": "Error",
+        "code": 2408
+    },
+    "Return type of constructor signature must be assignable to the instance type of the class": {
+        "category": "Error",
+        "code": 2409
+    },
+    "All symbols within a 'with' block will be resolved to 'any'.": {
+        "category": "Error",
+        "code": 2410
+    },
+    "Property '{0}' of type '{1}' is not assignable to string index type '{2}'.": {
+        "category": "Error",
+        "code": 2411
+    },
+    "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'.": {
+        "category": "Error",
+        "code": 2412
+    },
+    "Numeric index type '{0}' is not assignable to string index type '{1}'.": {
+        "category": "Error",
+        "code": 2413
+    },
+    "Class name cannot be '{0}'": {
+        "category": "Error",
+        "code": 2414
+    },
+    "Class '{0}' incorrectly extends base class '{1}'.": {
+        "category": "Error",
+        "code": 2415
+    },
+    "Class static side '{0}' incorrectly extends base class static side '{1}'.": {
+        "category": "Error",
+        "code": 2417
+    },
+    "Type name '{0}' in extends clause does not reference constructor function for '{0}'.": {
+        "category": "Error",
+        "code": 2419
+    },
+    "Class '{0}' incorrectly implements interface '{1}'.": {
+        "category": "Error",
+        "code": 2420
+    },
+    "A class may only implement another class or interface.": {
+        "category": "Error",
+        "code": 2422
+    },
+    "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor.": {
+        "category": "Error",
+        "code": 2423
+    },
+    "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property.": {
+        "category": "Error",
+        "code": 2424
+    },
+    "Class '{0}' defines instance member property '{1}', but extended class '{2}' defines it as instance member function.": {
+        "category": "Error",
+        "code": 2425
+    },
+    "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function.": {
+        "category": "Error",
+        "code": 2426
+    },
+    "Interface name cannot be '{0}'": {
+        "category": "Error",
+        "code": 2427
+    },
+    "All declarations of an interface must have identical type parameters.": {
+        "category": "Error",
+        "code": 2428
+    },
+    "Interface '{0}' incorrectly extends interface '{1}'.": {
+        "category": "Error",
+        "code": 2430
+    },
+    "Enum name cannot be '{0}'": {
+        "category": "Error",
+        "code": 2431
+    },
+    "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element.": {
+        "category": "Error",
+        "code": 2432
+    },
+    "A module declaration cannot be in a different file from a class or function with which it is merged": {
+        "category": "Error",
+        "code": 2433
+    },
+    "A module declaration cannot be located prior to a class or function with which it is merged": {
+        "category": "Error",
+        "code": 2434
+    },
+    "Ambient external modules cannot be nested in other modules.": {
+        "category": "Error",
+        "code": 2435
+    },
+    "Ambient external module declaration cannot specify relative module name.": {
+        "category": "Error",
+        "code": 2436
+    },
+    "Module '{0}' is hidden by a local declaration with the same name": {
+        "category": "Error",
+        "code": 2437
+    },
+    "Import name cannot be '{0}'": {
+        "category": "Error",
+        "code": 2438
+    },
+    "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name.": {
+        "category": "Error",
+        "code": 2439
+    },
+    "Import declaration conflicts with local declaration of '{0}'": {
+        "category": "Error",
+        "code": 2440
+    },
+    "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module.": {
+        "category": "Error",
+        "code": 2441
+    },
+    "Types have separate declarations of a private property '{0}'.": {
+        "category": "Error",
+        "code": 2442
+    },
+    "Property '{0}' is protected but type '{1}' is not a class derived from '{2}'.": {
+        "category": "Error",
+        "code": 2443
+    },
+    "Property '{0}' is protected in type '{1}' but public in type '{2}'.": {
+        "category": "Error",
+        "code": 2444
+    },
+    "Property '{0}' is protected and only accessible within class '{1}' and its subclasses.": {
+        "category": "Error",
+        "code": 2445
+    },
+    "Property '{0}' is protected and only accessible through an instance of class '{1}'.": {
+        "category": "Error",
+        "code": 2446
+    },
+    "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead.": {
+        "category": "Error",
+        "code": 2447
+    },
+    "Block-scoped variable '{0}' used before its declaration.": {
+        "category": "Error",
+        "code": 2448
+    },
+    "The operand of an increment or decrement operator cannot be a constant.": {
+        "category": "Error",
+        "code": 2449
+    },
+    "Left-hand side of assignment expression cannot be a constant.": {
+        "category": "Error",
+        "code": 2450
+    },
+    "Cannot redeclare block-scoped variable '{0}'.": {
+        "category": "Error",
+        "code": 2451
+    },
+    "An enum member cannot have a numeric name.": {
+        "category": "Error",
+        "code": 2452
+    },
+    "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly.": {
+        "category": "Error",
+        "code": 2453
+    },
+    "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'.": {
+        "category": "Error",
+        "code": 2455
+    },
+    "Type alias '{0}' circularly references itself.": {
+        "category": "Error",
+        "code": 2456
+    },
+    "Type alias name cannot be '{0}'": {
+        "category": "Error",
+        "code": 2457
+    },
+    "An AMD module cannot have multiple name assignments.": {
+        "category": "Error",
+        "code": 2458
+    },
+    "Type '{0}' has no property '{1}' and no string index signature.": {
+        "category": "Error",
+        "code": 2459
+    },
+    "Type '{0}' has no property '{1}'.": {
+        "category": "Error",
+        "code": 2460
+    },
+    "Type '{0}' is not an array type.": {
+        "category": "Error",
+        "code": 2461
+    },
+    "A rest element must be last in an array destructuring pattern": {
+        "category": "Error",
+        "code": 2462
+    },
+    "A binding pattern parameter cannot be optional in an implementation signature.": {
+        "category": "Error",
+        "code": 2463
+    },
+    "A computed property name must be of type 'string', 'number', 'symbol', or 'any'.": {
+        "category": "Error",
+        "code": 2464
+    },
+    "'this' cannot be referenced in a computed property name.": {
+        "category": "Error",
+        "code": 2465
+    },
+    "'super' cannot be referenced in a computed property name.": {
+        "category": "Error",
+        "code": 2466
+    },
+    "A computed property name cannot reference a type parameter from its containing type.": {
+        "category": "Error",
+        "code": 2467
+    },
+    "Cannot find global value '{0}'.": {
+        "category": "Error",
+        "code": 2468
+    },
+    "The '{0}' operator cannot be applied to type 'symbol'.": {
+        "category": "Error",
+        "code": 2469
+    },
+    "'Symbol' reference does not refer to the global Symbol constructor object.": {
+        "category": "Error",
+        "code": 2470
+    },
+    "A computed property name of the form '{0}' must be of type 'symbol'.": {
+        "category": "Error",
+        "code": 2471
+    },
+    "Spread operator in 'new' expressions is only available when targeting ECMAScript 6 and higher.": {
+        "category": "Error",
+        "code": 2472
+    },
+    "Enum declarations must all be const or non-const.": {
+        "category": "Error",
+        "code": 2473
+    },
+    "In 'const' enum declarations member initializer must be constant expression.": {
+        "category": "Error",
+        "code": 2474
+    },
+    "'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment.": {
+        "category": "Error",
+        "code": 2475
+    },
+    "A const enum member can only be accessed using a string literal.": {
+        "category": "Error",
+        "code": 2476
+    },
+    "'const' enum member initializer was evaluated to a non-finite value.": {
+        "category": "Error",
+        "code": 2477
+    },
+    "'const' enum member initializer was evaluated to disallowed value 'NaN'.": {
+        "category": "Error",
+        "code": 2478
+    },
+    "Property '{0}' does not exist on 'const' enum '{1}'.": {
+        "category": "Error",
+        "code": 2479
+    },
+    "'let' is not allowed to be used as a name in 'let' or 'const' declarations.": {
+        "category": "Error",
+        "code": 2480
+    },
+    "Cannot initialize outer scoped variable '{0}' in the same scope as block scoped declaration '{1}'.": {
+        "category": "Error",
+        "code": 2481
+    },
+    "The left-hand side of a 'for...of' statement cannot use a type annotation.": {
+        "category": "Error",
+        "code": 2483
+    },
+    "Export declaration conflicts with exported declaration of '{0}'": {
+        "category": "Error",
+        "code": 2484
+    },
+    "The left-hand side of a 'for...of' statement cannot be a previously defined constant.": {
+        "category": "Error",
+        "code": 2485
+    },
+    "The left-hand side of a 'for...in' statement cannot be a previously defined constant.": {
+        "category": "Error",
+        "code": 2486
+    },
+    "Invalid left-hand side in 'for...of' statement.": {
+        "category": "Error",
+        "code": 2487
+    },
+    "Type must have a '[Symbol.iterator]()' method that returns an iterator.": {
+        "category": "Error",
+        "code": 2488
+    },
+    "An iterator must have a 'next()' method.": {
+        "category": "Error",
+        "code": 2489
+    },
+    "The type returned by the 'next()' method of an iterator must have a 'value' property.": {
+        "category": "Error",
+        "code": 2490
+    },
+    "The left-hand side of a 'for...in' statement cannot be a destructuring pattern.": {
+        "category": "Error",
+        "code": 2491
+    },
+    "Cannot redeclare identifier '{0}' in catch clause": {
+        "category": "Error",
+        "code": 2492
+    },
+    "Tuple type '{0}' with length '{1}' cannot be assigned to tuple with length '{2}'.": {
+        "category": "Error",
+        "code": 2493
+    },
+    "Using a string in a 'for...of' statement is only supported in ECMAScript 5 and higher.": {
+        "category": "Error",
+        "code": 2494
+    },
+    "Type '{0}' is not an array type or a string type.": {
+        "category": "Error",
+        "code": 2495
+    },
+    "The 'arguments' object cannot be referenced in an arrow function in ES3 and ES5. Consider using a standard function expression.": {
+        "category": "Error",
+        "code": 2496
+    },
+    "External module '{0}' resolves to a non-module entity and cannot be imported using this construct.": {
+        "category": "Error",
+        "code": 2497
+    },
+    "External module '{0}' uses 'export =' and cannot be used with 'export *'.": {
+        "category": "Error",
+        "code": 2498
+    },
+    "An interface can only extend an identifier/qualified-name with optional type arguments.": {
+        "category": "Error",
+        "code": 2499
+    },
+    "A class can only implement an identifier/qualified-name with optional type arguments.": {
+        "category": "Error",
+        "code": 2500
+    },
+    "A rest element cannot contain a binding pattern.": {
+        "category": "Error",
+        "code": 2501
+    },
+
+    "Import declaration '{0}' is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4000
+    },
+    "Type parameter '{0}' of exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4002
+    },
+    "Type parameter '{0}' of exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4004
+    },
+    "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4006
+    },
+    "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4008
+    },
+    "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4010
+    },
+    "Type parameter '{0}' of public method from exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4012
+    },
+    "Type parameter '{0}' of method from exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4014
+    },
+    "Type parameter '{0}' of exported function has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4016
+    },
+    "Implements clause of exported class '{0}' has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4019
+    },
+    "Extends clause of exported class '{0}' has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4020
+    },
+    "Extends clause of exported interface '{0}' has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4022
+    },
+    "Exported variable '{0}' has or is using name '{1}' from external module {2} but cannot be named.": {
+        "category": "Error",
+        "code": 4023
+    },
+    "Exported variable '{0}' has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4024
+    },
+    "Exported variable '{0}' has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4025
+    },
+    "Public static property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named.": {
+        "category": "Error",
+        "code": 4026
+    },
+    "Public static property '{0}' of exported class has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4027
+    },
+    "Public static property '{0}' of exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4028
+    },
+    "Public property '{0}' of exported class has or is using name '{1}' from external module {2} but cannot be named.": {
+        "category": "Error",
+        "code": 4029
+    },
+    "Public property '{0}' of exported class has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4030
+    },
+    "Public property '{0}' of exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4031
+    },
+    "Property '{0}' of exported interface has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4032
+    },
+    "Property '{0}' of exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4033
+    },
+    "Parameter '{0}' of public static property setter from exported class has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4034
+    },
+    "Parameter '{0}' of public static property setter from exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4035
+    },
+    "Parameter '{0}' of public property setter from exported class has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4036
+    },
+    "Parameter '{0}' of public property setter from exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4037
+    },
+    "Return type of public static property getter from exported class has or is using name '{0}' from external module {1} but cannot be named.": {
+        "category": "Error",
+        "code": 4038
+    },
+    "Return type of public static property getter from exported class has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4039
+    },
+    "Return type of public static property getter from exported class has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4040
+    },
+    "Return type of public property getter from exported class has or is using name '{0}' from external module {1} but cannot be named.": {
+        "category": "Error",
+        "code": 4041
+    },
+    "Return type of public property getter from exported class has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4042
+    },
+    "Return type of public property getter from exported class has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4043
+    },
+    "Return type of constructor signature from exported interface has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4044
+    },
+    "Return type of constructor signature from exported interface has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4045
+    },
+    "Return type of call signature from exported interface has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4046
+    },
+    "Return type of call signature from exported interface has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4047
+    },
+    "Return type of index signature from exported interface has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4048
+    },
+    "Return type of index signature from exported interface has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4049
+    },
+    "Return type of public static method from exported class has or is using name '{0}' from external module {1} but cannot be named.": {
+        "category": "Error",
+        "code": 4050
+    },
+    "Return type of public static method from exported class has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4051
+    },
+    "Return type of public static method from exported class has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4052
+    },
+    "Return type of public method from exported class has or is using name '{0}' from external module {1} but cannot be named.": {
+        "category": "Error",
+        "code": 4053
+    },
+    "Return type of public method from exported class has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4054
+    },
+    "Return type of public method from exported class has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4055
+    },
+    "Return type of method from exported interface has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4056
+    },
+    "Return type of method from exported interface has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4057
+    },
+    "Return type of exported function has or is using name '{0}' from external module {1} but cannot be named.": {
+        "category": "Error",
+        "code": 4058
+    },
+    "Return type of exported function has or is using name '{0}' from private module '{1}'.": {
+        "category": "Error",
+        "code": 4059
+    },
+    "Return type of exported function has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4060
+    },
+    "Parameter '{0}' of constructor from exported class has or is using name '{1}' from external module {2} but cannot be named.": {
+        "category": "Error",
+        "code": 4061
+    },
+    "Parameter '{0}' of constructor from exported class has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4062
+    },
+    "Parameter '{0}' of constructor from exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4063
+    },
+    "Parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4064
+    },
+    "Parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4065
+    },
+    "Parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4066
+    },
+    "Parameter '{0}' of call signature from exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4067
+    },
+    "Parameter '{0}' of public static method from exported class has or is using name '{1}' from external module {2} but cannot be named.": {
+        "category": "Error",
+        "code": 4068
+    },
+    "Parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4069
+    },
+    "Parameter '{0}' of public static method from exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4070
+    },
+    "Parameter '{0}' of public method from exported class has or is using name '{1}' from external module {2} but cannot be named.": {
+        "category": "Error",
+        "code": 4071
+    },
+    "Parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4072
+    },
+    "Parameter '{0}' of public method from exported class has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4073
+    },
+    "Parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4074
+    },
+    "Parameter '{0}' of method from exported interface has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4075
+    },
+    "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named.": {
+        "category": "Error",
+        "code": 4076
+    },
+    "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'.": {
+        "category": "Error",
+        "code": 4077
+    },
+    "Parameter '{0}' of exported function has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4078
+    },
+    "Exported type alias '{0}' has or is using private name '{1}'.": {
+        "category": "Error",
+        "code": 4081
+    },
+    "Default export of the module has or is using private name '{0}'.": {
+        "category": "Error",
+        "code": 4082
+    },
+    "Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher.": {
+        "category": "Error",
+        "code": 4091
+    },
+    "The current host does not support the '{0}' option.": {
+        "category": "Error",
+        "code": 5001
+    },
+    "Cannot find the common subdirectory path for the input files.": {
+        "category": "Error",
+        "code": 5009
+    },
+    "Cannot read file '{0}': {1}": {
+        "category": "Error",
+        "code": 5012
+    },
+    "Unsupported file encoding.": {
+        "category": "Error",
+        "code": 5013
+    },
+    "Failed to parse file '{0}': {1}.": {
+        "category": "Error",
+        "code": 5014
+    },
+    "Unknown compiler option '{0}'.": {
+        "category": "Error",
+        "code": 5023
+    },
+    "Compiler option '{0}' requires a value of type {1}.": {
+        "category": "Error",
+        "code": 5024
+    },
+    "Could not write file '{0}': {1}": {
+        "category": "Error",
+        "code": 5033
+    },
+    "Option 'mapRoot' cannot be specified without specifying 'sourcemap' option.": {
+        "category": "Error",
+        "code": 5038
+    },
+    "Option 'sourceRoot' cannot be specified without specifying 'sourcemap' option.": {
+        "category": "Error",
+        "code": 5039
+    },
+    "Option 'noEmit' cannot be specified with option 'out' or 'outDir'.": {
+        "category": "Error",
+        "code": 5040
+    },
+    "Option 'noEmit' cannot be specified with option 'declaration'.": {
+        "category": "Error",
+        "code": 5041
+    },
+    "Option 'project' cannot be mixed with source files on a command line.": {
+        "category": "Error",
+        "code": 5042
+    },
+    "Option 'sourceMap' cannot be specified with option 'separateCompilation'.": {
+        "category": "Error",
+        "code": 5043
+    },
+    "Option 'declaration' cannot be specified with option 'separateCompilation'.": {
+        "category": "Error",
+        "code": 5044
+    },
+    "Option 'noEmitOnError' cannot be specified with option 'separateCompilation'.": {
+        "category": "Error",
+        "code": 5045
+    },
+    "Option 'out' cannot be specified with option 'separateCompilation'.": {
+        "category": "Error",
+        "code": 5046
+    },
+    "Option 'separateCompilation' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher.": {
+        "category": "Error",
+        "code": 5047
+    },
+    "Concatenate and emit output to single file.": {
+        "category": "Message",
+        "code": 6001
+    },
+    "Generates corresponding '.d.ts' file.": {
+        "category": "Message",
+        "code": 6002
+    },
+    "Specifies the location where debugger should locate map files instead of generated locations.": {
+        "category": "Message",
+        "code": 6003
+    },
+    "Specifies the location where debugger should locate TypeScript files instead of source locations.": {
+        "category": "Message",
+        "code": 6004
+    },
+    "Watch input files.": {
+        "category": "Message",
+        "code": 6005
+    },
+    "Redirect output structure to the directory.": {
+        "category": "Message",
+        "code": 6006
+    },
+    "Do not erase const enum declarations in generated code.": {
+        "category": "Message",
+        "code": 6007
+    },
+    "Do not emit outputs if any type checking errors were reported.": {
+        "category": "Message",
+        "code": 6008
+    },
+    "Do not emit comments to output.": {
+        "category": "Message",
+        "code": 6009
+    },
+    "Do not emit outputs.": {
+        "category": "Message",
+        "code": 6010
+    },
+    "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)": {
+        "category": "Message",
+        "code": 6015
+    },
+    "Specify module code generation: 'commonjs', 'amd', or 'umd'.": {
+        "category": "Message",
+        "code": 6016
+    },
+    "Print this message.": {
+        "category": "Message",
+        "code": 6017
+    },
+    "Print the compiler's version.": {
+        "category": "Message",
+        "code": 6019
+    },
+    "Compile the project in the given directory.": {
+        "category": "Message",
+        "code": 6020
+    },
+    "Syntax: {0}": {
+        "category": "Message",
+        "code": 6023
+    },
+    "options": {
+        "category": "Message",
+        "code": 6024
+    },
+    "file": {
+        "category": "Message",
+        "code": 6025
+    },
+    "Examples: {0}": {
+        "category": "Message",
+        "code": 6026
+    },
+    "Options:": {
+        "category": "Message",
+        "code": 6027
+    },
+    "Version {0}": {
+        "category": "Message",
+        "code": 6029
+    },
+    "Insert command line options and files from a file.": {
+        "category": "Message",
+        "code": 6030
+    },
+    "File change detected. Starting incremental compilation...": {
+        "category": "Message",
+        "code": 6032
+    },
+    "KIND": {
+        "category": "Message",
+        "code": 6034
+    },
+    "FILE": {
+        "category": "Message",
+        "code": 6035
+    },
+    "VERSION": {
+        "category": "Message",
+        "code": 6036
+    },
+    "LOCATION": {
+        "category": "Message",
+        "code": 6037
+    },
+    "DIRECTORY": {
+        "category": "Message",
+        "code": 6038
+    },
+    "Compilation complete. Watching for file changes.": {
+        "category": "Message",
+        "code": 6042
+    },
+    "Generates corresponding '.map' file.": {
+        "category": "Message",
+        "code": 6043
+    },
+    "Compiler option '{0}' expects an argument.": {
+        "category": "Error",
+        "code": 6044
+    },
+    "Unterminated quoted string in response file '{0}'.": {
+        "category": "Error",
+        "code": 6045
+    },
+    "Argument for '--module' option must be 'commonjs', 'amd', or 'umd'.": {
+        "category": "Error",
+        "code": 6046
+    },
+    "Argument for '--target' option must be 'ES3', 'ES5', or 'ES6'.": {
+        "category": "Error",
+        "code": 6047
+    },
+    "Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'.": {
+        "category": "Error",
+        "code": 6048
+    },
+    "Unsupported locale '{0}'.": {
+        "category": "Error",
+        "code": 6049
+    },
+    "Unable to open file '{0}'.": {
+        "category": "Error",
+        "code": 6050
+    },
+    "Corrupted locale file {0}.": {
+        "category": "Error",
+        "code": 6051
+    },
+    "Raise error on expressions and declarations with an implied 'any' type.": {
+        "category": "Message",
+        "code": 6052
+    },
+    "File '{0}' not found.": {
+        "category": "Error",
+        "code": 6053
+    },
+    "File '{0}' must have extension '.ts' or '.d.ts'.": {
+        "category": "Error",
+        "code": 6054
+    },
+    "Suppress noImplicitAny errors for indexing objects lacking index signatures.": {
+        "category": "Message",
+        "code": 6055
+    },
+    "Do not emit declarations for code that has an '@internal' annotation.": {
+        "category": "Message",
+        "code": 6056
+    },
+    "Preserve new-lines when emitting code.": {
+        "category": "Message",
+        "code": 6057
+    },
+    "Specifies the root directory of input files. Use to control the output directory structure with --outDir.": {
+        "category": "Message",
+        "code": 6058
+    },
+    "File '{0}' is not under 'rootDir' '{1}'. 'rootDir' is expected to contain all source files.": {
+        "category": "Error",
+        "code": 6059
+    },
+
+
+    "Variable '{0}' implicitly has an '{1}' type.": {
+        "category": "Error",
+        "code": 7005
+    },
+    "Parameter '{0}' implicitly has an '{1}' type.": {
+        "category": "Error",
+        "code": 7006
+    },
+    "Member '{0}' implicitly has an '{1}' type.": {
+        "category": "Error",
+        "code": 7008
+    },
+    "'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.": {
+        "category": "Error",
+        "code": 7009
+    },
+    "'{0}', which lacks return-type annotation, implicitly has an '{1}' return type.": {
+        "category": "Error",
+        "code": 7010
+    },
+    "Function expression, which lacks return-type annotation, implicitly has an '{0}' return type.": {
+        "category": "Error",
+        "code": 7011
+    },
+    "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.": {
+        "category": "Error",
+        "code": 7013
+    },
+    "Property '{0}' implicitly has type 'any', because its 'set' accessor lacks a type annotation.": {
+        "category": "Error",
+        "code": 7016
+    },
+    "Index signature of object type implicitly has an 'any' type.": {
+        "category": "Error",
+        "code": 7017
+    },
+    "Object literal's property '{0}' implicitly has an '{1}' type.": {
+        "category": "Error",
+        "code": 7018
+    },
+    "Rest parameter '{0}' implicitly has an 'any[]' type.": {
+        "category": "Error",
+        "code": 7019
+    },
+    "Call signature, which lacks return-type annotation, implicitly has an 'any' return type.": {
+        "category": "Error",
+        "code": 7020
+    },
+    "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation.": {
+        "category": "Error",
+        "code": 7021
+    },
+    "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer.": {
+        "category": "Error",
+        "code": 7022
+    },
+    "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.": {
+        "category": "Error",
+        "code": 7023
+    },
+    "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.": {
+        "category": "Error",
+        "code": 7024
+    },
+    "You cannot rename this element.": {
+        "category": "Error",
+        "code": 8000
+    },
+    "You cannot rename elements that are defined in the standard TypeScript library.": {
+        "category": "Error",
+        "code": 8001
+    },
+    "'import ... =' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8002
+    },
+    "'export=' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8003
+    },
+    "'type parameter declarations' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8004
+    },
+    "'implements clauses' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8005
+    },
+    "'interface declarations' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8006
+    },
+    "'module declarations' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8007
+    },
+    "'type aliases' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8008
+    },
+    "'{0}' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8009
+    },
+    "'types' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8010
+    },
+    "'type arguments' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8011
+    },
+    "'parameter modifiers' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8012
+    },
+    "'?' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8013
+    },
+    "'property declarations' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8014
+    },
+    "'enum declarations' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8015
+    },
+    "'type assertion expressions' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8016
+    },
+    "'decorators' can only be used in a .ts file.": {
+        "category": "Error",
+        "code": 8017
+    },
+
+    "'yield' expressions are not currently supported.": {
+        "category": "Error",
+        "code": 9000
+    },
+    "Generators are not currently supported.": {
+        "category": "Error",
+        "code": 9001
+    },
+    "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses.": {
+        "category": "Error",
+        "code": 9002
+    },
+    "'class' expressions are not currently supported.": {
+        "category": "Error",
+        "code": 9003
+    },
+    "'class' declarations are only supported directly inside a module or as a top level declaration.": {
+        "category": "Error",
+        "code": 9004
+    }
+}
diff --git a/lib/typescript/compiler/emitter.ts b/lib/typescript/compiler/emitter.ts
new file mode 100644
index 000000000..7c1da2005
--- /dev/null
+++ b/lib/typescript/compiler/emitter.ts
@@ -0,0 +1,5274 @@
+/// <reference path="checker.ts"/>
+/// <reference path="declarationEmitter.ts"/>
+
+/* @internal */
+module ts {
+    // represents one LexicalEnvironment frame to store unique generated names
+    interface ScopeFrame {
+        names: Map<string>;
+        previous: ScopeFrame;
+    }
+
+    export function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
+        return isExternalModule(sourceFile) || isDeclarationFile(sourceFile);
+    }
+
+    // Flags enum to track count of temp variables and a few dedicated names
+    const enum TempFlags {
+        Auto      = 0x00000000,  // No preferred name
+        CountMask = 0x0FFFFFFF,  // Temp variable counter
+        _i        = 0x10000000,  // Use/preference flag for '_i'
+        _n        = 0x20000000,  // Use/preference flag for '_n'
+    }
+
+    // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
+    export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
+        // emit output for the __extends helper function
+        const extendsHelper = `
+var __extends = this.__extends || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    __.prototype = b.prototype;
+    d.prototype = new __();
+};`;
+
+        // emit output for the __decorate helper function
+        const decorateHelper = `
+if (typeof __decorate !== "function") __decorate = function (decorators, target, key, desc) {
+    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
+    switch (arguments.length) {
+        case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
+        case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
+        case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
+    }
+};`;
+
+        // emit output for the __metadata helper function
+        const metadataHelper = `
+if (typeof __metadata !== "function") __metadata = function (k, v) {
+    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};`;
+
+        // emit output for the __param helper function
+        const paramHelper = `
+if (typeof __param !== "function") __param = function (paramIndex, decorator) {
+    return function (target, key) { decorator(target, key, paramIndex); }
+};`;
+
+        let compilerOptions = host.getCompilerOptions();
+        let languageVersion = compilerOptions.target || ScriptTarget.ES3;
+        let sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;
+        let diagnostics: Diagnostic[] = [];
+        let newLine = host.getNewLine();
+
+        if (targetSourceFile === undefined) {
+            forEach(host.getSourceFiles(), sourceFile => {
+                if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
+                    let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, ".js");
+                    emitFile(jsFilePath, sourceFile);
+                }
+            });
+
+            if (compilerOptions.out) {
+                emitFile(compilerOptions.out);
+            }
+        }
+        else {
+            // targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service)
+            if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
+                let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
+                emitFile(jsFilePath, targetSourceFile);
+            }
+            else if (!isDeclarationFile(targetSourceFile) && compilerOptions.out) {
+                emitFile(compilerOptions.out);
+            }
+        }
+
+        // Sort and make the unique list of diagnostics
+        diagnostics = sortAndDeduplicateDiagnostics(diagnostics);
+
+        return {
+            emitSkipped: false,
+            diagnostics,
+            sourceMaps: sourceMapDataList
+        };
+
+        function isNodeDescendentOf(node: Node, ancestor: Node): boolean {
+            while (node) {
+                if (node === ancestor) return true;
+                node = node.parent;
+            }
+            return false;
+        }
+
+        function isUniqueLocalName(name: string, container: Node): boolean {
+            for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
+                if (node.locals && hasProperty(node.locals, name)) {
+                    // We conservatively include alias symbols to cover cases where they're emitted as locals
+                    if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+
+        function emitJavaScript(jsFilePath: string, root?: SourceFile) {
+            let writer = createTextWriter(newLine);
+            let write = writer.write;
+            let writeTextOfNode = writer.writeTextOfNode;
+            let writeLine = writer.writeLine;
+            let increaseIndent = writer.increaseIndent;
+            let decreaseIndent = writer.decreaseIndent;
+
+            let currentSourceFile: SourceFile;
+
+            let generatedNameSet: Map<string> = {};
+            let nodeToGeneratedName: string[] = [];
+            let blockScopedVariableToGeneratedName: string[];
+            let computedPropertyNamesToGeneratedNames: string[];
+
+            let extendsEmitted = false;
+            let decorateEmitted = false;
+            let paramEmitted = false;
+            let tempFlags = 0;
+            let tempVariables: Identifier[];
+            let tempParameters: Identifier[];
+            let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
+            let exportSpecifiers: Map<ExportSpecifier[]>;
+            let exportEquals: ExportAssignment;
+            let hasExportStars: boolean;
+
+            /** write emitted output to disk*/
+            let writeEmittedFiles = writeJavaScriptFile;
+
+            let detachedCommentsInfo: { nodePos: number; detachedCommentEndPos: number }[];
+
+            let writeComment = writeCommentRange;
+
+            /** Emit a node */
+            let emit = emitNodeWithoutSourceMap;
+
+            /** Called just before starting emit of a node */
+            let emitStart = function (node: Node) { };
+
+            /** Called once the emit of the node is done */
+            let emitEnd = function (node: Node) { };
+
+            /** Emit the text for the given token that comes after startPos
+              * This by default writes the text provided with the given tokenKind
+              * but if optional emitFn callback is provided the text is emitted using the callback instead of default text
+              * @param tokenKind the kind of the token to search and emit
+              * @param startPos the position in the source to start searching for the token
+              * @param emitFn if given will be invoked to emit the text instead of actual token emit */
+            let emitToken = emitTokenText;
+
+            /** Called to before starting the lexical scopes as in function/class in the emitted code because of node
+              * @param scopeDeclaration node that starts the lexical scope
+              * @param scopeName Optional name of this scope instead of deducing one from the declaration node */
+            let scopeEmitStart = function (scopeDeclaration: Node, scopeName?: string) { }
+
+            /** Called after coming out of the scope */
+            let scopeEmitEnd = function () { }
+
+            /** Sourcemap data that will get encoded */
+            let sourceMapData: SourceMapData;
+
+            if (compilerOptions.sourceMap) {
+                initializeEmitterWithSourceMaps();
+            }
+
+            if (root) {
+                // Do not call emit directly. It does not set the currentSourceFile.
+                emitSourceFile(root);
+            }
+            else {
+                forEach(host.getSourceFiles(), sourceFile => {
+                    if (!isExternalModuleOrDeclarationFile(sourceFile)) {
+                        emitSourceFile(sourceFile);
+                    }
+                });
+            }
+
+            writeLine();
+            writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM);
+            return;
+
+            function emitSourceFile(sourceFile: SourceFile): void {
+                currentSourceFile = sourceFile;
+                emit(sourceFile);
+            }
+
+            function isUniqueName(name: string): boolean {
+                return !resolver.hasGlobalName(name) &&
+                    !hasProperty(currentSourceFile.identifiers, name) &&
+                    !hasProperty(generatedNameSet, name);
+            }
+
+            // Return the next available name in the pattern _a ... _z, _0, _1, ...
+            // TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name.
+            // Note that names generated by makeTempVariableName and makeUniqueName will never conflict.
+            function makeTempVariableName(flags: TempFlags): string {
+                if (flags && !(tempFlags & flags)) {
+                    var name = flags === TempFlags._i ? "_i" : "_n"
+                    if (isUniqueName(name)) {
+                        tempFlags |= flags;
+                        return name;
+                    }
+                }
+                while (true) {
+                    let count = tempFlags & TempFlags.CountMask;
+                    tempFlags++;
+                    // Skip over 'i' and 'n'
+                    if (count !== 8 && count !== 13) {
+                        let name = count < 26 ? "_" + String.fromCharCode(CharacterCodes.a + count) : "_" + (count - 26);
+                        if (isUniqueName(name)) {
+                            return name;
+                        }
+                    }
+                }
+            }
+
+            // Generate a name that is unique within the current file and doesn't conflict with any names
+            // in global scope. The name is formed by adding an '_n' suffix to the specified base name,
+            // where n is a positive integer. Note that names generated by makeTempVariableName and
+            // makeUniqueName are guaranteed to never conflict.
+            function makeUniqueName(baseName: string): string {
+                // Find the first unique 'name_n', where n is a positive number
+                if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
+                    baseName += "_";
+                }
+                let i = 1;
+                while (true) {
+                    let generatedName = baseName + i;
+                    if (isUniqueName(generatedName)) {
+                        return generatedNameSet[generatedName] = generatedName;
+                    }
+                    i++;
+                }
+            }
+
+            function assignGeneratedName(node: Node, name: string) {
+                nodeToGeneratedName[getNodeId(node)] = unescapeIdentifier(name);
+            }
+
+            function generateNameForFunctionOrClassDeclaration(node: Declaration) {
+                if (!node.name) {
+                    assignGeneratedName(node, makeUniqueName("default"));
+                }
+            }
+
+            function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) {
+                if (node.name.kind === SyntaxKind.Identifier) {
+                    let name = node.name.text;
+                    // Use module/enum name itself if it is unique, otherwise make a unique variation
+                    assignGeneratedName(node, isUniqueLocalName(name, node) ? name : makeUniqueName(name));
+                }
+            }
+
+            function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
+                let expr = getExternalModuleName(node);
+                let baseName = expr.kind === SyntaxKind.StringLiteral ?
+                    escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text)) : "module";
+                assignGeneratedName(node, makeUniqueName(baseName));
+            }
+
+            function generateNameForImportDeclaration(node: ImportDeclaration) {
+                if (node.importClause) {
+                    generateNameForImportOrExportDeclaration(node);
+                }
+            }
+
+            function generateNameForExportDeclaration(node: ExportDeclaration) {
+                if (node.moduleSpecifier) {
+                    generateNameForImportOrExportDeclaration(node);
+                }
+            }
+
+            function generateNameForExportAssignment(node: ExportAssignment) {
+                if (node.expression && node.expression.kind !== SyntaxKind.Identifier) {
+                    assignGeneratedName(node, makeUniqueName("default"));
+                }
+            }
+
+            function generateNameForNode(node: Node) {
+                switch (node.kind) {
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.ClassExpression:
+                        generateNameForFunctionOrClassDeclaration(<Declaration>node);
+                        break;
+                    case SyntaxKind.ModuleDeclaration:
+                        generateNameForModuleOrEnum(<ModuleDeclaration>node);
+                        generateNameForNode((<ModuleDeclaration>node).body);
+                        break;
+                    case SyntaxKind.EnumDeclaration:
+                        generateNameForModuleOrEnum(<EnumDeclaration>node);
+                        break;
+                    case SyntaxKind.ImportDeclaration:
+                        generateNameForImportDeclaration(<ImportDeclaration>node);
+                        break;
+                    case SyntaxKind.ExportDeclaration:
+                        generateNameForExportDeclaration(<ExportDeclaration>node);
+                        break;
+                    case SyntaxKind.ExportAssignment:
+                        generateNameForExportAssignment(<ExportAssignment>node);
+                        break;
+                }
+            }
+
+            function getGeneratedNameForNode(node: Node) {
+                let nodeId = getNodeId(node);
+                if (!nodeToGeneratedName[nodeId]) {
+                    generateNameForNode(node);
+                }
+                return nodeToGeneratedName[nodeId];
+            }
+
+            function initializeEmitterWithSourceMaps() {
+                let sourceMapDir: string; // The directory in which sourcemap will be
+
+                // Current source map file and its index in the sources list
+                let sourceMapSourceIndex = -1;
+
+                // Names and its index map
+                let sourceMapNameIndexMap: Map<number> = {};
+                let sourceMapNameIndices: number[] = [];
+                function getSourceMapNameIndex() {
+                    return sourceMapNameIndices.length ? sourceMapNameIndices[sourceMapNameIndices.length - 1] : -1;
+                }
+
+                // Last recorded and encoded spans
+                let lastRecordedSourceMapSpan: SourceMapSpan;
+                let lastEncodedSourceMapSpan: SourceMapSpan = {
+                    emittedLine: 1,
+                    emittedColumn: 1,
+                    sourceLine: 1,
+                    sourceColumn: 1,
+                    sourceIndex: 0
+                };
+                let lastEncodedNameIndex = 0;
+
+                // Encoding for sourcemap span
+                function encodeLastRecordedSourceMapSpan() {
+                    if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
+                        return;
+                    }
+
+                    let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
+                    // Line/Comma delimiters
+                    if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
+                        // Emit comma to separate the entry
+                        if (sourceMapData.sourceMapMappings) {
+                            sourceMapData.sourceMapMappings += ",";
+                        }
+                    }
+                    else {
+                        // Emit line delimiters
+                        for (let encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
+                            sourceMapData.sourceMapMappings += ";";
+                        }
+                        prevEncodedEmittedColumn = 1;
+                    }
+
+                    // 1. Relative Column 0 based
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
+
+                    // 2. Relative sourceIndex
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
+
+                    // 3. Relative sourceLine 0 based
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
+
+                    // 4. Relative sourceColumn 0 based
+                    sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
+
+                    // 5. Relative namePosition 0 based
+                    if (lastRecordedSourceMapSpan.nameIndex >= 0) {
+                        sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
+                        lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
+                    }
+
+                    lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
+                    sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
+
+                    function base64VLQFormatEncode(inValue: number) {
+                        function base64FormatEncode(inValue: number) {
+                            if (inValue < 64) {
+                                return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(inValue);
+                            }
+                            throw TypeError(inValue + ": not a 64 based value");
+                        }
+
+                        // Add a new least significant bit that has the sign of the value.
+                        // if negative number the least significant bit that gets added to the number has value 1
+                        // else least significant bit value that gets added is 0
+                        // eg. -1 changes to binary : 01 [1] => 3
+                        //     +1 changes to binary : 01 [0] => 2
+                        if (inValue < 0) {
+                            inValue = ((-inValue) << 1) + 1;
+                        }
+                        else {
+                            inValue = inValue << 1;
+                        }
+
+                        // Encode 5 bits at a time starting from least significant bits
+                        let encodedStr = "";
+                        do {
+                            let currentDigit = inValue & 31; // 11111
+                            inValue = inValue >> 5;
+                            if (inValue > 0) {
+                                // There are still more digits to decode, set the msb (6th bit)
+                                currentDigit = currentDigit | 32;
+                            }
+                            encodedStr = encodedStr + base64FormatEncode(currentDigit);
+                        } while (inValue > 0);
+
+                        return encodedStr;
+                    }
+                }
+
+                function recordSourceMapSpan(pos: number) {
+                    let sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
+
+                    // Convert the location to be one-based.
+                    sourceLinePos.line++;
+                    sourceLinePos.character++;
+
+                    let emittedLine = writer.getLine();
+                    let emittedColumn = writer.getColumn();
+
+                    // If this location wasn't recorded or the location in source is going backwards, record the span
+                    if (!lastRecordedSourceMapSpan ||
+                        lastRecordedSourceMapSpan.emittedLine != emittedLine ||
+                        lastRecordedSourceMapSpan.emittedColumn != emittedColumn ||
+                        (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
+                            (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
+                                (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
+                        // Encode the last recordedSpan before assigning new
+                        encodeLastRecordedSourceMapSpan();
+
+                        // New span
+                        lastRecordedSourceMapSpan = {
+                            emittedLine: emittedLine,
+                            emittedColumn: emittedColumn,
+                            sourceLine: sourceLinePos.line,
+                            sourceColumn: sourceLinePos.character,
+                            nameIndex: getSourceMapNameIndex(),
+                            sourceIndex: sourceMapSourceIndex
+                        };
+                    }
+                    else {
+                        // Take the new pos instead since there is no change in emittedLine and column since last location
+                        lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
+                        lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
+                        lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
+                    }
+                }
+
+                function recordEmitNodeStartSpan(node: Node) {
+                    // Get the token pos after skipping to the token (ignoring the leading trivia)
+                    recordSourceMapSpan(skipTrivia(currentSourceFile.text, node.pos));
+                }
+
+                function recordEmitNodeEndSpan(node: Node) {
+                    recordSourceMapSpan(node.end);
+                }
+
+                function writeTextWithSpanRecord(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
+                    let tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
+                    recordSourceMapSpan(tokenStartPos);
+                    let tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
+                    recordSourceMapSpan(tokenEndPos);
+                    return tokenEndPos;
+                }
+
+                function recordNewSourceFileStart(node: SourceFile) {
+                    // Add the file to tsFilePaths
+                    // If sourceroot option: Use the relative path corresponding to the common directory path
+                    // otherwise source locations relative to map file location
+                    let sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
+
+                    sourceMapData.sourceMapSources.push(getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
+                        node.fileName,
+                        host.getCurrentDirectory(),
+                        host.getCanonicalFileName,
+                        /*isAbsolutePathAnUrl*/ true));
+                    sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
+
+                    // The one that can be used from program to get the actual source file
+                    sourceMapData.inputSourceFileNames.push(node.fileName);
+                }
+
+                function recordScopeNameOfNode(node: Node, scopeName?: string) {
+                    function recordScopeNameIndex(scopeNameIndex: number) {
+                        sourceMapNameIndices.push(scopeNameIndex);
+                    }
+
+                    function recordScopeNameStart(scopeName: string) {
+                        let scopeNameIndex = -1;
+                        if (scopeName) {
+                            let parentIndex = getSourceMapNameIndex();
+                            if (parentIndex !== -1) {
+                                // Child scopes are always shown with a dot (even if they have no name),
+                                // unless it is a computed property. Then it is shown with brackets,
+                                // but the brackets are included in the name.
+                                let name = (<Declaration>node).name;
+                                if (!name || name.kind !== SyntaxKind.ComputedPropertyName) {
+                                    scopeName = "." + scopeName;
+                                }
+                                scopeName = sourceMapData.sourceMapNames[parentIndex] + scopeName;
+                            }
+
+                            scopeNameIndex = getProperty(sourceMapNameIndexMap, scopeName);
+                            if (scopeNameIndex === undefined) {
+                                scopeNameIndex = sourceMapData.sourceMapNames.length;
+                                sourceMapData.sourceMapNames.push(scopeName);
+                                sourceMapNameIndexMap[scopeName] = scopeNameIndex;
+                            }
+                        }
+                        recordScopeNameIndex(scopeNameIndex);
+                    }
+
+                    if (scopeName) {
+                        // The scope was already given a name  use it
+                        recordScopeNameStart(scopeName);
+                    }
+                    else if (node.kind === SyntaxKind.FunctionDeclaration ||
+                        node.kind === SyntaxKind.FunctionExpression ||
+                        node.kind === SyntaxKind.MethodDeclaration ||
+                        node.kind === SyntaxKind.MethodSignature ||
+                        node.kind === SyntaxKind.GetAccessor ||
+                        node.kind === SyntaxKind.SetAccessor ||
+                        node.kind === SyntaxKind.ModuleDeclaration ||
+                        node.kind === SyntaxKind.ClassDeclaration ||
+                        node.kind === SyntaxKind.EnumDeclaration) {
+                        // Declaration and has associated name use it
+                        if ((<Declaration>node).name) {
+                            let name = (<Declaration>node).name;
+                            // For computed property names, the text will include the brackets
+                            scopeName = name.kind === SyntaxKind.ComputedPropertyName
+                                ? getTextOfNode(name)
+                                : (<Identifier>(<Declaration>node).name).text;
+                        }
+                        recordScopeNameStart(scopeName);
+                    }
+                    else {
+                        // Block just use the name from upper level scope
+                        recordScopeNameIndex(getSourceMapNameIndex());
+                    }
+                }
+
+                function recordScopeNameEnd() {
+                    sourceMapNameIndices.pop();
+                };
+
+                function writeCommentRangeWithMap(curentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) {
+                    recordSourceMapSpan(comment.pos);
+                    writeCommentRange(currentSourceFile, writer, comment, newLine);
+                    recordSourceMapSpan(comment.end);
+                }
+
+                function serializeSourceMapContents(version: number, file: string, sourceRoot: string, sources: string[], names: string[], mappings: string) {
+                    if (typeof JSON !== "undefined") {
+                        return JSON.stringify({
+                            version: version,
+                            file: file,
+                            sourceRoot: sourceRoot,
+                            sources: sources,
+                            names: names,
+                            mappings: mappings
+                        });
+                    }
+
+                    return "{\"version\":" + version + ",\"file\":\"" + escapeString(file) + "\",\"sourceRoot\":\"" + escapeString(sourceRoot) + "\",\"sources\":[" + serializeStringArray(sources) + "],\"names\":[" + serializeStringArray(names) + "],\"mappings\":\"" + escapeString(mappings) + "\"}";
+
+                    function serializeStringArray(list: string[]): string {
+                        let output = "";
+                        for (let i = 0, n = list.length; i < n; i++) {
+                            if (i) {
+                                output += ",";
+                            }
+                            output += "\"" + escapeString(list[i]) + "\"";
+                        }
+                        return output;
+                    }
+                }
+
+                function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) {
+                    // Write source map file
+                    encodeLastRecordedSourceMapSpan();
+                    writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(
+                        3,
+                        sourceMapData.sourceMapFile,
+                        sourceMapData.sourceMapSourceRoot,
+                        sourceMapData.sourceMapSources,
+                        sourceMapData.sourceMapNames,
+                        sourceMapData.sourceMapMappings), /*writeByteOrderMark*/ false);
+                    sourceMapDataList.push(sourceMapData);
+
+                    // Write sourcemap url to the js file and write the js file
+                    writeJavaScriptFile(emitOutput + "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL, writeByteOrderMark);
+                }
+
+                // Initialize source map data
+                let sourceMapJsFile = getBaseFileName(normalizeSlashes(jsFilePath));
+                sourceMapData = {
+                    sourceMapFilePath: jsFilePath + ".map",
+                    jsSourceMappingURL: sourceMapJsFile + ".map",
+                    sourceMapFile: sourceMapJsFile,
+                    sourceMapSourceRoot: compilerOptions.sourceRoot || "",
+                    sourceMapSources: [],
+                    inputSourceFileNames: [],
+                    sourceMapNames: [],
+                    sourceMapMappings: "",
+                    sourceMapDecodedMappings: []
+                };
+
+                // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
+                // relative paths of the sources list in the sourcemap
+                sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
+                if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
+                    sourceMapData.sourceMapSourceRoot += directorySeparator;
+                }
+
+                if (compilerOptions.mapRoot) {
+                    sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
+                    if (root) { // emitting single module file
+                        // For modules or multiple emit files the mapRoot will have directory structure like the sources
+                        // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
+                        sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(root, host, sourceMapDir));
+                    }
+
+                    if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
+                        // The relative paths are relative to the common directory
+                        sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
+                        sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
+                            getDirectoryPath(normalizePath(jsFilePath)), // get the relative sourceMapDir path based on jsFilePath
+                            combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
+                            host.getCurrentDirectory(),
+                            host.getCanonicalFileName,
+                            /*isAbsolutePathAnUrl*/ true);
+                    }
+                    else {
+                        sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
+                    }
+                }
+                else {
+                    sourceMapDir = getDirectoryPath(normalizePath(jsFilePath));
+                }
+
+                function emitNodeWithSourceMap(node: Node, allowGeneratedIdentifiers?: boolean) {
+                    if (node) {
+                        if (nodeIsSynthesized(node)) {
+                            return emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
+                        }
+                        if (node.kind != SyntaxKind.SourceFile) {
+                            recordEmitNodeStartSpan(node);
+                            emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers);
+                            recordEmitNodeEndSpan(node);
+                        }
+                        else {
+                            recordNewSourceFileStart(<SourceFile>node);
+                            emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
+                        }
+                    }
+                }
+
+                writeEmittedFiles = writeJavaScriptAndSourceMapFile;
+                emit = emitNodeWithSourceMap;
+                emitStart = recordEmitNodeStartSpan;
+                emitEnd = recordEmitNodeEndSpan;
+                emitToken = writeTextWithSpanRecord;
+                scopeEmitStart = recordScopeNameOfNode;
+                scopeEmitEnd = recordScopeNameEnd;
+                writeComment = writeCommentRangeWithMap;
+            }
+
+            function writeJavaScriptFile(emitOutput: string, writeByteOrderMark: boolean) {
+                writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
+            }
+
+            // Create a temporary variable with a unique unused name.
+            function createTempVariable(flags: TempFlags): Identifier {
+                let result = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
+                result.text = makeTempVariableName(flags);
+                return result;
+            }
+
+            function recordTempDeclaration(name: Identifier): void {
+                if (!tempVariables) {
+                    tempVariables = [];
+                }
+                tempVariables.push(name);
+            }
+
+            function createAndRecordTempVariable(flags: TempFlags): Identifier {
+                let temp = createTempVariable(flags);
+                recordTempDeclaration(temp);
+
+                return temp;
+            }
+
+            function emitTempDeclarations(newLine: boolean) {
+                if (tempVariables) {
+                    if (newLine) {
+                        writeLine();
+                    }
+                    else {
+                        write(" ");
+                    }
+                    write("var ");
+                    emitCommaList(tempVariables);
+                    write(";");
+                }
+            }
+
+            function emitTokenText(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
+                let tokenString = tokenToString(tokenKind);
+                if (emitFn) {
+                    emitFn();
+                }
+                else {
+                    write(tokenString);
+                }
+                return startPos + tokenString.length;
+            }
+
+            function emitOptional(prefix: string, node: Node) {
+                if (node) {
+                    write(prefix);
+                    emit(node);
+                }
+            }
+
+            function emitParenthesizedIf(node: Node, parenthesized: boolean) {
+                if (parenthesized) {
+                    write("(");
+                }
+                emit(node);
+                if (parenthesized) {
+                    write(")");
+                }
+            }
+
+            function emitTrailingCommaIfPresent(nodeList: NodeArray<Node>): void {
+                if (nodeList.hasTrailingComma) {
+                    write(",");
+                }
+            }
+
+            function emitLinePreservingList(parent: Node, nodes: NodeArray<Node>, allowTrailingComma: boolean, spacesBetweenBraces: boolean) {
+                Debug.assert(nodes.length > 0);
+
+                increaseIndent();
+
+                if (nodeStartPositionsAreOnSameLine(parent, nodes[0])) {
+                    if (spacesBetweenBraces) {
+                        write(" ");
+                    }
+                }
+                else {
+                    writeLine();
+                }
+
+                for (let i = 0, n = nodes.length; i < n; i++) {
+                    if (i) {
+                        if (nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i])) {
+                            write(", ");
+                        }
+                        else {
+                            write(",");
+                            writeLine();
+                        }
+                    }
+
+                    emit(nodes[i]);
+                }
+
+                if (nodes.hasTrailingComma && allowTrailingComma) {
+                    write(",");
+                }
+
+                decreaseIndent();
+
+                if (nodeEndPositionsAreOnSameLine(parent, lastOrUndefined(nodes))) {
+                    if (spacesBetweenBraces) {
+                        write(" ");
+                    }
+                }
+                else {
+                    writeLine();
+                }
+            }
+
+            function emitList<TNode extends Node>(nodes: TNode[], start: number, count: number, multiLine: boolean, trailingComma: boolean, leadingComma?: boolean, noTrailingNewLine?: boolean, emitNode?: (node: TNode) => void): number {
+                if (!emitNode) {
+                    emitNode = emit;
+                }
+
+                for (let i = 0; i < count; i++) {
+                    if (multiLine) {
+                        if (i || leadingComma) {
+                            write(",");
+                        }
+                        writeLine();
+                    }
+                    else {
+                        if (i || leadingComma) {
+                            write(", ");
+                        }
+                    }
+                    emitNode(nodes[start + i]);
+                    leadingComma = true;
+                }
+                if (trailingComma) {
+                    write(",");
+                }
+                if (multiLine && !noTrailingNewLine) {
+                    writeLine();
+                }
+
+                return count;
+            }
+
+            function emitCommaList(nodes: Node[]) {
+                if (nodes) {
+                    emitList(nodes, 0, nodes.length, /*multiline*/ false, /*trailingComma*/ false);
+                }
+            }
+
+            function emitLines(nodes: Node[]) {
+                emitLinesStartingAt(nodes, /*startIndex*/ 0);
+            }
+
+            function emitLinesStartingAt(nodes: Node[], startIndex: number): void {
+                for (let i = startIndex; i < nodes.length; i++) {
+                    writeLine();
+                    emit(nodes[i]);
+                }
+            }
+
+            function isBinaryOrOctalIntegerLiteral(node: LiteralExpression, text: string): boolean {
+                if (node.kind === SyntaxKind.NumericLiteral && text.length > 1) {
+                    switch (text.charCodeAt(1)) {
+                        case CharacterCodes.b:
+                        case CharacterCodes.B:
+                        case CharacterCodes.o:
+                        case CharacterCodes.O:
+                            return true;
+                    }
+                }
+
+                return false;
+            }
+
+            function emitLiteral(node: LiteralExpression) {
+                let text = getLiteralText(node);
+
+                if (compilerOptions.sourceMap && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) {
+                    writer.writeLiteral(text);
+                }
+                // For versions below ES6, emit binary & octal literals in their canonical decimal form.
+                else if (languageVersion < ScriptTarget.ES6 && isBinaryOrOctalIntegerLiteral(node, text)) {
+                    write(node.text);
+                }
+                else {
+                    write(text);
+                }
+            }
+
+            function getLiteralText(node: LiteralExpression) {
+                // Any template literal or string literal with an extended escape
+                // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal.
+                if (languageVersion < ScriptTarget.ES6 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
+                    return getQuotedEscapedLiteralText('"', node.text, '"');
+                }
+                
+                // If we don't need to downlevel and we can reach the original source text using
+                // the node's parent reference, then simply get the text as it was originally written.
+                if (node.parent) {
+                    return getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
+                }
+                
+                // If we can't reach the original source text, use the canonical form if it's a number,
+                // or an escaped quoted form of the original text if it's string-like.
+                switch (node.kind) {
+                    case SyntaxKind.StringLiteral:
+                        return getQuotedEscapedLiteralText('"', node.text, '"');
+                    case SyntaxKind.NoSubstitutionTemplateLiteral:
+                        return getQuotedEscapedLiteralText('`', node.text, '`');
+                    case SyntaxKind.TemplateHead:
+                        return getQuotedEscapedLiteralText('`', node.text, '${');
+                    case SyntaxKind.TemplateMiddle:
+                        return getQuotedEscapedLiteralText('}', node.text, '${');
+                    case SyntaxKind.TemplateTail:
+                        return getQuotedEscapedLiteralText('}', node.text, '`');
+                    case SyntaxKind.NumericLiteral:
+                        return node.text;
+                }
+
+                Debug.fail(`Literal kind '${node.kind}' not accounted for.`);
+            }
+
+            function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) {
+                return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote;
+            }
+
+            function emitDownlevelRawTemplateLiteral(node: LiteralExpression) {
+                // Find original source text, since we need to emit the raw strings of the tagged template.
+                // The raw strings contain the (escaped) strings of what the user wrote.
+                // Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
+                let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
+                
+                // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
+                // thus we need to remove those characters.
+                // First template piece starts with "`", others with "}"
+                // Last template piece ends with "`", others with "${"
+                let isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail;
+                text = text.substring(1, text.length - (isLast ? 1 : 2));
+                
+                // Newline normalization:
+                // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's
+                // <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
+                text = text.replace(/\r\n?/g, "\n");
+                text = escapeString(text);
+
+                write('"' + text + '"');
+            }
+
+            function emitDownlevelTaggedTemplateArray(node: TaggedTemplateExpression, literalEmitter: (literal: LiteralExpression) => void) {
+                write("[");
+                if (node.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral) {
+                    literalEmitter(<LiteralExpression>node.template);
+                }
+                else {
+                    literalEmitter((<TemplateExpression>node.template).head);
+                    forEach((<TemplateExpression>node.template).templateSpans, (child) => {
+                        write(", ");
+                        literalEmitter(child.literal);
+                    });
+                }
+                write("]");
+            }
+
+            function emitDownlevelTaggedTemplate(node: TaggedTemplateExpression) {
+                let tempVariable = createAndRecordTempVariable(TempFlags.Auto);
+                write("(");
+                emit(tempVariable);
+                write(" = ");
+                emitDownlevelTaggedTemplateArray(node, emit);
+                write(", ");
+
+                emit(tempVariable);
+                write(".raw = ");
+                emitDownlevelTaggedTemplateArray(node, emitDownlevelRawTemplateLiteral);
+                write(", ");
+
+                emitParenthesizedIf(node.tag, needsParenthesisForPropertyAccessOrInvocation(node.tag));
+                write("(");
+                emit(tempVariable);
+                
+                // Now we emit the expressions
+                if (node.template.kind === SyntaxKind.TemplateExpression) {
+                    forEach((<TemplateExpression>node.template).templateSpans, templateSpan => {
+                        write(", ");
+                        let needsParens = templateSpan.expression.kind === SyntaxKind.BinaryExpression
+                            && (<BinaryExpression>templateSpan.expression).operatorToken.kind === SyntaxKind.CommaToken;
+                        emitParenthesizedIf(templateSpan.expression, needsParens);
+                    });
+                }
+                write("))");
+            }
+
+            function emitTemplateExpression(node: TemplateExpression): void {
+                // In ES6 mode and above, we can simply emit each portion of a template in order, but in
+                // ES3 & ES5 we must convert the template expression into a series of string concatenations.
+                if (languageVersion >= ScriptTarget.ES6) {
+                    forEachChild(node, emit);
+                    return;
+                }
+
+                let emitOuterParens = isExpression(node.parent)
+                    && templateNeedsParens(node, <Expression>node.parent);
+
+                if (emitOuterParens) {
+                    write("(");
+                }
+
+                let headEmitted = false;
+                if (shouldEmitTemplateHead()) {
+                    emitLiteral(node.head);
+                    headEmitted = true;
+                }
+
+                for (let i = 0, n = node.templateSpans.length; i < n; i++) {
+                    let templateSpan = node.templateSpans[i];
+
+                    // Check if the expression has operands and binds its operands less closely than binary '+'.
+                    // If it does, we need to wrap the expression in parentheses. Otherwise, something like
+                    //    `abc${ 1 << 2 }`
+                    // becomes
+                    //    "abc" + 1 << 2 + ""
+                    // which is really
+                    //    ("abc" + 1) << (2 + "")
+                    // rather than
+                    //    "abc" + (1 << 2) + ""
+                    let needsParens = templateSpan.expression.kind !== SyntaxKind.ParenthesizedExpression
+                        && comparePrecedenceToBinaryPlus(templateSpan.expression) !== Comparison.GreaterThan;
+
+                    if (i > 0 || headEmitted) {
+                        // If this is the first span and the head was not emitted, then this templateSpan's
+                        // expression will be the first to be emitted. Don't emit the preceding ' + ' in that
+                        // case.
+                        write(" + ");
+                    }
+
+                    emitParenthesizedIf(templateSpan.expression, needsParens);
+
+                    // Only emit if the literal is non-empty.
+                    // The binary '+' operator is left-associative, so the first string concatenation
+                    // with the head will force the result up to this point to be a string.
+                    // Emitting a '+ ""' has no semantic effect for middles and tails.
+                    if (templateSpan.literal.text.length !== 0) {
+                        write(" + ")
+                        emitLiteral(templateSpan.literal);
+                    }
+                }
+
+                if (emitOuterParens) {
+                    write(")");
+                }
+
+                function shouldEmitTemplateHead() {
+                    // If this expression has an empty head literal and the first template span has a non-empty
+                    // literal, then emitting the empty head literal is not necessary.
+                    //     `${ foo } and ${ bar }`
+                    // can be emitted as
+                    //     foo + " and " + bar
+                    // This is because it is only required that one of the first two operands in the emit
+                    // output must be a string literal, so that the other operand and all following operands
+                    // are forced into strings.
+                    //
+                    // If the first template span has an empty literal, then the head must still be emitted.
+                    //     `${ foo }${ bar }`
+                    // must still be emitted as
+                    //     "" + foo + bar
+
+                    // There is always atleast one templateSpan in this code path, since
+                    // NoSubstitutionTemplateLiterals are directly emitted via emitLiteral()
+                    Debug.assert(node.templateSpans.length !== 0);
+
+                    return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0;
+                }
+
+                function templateNeedsParens(template: TemplateExpression, parent: Expression) {
+                    switch (parent.kind) {
+                        case SyntaxKind.CallExpression:
+                        case SyntaxKind.NewExpression:
+                            return (<CallExpression>parent).expression === template;
+                        case SyntaxKind.TaggedTemplateExpression:
+                        case SyntaxKind.ParenthesizedExpression:
+                            return false;
+                        default:
+                            return comparePrecedenceToBinaryPlus(parent) !== Comparison.LessThan;
+                    }
+                }
+
+                /**
+                 * Returns whether the expression has lesser, greater,
+                 * or equal precedence to the binary '+' operator
+                 */
+                function comparePrecedenceToBinaryPlus(expression: Expression): Comparison {
+                    // All binary expressions have lower precedence than '+' apart from '*', '/', and '%'
+                    // which have greater precedence and '-' which has equal precedence.
+                    // All unary operators have a higher precedence apart from yield.
+                    // Arrow functions and conditionals have a lower precedence,
+                    // although we convert the former into regular function expressions in ES5 mode,
+                    // and in ES6 mode this function won't get called anyway.
+                    //
+                    // TODO (drosen): Note that we need to account for the upcoming 'yield' and
+                    //                spread ('...') unary operators that are anticipated for ES6.
+                    switch (expression.kind) {
+                        case SyntaxKind.BinaryExpression:
+                            switch ((<BinaryExpression>expression).operatorToken.kind) {
+                                case SyntaxKind.AsteriskToken:
+                                case SyntaxKind.SlashToken:
+                                case SyntaxKind.PercentToken:
+                                    return Comparison.GreaterThan;
+                                case SyntaxKind.PlusToken:
+                                case SyntaxKind.MinusToken:
+                                    return Comparison.EqualTo;
+                                default:
+                                    return Comparison.LessThan;
+                            }
+                        case SyntaxKind.YieldExpression:
+                        case SyntaxKind.ConditionalExpression:
+                            return Comparison.LessThan;
+                        default:
+                            return Comparison.GreaterThan;
+                    }
+                }
+            }
+
+            function emitTemplateSpan(span: TemplateSpan) {
+                emit(span.expression);
+                emit(span.literal);
+            }
+
+            // This function specifically handles numeric/string literals for enum and accessor 'identifiers'.
+            // In a sense, it does not actually emit identifiers as much as it declares a name for a specific property.
+            // For example, this is utilized when feeding in a result to Object.defineProperty.
+            function emitExpressionForPropertyName(node: DeclarationName) {
+                Debug.assert(node.kind !== SyntaxKind.BindingElement);
+
+                if (node.kind === SyntaxKind.StringLiteral) {
+                    emitLiteral(<LiteralExpression>node);
+                }
+                else if (node.kind === SyntaxKind.ComputedPropertyName) {
+                    // if this is a decorated computed property, we will need to capture the result
+                    // of the property expression so that we can apply decorators later. This is to ensure 
+                    // we don't introduce unintended side effects:
+                    //
+                    //   class C {
+                    //     [_a = x]() { }
+                    //   }
+                    //
+                    // The emit for the decorated computed property decorator is:
+                    //
+                    //   Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)));
+                    //
+                    if (nodeIsDecorated(node.parent)) {
+                        if (!computedPropertyNamesToGeneratedNames) {
+                            computedPropertyNamesToGeneratedNames = [];
+                        }
+                        
+                        let generatedName = computedPropertyNamesToGeneratedNames[getNodeId(node)];
+                        if (generatedName) {
+                            // we have already generated a variable for this node, write that value instead.
+                            write(generatedName);
+                            return;
+                        }
+
+                        generatedName = createAndRecordTempVariable(TempFlags.Auto).text;
+                        computedPropertyNamesToGeneratedNames[getNodeId(node)] = generatedName;
+                        write(generatedName);
+                        write(" = ");
+                    }
+
+                    emit((<ComputedPropertyName>node).expression);
+                }
+                else {
+                    write("\"");
+
+                    if (node.kind === SyntaxKind.NumericLiteral) {
+                        write((<LiteralExpression>node).text);
+                    }
+                    else {
+                        writeTextOfNode(currentSourceFile, node);
+                    }
+
+                    write("\"");
+                }
+            }
+
+            function isNotExpressionIdentifier(node: Identifier) {
+                let parent = node.parent;
+                switch (parent.kind) {
+                    case SyntaxKind.Parameter:
+                    case SyntaxKind.VariableDeclaration:
+                    case SyntaxKind.BindingElement:
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                    case SyntaxKind.PropertyAssignment:
+                    case SyntaxKind.ShorthandPropertyAssignment:
+                    case SyntaxKind.EnumMember:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.ModuleDeclaration:
+                    case SyntaxKind.ImportEqualsDeclaration:
+                    case SyntaxKind.ImportClause:
+                    case SyntaxKind.NamespaceImport:
+                        return (<Declaration>parent).name === node;
+                    case SyntaxKind.ImportSpecifier:
+                    case SyntaxKind.ExportSpecifier:
+                        return (<ImportOrExportSpecifier>parent).name === node || (<ImportOrExportSpecifier>parent).propertyName === node;
+                    case SyntaxKind.BreakStatement:
+                    case SyntaxKind.ContinueStatement:
+                    case SyntaxKind.ExportAssignment:
+                        return false;
+                    case SyntaxKind.LabeledStatement:
+                        return (<LabeledStatement>node.parent).label === node;
+                }
+            }
+
+            function emitExpressionIdentifier(node: Identifier) {
+                let substitution = resolver.getExpressionNameSubstitution(node, getGeneratedNameForNode);
+                if (substitution) {
+                    write(substitution);
+                }
+                else {
+                    writeTextOfNode(currentSourceFile, node);
+                }
+            }
+
+            function getGeneratedNameForIdentifier(node: Identifier): string {
+                if (nodeIsSynthesized(node) || !blockScopedVariableToGeneratedName) {
+                    return undefined;
+                }
+
+                var variableId = resolver.getBlockScopedVariableId(node)
+                if (variableId === undefined) {
+                    return undefined;
+                }
+
+                return blockScopedVariableToGeneratedName[variableId];
+            }
+
+            function emitIdentifier(node: Identifier, allowGeneratedIdentifiers: boolean) {
+                if (allowGeneratedIdentifiers) {
+                    let generatedName = getGeneratedNameForIdentifier(node);
+                    if (generatedName) {
+                        write(generatedName);
+                        return;
+                    }
+                }
+                if (!node.parent) {
+                    write(node.text);
+                }
+                else if (!isNotExpressionIdentifier(node)) {
+                    emitExpressionIdentifier(node);
+                }
+                else {
+                    writeTextOfNode(currentSourceFile, node);
+                }
+            }
+
+            function emitThis(node: Node) {
+                if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalThis) {
+                    write("_this");
+                }
+                else {
+                    write("this");
+                }
+            }
+
+            function emitSuper(node: Node) {
+                if (languageVersion >= ScriptTarget.ES6) {
+                    write("super");
+                }
+                else {
+                    var flags = resolver.getNodeCheckFlags(node);
+                    if (flags & NodeCheckFlags.SuperInstance) {
+                        write("_super.prototype");
+                    }
+                    else {
+                        write("_super");
+                    }
+                }
+            }
+
+            function emitObjectBindingPattern(node: BindingPattern) {
+                write("{ ");
+                let elements = node.elements;
+                emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma);
+                write(" }");
+            }
+
+            function emitArrayBindingPattern(node: BindingPattern) {
+                write("[");
+                let elements = node.elements;
+                emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma);
+                write("]");
+            }
+
+            function emitBindingElement(node: BindingElement) {
+                if (node.propertyName) {
+                    emit(node.propertyName, /*allowGeneratedIdentifiers*/ false);
+                    write(": ");
+                }
+                if (node.dotDotDotToken) {
+                    write("...");
+                }
+                if (isBindingPattern(node.name)) {
+                    emit(node.name);
+                }
+                else {
+                    emitModuleMemberName(node);
+                }
+                emitOptional(" = ", node.initializer);
+            }
+
+            function emitSpreadElementExpression(node: SpreadElementExpression) {
+                write("...");
+                emit((<SpreadElementExpression>node).expression);
+            }
+
+            function emitYieldExpression(node: YieldExpression) {
+                write(tokenToString(SyntaxKind.YieldKeyword));
+                if (node.asteriskToken) {
+                    write("*");
+                }
+                if (node.expression) {
+                    write(" ");
+                    emit(node.expression);
+                }
+            }
+
+            function needsParenthesisForPropertyAccessOrInvocation(node: Expression) {
+                switch (node.kind) {
+                    case SyntaxKind.Identifier:
+                    case SyntaxKind.ArrayLiteralExpression:
+                    case SyntaxKind.PropertyAccessExpression:
+                    case SyntaxKind.ElementAccessExpression:
+                    case SyntaxKind.CallExpression:
+                    case SyntaxKind.ParenthesizedExpression:
+                        // This list is not exhaustive and only includes those cases that are relevant
+                        // to the check in emitArrayLiteral. More cases can be added as needed.
+                        return false;
+                }
+                return true;
+            }
+
+            function emitListWithSpread(elements: Expression[], multiLine: boolean, trailingComma: boolean) {
+                let pos = 0;
+                let group = 0;
+                let length = elements.length;
+                while (pos < length) {
+                    // Emit using the pattern <group0>.concat(<group1>, <group2>, ...)
+                    if (group === 1) {
+                        write(".concat(");
+                    }
+                    else if (group > 1) {
+                        write(", ");
+                    }
+                    let e = elements[pos];
+                    if (e.kind === SyntaxKind.SpreadElementExpression) {
+                        e = (<SpreadElementExpression>e).expression;
+                        emitParenthesizedIf(e, /*parenthesized*/ group === 0 && needsParenthesisForPropertyAccessOrInvocation(e));
+                        pos++;
+                    }
+                    else {
+                        let i = pos;
+                        while (i < length && elements[i].kind !== SyntaxKind.SpreadElementExpression) {
+                            i++;
+                        }
+                        write("[");
+                        if (multiLine) {
+                            increaseIndent();
+                        }
+                        emitList(elements, pos, i - pos, multiLine, trailingComma && i === length);
+                        if (multiLine) {
+                            decreaseIndent();
+                        }
+                        write("]");
+                        pos = i;
+                    }
+                    group++;
+                }
+                if (group > 1) {
+                    write(")");
+                }
+            }
+
+            function isSpreadElementExpression(node: Node) {
+                return node.kind === SyntaxKind.SpreadElementExpression;
+            }
+
+            function emitArrayLiteral(node: ArrayLiteralExpression) {
+                let elements = node.elements;
+                if (elements.length === 0) {
+                    write("[]");
+                }
+                else if (languageVersion >= ScriptTarget.ES6 || !forEach(elements, isSpreadElementExpression)) {
+                    write("[");
+                    emitLinePreservingList(node, node.elements, elements.hasTrailingComma, /*spacesBetweenBraces:*/ false);
+                    write("]");
+                }
+                else {
+                    emitListWithSpread(elements, /*multiLine*/(node.flags & NodeFlags.MultiLine) !== 0,
+                        /*trailingComma*/ elements.hasTrailingComma);
+                }
+            }
+
+            function emitObjectLiteralBody(node: ObjectLiteralExpression, numElements: number): void {
+                if (numElements === 0) {
+                    write("{}");
+                    return;
+                }
+
+                write("{");
+
+                if (numElements > 0) {
+                    var properties = node.properties;
+
+                    // If we are not doing a downlevel transformation for object literals,
+                    // then try to preserve the original shape of the object literal.
+                    // Otherwise just try to preserve the formatting.
+                    if (numElements === properties.length) {
+                        emitLinePreservingList(node, properties, /* allowTrailingComma */ languageVersion >= ScriptTarget.ES5, /* spacesBetweenBraces */ true);
+                    }
+                    else {
+                        let multiLine = (node.flags & NodeFlags.MultiLine) !== 0;
+                        if (!multiLine) {
+                            write(" ");
+                        }
+                        else {
+                            increaseIndent();
+                        }
+
+                        emitList(properties, 0, numElements, /*multiLine*/ multiLine, /*trailingComma*/ false);
+
+                        if (!multiLine) {
+                            write(" ");
+                        }
+                        else {
+                            decreaseIndent();
+                        }
+                    }
+                }
+
+                write("}");
+            }
+
+            function emitDownlevelObjectLiteralWithComputedProperties(node: ObjectLiteralExpression, firstComputedPropertyIndex: number) {
+                let multiLine = (node.flags & NodeFlags.MultiLine) !== 0;
+                let properties = node.properties;
+
+                write("(");
+
+                if (multiLine) {
+                    increaseIndent();
+                }
+
+                // For computed properties, we need to create a unique handle to the object
+                // literal so we can modify it without risking internal assignments tainting the object.
+                let tempVar = createAndRecordTempVariable(TempFlags.Auto);
+
+                // Write out the first non-computed properties
+                // (or all properties if none of them are computed),
+                // then emit the rest through indexing on the temp variable.
+                emit(tempVar)
+                write(" = ");
+                emitObjectLiteralBody(node, firstComputedPropertyIndex);
+
+                for (let i = firstComputedPropertyIndex, n = properties.length; i < n; i++) {
+                    writeComma();
+
+                    let property = properties[i];
+
+                    emitStart(property)
+                    if (property.kind === SyntaxKind.GetAccessor || property.kind === SyntaxKind.SetAccessor) {
+                        // TODO (drosen): Reconcile with 'emitMemberFunctions'.
+                        let accessors = getAllAccessorDeclarations(node.properties, <AccessorDeclaration>property);
+                        if (property !== accessors.firstAccessor) {
+                            continue;
+                        }
+                        write("Object.defineProperty(");
+                        emit(tempVar);
+                        write(", ");
+                        emitStart(node.name);
+                        emitExpressionForPropertyName(property.name);
+                        emitEnd(property.name);
+                        write(", {");
+                        increaseIndent();
+                        if (accessors.getAccessor) {
+                            writeLine()
+                            emitLeadingComments(accessors.getAccessor);
+                            write("get: ");
+                            emitStart(accessors.getAccessor);
+                            write("function ");
+                            emitSignatureAndBody(accessors.getAccessor);
+                            emitEnd(accessors.getAccessor);
+                            emitTrailingComments(accessors.getAccessor);
+                            write(",");
+                        }
+                        if (accessors.setAccessor) {
+                            writeLine();
+                            emitLeadingComments(accessors.setAccessor);
+                            write("set: ");
+                            emitStart(accessors.setAccessor);
+                            write("function ");
+                            emitSignatureAndBody(accessors.setAccessor);
+                            emitEnd(accessors.setAccessor);
+                            emitTrailingComments(accessors.setAccessor);
+                            write(",");
+                        }
+                        writeLine();
+                        write("enumerable: true,");
+                        writeLine();
+                        write("configurable: true");
+                        decreaseIndent();
+                        writeLine();
+                        write("})");
+                        emitEnd(property);
+                    }
+                    else {
+                        emitLeadingComments(property);
+                        emitStart(property.name);
+                        emit(tempVar);
+                        emitMemberAccessForPropertyName(property.name);
+                        emitEnd(property.name);
+
+                        write(" = ");
+
+                        if (property.kind === SyntaxKind.PropertyAssignment) {
+                            emit((<PropertyAssignment>property).initializer);
+                        }
+                        else if (property.kind === SyntaxKind.ShorthandPropertyAssignment) {
+                            emitExpressionIdentifier((<ShorthandPropertyAssignment>property).name);
+                        }
+                        else if (property.kind === SyntaxKind.MethodDeclaration) {
+                            emitFunctionDeclaration(<MethodDeclaration>property);
+                        }
+                        else {
+                            Debug.fail("ObjectLiteralElement type not accounted for: " + property.kind);
+                        }
+                    }
+
+                    emitEnd(property);
+                }
+
+                writeComma();
+                emit(tempVar);
+
+                if (multiLine) {
+                    decreaseIndent();
+                    writeLine();
+                }
+
+                write(")");
+
+                function writeComma() {
+                    if (multiLine) {
+                        write(",");
+                        writeLine();
+                    }
+                    else {
+                        write(", ");
+                    }
+                }
+            }
+
+            function emitObjectLiteral(node: ObjectLiteralExpression): void {
+                let properties = node.properties;
+
+                if (languageVersion < ScriptTarget.ES6) {
+                    let numProperties = properties.length;
+
+                    // Find the first computed property.
+                    // Everything until that point can be emitted as part of the initial object literal.
+                    let numInitialNonComputedProperties = numProperties;
+                    for (let i = 0, n = properties.length; i < n; i++) {
+                        if (properties[i].name.kind === SyntaxKind.ComputedPropertyName) {
+                            numInitialNonComputedProperties = i;
+                            break;
+                        }
+                    }
+
+                    let hasComputedProperty = numInitialNonComputedProperties !== properties.length;
+                    if (hasComputedProperty) {
+                        emitDownlevelObjectLiteralWithComputedProperties(node, numInitialNonComputedProperties);
+                        return;
+                    }
+                }
+
+                // Ordinary case: either the object has no computed properties
+                // or we're compiling with an ES6+ target.
+                emitObjectLiteralBody(node, properties.length);
+            }
+
+            function createBinaryExpression(left: Expression, operator: SyntaxKind, right: Expression, startsOnNewLine?: boolean): BinaryExpression {
+                let result = <BinaryExpression>createSynthesizedNode(SyntaxKind.BinaryExpression, startsOnNewLine);
+                result.operatorToken = createSynthesizedNode(operator);
+                result.left = left;
+                result.right = right;
+
+                return result;
+            }
+
+            function createPropertyAccessExpression(expression: Expression, name: Identifier): PropertyAccessExpression {
+                let result = <PropertyAccessExpression>createSynthesizedNode(SyntaxKind.PropertyAccessExpression);
+                result.expression = parenthesizeForAccess(expression);
+                result.dotToken = createSynthesizedNode(SyntaxKind.DotToken);
+                result.name = name;
+
+                return result;
+            }
+
+            function createElementAccessExpression(expression: Expression, argumentExpression: Expression): ElementAccessExpression {
+                let result = <ElementAccessExpression>createSynthesizedNode(SyntaxKind.ElementAccessExpression);
+                result.expression = parenthesizeForAccess(expression);
+                result.argumentExpression = argumentExpression;
+
+                return result;
+            }
+
+            function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
+                // isLeftHandSideExpression is almost the correct criterion for when it is not necessary
+                // to parenthesize the expression before a dot. The known exceptions are:
+                //
+                //    NewExpression:
+                //       new C.x        -> not the same as (new C).x
+                //    NumberLiteral
+                //       1.x            -> not the same as (1).x
+                //
+                if (isLeftHandSideExpression(expr) && expr.kind !== SyntaxKind.NewExpression && expr.kind !== SyntaxKind.NumericLiteral) {
+                    return <LeftHandSideExpression>expr;
+                }
+                let node = <ParenthesizedExpression>createSynthesizedNode(SyntaxKind.ParenthesizedExpression);
+                node.expression = expr;
+                return node;
+            }
+
+            function emitComputedPropertyName(node: ComputedPropertyName) {
+                write("[");
+                emitExpressionForPropertyName(node);
+                write("]");
+            }
+
+            function emitMethod(node: MethodDeclaration) {
+                if (languageVersion >= ScriptTarget.ES6 && node.asteriskToken) {
+                    write("*");
+                }
+
+                emit(node.name, /*allowGeneratedIdentifiers*/ false);
+                if (languageVersion < ScriptTarget.ES6) {
+                    write(": function ");
+                }
+                emitSignatureAndBody(node);
+            }
+
+            function emitPropertyAssignment(node: PropertyDeclaration) {
+                emit(node.name, /*allowGeneratedIdentifiers*/ false);
+                write(": ");
+                emit(node.initializer);
+            }
+
+            function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) {
+                emit(node.name, /*allowGeneratedIdentifiers*/ false);
+                // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example:
+                //  module m {
+                //      export let y;
+                //  }
+                //  module m {
+                //      export let obj = { y };
+                //  }
+                //  The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version
+                if (languageVersion < ScriptTarget.ES6) {
+                    // Emit identifier as an identifier
+                    write(": ");
+                    var generatedName = getGeneratedNameForIdentifier(node.name);
+                    if (generatedName) {
+                        write(generatedName);
+                    }
+                    else {
+                        // Even though this is stored as identifier treat it as an expression
+                        // Short-hand, { x }, is equivalent of normal form { x: x }
+                        emitExpressionIdentifier(node.name);
+                    }
+                }
+                else if (resolver.getExpressionNameSubstitution(node.name, getGeneratedNameForNode)) {
+                    // Emit identifier as an identifier
+                    write(": ");
+                    // Even though this is stored as identifier treat it as an expression
+                    // Short-hand, { x }, is equivalent of normal form { x: x }
+                    emitExpressionIdentifier(node.name);
+                }
+            }
+
+            function tryEmitConstantValue(node: PropertyAccessExpression | ElementAccessExpression): boolean {
+                if (compilerOptions.separateCompilation) {
+                    // do not inline enum values in separate compilation mode
+                    return false;
+                }
+
+                let constantValue = resolver.getConstantValue(node);
+                if (constantValue !== undefined) {
+                    write(constantValue.toString());
+                    if (!compilerOptions.removeComments) {
+                        let propertyName: string = node.kind === SyntaxKind.PropertyAccessExpression ? declarationNameToString((<PropertyAccessExpression>node).name) : getTextOfNode((<ElementAccessExpression>node).argumentExpression);
+                        write(" /* " + propertyName + " */");
+                    }
+                    return true;
+                }
+                return false;
+            }
+
+            // Returns 'true' if the code was actually indented, false otherwise. 
+            // If the code is not indented, an optional valueToWriteWhenNotIndenting will be 
+            // emitted instead.
+            function indentIfOnDifferentLines(parent: Node, node1: Node, node2: Node, valueToWriteWhenNotIndenting?: string): boolean {
+                let realNodesAreOnDifferentLines = !nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2);
+
+                // Always use a newline for synthesized code if the synthesizer desires it.
+                let synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2);
+
+                if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) {
+                    increaseIndent();
+                    writeLine();
+                    return true;
+                }
+                else {
+                    if (valueToWriteWhenNotIndenting) {
+                        write(valueToWriteWhenNotIndenting);
+                    }
+                    return false;
+                }
+            }
+
+            function emitPropertyAccess(node: PropertyAccessExpression) {
+                if (tryEmitConstantValue(node)) {
+                    return;
+                }
+
+                emit(node.expression);
+                let indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
+                write(".");
+                let indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
+                emit(node.name, /*allowGeneratedIdentifiers*/ false);
+                decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
+            }
+
+            function emitQualifiedName(node: QualifiedName) {
+                emit(node.left);
+                write(".");
+                emit(node.right);
+            }
+
+            function emitIndexedAccess(node: ElementAccessExpression) {
+                if (tryEmitConstantValue(node)) {
+                    return;
+                }
+                emit(node.expression);
+                write("[");
+                emit(node.argumentExpression);
+                write("]");
+            }
+
+            function hasSpreadElement(elements: Expression[]) {
+                return forEach(elements, e => e.kind === SyntaxKind.SpreadElementExpression);
+            }
+
+            function skipParentheses(node: Expression): Expression {
+                while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression) {
+                    node = (<ParenthesizedExpression | TypeAssertion>node).expression;
+                }
+                return node;
+            }
+
+            function emitCallTarget(node: Expression): Expression {
+                if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword) {
+                    emit(node);
+                    return node;
+                }
+                let temp = createAndRecordTempVariable(TempFlags.Auto);
+
+                write("(");
+                emit(temp);
+                write(" = ");
+                emit(node);
+                write(")");
+                return temp;
+            }
+
+            function emitCallWithSpread(node: CallExpression) {
+                let target: Expression;
+                let expr = skipParentheses(node.expression);
+                if (expr.kind === SyntaxKind.PropertyAccessExpression) {
+                    // Target will be emitted as "this" argument
+                    target = emitCallTarget((<PropertyAccessExpression>expr).expression);
+                    write(".");
+                    emit((<PropertyAccessExpression>expr).name);
+                }
+                else if (expr.kind === SyntaxKind.ElementAccessExpression) {
+                    // Target will be emitted as "this" argument
+                    target = emitCallTarget((<PropertyAccessExpression>expr).expression);
+                    write("[");
+                    emit((<ElementAccessExpression>expr).argumentExpression);
+                    write("]");
+                }
+                else if (expr.kind === SyntaxKind.SuperKeyword) {
+                    target = expr;
+                    write("_super");
+                }
+                else {
+                    emit(node.expression);
+                }
+                write(".apply(");
+                if (target) {
+                    if (target.kind === SyntaxKind.SuperKeyword) {
+                        // Calls of form super(...) and super.foo(...)
+                        emitThis(target);
+                    }
+                    else {
+                        // Calls of form obj.foo(...)
+                        emit(target);
+                    }
+                }
+                else {
+                    // Calls of form foo(...)
+                    write("void 0");
+                }
+                write(", ");
+                emitListWithSpread(node.arguments, /*multiLine*/ false, /*trailingComma*/ false);
+                write(")");
+            }
+
+            function emitCallExpression(node: CallExpression) {
+                if (languageVersion < ScriptTarget.ES6 && hasSpreadElement(node.arguments)) {
+                    emitCallWithSpread(node);
+                    return;
+                }
+                let superCall = false;
+                if (node.expression.kind === SyntaxKind.SuperKeyword) {
+                    emitSuper(node.expression);
+                    superCall = true;
+                }
+                else {
+                    emit(node.expression);
+                    superCall = node.expression.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.expression).expression.kind === SyntaxKind.SuperKeyword;
+                }
+                if (superCall && languageVersion < ScriptTarget.ES6) {
+                    write(".call(");
+                    emitThis(node.expression);
+                    if (node.arguments.length) {
+                        write(", ");
+                        emitCommaList(node.arguments);
+                    }
+                    write(")");
+                }
+                else {
+                    write("(");
+                    emitCommaList(node.arguments);
+                    write(")");
+                }
+            }
+
+            function emitNewExpression(node: NewExpression) {
+                write("new ");
+                emit(node.expression);
+                if (node.arguments) {
+                    write("(");
+                    emitCommaList(node.arguments);
+                    write(")");
+                }
+            }
+
+            function emitTaggedTemplateExpression(node: TaggedTemplateExpression): void {
+                if (languageVersion >= ScriptTarget.ES6) {
+                    emit(node.tag);
+                    write(" ");
+                    emit(node.template);
+                }
+                else {
+                    emitDownlevelTaggedTemplate(node);
+                }
+            }
+
+            function emitParenExpression(node: ParenthesizedExpression) {
+                if (!node.parent || node.parent.kind !== SyntaxKind.ArrowFunction) {
+                    if (node.expression.kind === SyntaxKind.TypeAssertionExpression) {
+                        let operand = (<TypeAssertion>node.expression).expression;
+
+                        // Make sure we consider all nested cast expressions, e.g.:
+                        // (<any><number><any>-A).x;
+                        while (operand.kind == SyntaxKind.TypeAssertionExpression) {
+                            operand = (<TypeAssertion>operand).expression;
+                        }
+
+                        // We have an expression of the form: (<Type>SubExpr)
+                        // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is.
+                        // Omitting the parentheses, however, could cause change in the semantics of the generated
+                        // code if the casted expression has a lower precedence than the rest of the expression, e.g.:
+                        //      (<any>new A).foo should be emitted as (new A).foo and not new A.foo
+                        //      (<any>typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString()
+                        //      new (<any>A()) should be emitted as new (A()) and not new A()
+                        //      (<any>function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} ()
+                        if (operand.kind !== SyntaxKind.PrefixUnaryExpression &&
+                            operand.kind !== SyntaxKind.VoidExpression &&
+                            operand.kind !== SyntaxKind.TypeOfExpression &&
+                            operand.kind !== SyntaxKind.DeleteExpression &&
+                            operand.kind !== SyntaxKind.PostfixUnaryExpression &&
+                            operand.kind !== SyntaxKind.NewExpression &&
+                            !(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) &&
+                            !(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression)) {
+                            emit(operand);
+                            return;
+                        }
+                    }
+                }
+
+                write("(");
+                emit(node.expression);
+                write(")");
+            }
+
+            function emitDeleteExpression(node: DeleteExpression) {
+                write(tokenToString(SyntaxKind.DeleteKeyword));
+                write(" ");
+                emit(node.expression);
+            }
+
+            function emitVoidExpression(node: VoidExpression) {
+                write(tokenToString(SyntaxKind.VoidKeyword));
+                write(" ");
+                emit(node.expression);
+            }
+
+            function emitTypeOfExpression(node: TypeOfExpression) {
+                write(tokenToString(SyntaxKind.TypeOfKeyword));
+                write(" ");
+                emit(node.expression);
+            }
+
+            function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
+                write(tokenToString(node.operator));
+                // In some cases, we need to emit a space between the operator and the operand. One obvious case
+                // is when the operator is an identifier, like delete or typeof. We also need to do this for plus
+                // and minus expressions in certain cases. Specifically, consider the following two cases (parens
+                // are just for clarity of exposition, and not part of the source code):
+                //
+                //  (+(+1))
+                //  (+(++1))
+                //
+                // We need to emit a space in both cases. In the first case, the absence of a space will make
+                // the resulting expression a prefix increment operation. And in the second, it will make the resulting
+                // expression a prefix increment whose operand is a plus expression - (++(+x))
+                // The same is true of minus of course.
+                if (node.operand.kind === SyntaxKind.PrefixUnaryExpression) {
+                    let operand = <PrefixUnaryExpression>node.operand;
+                    if (node.operator === SyntaxKind.PlusToken && (operand.operator === SyntaxKind.PlusToken || operand.operator === SyntaxKind.PlusPlusToken)) {
+                        write(" ");
+                    }
+                    else if (node.operator === SyntaxKind.MinusToken && (operand.operator === SyntaxKind.MinusToken || operand.operator === SyntaxKind.MinusMinusToken)) {
+                        write(" ");
+                    }
+                }
+                emit(node.operand);
+            }
+
+            function emitPostfixUnaryExpression(node: PostfixUnaryExpression) {
+                emit(node.operand);
+                write(tokenToString(node.operator));
+            }
+
+            function emitBinaryExpression(node: BinaryExpression) {
+                if (languageVersion < ScriptTarget.ES6 && node.operatorToken.kind === SyntaxKind.EqualsToken &&
+                    (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
+                    emitDestructuring(node, node.parent.kind === SyntaxKind.ExpressionStatement);
+                }
+                else {
+                    emit(node.left);
+                    let indentedBeforeOperator = indentIfOnDifferentLines(node, node.left, node.operatorToken, node.operatorToken.kind !== SyntaxKind.CommaToken ? " " : undefined);
+                    write(tokenToString(node.operatorToken.kind));
+                    let indentedAfterOperator = indentIfOnDifferentLines(node, node.operatorToken, node.right, " ");
+                    emit(node.right);
+                    decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator);
+                }
+            }
+
+            function synthesizedNodeStartsOnNewLine(node: Node) {
+                return nodeIsSynthesized(node) && (<SynthesizedNode>node).startsOnNewLine;
+            }
+
+            function emitConditionalExpression(node: ConditionalExpression) {
+                emit(node.condition);
+                let indentedBeforeQuestion = indentIfOnDifferentLines(node, node.condition, node.questionToken, " ");
+                write("?");
+                let indentedAfterQuestion = indentIfOnDifferentLines(node, node.questionToken, node.whenTrue, " ");
+                emit(node.whenTrue);
+                decreaseIndentIf(indentedBeforeQuestion, indentedAfterQuestion);
+                let indentedBeforeColon = indentIfOnDifferentLines(node, node.whenTrue, node.colonToken, " ");
+                write(":");
+                let indentedAfterColon = indentIfOnDifferentLines(node, node.colonToken, node.whenFalse, " ");
+                emit(node.whenFalse);
+                decreaseIndentIf(indentedBeforeColon, indentedAfterColon);
+            }
+
+            // Helper function to decrease the indent if we previously indented.  Allows multiple 
+            // previous indent values to be considered at a time.  This also allows caller to just
+            // call this once, passing in all their appropriate indent values, instead of needing
+            // to call this helper function multiple times.
+            function decreaseIndentIf(value1: boolean, value2?: boolean) {
+                if (value1) {
+                    decreaseIndent();
+                }
+                if (value2) {
+                    decreaseIndent();
+                }
+            }
+
+            function isSingleLineEmptyBlock(node: Node) {
+                if (node && node.kind === SyntaxKind.Block) {
+                    let block = <Block>node;
+                    return block.statements.length === 0 && nodeEndIsOnSameLineAsNodeStart(block, block);
+                }
+            }
+
+            function emitBlock(node: Block) {
+                if (isSingleLineEmptyBlock(node)) {
+                    emitToken(SyntaxKind.OpenBraceToken, node.pos);
+                    write(" ");
+                    emitToken(SyntaxKind.CloseBraceToken, node.statements.end);
+                    return;
+                }
+
+                emitToken(SyntaxKind.OpenBraceToken, node.pos);
+                increaseIndent();
+                scopeEmitStart(node.parent);
+                if (node.kind === SyntaxKind.ModuleBlock) {
+                    Debug.assert(node.parent.kind === SyntaxKind.ModuleDeclaration);
+                    emitCaptureThisForNodeIfNecessary(node.parent);
+                }
+                emitLines(node.statements);
+                if (node.kind === SyntaxKind.ModuleBlock) {
+                    emitTempDeclarations(/*newLine*/ true);
+                }
+                decreaseIndent();
+                writeLine();
+                emitToken(SyntaxKind.CloseBraceToken, node.statements.end);
+                scopeEmitEnd();
+            }
+
+            function emitEmbeddedStatement(node: Node) {
+                if (node.kind === SyntaxKind.Block) {
+                    write(" ");
+                    emit(<Block>node);
+                }
+                else {
+                    increaseIndent();
+                    writeLine();
+                    emit(node);
+                    decreaseIndent();
+                }
+            }
+
+            function emitExpressionStatement(node: ExpressionStatement) {
+                emitParenthesizedIf(node.expression, /*parenthesized*/ node.expression.kind === SyntaxKind.ArrowFunction);
+                write(";");
+            }
+
+            function emitIfStatement(node: IfStatement) {
+                let endPos = emitToken(SyntaxKind.IfKeyword, node.pos);
+                write(" ");
+                endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
+                emit(node.expression);
+                emitToken(SyntaxKind.CloseParenToken, node.expression.end);
+                emitEmbeddedStatement(node.thenStatement);
+                if (node.elseStatement) {
+                    writeLine();
+                    emitToken(SyntaxKind.ElseKeyword, node.thenStatement.end);
+                    if (node.elseStatement.kind === SyntaxKind.IfStatement) {
+                        write(" ");
+                        emit(node.elseStatement);
+                    }
+                    else {
+                        emitEmbeddedStatement(node.elseStatement);
+                    }
+                }
+            }
+
+            function emitDoStatement(node: DoStatement) {
+                write("do");
+                emitEmbeddedStatement(node.statement);
+                if (node.statement.kind === SyntaxKind.Block) {
+                    write(" ");
+                }
+                else {
+                    writeLine();
+                }
+                write("while (");
+                emit(node.expression);
+                write(");");
+            }
+
+            function emitWhileStatement(node: WhileStatement) {
+                write("while (");
+                emit(node.expression);
+                write(")");
+                emitEmbeddedStatement(node.statement);
+            }
+
+            function emitStartOfVariableDeclarationList(decl: Node, startPos?: number): void {
+                let tokenKind = SyntaxKind.VarKeyword;
+                if (decl && languageVersion >= ScriptTarget.ES6) {
+                    if (isLet(decl)) {
+                        tokenKind = SyntaxKind.LetKeyword;
+                    }
+                    else if (isConst(decl)) {
+                        tokenKind = SyntaxKind.ConstKeyword;
+                    }
+                }
+
+                if (startPos !== undefined) {
+                    emitToken(tokenKind, startPos);
+                }
+                else {
+                    switch (tokenKind) {
+                        case SyntaxKind.VarKeyword:
+                            return write("var ");
+                        case SyntaxKind.LetKeyword:
+                            return write("let ");
+                        case SyntaxKind.ConstKeyword:
+                            return write("const ");
+                    }
+                }
+            }
+
+            function emitForStatement(node: ForStatement) {
+                let endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
+                write(" ");
+                endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
+                if (node.initializer && node.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                    let variableDeclarationList = <VariableDeclarationList>node.initializer;
+                    let declarations = variableDeclarationList.declarations;
+                    emitStartOfVariableDeclarationList(declarations[0], endPos);
+                    write(" ");
+                    emitCommaList(declarations);
+                }
+                else if (node.initializer) {
+                    emit(node.initializer);
+                }
+                write(";");
+                emitOptional(" ", node.condition);
+                write(";");
+                emitOptional(" ", node.incrementor);
+                write(")");
+                emitEmbeddedStatement(node.statement);
+            }
+
+            function emitForInOrForOfStatement(node: ForInStatement | ForOfStatement) {
+                if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.ForOfStatement) {
+                    return emitDownLevelForOfStatement(node);
+                }
+
+                let endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
+                write(" ");
+                endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
+                if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                    let variableDeclarationList = <VariableDeclarationList>node.initializer;
+                    if (variableDeclarationList.declarations.length >= 1) {
+                        let decl = variableDeclarationList.declarations[0];
+                        emitStartOfVariableDeclarationList(decl, endPos);
+                        write(" ");
+                        emit(decl);
+                    }
+                }
+                else {
+                    emit(node.initializer);
+                }
+
+                if (node.kind === SyntaxKind.ForInStatement) {
+                    write(" in ");
+                }
+                else {
+                    write(" of ");
+                }
+                emit(node.expression);
+                emitToken(SyntaxKind.CloseParenToken, node.expression.end);
+                emitEmbeddedStatement(node.statement);
+            }
+
+            function emitDownLevelForOfStatement(node: ForOfStatement) {
+                // The following ES6 code:
+                //
+                //    for (let v of expr) { }
+                //
+                // should be emitted as
+                //
+                //    for (let _i = 0, _a = expr; _i < _a.length; _i++) {
+                //        let v = _a[_i];
+                //    }
+                //
+                // where _a and _i are temps emitted to capture the RHS and the counter,
+                // respectively.
+                // When the left hand side is an expression instead of a let declaration,
+                // the "let v" is not emitted.
+                // When the left hand side is a let/const, the v is renamed if there is
+                // another v in scope.
+                // Note that all assignments to the LHS are emitted in the body, including
+                // all destructuring.
+                // Note also that because an extra statement is needed to assign to the LHS,
+                // for-of bodies are always emitted as blocks.
+                
+                let endPos = emitToken(SyntaxKind.ForKeyword, node.pos);
+                write(" ");
+                endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
+                
+                // Do not emit the LHS let declaration yet, because it might contain destructuring.
+                
+                // Do not call recordTempDeclaration because we are declaring the temps
+                // right here. Recording means they will be declared later.
+                // In the case where the user wrote an identifier as the RHS, like this:
+                //
+                //     for (let v of arr) { }
+                //
+                // we don't want to emit a temporary variable for the RHS, just use it directly.
+                let rhsIsIdentifier = node.expression.kind === SyntaxKind.Identifier;
+                let counter = createTempVariable(TempFlags._i);
+                let rhsReference = rhsIsIdentifier ? <Identifier>node.expression : createTempVariable(TempFlags.Auto);
+
+                // This is the let keyword for the counter and rhsReference. The let keyword for
+                // the LHS will be emitted inside the body.
+                emitStart(node.expression);
+                write("var ");
+                
+                // _i = 0
+                emitNodeWithoutSourceMap(counter);
+                write(" = 0");
+                emitEnd(node.expression);
+
+                if (!rhsIsIdentifier) {
+                    // , _a = expr
+                    write(", ");
+                    emitStart(node.expression);
+                    emitNodeWithoutSourceMap(rhsReference);
+                    write(" = ");
+                    emitNodeWithoutSourceMap(node.expression);
+                    emitEnd(node.expression);
+                }
+
+                write("; ");
+                
+                // _i < _a.length;
+                emitStart(node.initializer);
+                emitNodeWithoutSourceMap(counter);
+                write(" < ");
+
+                emitNodeWithoutSourceMap(rhsReference);
+                write(".length");
+
+                emitEnd(node.initializer);
+                write("; ");
+                
+                // _i++)
+                emitStart(node.initializer);
+                emitNodeWithoutSourceMap(counter);
+                write("++");
+                emitEnd(node.initializer);
+                emitToken(SyntaxKind.CloseParenToken, node.expression.end);
+                
+                // Body
+                write(" {");
+                writeLine();
+                increaseIndent();
+                
+                // Initialize LHS
+                // let v = _a[_i];
+                let rhsIterationValue = createElementAccessExpression(rhsReference, counter);
+                emitStart(node.initializer);
+                if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                    write("var ");
+                    let variableDeclarationList = <VariableDeclarationList>node.initializer;
+                    if (variableDeclarationList.declarations.length > 0) {
+                        let declaration = variableDeclarationList.declarations[0];
+                        if (isBindingPattern(declaration.name)) {
+                            // This works whether the declaration is a var, let, or const.
+                            // It will use rhsIterationValue _a[_i] as the initializer.
+                            emitDestructuring(declaration, /*isAssignmentExpressionStatement*/ false, rhsIterationValue);
+                        }
+                        else {
+                            // The following call does not include the initializer, so we have
+                            // to emit it separately.
+                            emitNodeWithoutSourceMap(declaration);
+                            write(" = ");
+                            emitNodeWithoutSourceMap(rhsIterationValue);
+                        }
+                    }
+                    else {
+                        // It's an empty declaration list. This can only happen in an error case, if the user wrote
+                        //     for (let of []) {}
+                        emitNodeWithoutSourceMap(createTempVariable(TempFlags.Auto));
+                        write(" = ");
+                        emitNodeWithoutSourceMap(rhsIterationValue);
+                    }
+                }
+                else {
+                    // Initializer is an expression. Emit the expression in the body, so that it's
+                    // evaluated on every iteration.
+                    let assignmentExpression = createBinaryExpression(<Expression>node.initializer, SyntaxKind.EqualsToken, rhsIterationValue, /*startsOnNewLine*/ false);
+                    if (node.initializer.kind === SyntaxKind.ArrayLiteralExpression || node.initializer.kind === SyntaxKind.ObjectLiteralExpression) {
+                        // This is a destructuring pattern, so call emitDestructuring instead of emit. Calling emit will not work, because it will cause
+                        // the BinaryExpression to be passed in instead of the expression statement, which will cause emitDestructuring to crash.
+                        emitDestructuring(assignmentExpression, /*isAssignmentExpressionStatement*/ true, /*value*/ undefined);
+                    }
+                    else {
+                        emitNodeWithoutSourceMap(assignmentExpression);
+                    }
+                }
+                emitEnd(node.initializer);
+                write(";");
+
+                if (node.statement.kind === SyntaxKind.Block) {
+                    emitLines((<Block>node.statement).statements);
+                }
+                else {
+                    writeLine();
+                    emit(node.statement);
+                }
+
+                writeLine();
+                decreaseIndent();
+                write("}");
+            }
+
+            function emitBreakOrContinueStatement(node: BreakOrContinueStatement) {
+                emitToken(node.kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword, node.pos);
+                emitOptional(" ", node.label);
+                write(";");
+            }
+
+            function emitReturnStatement(node: ReturnStatement) {
+                emitToken(SyntaxKind.ReturnKeyword, node.pos);
+                emitOptional(" ", node.expression);
+                write(";");
+            }
+
+            function emitWithStatement(node: WhileStatement) {
+                write("with (");
+                emit(node.expression);
+                write(")");
+                emitEmbeddedStatement(node.statement);
+            }
+
+            function emitSwitchStatement(node: SwitchStatement) {
+                let endPos = emitToken(SyntaxKind.SwitchKeyword, node.pos);
+                write(" ");
+                emitToken(SyntaxKind.OpenParenToken, endPos);
+                emit(node.expression);
+                endPos = emitToken(SyntaxKind.CloseParenToken, node.expression.end);
+                write(" ");
+                emitCaseBlock(node.caseBlock, endPos)
+            }
+
+            function emitCaseBlock(node: CaseBlock, startPos: number): void {
+                emitToken(SyntaxKind.OpenBraceToken, startPos);
+                increaseIndent();
+                emitLines(node.clauses);
+                decreaseIndent();
+                writeLine();
+                emitToken(SyntaxKind.CloseBraceToken, node.clauses.end);
+            }
+
+            function nodeStartPositionsAreOnSameLine(node1: Node, node2: Node) {
+                return getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node1.pos)) ===
+                    getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node2.pos));
+            }
+
+            function nodeEndPositionsAreOnSameLine(node1: Node, node2: Node) {
+                return getLineOfLocalPosition(currentSourceFile, node1.end) ===
+                    getLineOfLocalPosition(currentSourceFile, node2.end);
+            }
+
+            function nodeEndIsOnSameLineAsNodeStart(node1: Node, node2: Node) {
+                return getLineOfLocalPosition(currentSourceFile, node1.end) ===
+                    getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node2.pos));
+            }
+
+            function emitCaseOrDefaultClause(node: CaseOrDefaultClause) {
+                if (node.kind === SyntaxKind.CaseClause) {
+                    write("case ");
+                    emit((<CaseClause>node).expression);
+                    write(":");
+                }
+                else {
+                    write("default:");
+                }
+
+                if (node.statements.length === 1 && nodeStartPositionsAreOnSameLine(node, node.statements[0])) {
+                    write(" ");
+                    emit(node.statements[0]);
+                }
+                else {
+                    increaseIndent();
+                    emitLines(node.statements);
+                    decreaseIndent();
+                }
+            }
+
+            function emitThrowStatement(node: ThrowStatement) {
+                write("throw ");
+                emit(node.expression);
+                write(";");
+            }
+
+            function emitTryStatement(node: TryStatement) {
+                write("try ");
+                emit(node.tryBlock);
+                emit(node.catchClause);
+                if (node.finallyBlock) {
+                    writeLine();
+                    write("finally ");
+                    emit(node.finallyBlock);
+                }
+            }
+
+            function emitCatchClause(node: CatchClause) {
+                writeLine();
+                let endPos = emitToken(SyntaxKind.CatchKeyword, node.pos);
+                write(" ");
+                emitToken(SyntaxKind.OpenParenToken, endPos);
+                emit(node.variableDeclaration);
+                emitToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : endPos);
+                write(" ");
+                emitBlock(node.block);
+            }
+
+            function emitDebuggerStatement(node: Node) {
+                emitToken(SyntaxKind.DebuggerKeyword, node.pos);
+                write(";");
+            }
+
+            function emitLabelledStatement(node: LabeledStatement) {
+                emit(node.label);
+                write(": ");
+                emit(node.statement);
+            }
+
+            function getContainingModule(node: Node): ModuleDeclaration {
+                do {
+                    node = node.parent;
+                } while (node && node.kind !== SyntaxKind.ModuleDeclaration);
+                return <ModuleDeclaration>node;
+            }
+
+            function emitContainingModuleName(node: Node) {
+                let container = getContainingModule(node);
+                write(container ? getGeneratedNameForNode(container) : "exports");
+            }
+
+            function emitModuleMemberName(node: Declaration) {
+                emitStart(node.name);
+                if (getCombinedNodeFlags(node) & NodeFlags.Export) {
+                    var container = getContainingModule(node);
+                    if (container) {
+                        write(getGeneratedNameForNode(container));
+                        write(".");
+                    }
+                    else if (languageVersion < ScriptTarget.ES6) {
+                        write("exports.");
+                    }
+                }
+                emitNodeWithoutSourceMap(node.name);
+                emitEnd(node.name);
+            }
+
+            function createVoidZero(): Expression {
+                let zero = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
+                zero.text = "0";
+                let result = <VoidExpression>createSynthesizedNode(SyntaxKind.VoidExpression);
+                result.expression = zero;
+                return result;
+            }
+
+            function emitExportMemberAssignment(node: FunctionLikeDeclaration | ClassDeclaration) {
+                if (node.flags & NodeFlags.Export) {
+                    writeLine();
+                    emitStart(node);
+                    if (node.flags & NodeFlags.Default) {
+                        if (languageVersion === ScriptTarget.ES3) {
+                            write("exports[\"default\"]");
+                        } else {
+                            write("exports.default");
+                        }
+                    }
+                    else {
+                        emitModuleMemberName(node);
+                    }
+                    write(" = ");
+                    emitDeclarationName(node);
+                    emitEnd(node);
+                    write(";");
+                }
+            }
+
+            function emitExportMemberAssignments(name: Identifier) {
+                if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
+                    for (let specifier of exportSpecifiers[name.text]) {
+                        writeLine();
+                        emitStart(specifier.name);
+                        emitContainingModuleName(specifier);
+                        write(".");
+                        emitNodeWithoutSourceMap(specifier.name);
+                        emitEnd(specifier.name);
+                        write(" = ");
+                        emitExpressionIdentifier(name);
+                        write(";");
+                    }
+                }
+            }
+
+            function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, isAssignmentExpressionStatement: boolean, value?: Expression) {
+                let emitCount = 0;
+                // An exported declaration is actually emitted as an assignment (to a property on the module object), so
+                // temporary variables in an exported declaration need to have real declarations elsewhere
+                let isDeclaration = (root.kind === SyntaxKind.VariableDeclaration && !(getCombinedNodeFlags(root) & NodeFlags.Export)) || root.kind === SyntaxKind.Parameter;
+                if (root.kind === SyntaxKind.BinaryExpression) {
+                    emitAssignmentExpression(<BinaryExpression>root);
+                }
+                else {
+                    Debug.assert(!isAssignmentExpressionStatement);
+                    emitBindingElement(<BindingElement>root, value);
+                }
+
+                function emitAssignment(name: Identifier, value: Expression) {
+                    if (emitCount++) {
+                        write(", ");
+                    }
+
+                    renameNonTopLevelLetAndConst(name);
+                    if (name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement)) {
+                        emitModuleMemberName(<Declaration>name.parent);
+                    }
+                    else {
+                        emit(name);
+                    }
+                    write(" = ");
+                    emit(value);
+                }
+
+                function ensureIdentifier(expr: Expression): Expression {
+                    if (expr.kind !== SyntaxKind.Identifier) {
+                        let identifier = createTempVariable(TempFlags.Auto);
+                        if (!isDeclaration) {
+                            recordTempDeclaration(identifier);
+                        }
+                        emitAssignment(identifier, expr);
+                        expr = identifier;
+                    }
+                    return expr;
+                }
+
+                function createDefaultValueCheck(value: Expression, defaultValue: Expression): Expression {
+                    // The value expression will be evaluated twice, so for anything but a simple identifier
+                    // we need to generate a temporary variable
+                    value = ensureIdentifier(value);
+                    // Return the expression 'value === void 0 ? defaultValue : value'
+                    let equals = <BinaryExpression>createSynthesizedNode(SyntaxKind.BinaryExpression);
+                    equals.left = value;
+                    equals.operatorToken = createSynthesizedNode(SyntaxKind.EqualsEqualsEqualsToken);
+                    equals.right = createVoidZero();
+                    return createConditionalExpression(equals, defaultValue, value);
+                }
+
+                function createConditionalExpression(condition: Expression, whenTrue: Expression, whenFalse: Expression) {
+                    let cond = <ConditionalExpression>createSynthesizedNode(SyntaxKind.ConditionalExpression);
+                    cond.condition = condition;
+                    cond.questionToken = createSynthesizedNode(SyntaxKind.QuestionToken);
+                    cond.whenTrue = whenTrue;
+                    cond.colonToken = createSynthesizedNode(SyntaxKind.ColonToken);
+                    cond.whenFalse = whenFalse;
+                    return cond;
+                }
+
+                function createNumericLiteral(value: number) {
+                    let node = <LiteralExpression>createSynthesizedNode(SyntaxKind.NumericLiteral);
+                    node.text = "" + value;
+                    return node;
+                }
+
+                function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier | LiteralExpression): Expression {
+                    if (propName.kind !== SyntaxKind.Identifier) {
+                        return createElementAccessExpression(object, propName);
+                    }
+
+                    return createPropertyAccessExpression(object, propName);
+                }
+
+                function createSliceCall(value: Expression, sliceIndex: number): CallExpression {
+                    let call = <CallExpression>createSynthesizedNode(SyntaxKind.CallExpression);
+                    let sliceIdentifier = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
+                    sliceIdentifier.text = "slice";
+                    call.expression = createPropertyAccessExpression(value, sliceIdentifier);
+                    call.arguments = <NodeArray<LiteralExpression>>createSynthesizedNodeArray();
+                    call.arguments[0] = createNumericLiteral(sliceIndex);
+                    return call;
+                }
+
+                function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression) {
+                    let properties = target.properties;
+                    if (properties.length !== 1) {
+                        // For anything but a single element destructuring we need to generate a temporary
+                        // to ensure value is evaluated exactly once.
+                        value = ensureIdentifier(value);
+                    }
+                    for (let p of properties) {
+                        if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
+                            // TODO(andersh): Computed property support
+                            let propName = <Identifier | LiteralExpression>((<PropertyAssignment>p).name);
+                            emitDestructuringAssignment((<PropertyAssignment>p).initializer || propName, createPropertyAccessForDestructuringProperty(value, propName));
+                        }
+                    }
+                }
+
+                function emitArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression) {
+                    let elements = target.elements;
+                    if (elements.length !== 1) {
+                        // For anything but a single element destructuring we need to generate a temporary
+                        // to ensure value is evaluated exactly once.
+                        value = ensureIdentifier(value);
+                    }
+                    for (let i = 0; i < elements.length; i++) {
+                        let e = elements[i];
+                        if (e.kind !== SyntaxKind.OmittedExpression) {
+                            if (e.kind !== SyntaxKind.SpreadElementExpression) {
+                                emitDestructuringAssignment(e, createElementAccessExpression(value, createNumericLiteral(i)));
+                            }
+                            else if (i === elements.length - 1) {
+                                emitDestructuringAssignment((<SpreadElementExpression>e).expression, createSliceCall(value, i));
+                            }
+                        }
+                    }
+                }
+
+                function emitDestructuringAssignment(target: Expression, value: Expression) {
+                    if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operatorToken.kind === SyntaxKind.EqualsToken) {
+                        value = createDefaultValueCheck(value, (<BinaryExpression>target).right);
+                        target = (<BinaryExpression>target).left;
+                    }
+                    if (target.kind === SyntaxKind.ObjectLiteralExpression) {
+                        emitObjectLiteralAssignment(<ObjectLiteralExpression>target, value);
+                    }
+                    else if (target.kind === SyntaxKind.ArrayLiteralExpression) {
+                        emitArrayLiteralAssignment(<ArrayLiteralExpression>target, value);
+                    }
+                    else {
+                        emitAssignment(<Identifier>target, value);
+                    }
+                }
+
+                function emitAssignmentExpression(root: BinaryExpression) {
+                    let target = root.left;
+                    let value = root.right;
+                    if (isAssignmentExpressionStatement) {
+                        emitDestructuringAssignment(target, value);
+                    }
+                    else {
+                        if (root.parent.kind !== SyntaxKind.ParenthesizedExpression) {
+                            write("(");
+                        }
+                        value = ensureIdentifier(value);
+                        emitDestructuringAssignment(target, value);
+                        write(", ");
+                        emit(value);
+                        if (root.parent.kind !== SyntaxKind.ParenthesizedExpression) {
+                            write(")");
+                        }
+                    }
+                }
+
+                function emitBindingElement(target: BindingElement, value: Expression) {
+                    if (target.initializer) {
+                        // Combine value and initializer
+                        value = value ? createDefaultValueCheck(value, target.initializer) : target.initializer;
+                    }
+                    else if (!value) {
+                        // Use 'void 0' in absence of value and initializer
+                        value = createVoidZero();
+                    }
+                    if (isBindingPattern(target.name)) {
+                        let pattern = <BindingPattern>target.name;
+                        let elements = pattern.elements;
+                        if (elements.length !== 1) {
+                            // For anything but a single element destructuring we need to generate a temporary
+                            // to ensure value is evaluated exactly once.
+                            value = ensureIdentifier(value);
+                        }
+                        for (let i = 0; i < elements.length; i++) {
+                            let element = elements[i];
+                            if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
+                                // Rewrite element to a declaration with an initializer that fetches property
+                                let propName = element.propertyName || <Identifier>element.name;
+                                emitBindingElement(element, createPropertyAccessForDestructuringProperty(value, propName));
+                            }
+                            else if (element.kind !== SyntaxKind.OmittedExpression) {
+                                if (!element.dotDotDotToken) {
+                                    // Rewrite element to a declaration that accesses array element at index i
+                                    emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i)));
+                                }
+                                else if (i === elements.length - 1) {
+                                    emitBindingElement(element, createSliceCall(value, i));
+                                }
+                            }
+                        }
+                    }
+                    else {
+                        emitAssignment(<Identifier>target.name, value);
+                    }
+                }
+            }
+
+            function emitVariableDeclaration(node: VariableDeclaration) {
+                if (isBindingPattern(node.name)) {
+                    if (languageVersion < ScriptTarget.ES6) {
+                        emitDestructuring(node, /*isAssignmentExpressionStatement*/ false);
+                    }
+                    else {
+                        emit(node.name);
+                        emitOptional(" = ", node.initializer);
+                    }
+                }
+                else {
+                    renameNonTopLevelLetAndConst(<Identifier>node.name);
+                    emitModuleMemberName(node);
+
+                    let initializer = node.initializer;
+                    if (!initializer && languageVersion < ScriptTarget.ES6) {
+
+                        // downlevel emit for non-initialized let bindings defined in loops
+                        // for (...) {  let x; }
+                        // should be
+                        // for (...) { var <some-uniqie-name> = void 0; }
+                        // this is necessary to preserve ES6 semantic in scenarios like
+                        // for (...) { let x; console.log(x); x = 1 } // assignment on one iteration should not affect other iterations
+                        let isUninitializedLet =
+                            (resolver.getNodeCheckFlags(node) & NodeCheckFlags.BlockScopedBindingInLoop) &&
+                            (getCombinedFlagsForIdentifier(<Identifier>node.name) & NodeFlags.Let);
+
+                        // NOTE: default initialization should not be added to let bindings in for-in\for-of statements
+                        if (isUninitializedLet &&
+                            node.parent.parent.kind !== SyntaxKind.ForInStatement &&
+                            node.parent.parent.kind !== SyntaxKind.ForOfStatement) {
+                            initializer = createVoidZero();
+                        }
+                    }
+
+                    emitOptional(" = ", initializer);
+                }
+            }
+
+            function emitExportVariableAssignments(node: VariableDeclaration | BindingElement) {
+                if (node.kind === SyntaxKind.OmittedExpression) {
+                    return;
+                }
+                let name = node.name;
+                if (name.kind === SyntaxKind.Identifier) {
+                    emitExportMemberAssignments(<Identifier>name);
+                }
+                else if (isBindingPattern(name)) {
+                    forEach((<BindingPattern>name).elements, emitExportVariableAssignments);
+                }
+            }
+
+            function getCombinedFlagsForIdentifier(node: Identifier): NodeFlags {
+                if (!node.parent || (node.parent.kind !== SyntaxKind.VariableDeclaration && node.parent.kind !== SyntaxKind.BindingElement)) {
+                    return 0;
+                }
+
+                return getCombinedNodeFlags(node.parent);
+            }
+
+            function renameNonTopLevelLetAndConst(node: Node): void {
+                // do not rename if
+                // - language version is ES6+
+                // - node is synthesized
+                // - node is not identifier (can happen when tree is malformed)
+                // - node is definitely not name of variable declaration. 
+                // it still can be part of parameter declaration, this check will be done next
+                if (languageVersion >= ScriptTarget.ES6 ||
+                    nodeIsSynthesized(node) ||
+                    node.kind !== SyntaxKind.Identifier ||
+                    (node.parent.kind !== SyntaxKind.VariableDeclaration && node.parent.kind !== SyntaxKind.BindingElement)) {
+                    return;
+                }
+
+                let combinedFlags = getCombinedFlagsForIdentifier(<Identifier>node);
+                if (((combinedFlags & NodeFlags.BlockScoped) === 0) || combinedFlags & NodeFlags.Export) {
+                    // do not rename exported or non-block scoped variables
+                    return;
+                }
+
+                // here it is known that node is a block scoped variable
+                let list = getAncestor(node, SyntaxKind.VariableDeclarationList);
+                if (list.parent.kind === SyntaxKind.VariableStatement) {
+                    let isSourceFileLevelBinding = list.parent.parent.kind === SyntaxKind.SourceFile;
+                    let isModuleLevelBinding = list.parent.parent.kind === SyntaxKind.ModuleBlock;
+                    let isFunctionLevelBinding =
+                        list.parent.parent.kind === SyntaxKind.Block && isFunctionLike(list.parent.parent.parent);
+                    if (isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding) {
+                        return;
+                    }
+                }
+
+                let blockScopeContainer = getEnclosingBlockScopeContainer(node);
+                let parent = blockScopeContainer.kind === SyntaxKind.SourceFile
+                    ? blockScopeContainer
+                    : blockScopeContainer.parent;
+
+                if (resolver.resolvesToSomeValue(parent, (<Identifier>node).text)) {
+                    let variableId = resolver.getBlockScopedVariableId(<Identifier>node);
+                    if (!blockScopedVariableToGeneratedName) {
+                        blockScopedVariableToGeneratedName = [];
+                    }
+
+                    let generatedName = makeUniqueName((<Identifier>node).text);
+                    blockScopedVariableToGeneratedName[variableId] = generatedName;
+                }
+            }
+
+            function isES6ExportedDeclaration(node: Node) {
+                return !!(node.flags & NodeFlags.Export) &&
+                    languageVersion >= ScriptTarget.ES6 &&
+                    node.parent.kind === SyntaxKind.SourceFile;
+            }
+
+            function emitVariableStatement(node: VariableStatement) {
+                if (!(node.flags & NodeFlags.Export)) {
+                    emitStartOfVariableDeclarationList(node.declarationList);
+                }
+                else if (isES6ExportedDeclaration(node)) {
+                    // Exported ES6 module member
+                    write("export ");
+                    emitStartOfVariableDeclarationList(node.declarationList);
+                }
+                emitCommaList(node.declarationList.declarations);
+                write(";");
+                if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) {
+                    forEach(node.declarationList.declarations, emitExportVariableAssignments);
+                }
+            }
+
+            function emitParameter(node: ParameterDeclaration) {
+                if (languageVersion < ScriptTarget.ES6) {
+                    if (isBindingPattern(node.name)) {
+                        let name = createTempVariable(TempFlags.Auto);
+                        if (!tempParameters) {
+                            tempParameters = [];
+                        }
+                        tempParameters.push(name);
+                        emit(name);
+                    }
+                    else {
+                        emit(node.name);
+                    }
+                }
+                else {
+                    if (node.dotDotDotToken) {
+                        write("...");
+                    }
+                    emit(node.name);
+                    emitOptional(" = ", node.initializer);
+                }
+            }
+
+            function emitDefaultValueAssignments(node: FunctionLikeDeclaration) {
+                if (languageVersion < ScriptTarget.ES6) {
+                    let tempIndex = 0;
+                    forEach(node.parameters, p => {
+                        // A rest parameter cannot have a binding pattern or an initializer,
+                        // so let's just ignore it.
+                        if (p.dotDotDotToken) {
+                            return;
+                        }
+
+                        if (isBindingPattern(p.name)) {
+                            writeLine();
+                            write("var ");
+                            emitDestructuring(p, /*isAssignmentExpressionStatement*/ false, tempParameters[tempIndex]);
+                            write(";");
+                            tempIndex++;
+                        }
+                        else if (p.initializer) {
+                            writeLine();
+                            emitStart(p);
+                            write("if (");
+                            emitNodeWithoutSourceMap(p.name);
+                            write(" === void 0)");
+                            emitEnd(p);
+                            write(" { ");
+                            emitStart(p);
+                            emitNodeWithoutSourceMap(p.name);
+                            write(" = ");
+                            emitNodeWithoutSourceMap(p.initializer);
+                            emitEnd(p);
+                            write("; }");
+                        }
+                    });
+                }
+            }
+
+            function emitRestParameter(node: FunctionLikeDeclaration) {
+                if (languageVersion < ScriptTarget.ES6 && hasRestParameters(node)) {
+                    let restIndex = node.parameters.length - 1;
+                    let restParam = node.parameters[restIndex];
+
+                    // A rest parameter cannot have a binding pattern, so let's just ignore it if it does.
+                    if (isBindingPattern(restParam.name)) {
+                        return;
+                    }
+
+                    let tempName = createTempVariable(TempFlags._i).text;
+                    writeLine();
+                    emitLeadingComments(restParam);
+                    emitStart(restParam);
+                    write("var ");
+                    emitNodeWithoutSourceMap(restParam.name);
+                    write(" = [];");
+                    emitEnd(restParam);
+                    emitTrailingComments(restParam);
+                    writeLine();
+                    write("for (");
+                    emitStart(restParam);
+                    write("var " + tempName + " = " + restIndex + ";");
+                    emitEnd(restParam);
+                    write(" ");
+                    emitStart(restParam);
+                    write(tempName + " < arguments.length;");
+                    emitEnd(restParam);
+                    write(" ");
+                    emitStart(restParam);
+                    write(tempName + "++");
+                    emitEnd(restParam);
+                    write(") {");
+                    increaseIndent();
+                    writeLine();
+                    emitStart(restParam);
+                    emitNodeWithoutSourceMap(restParam.name);
+                    write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];");
+                    emitEnd(restParam);
+                    decreaseIndent();
+                    writeLine();
+                    write("}");
+                }
+            }
+
+            function emitAccessor(node: AccessorDeclaration) {
+                write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
+                emit(node.name, /*allowGeneratedIdentifiers*/ false);
+                emitSignatureAndBody(node);
+            }
+
+            function shouldEmitAsArrowFunction(node: FunctionLikeDeclaration): boolean {
+                return node.kind === SyntaxKind.ArrowFunction && languageVersion >= ScriptTarget.ES6;
+            }
+
+            function emitDeclarationName(node: Declaration) {
+                if (node.name) {
+                    emitNodeWithoutSourceMap(node.name);
+                }
+                else {
+                    write(getGeneratedNameForNode(node));
+                }
+            }
+
+            function shouldEmitFunctionName(node: FunctionLikeDeclaration) {
+                if (node.kind === SyntaxKind.FunctionExpression) {
+                    // Emit name if one is present
+                    return !!node.name;
+                }
+                if (node.kind === SyntaxKind.FunctionDeclaration) {
+                    // Emit name if one is present, or emit generated name in down-level case (for export default case)
+                    return !!node.name || languageVersion < ScriptTarget.ES6;
+                }
+            }
+
+            function emitFunctionDeclaration(node: FunctionLikeDeclaration) {
+                if (nodeIsMissing(node.body)) {
+                    return emitOnlyPinnedOrTripleSlashComments(node);
+                }
+
+                if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
+                    // Methods will emit the comments as part of emitting method declaration
+                    emitLeadingComments(node);
+                }
+
+                // For targeting below es6, emit functions-like declaration including arrow function using function keyword.
+                // When targeting ES6, emit arrow function natively in ES6 by omitting function keyword and using fat arrow instead
+                if (!shouldEmitAsArrowFunction(node)) {
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                        if (node.flags & NodeFlags.Default) {
+                            write("default ");
+                        }
+                    }
+
+                    write("function");
+                    if (languageVersion >= ScriptTarget.ES6 && node.asteriskToken) {
+                        write("*");
+                    }
+                    write(" ");
+                }
+
+                if (shouldEmitFunctionName(node)) {
+                    emitDeclarationName(node);
+                }
+
+                emitSignatureAndBody(node);
+                if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.FunctionDeclaration && node.parent === currentSourceFile && node.name) {
+                    emitExportMemberAssignments((<FunctionDeclaration>node).name);
+                }
+                if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
+                    emitTrailingComments(node);
+                }
+            }
+
+            function emitCaptureThisForNodeIfNecessary(node: Node): void {
+                if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureThis) {
+                    writeLine();
+                    emitStart(node);
+                    write("var _this = this;");
+                    emitEnd(node);
+                }
+            }
+
+            function emitSignatureParameters(node: FunctionLikeDeclaration) {
+                increaseIndent();
+                write("(");
+                if (node) {
+                    let parameters = node.parameters;
+                    let omitCount = languageVersion < ScriptTarget.ES6 && hasRestParameters(node) ? 1 : 0;
+                    emitList(parameters, 0, parameters.length - omitCount, /*multiLine*/ false, /*trailingComma*/ false);
+                }
+                write(")");
+                decreaseIndent();
+            }
+
+            function emitSignatureParametersForArrow(node: FunctionLikeDeclaration) {
+                // Check whether the parameter list needs parentheses and preserve no-parenthesis
+                if (node.parameters.length === 1 && node.pos === node.parameters[0].pos) {
+                    emit(node.parameters[0]);
+                    return;
+                }
+                emitSignatureParameters(node);
+            }
+
+            function emitSignatureAndBody(node: FunctionLikeDeclaration) {
+                let saveTempFlags = tempFlags;
+                let saveTempVariables = tempVariables;
+                let saveTempParameters = tempParameters;
+                tempFlags = 0;
+                tempVariables = undefined;
+                tempParameters = undefined;
+
+                // When targeting ES6, emit arrow function natively in ES6
+                if (shouldEmitAsArrowFunction(node)) {
+                    emitSignatureParametersForArrow(node);
+                    write(" =>");
+                }
+                else {
+                    emitSignatureParameters(node);
+                }
+
+                if (!node.body) {
+                    // There can be no body when there are parse errors.  Just emit an empty block 
+                    // in that case.
+                    write(" { }");
+                }
+                else if (node.body.kind === SyntaxKind.Block) {
+                    emitBlockFunctionBody(node, <Block>node.body);
+                }
+                else {
+                    emitExpressionFunctionBody(node, <Expression>node.body);
+                }
+
+                if (!isES6ExportedDeclaration(node)) {
+                    emitExportMemberAssignment(node);
+                }
+
+                tempFlags = saveTempFlags;
+                tempVariables = saveTempVariables;
+                tempParameters = saveTempParameters;
+            }
+
+            // Returns true if any preamble code was emitted.
+            function emitFunctionBodyPreamble(node: FunctionLikeDeclaration): void {
+                emitCaptureThisForNodeIfNecessary(node);
+                emitDefaultValueAssignments(node);
+                emitRestParameter(node);
+            }
+
+            function emitExpressionFunctionBody(node: FunctionLikeDeclaration, body: Expression) {
+                if (languageVersion < ScriptTarget.ES6) {
+                    emitDownLevelExpressionFunctionBody(node, body);
+                    return;
+                }
+
+                // For es6 and higher we can emit the expression as is.  However, in the case 
+                // where the expression might end up looking like a block when emitted, we'll
+                // also wrap it in parentheses first.  For example if you have: a => <foo>{}
+                // then we need to generate: a => ({})
+                write(" ");
+
+                // Unwrap all type assertions.
+                let current = body;
+                while (current.kind === SyntaxKind.TypeAssertionExpression) {
+                    current = (<TypeAssertion>current).expression;
+                }
+
+                emitParenthesizedIf(body, current.kind === SyntaxKind.ObjectLiteralExpression);
+            }
+
+            function emitDownLevelExpressionFunctionBody(node: FunctionLikeDeclaration, body: Expression) {
+                write(" {");
+                scopeEmitStart(node);
+
+                increaseIndent();
+                let outPos = writer.getTextPos();
+                emitDetachedComments(node.body);
+                emitFunctionBodyPreamble(node);
+                let preambleEmitted = writer.getTextPos() !== outPos;
+                decreaseIndent();
+
+                // If we didn't have to emit any preamble code, then attempt to keep the arrow
+                // function on one line.
+                if (!preambleEmitted && nodeStartPositionsAreOnSameLine(node, body)) {
+                    write(" ");
+                    emitStart(body);
+                    write("return ");
+                    emit(body);
+                    emitEnd(body);
+                    write(";");
+                    emitTempDeclarations(/*newLine*/ false);
+                    write(" ");
+                }
+                else {
+                    increaseIndent();
+                    writeLine();
+                    emitLeadingComments(node.body);
+                    write("return ");
+                    emit(body);
+                    write(";");
+                    emitTrailingComments(node.body);
+
+                    emitTempDeclarations(/*newLine*/ true);
+                    decreaseIndent();
+                    writeLine();
+                }
+
+                emitStart(node.body);
+                write("}");
+                emitEnd(node.body);
+
+                scopeEmitEnd();
+            }
+
+            function emitBlockFunctionBody(node: FunctionLikeDeclaration, body: Block) {
+                write(" {");
+                scopeEmitStart(node);
+
+                let initialTextPos = writer.getTextPos();
+
+                increaseIndent();
+                emitDetachedComments(body.statements);
+
+                // Emit all the directive prologues (like "use strict").  These have to come before
+                // any other preamble code we write (like parameter initializers).
+                let startIndex = emitDirectivePrologues(body.statements, /*startWithNewLine*/ true);
+                emitFunctionBodyPreamble(node);
+                decreaseIndent();
+
+                let preambleEmitted = writer.getTextPos() !== initialTextPos;
+
+                if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)) {
+                    for (let statement of body.statements) {
+                        write(" ");
+                        emit(statement);
+                    }
+                    emitTempDeclarations(/*newLine*/ false);
+                    write(" ");
+                    emitLeadingCommentsOfPosition(body.statements.end);
+                }
+                else {
+                    increaseIndent();
+                    emitLinesStartingAt(body.statements, startIndex);
+                    emitTempDeclarations(/*newLine*/ true);
+
+                    writeLine();
+                    emitLeadingCommentsOfPosition(body.statements.end);
+                    decreaseIndent();
+                }
+
+                emitToken(SyntaxKind.CloseBraceToken, body.statements.end);
+                scopeEmitEnd();
+            }
+
+            function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement {
+                if (ctor.body) {
+                    let statement = (<Block>ctor.body).statements[0];
+                    if (statement && statement.kind === SyntaxKind.ExpressionStatement) {
+                        let expr = (<ExpressionStatement>statement).expression;
+                        if (expr && expr.kind === SyntaxKind.CallExpression) {
+                            let func = (<CallExpression>expr).expression;
+                            if (func && func.kind === SyntaxKind.SuperKeyword) {
+                                return <ExpressionStatement>statement;
+                            }
+                        }
+                    }
+                }
+            }
+
+            function emitParameterPropertyAssignments(node: ConstructorDeclaration) {
+                forEach(node.parameters, param => {
+                    if (param.flags & NodeFlags.AccessibilityModifier) {
+                        writeLine();
+                        emitStart(param);
+                        emitStart(param.name);
+                        write("this.");
+                        emitNodeWithoutSourceMap(param.name);
+                        emitEnd(param.name);
+                        write(" = ");
+                        emit(param.name);
+                        write(";");
+                        emitEnd(param);
+                    }
+                });
+            }
+
+            function emitMemberAccessForPropertyName(memberName: DeclarationName) {
+                // TODO: (jfreeman,drosen): comment on why this is emitNodeWithoutSourceMap instead of emit here.
+                if (memberName.kind === SyntaxKind.StringLiteral || memberName.kind === SyntaxKind.NumericLiteral) {
+                    write("[");
+                    emitNodeWithoutSourceMap(memberName);
+                    write("]");
+                }
+                else if (memberName.kind === SyntaxKind.ComputedPropertyName) {
+                    emitComputedPropertyName(<ComputedPropertyName>memberName);
+                }
+                else {
+                    write(".");
+                    emitNodeWithoutSourceMap(memberName);
+                }
+            }
+
+            function getInitializedProperties(node: ClassLikeDeclaration, static: boolean) {
+                let properties: PropertyDeclaration[] = [];
+                for (let member of node.members) {
+                    if (member.kind === SyntaxKind.PropertyDeclaration && static === ((member.flags & NodeFlags.Static) !== 0) && (<PropertyDeclaration>member).initializer) {
+                        properties.push(<PropertyDeclaration>member);
+                    }
+                }
+
+                return properties;
+            }
+
+            function emitPropertyDeclarations(node: ClassLikeDeclaration, properties: PropertyDeclaration[]) {
+                for (let property of properties) {
+                    emitPropertyDeclaration(node, property);
+                }
+            }
+
+            function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: Identifier, isExpression?: boolean) {
+                writeLine();
+                emitLeadingComments(property);
+                emitStart(property);
+                emitStart(property.name);
+                if (receiver) {
+                    emit(receiver);
+                }
+                else {
+                    if (property.flags & NodeFlags.Static) {
+                        emitDeclarationName(node);
+                    }
+                    else {
+                        write("this");
+                    }
+                }
+                emitMemberAccessForPropertyName(property.name);
+                emitEnd(property.name);
+                write(" = ");
+                emit(property.initializer);
+                if (!isExpression) {
+                    write(";");
+                }
+
+                emitEnd(property);
+                emitTrailingComments(property);
+            }
+
+            function emitMemberFunctionsForES5AndLower(node: ClassLikeDeclaration) {
+                forEach(node.members, member => {
+                    if (member.kind === SyntaxKind.SemicolonClassElement) {
+                        writeLine();
+                        write(";");
+                    }
+                    else if (member.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) {
+                        if (!(<MethodDeclaration>member).body) {
+                            return emitOnlyPinnedOrTripleSlashComments(member);
+                        }
+
+                        writeLine();
+                        emitLeadingComments(member);
+                        emitStart(member);
+                        emitStart((<MethodDeclaration>member).name);
+                        emitClassMemberPrefix(node, member);
+                        emitMemberAccessForPropertyName((<MethodDeclaration>member).name);
+                        emitEnd((<MethodDeclaration>member).name);
+                        write(" = ");
+                        emitStart(member);
+                        emitFunctionDeclaration(<MethodDeclaration>member);
+                        emitEnd(member);
+                        emitEnd(member);
+                        write(";");
+                        emitTrailingComments(member);
+                    }
+                    else if (member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) {
+                        let accessors = getAllAccessorDeclarations(node.members, <AccessorDeclaration>member);
+                        if (member === accessors.firstAccessor) {
+                            writeLine();
+                            emitStart(member);
+                            write("Object.defineProperty(");
+                            emitStart((<AccessorDeclaration>member).name);
+                            emitClassMemberPrefix(node, member);
+                            write(", ");
+                            emitExpressionForPropertyName((<AccessorDeclaration>member).name);
+                            emitEnd((<AccessorDeclaration>member).name);
+                            write(", {");
+                            increaseIndent();
+                            if (accessors.getAccessor) {
+                                writeLine();
+                                emitLeadingComments(accessors.getAccessor);
+                                write("get: ");
+                                emitStart(accessors.getAccessor);
+                                write("function ");
+                                emitSignatureAndBody(accessors.getAccessor);
+                                emitEnd(accessors.getAccessor);
+                                emitTrailingComments(accessors.getAccessor);
+                                write(",");
+                            }
+                            if (accessors.setAccessor) {
+                                writeLine();
+                                emitLeadingComments(accessors.setAccessor);
+                                write("set: ");
+                                emitStart(accessors.setAccessor);
+                                write("function ");
+                                emitSignatureAndBody(accessors.setAccessor);
+                                emitEnd(accessors.setAccessor);
+                                emitTrailingComments(accessors.setAccessor);
+                                write(",");
+                            }
+                            writeLine();
+                            write("enumerable: true,");
+                            writeLine();
+                            write("configurable: true");
+                            decreaseIndent();
+                            writeLine();
+                            write("});");
+                            emitEnd(member);
+                        }
+                    }
+                });
+            }
+
+            function emitMemberFunctionsForES6AndHigher(node: ClassLikeDeclaration) {
+                for (let member of node.members) {
+                    if ((member.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && !(<MethodDeclaration>member).body) {
+                        emitOnlyPinnedOrTripleSlashComments(member);
+                    }
+                    else if (member.kind === SyntaxKind.MethodDeclaration ||
+                             member.kind === SyntaxKind.GetAccessor ||
+                             member.kind === SyntaxKind.SetAccessor) {
+                        writeLine();
+                        emitLeadingComments(member);
+                        emitStart(member);
+                        if (member.flags & NodeFlags.Static) {
+                            write("static ");
+                        }
+
+                        if (member.kind === SyntaxKind.GetAccessor) {
+                            write("get ");
+                        }
+                        else if (member.kind === SyntaxKind.SetAccessor) {
+                            write("set ");
+                        }
+                        if ((<MethodDeclaration>member).asteriskToken) {
+                            write("*");
+                        }
+                        emit((<MethodDeclaration>member).name);
+                        emitSignatureAndBody(<MethodDeclaration>member);
+                        emitEnd(member);
+                        emitTrailingComments(member);
+                    }
+                    else if (member.kind === SyntaxKind.SemicolonClassElement) {
+                        writeLine();
+                        write(";");
+                    }
+                }
+            }
+
+            function emitConstructor(node: ClassLikeDeclaration, baseTypeElement: HeritageClauseElement) {
+                let saveTempFlags = tempFlags;
+                let saveTempVariables = tempVariables;
+                let saveTempParameters = tempParameters;
+                tempFlags = 0;
+                tempVariables = undefined;
+                tempParameters = undefined;
+
+                emitConstructorWorker(node, baseTypeElement);
+
+                tempFlags = saveTempFlags;
+                tempVariables = saveTempVariables;
+                tempParameters = saveTempParameters;
+            }
+
+            function emitConstructorWorker(node: ClassLikeDeclaration, baseTypeElement: HeritageClauseElement) {
+                // Check if we have property assignment inside class declaration.
+                // If there is property assignment, we need to emit constructor whether users define it or not
+                // If there is no property assignment, we can omit constructor if users do not define it
+                let hasInstancePropertyWithInitializer = false;
+
+                // Emit the constructor overload pinned comments
+                forEach(node.members, member => {
+                    if (member.kind === SyntaxKind.Constructor && !(<ConstructorDeclaration>member).body) {
+                        emitOnlyPinnedOrTripleSlashComments(member);
+                    }
+                    // Check if there is any non-static property assignment
+                    if (member.kind === SyntaxKind.PropertyDeclaration && (<PropertyDeclaration>member).initializer && (member.flags & NodeFlags.Static) === 0) {
+                        hasInstancePropertyWithInitializer = true;
+                    }
+                });
+
+                let ctor = getFirstConstructorWithBody(node);
+
+                // For target ES6 and above, if there is no user-defined constructor and there is no property assignment
+                // do not emit constructor in class declaration.
+                if (languageVersion >= ScriptTarget.ES6 && !ctor && !hasInstancePropertyWithInitializer) {
+                    return;
+                }
+
+                if (ctor) {
+                    emitLeadingComments(ctor);
+                }
+                emitStart(ctor || node);
+
+                if (languageVersion < ScriptTarget.ES6) {
+                    write("function ");
+                    emitDeclarationName(node);
+                    emitSignatureParameters(ctor);
+                }
+                else {
+                    write("constructor");
+                    if (ctor) {
+                        emitSignatureParameters(ctor);
+                    }
+                    else {
+                        // Based on EcmaScript6 section 14.5.14: Runtime Semantics: ClassDefinitionEvaluation.
+                        // If constructor is empty, then,
+                        //      If ClassHeritageopt is present, then
+                        //          Let constructor be the result of parsing the String "constructor(... args){ super (...args);}" using the syntactic grammar with the goal symbol MethodDefinition.
+                        //      Else,
+                        //          Let constructor be the result of parsing the String "constructor( ){ }" using the syntactic grammar with the goal symbol MethodDefinition
+                        if (baseTypeElement) {
+                            write("(...args)");
+                        }
+                        else {
+                            write("()");
+                        }
+                    }
+                }
+
+                write(" {");
+                scopeEmitStart(node, "constructor");
+                increaseIndent();
+                if (ctor) {
+                    emitDetachedComments(ctor.body.statements);
+                }
+                emitCaptureThisForNodeIfNecessary(node);
+                if (ctor) {
+                    emitDefaultValueAssignments(ctor);
+                    emitRestParameter(ctor);
+                    if (baseTypeElement) {
+                        var superCall = findInitialSuperCall(ctor);
+                        if (superCall) {
+                            writeLine();
+                            emit(superCall);
+                        }
+                    }
+                    emitParameterPropertyAssignments(ctor);
+                }
+                else {
+                    if (baseTypeElement) {
+                        writeLine();
+                        emitStart(baseTypeElement);
+                        if (languageVersion < ScriptTarget.ES6) {
+                            write("_super.apply(this, arguments);");
+                        }
+                        else {
+                            write("super(...args);");
+                        }
+                        emitEnd(baseTypeElement);
+                    }
+                }
+                emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ false));
+                if (ctor) {
+                    var statements: Node[] = (<Block>ctor.body).statements;
+                    if (superCall) {
+                        statements = statements.slice(1);
+                    }
+                    emitLines(statements);
+                }
+                emitTempDeclarations(/*newLine*/ true);
+                writeLine();
+                if (ctor) {
+                    emitLeadingCommentsOfPosition((<Block>ctor.body).statements.end);
+                }
+                decreaseIndent();
+                emitToken(SyntaxKind.CloseBraceToken, ctor ? (<Block>ctor.body).statements.end : node.members.end);
+                scopeEmitEnd();
+                emitEnd(<Node>ctor || node);
+                if (ctor) {
+                    emitTrailingComments(ctor);
+                }
+            }
+
+            function emitClassExpression(node: ClassExpression) {
+                return emitClassLikeDeclaration(node);
+            }
+
+            function emitClassDeclaration(node: ClassDeclaration) {
+                return emitClassLikeDeclaration(node);
+            }
+
+            function emitClassLikeDeclaration(node: ClassLikeDeclaration) {
+                if (languageVersion < ScriptTarget.ES6) {
+                    emitClassLikeDeclarationBelowES6(node);
+                }
+                else {
+                    emitClassLikeDeclarationForES6AndHigher(node);
+                }
+            }
+            
+            function emitClassLikeDeclarationForES6AndHigher(node: ClassLikeDeclaration) {
+                let thisNodeIsDecorated = nodeIsDecorated(node);
+                if (node.kind === SyntaxKind.ClassDeclaration) {
+                    if (thisNodeIsDecorated) {
+                        // To preserve the correct runtime semantics when decorators are applied to the class,
+                        // the emit needs to follow one of the following rules:
+                        //
+                        // * For a local class declaration:
+                        //
+                        //     @dec class C {
+                        //     }
+                        //
+                        //   The emit should be:
+                        //
+                        //     let C = class {
+                        //     };
+                        //     Object.defineProperty(C, "name", { value: "C", configurable: true });
+                        //     C = __decorate([dec], C);
+                        //
+                        // * For an exported class declaration:
+                        //
+                        //     @dec export class C {
+                        //     }
+                        //
+                        //   The emit should be:
+                        //
+                        //     export let C = class {
+                        //     };
+                        //     Object.defineProperty(C, "name", { value: "C", configurable: true });
+                        //     C = __decorate([dec], C);
+                        //
+                        // * For a default export of a class declaration with a name:
+                        //
+                        //     @dec default export class C {
+                        //     }
+                        //
+                        //   The emit should be:
+                        //
+                        //     let C = class {
+                        //     }
+                        //     Object.defineProperty(C, "name", { value: "C", configurable: true });
+                        //     C = __decorate([dec], C);
+                        //     export default C;
+                        //
+                        // * For a default export of a class declaration without a name:
+                        //
+                        //     @dec default export class {
+                        //     }
+                        //
+                        //   The emit should be:
+                        //
+                        //     let _default = class {
+                        //     }
+                        //     _default = __decorate([dec], _default);
+                        //     export default _default;
+                        //
+                        if (isES6ExportedDeclaration(node) && !(node.flags & NodeFlags.Default)) {
+                            write("export ");
+                        }
+
+                        write("let ");
+                        emitDeclarationName(node);
+                        write(" = ");
+                    }
+                    else if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                        if (node.flags & NodeFlags.Default) {
+                            write("default ");
+                        }
+                    }
+                }
+
+                // If the class has static properties, and it's a class expression, then we'll need
+                // to specialize the emit a bit.  for a class expression of the form: 
+                //
+                //      class C { static a = 1; static b = 2; ... } 
+                //
+                // We'll emit:
+                //
+                //      (_temp = class C { ... }, _temp.a = 1, _temp.b = 2, _temp)
+                //
+                // This keeps the expression as an expression, while ensuring that the static parts
+                // of it have been initialized by the time it is used.
+                let staticProperties = getInitializedProperties(node, /*static:*/ true);
+                let isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
+                let tempVariable: Identifier;
+
+                if (isClassExpressionWithStaticProperties) {
+                    tempVariable = createAndRecordTempVariable(TempFlags.Auto);
+                    write("(");
+                    increaseIndent();
+                    emit(tempVariable);
+                    write(" = ")
+                }
+
+                write("class");
+
+                // check if this is an "export default class" as it may not have a name. Do not emit the name if the class is decorated.
+                if ((node.name || !(node.flags & NodeFlags.Default)) && !thisNodeIsDecorated) {
+                    write(" ");
+                    emitDeclarationName(node);
+                }
+
+                var baseTypeNode = getClassExtendsHeritageClauseElement(node);
+                if (baseTypeNode) {
+                    write(" extends ");
+                    emit(baseTypeNode.expression);
+                }
+
+                write(" {");
+                increaseIndent();
+                scopeEmitStart(node);
+                writeLine();
+                emitConstructor(node, baseTypeNode);
+                emitMemberFunctionsForES6AndHigher(node);
+                decreaseIndent();
+                writeLine();
+                emitToken(SyntaxKind.CloseBraceToken, node.members.end);
+                scopeEmitEnd();
+
+                // For a decorated class, we need to assign its name (if it has one). This is because we emit
+                // the class as a class expression to avoid the double-binding of the identifier:
+                //
+                //   let C = class {
+                //   }
+                //   Object.defineProperty(C, "name", { value: "C", configurable: true });
+                //
+                if (thisNodeIsDecorated) {
+                    write(";");
+                    if (node.name) {
+                        writeLine();
+                        write("Object.defineProperty(");
+                        emitDeclarationName(node);
+                        write(", \"name\", { value: \"");
+                        emitDeclarationName(node);
+                        write("\", configurable: true });");
+                        writeLine();
+                    }
+                }
+
+                // Emit static property assignment. Because classDeclaration is lexically evaluated,
+                // it is safe to emit static property assignment after classDeclaration
+                // From ES6 specification:
+                //      HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
+                //                                  a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
+
+                if (isClassExpressionWithStaticProperties) {
+                    for (var property of staticProperties) {
+                        write(",");
+                        writeLine();
+                        emitPropertyDeclaration(node, property, /*receiver:*/ tempVariable, /*isExpression:*/ true);
+                    }
+                    write(",");
+                    writeLine();
+                    emit(tempVariable);
+                    decreaseIndent();
+                    write(")");
+                }
+                else {
+                    writeLine();
+                    emitPropertyDeclarations(node, staticProperties);
+                    emitDecoratorsOfClass(node);
+                }
+
+                // If this is an exported class, but not on the top level (i.e. on an internal
+                // module), export it
+                if (!isES6ExportedDeclaration(node) && (node.flags & NodeFlags.Export)) {
+                    writeLine();
+                    emitStart(node);
+                    emitModuleMemberName(node);
+                    write(" = ");
+                    emitDeclarationName(node);
+                    emitEnd(node);
+                    write(";");
+                }
+                else if (isES6ExportedDeclaration(node) && (node.flags & NodeFlags.Default) && thisNodeIsDecorated) {
+                    // if this is a top level default export of decorated class, write the export after the declaration.
+                    writeLine();
+                    write("export default ");
+                    emitDeclarationName(node);
+                    write(";");
+                }
+            }
+
+            function emitClassLikeDeclarationBelowES6(node: ClassLikeDeclaration) {
+                if (node.kind === SyntaxKind.ClassDeclaration) {
+                    write("var ");
+                    emitDeclarationName(node);
+                    write(" = ");
+                }
+
+                write("(function (");
+                let baseTypeNode = getClassExtendsHeritageClauseElement(node);
+                if (baseTypeNode) {
+                    write("_super");
+                }
+                write(") {");
+                let saveTempFlags = tempFlags;
+                let saveTempVariables = tempVariables;
+                let saveTempParameters = tempParameters;
+                let saveComputedPropertyNamesToGeneratedNames = computedPropertyNamesToGeneratedNames;
+                tempFlags = 0;
+                tempVariables = undefined;
+                tempParameters = undefined;
+                computedPropertyNamesToGeneratedNames = undefined;
+                increaseIndent();
+                scopeEmitStart(node);
+                if (baseTypeNode) {
+                    writeLine();
+                    emitStart(baseTypeNode);
+                    write("__extends(");
+                    emitDeclarationName(node);
+                    write(", _super);");
+                    emitEnd(baseTypeNode);
+                }
+                writeLine();
+                emitConstructor(node, baseTypeNode);
+                emitMemberFunctionsForES5AndLower(node);
+                emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ true));
+                writeLine();
+                emitDecoratorsOfClass(node);
+                writeLine();
+                emitToken(SyntaxKind.CloseBraceToken, node.members.end, () => {
+                    write("return ");
+                    emitDeclarationName(node);
+                });
+                write(";");
+                emitTempDeclarations(/*newLine*/ true);
+                tempFlags = saveTempFlags;
+                tempVariables = saveTempVariables;
+                tempParameters = saveTempParameters;
+                computedPropertyNamesToGeneratedNames = saveComputedPropertyNamesToGeneratedNames;
+                decreaseIndent();
+                writeLine();
+                emitToken(SyntaxKind.CloseBraceToken, node.members.end);
+                scopeEmitEnd();
+                emitStart(node);
+                write(")(");
+                if (baseTypeNode) {
+                    emit(baseTypeNode.expression);
+                }
+                write(")");
+                if (node.kind === SyntaxKind.ClassDeclaration) {
+                    write(";");
+                }
+                emitEnd(node);
+
+                if (node.kind === SyntaxKind.ClassDeclaration) {
+                    emitExportMemberAssignment(<ClassDeclaration>node);
+                }
+
+                if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile && node.name) {
+                    emitExportMemberAssignments(node.name);
+                }
+            }
+
+            function emitClassMemberPrefix(node: ClassLikeDeclaration, member: Node) {
+                emitDeclarationName(node);
+                if (!(member.flags & NodeFlags.Static)) {
+                    write(".prototype");
+                }
+            }
+            
+            function emitDecoratorsOfClass(node: ClassLikeDeclaration) {
+                emitDecoratorsOfMembers(node, /*staticFlag*/ 0);
+                emitDecoratorsOfMembers(node, NodeFlags.Static);
+                emitDecoratorsOfConstructor(node);
+            }
+
+            function emitDecoratorsOfConstructor(node: ClassLikeDeclaration) {
+                let decorators = node.decorators;
+                let constructor = getFirstConstructorWithBody(node);
+                let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated);
+
+                // skip decoration of the constructor if neither it nor its parameters are decorated
+                if (!decorators && !hasDecoratedParameters) {
+                    return;
+                }
+
+                // Emit the call to __decorate. Given the class:
+                //
+                //   @dec
+                //   class C {
+                //   }
+                //
+                // The emit for the class is:
+                //
+                //   C = __decorate([dec], C);
+                //
+
+                writeLine();
+                emitStart(node);
+                emitDeclarationName(node);
+                write(" = __decorate([");
+                increaseIndent();
+                writeLine();
+
+                let decoratorCount = decorators ? decorators.length : 0;
+                let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
+                    emitStart(decorator);
+                    emit(decorator.expression);
+                    emitEnd(decorator);
+                });
+
+                argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
+                emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0);
+
+                decreaseIndent();
+                writeLine();
+                write("], ");
+                emitDeclarationName(node);
+                write(");");
+                emitEnd(node);
+                writeLine();
+            }
+
+            function emitDecoratorsOfMembers(node: ClassLikeDeclaration, staticFlag: NodeFlags) {
+                for (let member of node.members) {
+                    // only emit members in the correct group
+                    if ((member.flags & NodeFlags.Static) !== staticFlag) {
+                        continue;
+                    }
+
+                    // skip members that cannot be decorated (such as the constructor)
+                    if (!nodeCanBeDecorated(member)) {
+                        continue;
+                    }
+
+                    // skip a member if it or any of its parameters are not decorated
+                    if (!nodeOrChildIsDecorated(member)) {
+                        continue;
+                    }
+
+                    // skip an accessor declaration if it is not the first accessor
+                    let decorators: NodeArray<Decorator>;
+                    let functionLikeMember: FunctionLikeDeclaration;
+                    if (isAccessor(member)) {
+                        let accessors = getAllAccessorDeclarations(node.members, <AccessorDeclaration>member);
+                        if (member !== accessors.firstAccessor) {
+                            continue;
+                        }
+
+                        // get the decorators from the first accessor with decorators
+                        decorators = accessors.firstAccessor.decorators;
+                        if (!decorators && accessors.secondAccessor) {
+                            decorators = accessors.secondAccessor.decorators;
+                        }
+
+                        // we only decorate parameters of the set accessor
+                        functionLikeMember = accessors.setAccessor;
+                    }
+                    else {
+                        decorators = member.decorators;
+
+                        // we only decorate the parameters here if this is a method
+                        if (member.kind === SyntaxKind.MethodDeclaration) {
+                            functionLikeMember = <MethodDeclaration>member;
+                        }
+                    }
+
+                    // Emit the call to __decorate. Given the following:
+                    //
+                    //   class C {
+                    //     @dec method(@dec2 x) {}
+                    //     @dec get accessor() {}
+                    //     @dec prop;
+                    //   }
+                    //
+                    // The emit for a method is:
+                    //
+                    //   Object.defineProperty(C.prototype, "method", 
+                    //       __decorate([
+                    //           dec,
+                    //           __param(0, dec2),
+                    //           __metadata("design:type", Function),
+                    //           __metadata("design:paramtypes", [Object]),
+                    //           __metadata("design:returntype", void 0)
+                    //       ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
+                    // 
+                    // The emit for an accessor is:
+                    //
+                    //   Object.defineProperty(C.prototype, "accessor", 
+                    //       __decorate([
+                    //           dec
+                    //       ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
+                    //
+                    // The emit for a property is:
+                    //
+                    //   __decorate([
+                    //       dec
+                    //   ], C.prototype, "prop");
+                    //
+
+                    writeLine();
+                    emitStart(member);
+                    if (member.kind !== SyntaxKind.PropertyDeclaration) {
+                        write("Object.defineProperty(");
+                        emitStart(member.name);
+                        emitClassMemberPrefix(node, member);
+                        write(", ");
+                        emitExpressionForPropertyName(member.name);
+                        emitEnd(member.name);
+                        write(",");
+                        increaseIndent();
+                        writeLine();
+                    }
+
+                    write("__decorate([");
+                    increaseIndent();
+                    writeLine();
+
+                    let decoratorCount = decorators ? decorators.length : 0;
+                    let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
+                        emitStart(decorator);
+                        emit(decorator.expression);
+                        emitEnd(decorator);
+                    });
+
+                    argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
+                    emitSerializedTypeMetadata(member, argumentsWritten > 0);
+
+                    decreaseIndent();
+                    writeLine();
+                    write("], ");
+                    emitStart(member.name);
+                    emitClassMemberPrefix(node, member);
+                    write(", ");
+                    emitExpressionForPropertyName(member.name);
+                    emitEnd(member.name);
+
+                    if (member.kind !== SyntaxKind.PropertyDeclaration) {
+                        write(", Object.getOwnPropertyDescriptor(");
+                        emitStart(member.name);
+                        emitClassMemberPrefix(node, member);
+                        write(", ");
+                        emitExpressionForPropertyName(member.name);
+                        emitEnd(member.name);
+                        write("))");
+                        decreaseIndent();
+                    }
+
+                    write(");");
+                    emitEnd(member);
+                    writeLine();
+                }
+            }
+
+            function emitDecoratorsOfParameters(node: FunctionLikeDeclaration, leadingComma: boolean): number {
+                let argumentsWritten = 0;
+                if (node) {
+                    let parameterIndex = 0;
+                    for (let parameter of node.parameters) {
+                        if (nodeIsDecorated(parameter)) {
+                            let decorators = parameter.decorators;
+                            argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, decorator => {
+                                emitStart(decorator);
+                                write(`__param(${parameterIndex}, `);
+                                emit(decorator.expression);
+                                write(")");
+                                emitEnd(decorator);
+                            });
+                            leadingComma = true;
+                        }
+                        ++parameterIndex;
+                    }
+                }
+                return argumentsWritten;
+            }
+
+            function shouldEmitTypeMetadata(node: Declaration): boolean {
+                // This method determines whether to emit the "design:type" metadata based on the node's kind.
+                // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata 
+                // compiler option is set.
+                switch (node.kind) {
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.PropertyDeclaration:
+                        return true;
+                }
+
+                return false;
+            }
+
+            function shouldEmitReturnTypeMetadata(node: Declaration): boolean {
+                // This method determines whether to emit the "design:returntype" metadata based on the node's kind.
+                // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata 
+                // compiler option is set.
+                switch (node.kind) {
+                    case SyntaxKind.MethodDeclaration:
+                        return true;
+                }
+                return false;
+            }
+
+            function shouldEmitParamTypesMetadata(node: Declaration): boolean {
+                // This method determines whether to emit the "design:paramtypes" metadata based on the node's kind.
+                // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata 
+                // compiler option is set.
+                switch (node.kind) {
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.SetAccessor:
+                        return true;
+                }
+                return false;
+            }
+
+            function emitSerializedTypeMetadata(node: Declaration, writeComma: boolean): number {
+                // This method emits the serialized type metadata for a decorator target.
+                // The caller should have already tested whether the node has decorators.
+                let argumentsWritten = 0;
+                if (compilerOptions.emitDecoratorMetadata) {
+                    if (shouldEmitTypeMetadata(node)) {
+                        var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
+                        if (serializedType) {
+                            if (writeComma) {
+                                write(", ");
+                            }
+                            writeLine();
+                            write("__metadata('design:type', ");
+                            emitSerializedType(node, serializedType);
+                            write(")");
+                            argumentsWritten++;
+                        }
+                    }
+                    if (shouldEmitParamTypesMetadata(node)) {
+                        var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
+                        if (serializedTypes) {
+                            if (writeComma || argumentsWritten) {
+                                write(", ");
+                            }
+                            writeLine();
+                            write("__metadata('design:paramtypes', [");
+                            for (var i = 0; i < serializedTypes.length; ++i) {
+                                if (i > 0) {
+                                    write(", ");
+                                }
+                                emitSerializedType(node, serializedTypes[i]);
+                            }
+                            write("])");
+                            argumentsWritten++;
+                        }
+                    }
+                    if (shouldEmitReturnTypeMetadata(node)) {
+                        var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
+                        if (serializedType) {
+                            if (writeComma || argumentsWritten) {
+                                write(", ");
+                            }
+                            writeLine();
+                            write("__metadata('design:returntype', ");
+                            emitSerializedType(node, serializedType);
+                            write(")");
+                            argumentsWritten++;
+                        }
+                    }
+                }
+                return argumentsWritten;
+            }
+
+            function serializeTypeNameSegment(location: Node, path: string[], index: number): string {
+                switch (index) {
+                    case 0:
+                        return `typeof ${path[index]} !== 'undefined' && ${path[index]}`;
+                    case 1:
+                        return `${serializeTypeNameSegment(location, path, index - 1) }.${path[index]}`;
+                    default:
+                        let temp = createAndRecordTempVariable(TempFlags.Auto).text;
+                        return `(${temp} = ${serializeTypeNameSegment(location, path, index - 1) }) && ${temp}.${path[index]}`;
+                }
+            }
+
+            function emitSerializedType(location: Node, name: string | string[]): void {
+                if (typeof name === "string") {
+                    write(name);
+                    return;
+                }
+                else {
+                    Debug.assert(name.length > 0, "Invalid serialized type name");
+                    write(`(${serializeTypeNameSegment(location, name, name.length - 1) }) || Object`);
+                }
+            }
+
+            function emitInterfaceDeclaration(node: InterfaceDeclaration) {
+                emitOnlyPinnedOrTripleSlashComments(node);
+            }
+
+            function shouldEmitEnumDeclaration(node: EnumDeclaration) {
+                let isConstEnum = isConst(node);
+                return !isConstEnum || compilerOptions.preserveConstEnums || compilerOptions.separateCompilation;
+            }
+
+            function emitEnumDeclaration(node: EnumDeclaration) {
+                // const enums are completely erased during compilation.
+                if (!shouldEmitEnumDeclaration(node)) {
+                    return;
+                }
+
+                if (!(node.flags & NodeFlags.Export) || isES6ExportedDeclaration(node)) {
+                    emitStart(node);
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                    }
+                    write("var ");
+                    emit(node.name);
+                    emitEnd(node);
+                    write(";");
+                }
+                writeLine();
+                emitStart(node);
+                write("(function (");
+                emitStart(node.name);
+                write(getGeneratedNameForNode(node));
+                emitEnd(node.name);
+                write(") {");
+                increaseIndent();
+                scopeEmitStart(node);
+                emitLines(node.members);
+                decreaseIndent();
+                writeLine();
+                emitToken(SyntaxKind.CloseBraceToken, node.members.end);
+                scopeEmitEnd();
+                write(")(");
+                emitModuleMemberName(node);
+                write(" || (");
+                emitModuleMemberName(node);
+                write(" = {}));");
+                emitEnd(node);
+                if (!isES6ExportedDeclaration(node) && node.flags & NodeFlags.Export) {
+                    writeLine();
+                    emitStart(node);
+                    write("var ");
+                    emit(node.name);
+                    write(" = ");
+                    emitModuleMemberName(node);
+                    emitEnd(node);
+                    write(";");
+                }
+                if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) {
+                    emitExportMemberAssignments(node.name);
+                }
+            }
+
+            function emitEnumMember(node: EnumMember) {
+                let enumParent = <EnumDeclaration>node.parent;
+                emitStart(node);
+                write(getGeneratedNameForNode(enumParent));
+                write("[");
+                write(getGeneratedNameForNode(enumParent));
+                write("[");
+                emitExpressionForPropertyName(node.name);
+                write("] = ");
+                writeEnumMemberDeclarationValue(node);
+                write("] = ");
+                emitExpressionForPropertyName(node.name);
+                emitEnd(node);
+                write(";");
+            }
+
+            function writeEnumMemberDeclarationValue(member: EnumMember) {
+                let value = resolver.getConstantValue(member);
+                if (value !== undefined) {
+                    write(value.toString());
+                    return;
+                }
+                else if (member.initializer) {
+                    emit(member.initializer);
+                }
+                else {
+                    write("undefined");
+                }
+            }
+
+            function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration: ModuleDeclaration): ModuleDeclaration {
+                if (moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
+                    let recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(<ModuleDeclaration>moduleDeclaration.body);
+                    return recursiveInnerModule || <ModuleDeclaration>moduleDeclaration.body;
+                }
+            }
+
+            function shouldEmitModuleDeclaration(node: ModuleDeclaration) {
+                return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.separateCompilation);
+            }
+
+            function isModuleMergedWithES6Class(node: ModuleDeclaration) {
+                return languageVersion === ScriptTarget.ES6 && !!(resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalModuleMergesWithClass);
+            }
+
+            function emitModuleDeclaration(node: ModuleDeclaration) {
+                // Emit only if this module is non-ambient.
+                let shouldEmit = shouldEmitModuleDeclaration(node);
+
+                if (!shouldEmit) {
+                    return emitOnlyPinnedOrTripleSlashComments(node);
+                }
+
+                if (!isModuleMergedWithES6Class(node)) {
+                    emitStart(node);
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                    }
+
+                    write("var ");
+                    emit(node.name);
+                    write(";");
+                    emitEnd(node);
+                    writeLine();
+                }
+
+                emitStart(node);
+                write("(function (");
+                emitStart(node.name);
+                write(getGeneratedNameForNode(node));
+                emitEnd(node.name);
+                write(") ");
+                if (node.body.kind === SyntaxKind.ModuleBlock) {
+                    let saveTempFlags = tempFlags;
+                    let saveTempVariables = tempVariables;
+                    tempFlags = 0;
+                    tempVariables = undefined;
+
+                    emit(node.body);
+
+                    tempFlags = saveTempFlags;
+                    tempVariables = saveTempVariables;
+                }
+                else {
+                    write("{");
+                    increaseIndent();
+                    scopeEmitStart(node);
+                    emitCaptureThisForNodeIfNecessary(node);
+                    writeLine();
+                    emit(node.body);
+                    decreaseIndent();
+                    writeLine();
+                    let moduleBlock = <ModuleBlock>getInnerMostModuleDeclarationFromDottedModule(node).body;
+                    emitToken(SyntaxKind.CloseBraceToken, moduleBlock.statements.end);
+                    scopeEmitEnd();
+                }
+                write(")(");
+                // write moduleDecl = containingModule.m only if it is not exported es6 module member
+                if ((node.flags & NodeFlags.Export) && !isES6ExportedDeclaration(node)) {
+                    emit(node.name);
+                    write(" = ");
+                }
+                emitModuleMemberName(node);
+                write(" || (");
+                emitModuleMemberName(node);
+                write(" = {}));");
+                emitEnd(node);
+                if (!isES6ExportedDeclaration(node) && node.name.kind === SyntaxKind.Identifier && node.parent === currentSourceFile) {
+                    emitExportMemberAssignments(<Identifier>node.name);
+                }
+            }
+
+            function emitRequire(moduleName: Expression) {
+                if (moduleName.kind === SyntaxKind.StringLiteral) {
+                    write("require(");
+                    emitStart(moduleName);
+                    emitLiteral(<LiteralExpression>moduleName);
+                    emitEnd(moduleName);
+                    emitToken(SyntaxKind.CloseParenToken, moduleName.end);
+                }
+                else {
+                    write("require()");
+                }
+            }
+
+            function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
+                if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
+                    return <ImportEqualsDeclaration>node;
+                }
+                let importClause = (<ImportDeclaration>node).importClause;
+                if (importClause && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
+                    return <NamespaceImport>importClause.namedBindings;
+                }
+            }
+
+            function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
+                return node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause && !!(<ImportDeclaration>node).importClause.name;
+            }
+
+            function emitExportImportAssignments(node: Node) {
+                if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) {
+                    emitExportMemberAssignments(<Identifier>(<Declaration>node).name);
+                }
+                forEachChild(node, emitExportImportAssignments);
+            }
+
+            function emitImportDeclaration(node: ImportDeclaration) {
+                if (languageVersion < ScriptTarget.ES6) {
+                    return emitExternalImportDeclaration(node);
+                }
+
+                // ES6 import
+                if (node.importClause) {
+                    let shouldEmitDefaultBindings = resolver.isReferencedAliasDeclaration(node.importClause);
+                    let shouldEmitNamedBindings = node.importClause.namedBindings && resolver.isReferencedAliasDeclaration(node.importClause.namedBindings, /* checkChildren */ true);
+                    if (shouldEmitDefaultBindings || shouldEmitNamedBindings) {
+                        write("import ");
+                        emitStart(node.importClause);
+                        if (shouldEmitDefaultBindings) {
+                            emit(node.importClause.name);
+                            if (shouldEmitNamedBindings) {
+                                write(", ");
+                            }
+                        }
+                        if (shouldEmitNamedBindings) {
+                            emitLeadingComments(node.importClause.namedBindings);
+                            emitStart(node.importClause.namedBindings);
+                            if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
+                                write("* as ");
+                                emit((<NamespaceImport>node.importClause.namedBindings).name);
+                            }
+                            else {
+                                write("{ ");
+                                emitExportOrImportSpecifierList((<NamedImports>node.importClause.namedBindings).elements, resolver.isReferencedAliasDeclaration);
+                                write(" }");
+                            }
+                            emitEnd(node.importClause.namedBindings);
+                            emitTrailingComments(node.importClause.namedBindings);
+                        }
+
+                        emitEnd(node.importClause);
+                        write(" from ");
+                        emit(node.moduleSpecifier);
+                        write(";");
+                    }
+                }
+                else {
+                    write("import ");
+                    emit(node.moduleSpecifier);
+                    write(";");
+                }
+            }
+
+            function emitExternalImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration) {
+                if (contains(externalImports, node)) {
+                    let isExportedImport = node.kind === SyntaxKind.ImportEqualsDeclaration && (node.flags & NodeFlags.Export) !== 0;
+                    let namespaceDeclaration = getNamespaceDeclarationNode(node);
+
+                    if (compilerOptions.module !== ModuleKind.AMD) {
+                        emitLeadingComments(node);
+                        emitStart(node);
+                        if (namespaceDeclaration && !isDefaultImport(node)) {
+                            // import x = require("foo")
+                            // import * as x from "foo"
+                            if (!isExportedImport) write("var ");
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                        }
+                        else {
+                            // import "foo"
+                            // import x from "foo"
+                            // import { x, y } from "foo"
+                            // import d, * as x from "foo"
+                            // import d, { x, y } from "foo"
+                            let isNakedImport = SyntaxKind.ImportDeclaration && !(<ImportDeclaration>node).importClause;
+                            if (!isNakedImport) {
+                                write("var ");
+                                write(getGeneratedNameForNode(<ImportDeclaration>node));
+                                write(" = ");
+                            }
+                        }
+                        emitRequire(getExternalModuleName(node));
+                        if (namespaceDeclaration && isDefaultImport(node)) {
+                            // import d, * as x from "foo"
+                            write(", ");
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                            write(getGeneratedNameForNode(<ImportDeclaration>node));
+                        }
+                        write(";");
+                        emitEnd(node);
+                        emitExportImportAssignments(node);
+                        emitTrailingComments(node);
+                    }
+                    else {
+                        if (isExportedImport) {
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                            emit(namespaceDeclaration.name);
+                            write(";");
+                        }
+                        else if (namespaceDeclaration && isDefaultImport(node)) {
+                            // import d, * as x from "foo"
+                            write("var ");
+                            emitModuleMemberName(namespaceDeclaration);
+                            write(" = ");
+                            write(getGeneratedNameForNode(<ImportDeclaration>node));
+                            write(";");
+                        }
+                        emitExportImportAssignments(node);
+                    }
+                }
+            }
+
+            function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) {
+                if (isExternalModuleImportEqualsDeclaration(node)) {
+                    emitExternalImportDeclaration(node);
+                    return;
+                }
+                // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when
+                // - current file is not external module
+                // - import declaration is top level and target is value imported by entity name
+                if (resolver.isReferencedAliasDeclaration(node) ||
+                    (!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
+                    emitLeadingComments(node);
+                    emitStart(node);
+                    if (isES6ExportedDeclaration(node)) {
+                        write("export ");
+                        write("var ");
+                    }
+                    else if (!(node.flags & NodeFlags.Export)) {
+                        write("var ");
+                    }
+                    emitModuleMemberName(node);
+                    write(" = ");
+                    emit(node.moduleReference);
+                    write(";");
+                    emitEnd(node);
+                    emitExportImportAssignments(node);
+                    emitTrailingComments(node);
+                }
+            }
+
+            function emitExportDeclaration(node: ExportDeclaration) {
+                if (languageVersion < ScriptTarget.ES6) {
+                    if (node.moduleSpecifier && (!node.exportClause || resolver.isValueAliasDeclaration(node))) {
+                        emitStart(node);
+                        let generatedName = getGeneratedNameForNode(node);
+                        if (node.exportClause) {
+                            // export { x, y, ... } from "foo"
+                            if (compilerOptions.module !== ModuleKind.AMD) {
+                                write("var ");
+                                write(generatedName);
+                                write(" = ");
+                                emitRequire(getExternalModuleName(node));
+                                write(";");
+                            }
+                            for (let specifier of node.exportClause.elements) {
+                                if (resolver.isValueAliasDeclaration(specifier)) {
+                                    writeLine();
+                                    emitStart(specifier);
+                                    emitContainingModuleName(specifier);
+                                    write(".");
+                                    emitNodeWithoutSourceMap(specifier.name);
+                                    write(" = ");
+                                    write(generatedName);
+                                    write(".");
+                                    emitNodeWithoutSourceMap(specifier.propertyName || specifier.name);
+                                    write(";");
+                                    emitEnd(specifier);
+                                }
+                            }
+                        }
+                        else {
+                            // export * from "foo"
+                            writeLine();
+                            write("__export(");
+                            if (compilerOptions.module !== ModuleKind.AMD) {
+                                emitRequire(getExternalModuleName(node));
+                            }
+                            else {
+                                write(generatedName);
+                            }
+                            write(");");
+                        }
+                        emitEnd(node);
+                    }
+                }
+                else {
+                    if (!node.exportClause || resolver.isValueAliasDeclaration(node)) {
+                        emitStart(node);
+                        write("export ");
+                        if (node.exportClause) {
+                            // export { x, y, ... }
+                            write("{ ");
+                            emitExportOrImportSpecifierList(node.exportClause.elements, resolver.isValueAliasDeclaration);
+                            write(" }");
+                        }
+                        else {
+                            write("*");
+                        }
+                        if (node.moduleSpecifier) {
+                            write(" from ");
+                            emitNodeWithoutSourceMap(node.moduleSpecifier);
+                        }
+                        write(";");
+                        emitEnd(node);
+                    }
+                }
+            }
+
+            function emitExportOrImportSpecifierList(specifiers: ImportOrExportSpecifier[], shouldEmit: (node: Node) => boolean) {
+                Debug.assert(languageVersion >= ScriptTarget.ES6);
+
+                let needsComma = false;
+                for (let specifier of specifiers) {
+                    if (shouldEmit(specifier)) {
+                        if (needsComma) {
+                            write(", ");
+                        }
+                        emitStart(specifier);
+                        if (specifier.propertyName) {
+                            emitNodeWithoutSourceMap(specifier.propertyName);
+                            write(" as ");
+                        }
+                        emitNodeWithoutSourceMap(specifier.name);
+                        emitEnd(specifier);
+                        needsComma = true;
+                    }
+                }
+            }
+
+            function emitExportAssignment(node: ExportAssignment) {
+                if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) {
+                    if (languageVersion >= ScriptTarget.ES6) {
+                        writeLine();
+                        emitStart(node);
+                        write("export default ");
+                        var expression = node.expression;
+                        emit(expression);
+                        if (expression.kind !== SyntaxKind.FunctionDeclaration &&
+                            expression.kind !== SyntaxKind.ClassDeclaration) {
+                            write(";");
+                        }
+                        emitEnd(node);
+                    }
+                    else {
+                        writeLine();
+                        emitStart(node);
+                        emitContainingModuleName(node);
+                        if (languageVersion === ScriptTarget.ES3) {
+                            write("[\"default\"] = ");
+                        } else {
+                            write(".default = ");
+                        }
+                        emit(node.expression);
+                        write(";");
+                        emitEnd(node);
+                    }
+                }
+            }
+
+            function collectExternalModuleInfo(sourceFile: SourceFile) {
+                externalImports = [];
+                exportSpecifiers = {};
+                exportEquals = undefined;
+                hasExportStars = false;
+                for (let node of sourceFile.statements) {
+                    switch (node.kind) {
+                        case SyntaxKind.ImportDeclaration:
+                            if (!(<ImportDeclaration>node).importClause ||
+                                resolver.isReferencedAliasDeclaration((<ImportDeclaration>node).importClause, /*checkChildren*/ true)) {
+                                // import "mod"
+                                // import x from "mod" where x is referenced
+                                // import * as x from "mod" where x is referenced
+                                // import { x, y } from "mod" where at least one import is referenced
+                                externalImports.push(<ImportDeclaration>node);
+                            }
+                            break;
+                        case SyntaxKind.ImportEqualsDeclaration:
+                            if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(node)) {
+                                // import x = require("mod") where x is referenced
+                                externalImports.push(<ImportEqualsDeclaration>node);
+                            }
+                            break;
+                        case SyntaxKind.ExportDeclaration:
+                            if ((<ExportDeclaration>node).moduleSpecifier) {
+                                if (!(<ExportDeclaration>node).exportClause) {
+                                    // export * from "mod"
+                                    externalImports.push(<ExportDeclaration>node);
+                                    hasExportStars = true;
+                                }
+                                else if (resolver.isValueAliasDeclaration(node)) {
+                                    // export { x, y } from "mod" where at least one export is a value symbol
+                                    externalImports.push(<ExportDeclaration>node);
+                                }
+                            }
+                            else {
+                                // export { x, y }
+                                for (let specifier of (<ExportDeclaration>node).exportClause.elements) {
+                                    let name = (specifier.propertyName || specifier.name).text;
+                                    (exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
+                                }
+                            }
+                            break;
+                        case SyntaxKind.ExportAssignment:
+                            if ((<ExportAssignment>node).isExportEquals && !exportEquals) {
+                                // export = x
+                                exportEquals = <ExportAssignment>node;
+                            }
+                            break;
+                    }
+                }
+            }
+
+            function emitExportStarHelper() {
+                if (hasExportStars) {
+                    writeLine();
+                    write("function __export(m) {");
+                    increaseIndent();
+                    writeLine();
+                    write("for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];");
+                    decreaseIndent();
+                    writeLine();
+                    write("}");
+                }
+            }
+
+            function emitAMDDependencies(node: SourceFile, includeNonAmdDependencies: boolean) {
+                // An AMD define function has the following shape:
+                //     define(id?, dependencies?, factory);
+                //
+                // This has the shape of
+                //     define(name, ["module1", "module2"], function (module1Alias) {
+                // The location of the alias in the parameter list in the factory function needs to
+                // match the position of the module name in the dependency list.
+                //
+                // To ensure this is true in cases of modules with no aliases, e.g.:
+                // `import "module"` or `<amd-dependency path= "a.css" />`
+                // we need to add modules without alias names to the end of the dependencies list
+
+                let aliasedModuleNames: string[] = [];   // names of modules with corresponding parameter in the
+                                                         // factory function.
+                let unaliasedModuleNames: string[] = []; // names of modules with no corresponding parameters in
+                                                         // factory function.
+                let importAliasNames: string[] = [];     // names of the parameters in the factory function; these
+                                                         // parameters need to match the indexes of the corresponding
+                                                         // module names in aliasedModuleNames.
+
+                // Fill in amd-dependency tags
+                for (let amdDependency of node.amdDependencies) {
+                    if (amdDependency.name) {
+                        aliasedModuleNames.push("\"" + amdDependency.path + "\"");
+                        importAliasNames.push(amdDependency.name);
+                    }
+                    else {
+                        unaliasedModuleNames.push("\"" + amdDependency.path + "\"");
+                    }
+                }
+
+                for (let importNode of externalImports) {
+                    // Find the name of the external module
+                    let externalModuleName = "";
+                    let moduleName = getExternalModuleName(importNode);
+                    if (moduleName.kind === SyntaxKind.StringLiteral) {
+                        externalModuleName = getLiteralText(<LiteralExpression>moduleName);
+                    }
+
+                    // Find the name of the module alias, if there is one
+                    let importAliasName: string;
+                    let namespaceDeclaration = getNamespaceDeclarationNode(importNode);
+                    if (namespaceDeclaration && !isDefaultImport(importNode)) {
+                        importAliasName = getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name);
+                    }
+                    else {
+                        importAliasName = getGeneratedNameForNode(<ImportDeclaration | ExportDeclaration>importNode);
+                    }
+
+                    if (includeNonAmdDependencies && importAliasName) {
+                        aliasedModuleNames.push(externalModuleName);
+                        importAliasNames.push(importAliasName);
+                    }
+                    else {
+                        unaliasedModuleNames.push(externalModuleName);
+                    }
+                }
+
+                write("[\"require\", \"exports\"");
+                if (aliasedModuleNames.length) {
+                    write(", ");
+                    write(aliasedModuleNames.join(", "));
+                }
+                if (unaliasedModuleNames.length) {
+                    write(", ");
+                    write(unaliasedModuleNames.join(", "));
+                }
+                write("], function (require, exports");
+                if (importAliasNames.length) {
+                    write(", ");
+                    write(importAliasNames.join(", "));
+                }
+            }
+
+            function emitAMDModule(node: SourceFile, startIndex: number) {
+                collectExternalModuleInfo(node);
+
+                writeLine();
+                write("define(");
+                if (node.amdModuleName) {
+                    write("\"" + node.amdModuleName + "\", ");
+                }
+                emitAMDDependencies(node, /*includeNonAmdDependencies*/ true);
+                write(") {");
+                increaseIndent();
+                emitExportStarHelper();
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(/*newLine*/ true);
+                emitExportEquals(/*emitAsReturn*/ true);
+                decreaseIndent();
+                writeLine();
+                write("});");
+            }
+
+            function emitCommonJSModule(node: SourceFile, startIndex: number) {
+                collectExternalModuleInfo(node);
+                emitExportStarHelper();
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(/*newLine*/ true);
+                emitExportEquals(/*emitAsReturn*/ false);
+            }
+
+            function emitUMDModule(node: SourceFile, startIndex: number) {
+                collectExternalModuleInfo(node);
+
+                // Module is detected first to support Browserify users that load into a browser with an AMD loader
+                writeLines(`(function (deps, factory) {
+    if (typeof module === 'object' && typeof module.exports === 'object') {
+        var v = factory(require, exports); if (v !== undefined) module.exports = v;
+    }
+    else if (typeof define === 'function' && define.amd) {
+        define(deps, factory);
+    }
+})(`);
+                emitAMDDependencies(node, false);
+                write(") {");
+                increaseIndent();
+                emitExportStarHelper();
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(/*newLine*/ true);
+                emitExportEquals(/*emitAsReturn*/ true);
+                decreaseIndent();
+                writeLine();
+                write("});");
+            }
+
+            function emitES6Module(node: SourceFile, startIndex: number) {
+                externalImports = undefined;
+                exportSpecifiers = undefined;
+                exportEquals = undefined;
+                hasExportStars = false;
+                emitCaptureThisForNodeIfNecessary(node);
+                emitLinesStartingAt(node.statements, startIndex);
+                emitTempDeclarations(/*newLine*/ true);
+                // Emit exportDefault if it exists will happen as part 
+                // or normal statement emit.
+            }
+
+            function emitExportEquals(emitAsReturn: boolean) {
+                if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
+                    writeLine();
+                    emitStart(exportEquals);
+                    write(emitAsReturn ? "return " : "module.exports = ");
+                    emit((<ExportAssignment>exportEquals).expression);
+                    write(";");
+                    emitEnd(exportEquals);
+                }
+            }
+
+            function emitDirectivePrologues(statements: Node[], startWithNewLine: boolean): number {
+                for (let i = 0; i < statements.length; ++i) {
+                    if (isPrologueDirective(statements[i])) {
+                        if (startWithNewLine || i > 0) {
+                            writeLine();
+                        }
+                        emit(statements[i]);
+                    }
+                    else {
+                        // return index of the first non prologue directive
+                        return i;
+                    }
+                }
+                return statements.length;
+            }
+
+            function writeLines(text: string): void {
+                let lines = text.split(/\r\n|\r|\n/g);
+                for (let i = 0; i < lines.length; ++i) {
+                    let line = lines[i];
+                    if (line.length) {
+                        writeLine();
+                        write(line);
+                    }
+                }
+            }
+
+            function emitSourceFileNode(node: SourceFile) {
+                // Start new file on new line
+                writeLine();
+                emitDetachedComments(node);
+
+                // emit prologue directives prior to __extends
+                var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false);
+                // Only Emit __extends function when target ES5.
+                // For target ES6 and above, we can emit classDeclaration as is.
+                if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitExtends)) {
+                    writeLines(extendsHelper);
+                    extendsEmitted = true;
+                }
+
+                if (!decorateEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitDecorate) {
+                    writeLines(decorateHelper);
+                    if (compilerOptions.emitDecoratorMetadata) {
+                        writeLines(metadataHelper);
+                    }
+                    decorateEmitted = true;
+                }
+
+                if (!paramEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitParam) {
+                    writeLines(paramHelper);
+                    paramEmitted = true;
+                }
+
+                if (isExternalModule(node)) {
+                    if (languageVersion >= ScriptTarget.ES6) {
+                        emitES6Module(node, startIndex);
+                    }
+                    else if (compilerOptions.module === ModuleKind.AMD) {
+                        emitAMDModule(node, startIndex);
+                    }
+                    else if (compilerOptions.module === ModuleKind.UMD) {
+                        emitUMDModule(node, startIndex);
+                    }
+                    else {
+                        emitCommonJSModule(node, startIndex);
+                    }
+                }
+                else {
+                    externalImports = undefined;
+                    exportSpecifiers = undefined;
+                    exportEquals = undefined;
+                    hasExportStars = false;
+                    emitCaptureThisForNodeIfNecessary(node);
+                    emitLinesStartingAt(node.statements, startIndex);
+                    emitTempDeclarations(/*newLine*/ true);
+                }
+
+                emitLeadingComments(node.endOfFileToken);
+            }
+
+            function emitNodeWithoutSourceMap(node: Node, allowGeneratedIdentifiers?: boolean): void {
+                if (!node) {
+                    return;
+                }
+
+                if (node.flags & NodeFlags.Ambient) {
+                    return emitOnlyPinnedOrTripleSlashComments(node);
+                }
+
+                let emitComments = shouldEmitLeadingAndTrailingComments(node);
+                if (emitComments) {
+                    emitLeadingComments(node);
+                }
+
+                emitJavaScriptWorker(node, allowGeneratedIdentifiers);
+
+                if (emitComments) {
+                    emitTrailingComments(node);
+                }
+            }
+
+            function shouldEmitLeadingAndTrailingComments(node: Node) {
+                switch (node.kind) {
+                    // All of these entities are emitted in a specialized fashion.  As such, we allow
+                    // the specialized methods for each to handle the comments on the nodes.
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.ImportDeclaration:
+                    case SyntaxKind.ImportEqualsDeclaration:
+                    case SyntaxKind.TypeAliasDeclaration:
+                    case SyntaxKind.ExportAssignment:
+                        return false;
+
+                    case SyntaxKind.ModuleDeclaration:
+                        // Only emit the leading/trailing comments for a module if we're actually
+                        // emitting the module as well.
+                        return shouldEmitModuleDeclaration(<ModuleDeclaration>node);
+
+                    case SyntaxKind.EnumDeclaration:
+                        // Only emit the leading/trailing comments for an enum if we're actually
+                        // emitting the module as well.
+                        return shouldEmitEnumDeclaration(<EnumDeclaration>node);
+                }
+
+                // If this is the expression body of an arrow function that we're down-leveling, 
+                // then we don't want to emit comments when we emit the body.  It will have already
+                // been taken care of when we emitted the 'return' statement for the function
+                // expression body.
+                if (node.kind !== SyntaxKind.Block &&
+                    node.parent &&
+                    node.parent.kind === SyntaxKind.ArrowFunction &&
+                    (<ArrowFunction>node.parent).body === node && 
+                    compilerOptions.target <= ScriptTarget.ES5) {
+
+                    return false;
+                }
+
+                // Emit comments for everything else.
+                return true;
+            }
+
+            function emitJavaScriptWorker(node: Node, allowGeneratedIdentifiers: boolean = true) {
+                // Check if the node can be emitted regardless of the ScriptTarget
+                switch (node.kind) {
+                    case SyntaxKind.Identifier:
+                        return emitIdentifier(<Identifier>node, allowGeneratedIdentifiers);
+                    case SyntaxKind.Parameter:
+                        return emitParameter(<ParameterDeclaration>node);
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                        return emitMethod(<MethodDeclaration>node);
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                        return emitAccessor(<AccessorDeclaration>node);
+                    case SyntaxKind.ThisKeyword:
+                        return emitThis(node);
+                    case SyntaxKind.SuperKeyword:
+                        return emitSuper(node);
+                    case SyntaxKind.NullKeyword:
+                        return write("null");
+                    case SyntaxKind.TrueKeyword:
+                        return write("true");
+                    case SyntaxKind.FalseKeyword:
+                        return write("false");
+                    case SyntaxKind.NumericLiteral:
+                    case SyntaxKind.StringLiteral:
+                    case SyntaxKind.RegularExpressionLiteral:
+                    case SyntaxKind.NoSubstitutionTemplateLiteral:
+                    case SyntaxKind.TemplateHead:
+                    case SyntaxKind.TemplateMiddle:
+                    case SyntaxKind.TemplateTail:
+                        return emitLiteral(<LiteralExpression>node);
+                    case SyntaxKind.TemplateExpression:
+                        return emitTemplateExpression(<TemplateExpression>node);
+                    case SyntaxKind.TemplateSpan:
+                        return emitTemplateSpan(<TemplateSpan>node);
+                    case SyntaxKind.QualifiedName:
+                        return emitQualifiedName(<QualifiedName>node);
+                    case SyntaxKind.ObjectBindingPattern:
+                        return emitObjectBindingPattern(<BindingPattern>node);
+                    case SyntaxKind.ArrayBindingPattern:
+                        return emitArrayBindingPattern(<BindingPattern>node);
+                    case SyntaxKind.BindingElement:
+                        return emitBindingElement(<BindingElement>node);
+                    case SyntaxKind.ArrayLiteralExpression:
+                        return emitArrayLiteral(<ArrayLiteralExpression>node);
+                    case SyntaxKind.ObjectLiteralExpression:
+                        return emitObjectLiteral(<ObjectLiteralExpression>node);
+                    case SyntaxKind.PropertyAssignment:
+                        return emitPropertyAssignment(<PropertyDeclaration>node);
+                    case SyntaxKind.ShorthandPropertyAssignment:
+                        return emitShorthandPropertyAssignment(<ShorthandPropertyAssignment>node);
+                    case SyntaxKind.ComputedPropertyName:
+                        return emitComputedPropertyName(<ComputedPropertyName>node);
+                    case SyntaxKind.PropertyAccessExpression:
+                        return emitPropertyAccess(<PropertyAccessExpression>node);
+                    case SyntaxKind.ElementAccessExpression:
+                        return emitIndexedAccess(<ElementAccessExpression>node);
+                    case SyntaxKind.CallExpression:
+                        return emitCallExpression(<CallExpression>node);
+                    case SyntaxKind.NewExpression:
+                        return emitNewExpression(<NewExpression>node);
+                    case SyntaxKind.TaggedTemplateExpression:
+                        return emitTaggedTemplateExpression(<TaggedTemplateExpression>node);
+                    case SyntaxKind.TypeAssertionExpression:
+                        return emit((<TypeAssertion>node).expression);
+                    case SyntaxKind.ParenthesizedExpression:
+                        return emitParenExpression(<ParenthesizedExpression>node);
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.ArrowFunction:
+                        return emitFunctionDeclaration(<FunctionLikeDeclaration>node);
+                    case SyntaxKind.DeleteExpression:
+                        return emitDeleteExpression(<DeleteExpression>node);
+                    case SyntaxKind.TypeOfExpression:
+                        return emitTypeOfExpression(<TypeOfExpression>node);
+                    case SyntaxKind.VoidExpression:
+                        return emitVoidExpression(<VoidExpression>node);
+                    case SyntaxKind.PrefixUnaryExpression:
+                        return emitPrefixUnaryExpression(<PrefixUnaryExpression>node);
+                    case SyntaxKind.PostfixUnaryExpression:
+                        return emitPostfixUnaryExpression(<PostfixUnaryExpression>node);
+                    case SyntaxKind.BinaryExpression:
+                        return emitBinaryExpression(<BinaryExpression>node);
+                    case SyntaxKind.ConditionalExpression:
+                        return emitConditionalExpression(<ConditionalExpression>node);
+                    case SyntaxKind.SpreadElementExpression:
+                        return emitSpreadElementExpression(<SpreadElementExpression>node);
+                    case SyntaxKind.YieldExpression:
+                        return emitYieldExpression(<YieldExpression>node);
+                    case SyntaxKind.OmittedExpression:
+                        return;
+                    case SyntaxKind.Block:
+                    case SyntaxKind.ModuleBlock:
+                        return emitBlock(<Block>node);
+                    case SyntaxKind.VariableStatement:
+                        return emitVariableStatement(<VariableStatement>node);
+                    case SyntaxKind.EmptyStatement:
+                        return write(";");
+                    case SyntaxKind.ExpressionStatement:
+                        return emitExpressionStatement(<ExpressionStatement>node);
+                    case SyntaxKind.IfStatement:
+                        return emitIfStatement(<IfStatement>node);
+                    case SyntaxKind.DoStatement:
+                        return emitDoStatement(<DoStatement>node);
+                    case SyntaxKind.WhileStatement:
+                        return emitWhileStatement(<WhileStatement>node);
+                    case SyntaxKind.ForStatement:
+                        return emitForStatement(<ForStatement>node);
+                    case SyntaxKind.ForOfStatement:
+                    case SyntaxKind.ForInStatement:
+                        return emitForInOrForOfStatement(<ForInStatement>node);
+                    case SyntaxKind.ContinueStatement:
+                    case SyntaxKind.BreakStatement:
+                        return emitBreakOrContinueStatement(<BreakOrContinueStatement>node);
+                    case SyntaxKind.ReturnStatement:
+                        return emitReturnStatement(<ReturnStatement>node);
+                    case SyntaxKind.WithStatement:
+                        return emitWithStatement(<WithStatement>node);
+                    case SyntaxKind.SwitchStatement:
+                        return emitSwitchStatement(<SwitchStatement>node);
+                    case SyntaxKind.CaseClause:
+                    case SyntaxKind.DefaultClause:
+                        return emitCaseOrDefaultClause(<CaseOrDefaultClause>node);
+                    case SyntaxKind.LabeledStatement:
+                        return emitLabelledStatement(<LabeledStatement>node);
+                    case SyntaxKind.ThrowStatement:
+                        return emitThrowStatement(<ThrowStatement>node);
+                    case SyntaxKind.TryStatement:
+                        return emitTryStatement(<TryStatement>node);
+                    case SyntaxKind.CatchClause:
+                        return emitCatchClause(<CatchClause>node);
+                    case SyntaxKind.DebuggerStatement:
+                        return emitDebuggerStatement(node);
+                    case SyntaxKind.VariableDeclaration:
+                        return emitVariableDeclaration(<VariableDeclaration>node);
+                    case SyntaxKind.ClassExpression:
+                        return emitClassExpression(<ClassExpression>node);
+                    case SyntaxKind.ClassDeclaration:
+                        return emitClassDeclaration(<ClassDeclaration>node);
+                    case SyntaxKind.InterfaceDeclaration:
+                        return emitInterfaceDeclaration(<InterfaceDeclaration>node);
+                    case SyntaxKind.EnumDeclaration:
+                        return emitEnumDeclaration(<EnumDeclaration>node);
+                    case SyntaxKind.EnumMember:
+                        return emitEnumMember(<EnumMember>node);
+                    case SyntaxKind.ModuleDeclaration:
+                        return emitModuleDeclaration(<ModuleDeclaration>node);
+                    case SyntaxKind.ImportDeclaration:
+                        return emitImportDeclaration(<ImportDeclaration>node);
+                    case SyntaxKind.ImportEqualsDeclaration:
+                        return emitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
+                    case SyntaxKind.ExportDeclaration:
+                        return emitExportDeclaration(<ExportDeclaration>node);
+                    case SyntaxKind.ExportAssignment:
+                        return emitExportAssignment(<ExportAssignment>node);
+                    case SyntaxKind.SourceFile:
+                        return emitSourceFileNode(<SourceFile>node);
+                }
+            }
+
+            function hasDetachedComments(pos: number) {
+                return detachedCommentsInfo !== undefined && detachedCommentsInfo[detachedCommentsInfo.length - 1].nodePos === pos;
+            }
+
+            function getLeadingCommentsWithoutDetachedComments() {
+                // get the leading comments from detachedPos
+                let leadingComments = getLeadingCommentRanges(currentSourceFile.text,
+                    detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
+                if (detachedCommentsInfo.length - 1) {
+                    detachedCommentsInfo.pop();
+                }
+                else {
+                    detachedCommentsInfo = undefined;
+                }
+
+                return leadingComments;
+            }
+
+            function filterComments(ranges: CommentRange[], onlyPinnedOrTripleSlashComments: boolean): CommentRange[] {
+                // If we're removing comments, then we want to strip out all but the pinned or
+                // triple slash comments.
+                if (ranges && onlyPinnedOrTripleSlashComments) {
+                    ranges = filter(ranges, isPinnedOrTripleSlashComment);
+                    if (ranges.length === 0) {
+                        return undefined;
+                    }
+                }
+
+                return ranges;
+            }
+
+            function getLeadingCommentsToEmit(node: Node) {
+                // Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments
+                if (node.parent) {
+                    if (node.parent.kind === SyntaxKind.SourceFile || node.pos !== node.parent.pos) {
+                        if (hasDetachedComments(node.pos)) {
+                            // get comments without detached comments
+                            return getLeadingCommentsWithoutDetachedComments();
+                        }
+                        else {
+                            // get the leading comments from the node
+                            return getLeadingCommentRangesOfNode(node, currentSourceFile);
+                        }
+                    }
+                }
+            }
+
+            function getTrailingCommentsToEmit(node: Node) {
+                // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments
+                if (node.parent) {
+                    if (node.parent.kind === SyntaxKind.SourceFile || node.end !== node.parent.end) {
+                        return getTrailingCommentRanges(currentSourceFile.text, node.end);
+                    }
+                }
+            }
+
+            function emitOnlyPinnedOrTripleSlashComments(node: Node) {
+                emitLeadingCommentsWorker(node, /*onlyPinnedOrTripleSlashComments:*/ true);
+            }
+
+            function emitLeadingComments(node: Node) {
+                return emitLeadingCommentsWorker(node, /*onlyPinnedOrTripleSlashComments:*/ compilerOptions.removeComments);
+            }
+
+            function emitLeadingCommentsWorker(node: Node, onlyPinnedOrTripleSlashComments: boolean) {
+                // If the caller only wants pinned or triple slash comments, then always filter
+                // down to that set.  Otherwise, filter based on the current compiler options.
+                let leadingComments = filterComments(getLeadingCommentsToEmit(node), onlyPinnedOrTripleSlashComments);
+
+                emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
+
+                // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
+                emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
+            }
+
+            function emitTrailingComments(node: Node) {
+                // Emit the trailing comments only if the parent's end doesn't match
+                var trailingComments = filterComments(getTrailingCommentsToEmit(node), /*onlyPinnedOrTripleSlashComments:*/ compilerOptions.removeComments);
+
+                // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
+                emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
+            }
+
+            function emitLeadingCommentsOfPosition(pos: number) {
+                let leadingComments: CommentRange[];
+                if (hasDetachedComments(pos)) {
+                    // get comments without detached comments
+                    leadingComments = getLeadingCommentsWithoutDetachedComments();
+                }
+                else {
+                    // get the leading comments from the node
+                    leadingComments = getLeadingCommentRanges(currentSourceFile.text, pos);
+                }
+
+                leadingComments = filterComments(leadingComments, compilerOptions.removeComments);
+                emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments);
+
+                // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
+                emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
+            }
+
+            function emitDetachedComments(node: TextRange) {
+                let leadingComments = getLeadingCommentRanges(currentSourceFile.text, node.pos);
+                if (leadingComments) {
+                    let detachedComments: CommentRange[] = [];
+                    let lastComment: CommentRange;
+
+                    forEach(leadingComments, comment => {
+                        if (lastComment) {
+                            let lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end);
+                            let commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos);
+
+                            if (commentLine >= lastCommentLine + 2) {
+                                // There was a blank line between the last comment and this comment.  This
+                                // comment is not part of the copyright comments.  Return what we have so
+                                // far.
+                                return detachedComments;
+                            }
+                        }
+
+                        detachedComments.push(comment);
+                        lastComment = comment;
+                    });
+
+                    if (detachedComments.length) {
+                        // All comments look like they could have been part of the copyright header.  Make
+                        // sure there is at least one blank line between it and the node.  If not, it's not
+                        // a copyright header.
+                        let lastCommentLine = getLineOfLocalPosition(currentSourceFile, detachedComments[detachedComments.length - 1].end);
+                        let nodeLine = getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node.pos));
+                        if (nodeLine >= lastCommentLine + 2) {
+                            // Valid detachedComments
+                            emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments);
+                            emitComments(currentSourceFile, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment);
+                            let currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: detachedComments[detachedComments.length - 1].end };
+                            if (detachedCommentsInfo) {
+                                detachedCommentsInfo.push(currentDetachedCommentInfo);
+                            }
+                            else {
+                                detachedCommentsInfo = [currentDetachedCommentInfo];
+                            }
+                        }
+                    }
+                }
+            }
+
+            function isPinnedOrTripleSlashComment(comment: CommentRange) {
+                if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
+                    return currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
+                }
+                // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
+                // so that we don't end up computing comment string and doing match for all // comments
+                else if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
+                    comment.pos + 2 < comment.end &&
+                    currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.slash &&
+                    currentSourceFile.text.substring(comment.pos, comment.end).match(fullTripleSlashReferencePathRegEx)) {
+                    return true;
+                }
+            }
+        }
+
+        function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
+            emitJavaScript(jsFilePath, sourceFile);
+
+            if (compilerOptions.declaration) {
+                writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics);
+            }
+        }
+    }
+}
diff --git a/lib/typescript/compiler/parser.ts b/lib/typescript/compiler/parser.ts
new file mode 100644
index 000000000..642db3e78
--- /dev/null
+++ b/lib/typescript/compiler/parser.ts
@@ -0,0 +1,5420 @@
+/// <reference path="scanner.ts"/>
+/// <reference path="utilities.ts"/>
+
+module ts {
+    let nodeConstructors = new Array<new () => Node>(SyntaxKind.Count);
+    /* @internal */ export let parseTime = 0;
+
+    export function getNodeConstructor(kind: SyntaxKind): new () => Node {
+        return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind));
+    }
+
+    export function createNode(kind: SyntaxKind): Node {
+        return new (getNodeConstructor(kind))();
+    }
+
+    function visitNode<T>(cbNode: (node: Node) => T, node: Node): T {
+        if (node) {
+            return cbNode(node);
+        }
+    }
+
+    function visitNodeArray<T>(cbNodes: (nodes: Node[]) => T, nodes: Node[]) {
+        if (nodes) {
+            return cbNodes(nodes);
+        }
+    }
+
+    function visitEachNode<T>(cbNode: (node: Node) => T, nodes: Node[]) {
+        if (nodes) {
+            for (let node of nodes) {
+                let result = cbNode(node);
+                if (result) {
+                    return result;
+                }
+            }
+        }
+    }
+
+    // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
+    // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
+    // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
+    // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
+    export function forEachChild<T>(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T {
+        if (!node) {
+            return;
+        }
+        // The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray
+        // callback parameters, but that causes a closure allocation for each invocation with noticeable effects
+        // on performance.
+        let visitNodes: (cb: (node: Node | Node[]) => T, nodes: Node[]) => T = cbNodeArray ? visitNodeArray : visitEachNode;
+        let cbNodes = cbNodeArray || cbNode;
+        switch (node.kind) {
+            case SyntaxKind.QualifiedName:
+                return visitNode(cbNode, (<QualifiedName>node).left) ||
+                    visitNode(cbNode, (<QualifiedName>node).right);
+            case SyntaxKind.TypeParameter:
+                return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
+                    visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
+                    visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
+            case SyntaxKind.Parameter:
+            case SyntaxKind.PropertyDeclaration:
+            case SyntaxKind.PropertySignature:
+            case SyntaxKind.PropertyAssignment:
+            case SyntaxKind.ShorthandPropertyAssignment:
+            case SyntaxKind.VariableDeclaration:
+            case SyntaxKind.BindingElement:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<VariableLikeDeclaration>node).propertyName) ||
+                    visitNode(cbNode, (<VariableLikeDeclaration>node).dotDotDotToken) ||
+                    visitNode(cbNode, (<VariableLikeDeclaration>node).name) ||
+                    visitNode(cbNode, (<VariableLikeDeclaration>node).questionToken) ||
+                    visitNode(cbNode, (<VariableLikeDeclaration>node).type) ||
+                    visitNode(cbNode, (<VariableLikeDeclaration>node).initializer);
+            case SyntaxKind.FunctionType:
+            case SyntaxKind.ConstructorType:
+            case SyntaxKind.CallSignature:
+            case SyntaxKind.ConstructSignature:
+            case SyntaxKind.IndexSignature:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNodes(cbNodes, (<SignatureDeclaration>node).typeParameters) ||
+                    visitNodes(cbNodes, (<SignatureDeclaration>node).parameters) ||
+                    visitNode(cbNode, (<SignatureDeclaration>node).type);
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.MethodSignature:
+            case SyntaxKind.Constructor:
+            case SyntaxKind.GetAccessor:
+            case SyntaxKind.SetAccessor:
+            case SyntaxKind.FunctionExpression:
+            case SyntaxKind.FunctionDeclaration:
+            case SyntaxKind.ArrowFunction:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<FunctionLikeDeclaration>node).asteriskToken) ||
+                    visitNode(cbNode, (<FunctionLikeDeclaration>node).name) ||
+                    visitNode(cbNode, (<FunctionLikeDeclaration>node).questionToken) ||
+                    visitNodes(cbNodes, (<FunctionLikeDeclaration>node).typeParameters) ||
+                    visitNodes(cbNodes, (<FunctionLikeDeclaration>node).parameters) ||
+                    visitNode(cbNode, (<FunctionLikeDeclaration>node).type) ||
+                    visitNode(cbNode, (<ArrowFunction>node).equalsGreaterThanToken) ||
+                    visitNode(cbNode, (<FunctionLikeDeclaration>node).body);
+            case SyntaxKind.TypeReference:
+                return visitNode(cbNode, (<TypeReferenceNode>node).typeName) ||
+                    visitNodes(cbNodes, (<TypeReferenceNode>node).typeArguments);
+            case SyntaxKind.TypeQuery:
+                return visitNode(cbNode, (<TypeQueryNode>node).exprName);
+            case SyntaxKind.TypeLiteral:
+                return visitNodes(cbNodes, (<TypeLiteralNode>node).members);
+            case SyntaxKind.ArrayType:
+                return visitNode(cbNode, (<ArrayTypeNode>node).elementType);
+            case SyntaxKind.TupleType:
+                return visitNodes(cbNodes, (<TupleTypeNode>node).elementTypes);
+            case SyntaxKind.UnionType:
+                return visitNodes(cbNodes, (<UnionTypeNode>node).types);
+            case SyntaxKind.ParenthesizedType:
+                return visitNode(cbNode, (<ParenthesizedTypeNode>node).type);
+            case SyntaxKind.ObjectBindingPattern:
+            case SyntaxKind.ArrayBindingPattern:
+                return visitNodes(cbNodes, (<BindingPattern>node).elements);
+            case SyntaxKind.ArrayLiteralExpression:
+                return visitNodes(cbNodes, (<ArrayLiteralExpression>node).elements);
+            case SyntaxKind.ObjectLiteralExpression:
+                return visitNodes(cbNodes, (<ObjectLiteralExpression>node).properties);
+            case SyntaxKind.PropertyAccessExpression:
+                return visitNode(cbNode, (<PropertyAccessExpression>node).expression) ||
+                    visitNode(cbNode, (<PropertyAccessExpression>node).dotToken) ||
+                    visitNode(cbNode, (<PropertyAccessExpression>node).name);
+            case SyntaxKind.ElementAccessExpression:
+                return visitNode(cbNode, (<ElementAccessExpression>node).expression) ||
+                    visitNode(cbNode, (<ElementAccessExpression>node).argumentExpression);
+            case SyntaxKind.CallExpression:
+            case SyntaxKind.NewExpression:
+                return visitNode(cbNode, (<CallExpression>node).expression) ||
+                    visitNodes(cbNodes, (<CallExpression>node).typeArguments) ||
+                    visitNodes(cbNodes, (<CallExpression>node).arguments);
+            case SyntaxKind.TaggedTemplateExpression:
+                return visitNode(cbNode, (<TaggedTemplateExpression>node).tag) ||
+                    visitNode(cbNode, (<TaggedTemplateExpression>node).template);
+            case SyntaxKind.TypeAssertionExpression:
+                return visitNode(cbNode, (<TypeAssertion>node).type) ||
+                    visitNode(cbNode, (<TypeAssertion>node).expression);
+            case SyntaxKind.ParenthesizedExpression:
+                return visitNode(cbNode, (<ParenthesizedExpression>node).expression);
+            case SyntaxKind.DeleteExpression:
+                return visitNode(cbNode, (<DeleteExpression>node).expression);
+            case SyntaxKind.TypeOfExpression:
+                return visitNode(cbNode, (<TypeOfExpression>node).expression);
+            case SyntaxKind.VoidExpression:
+                return visitNode(cbNode, (<VoidExpression>node).expression);
+            case SyntaxKind.PrefixUnaryExpression:
+                return visitNode(cbNode, (<PrefixUnaryExpression>node).operand);
+            case SyntaxKind.YieldExpression:
+                return visitNode(cbNode, (<YieldExpression>node).asteriskToken) ||
+                    visitNode(cbNode, (<YieldExpression>node).expression);
+            case SyntaxKind.PostfixUnaryExpression:
+                return visitNode(cbNode, (<PostfixUnaryExpression>node).operand);
+            case SyntaxKind.BinaryExpression:
+                return visitNode(cbNode, (<BinaryExpression>node).left) ||
+                    visitNode(cbNode, (<BinaryExpression>node).operatorToken) ||
+                    visitNode(cbNode, (<BinaryExpression>node).right);
+            case SyntaxKind.ConditionalExpression:
+                return visitNode(cbNode, (<ConditionalExpression>node).condition) ||
+                    visitNode(cbNode, (<ConditionalExpression>node).questionToken) ||
+                    visitNode(cbNode, (<ConditionalExpression>node).whenTrue) ||
+                    visitNode(cbNode, (<ConditionalExpression>node).colonToken) ||
+                    visitNode(cbNode, (<ConditionalExpression>node).whenFalse);
+            case SyntaxKind.SpreadElementExpression:
+                return visitNode(cbNode, (<SpreadElementExpression>node).expression);
+            case SyntaxKind.Block:
+            case SyntaxKind.ModuleBlock:
+                return visitNodes(cbNodes, (<Block>node).statements);
+            case SyntaxKind.SourceFile:
+                return visitNodes(cbNodes, (<SourceFile>node).statements) ||
+                    visitNode(cbNode, (<SourceFile>node).endOfFileToken);
+            case SyntaxKind.VariableStatement:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<VariableStatement>node).declarationList);
+            case SyntaxKind.VariableDeclarationList:
+                return visitNodes(cbNodes, (<VariableDeclarationList>node).declarations);
+            case SyntaxKind.ExpressionStatement:
+                return visitNode(cbNode, (<ExpressionStatement>node).expression);
+            case SyntaxKind.IfStatement:
+                return visitNode(cbNode, (<IfStatement>node).expression) ||
+                    visitNode(cbNode, (<IfStatement>node).thenStatement) ||
+                    visitNode(cbNode, (<IfStatement>node).elseStatement);
+            case SyntaxKind.DoStatement:
+                return visitNode(cbNode, (<DoStatement>node).statement) ||
+                    visitNode(cbNode, (<DoStatement>node).expression);
+            case SyntaxKind.WhileStatement:
+                return visitNode(cbNode, (<WhileStatement>node).expression) ||
+                    visitNode(cbNode, (<WhileStatement>node).statement);
+            case SyntaxKind.ForStatement:
+                return visitNode(cbNode, (<ForStatement>node).initializer) ||
+                    visitNode(cbNode, (<ForStatement>node).condition) ||
+                    visitNode(cbNode, (<ForStatement>node).incrementor) ||
+                    visitNode(cbNode, (<ForStatement>node).statement);
+            case SyntaxKind.ForInStatement:
+                return visitNode(cbNode, (<ForInStatement>node).initializer) ||
+                    visitNode(cbNode, (<ForInStatement>node).expression) ||
+                    visitNode(cbNode, (<ForInStatement>node).statement);
+            case SyntaxKind.ForOfStatement:
+                return visitNode(cbNode, (<ForOfStatement>node).initializer) ||
+                    visitNode(cbNode, (<ForOfStatement>node).expression) ||
+                    visitNode(cbNode, (<ForOfStatement>node).statement);
+            case SyntaxKind.ContinueStatement:
+            case SyntaxKind.BreakStatement:
+                return visitNode(cbNode, (<BreakOrContinueStatement>node).label);
+            case SyntaxKind.ReturnStatement:
+                return visitNode(cbNode, (<ReturnStatement>node).expression);
+            case SyntaxKind.WithStatement:
+                return visitNode(cbNode, (<WithStatement>node).expression) ||
+                    visitNode(cbNode, (<WithStatement>node).statement);
+            case SyntaxKind.SwitchStatement:
+                return visitNode(cbNode, (<SwitchStatement>node).expression) ||
+                    visitNode(cbNode, (<SwitchStatement>node).caseBlock);
+            case SyntaxKind.CaseBlock:
+                return visitNodes(cbNodes, (<CaseBlock>node).clauses);
+            case SyntaxKind.CaseClause:
+                return visitNode(cbNode, (<CaseClause>node).expression) ||
+                    visitNodes(cbNodes, (<CaseClause>node).statements);
+            case SyntaxKind.DefaultClause:
+                return visitNodes(cbNodes, (<DefaultClause>node).statements);
+            case SyntaxKind.LabeledStatement:
+                return visitNode(cbNode, (<LabeledStatement>node).label) ||
+                    visitNode(cbNode, (<LabeledStatement>node).statement);
+            case SyntaxKind.ThrowStatement:
+                return visitNode(cbNode, (<ThrowStatement>node).expression);
+            case SyntaxKind.TryStatement:
+                return visitNode(cbNode, (<TryStatement>node).tryBlock) ||
+                    visitNode(cbNode, (<TryStatement>node).catchClause) ||
+                    visitNode(cbNode, (<TryStatement>node).finallyBlock);
+            case SyntaxKind.CatchClause:
+                return visitNode(cbNode, (<CatchClause>node).variableDeclaration) ||
+                    visitNode(cbNode, (<CatchClause>node).block);
+            case SyntaxKind.Decorator:
+                return visitNode(cbNode, (<Decorator>node).expression);
+            case SyntaxKind.ClassDeclaration:
+            case SyntaxKind.ClassExpression:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<ClassLikeDeclaration>node).name) ||
+                    visitNodes(cbNodes, (<ClassLikeDeclaration>node).typeParameters) ||
+                    visitNodes(cbNodes, (<ClassLikeDeclaration>node).heritageClauses) ||
+                    visitNodes(cbNodes, (<ClassLikeDeclaration>node).members);
+            case SyntaxKind.InterfaceDeclaration:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<InterfaceDeclaration>node).name) ||
+                    visitNodes(cbNodes, (<InterfaceDeclaration>node).typeParameters) ||
+                    visitNodes(cbNodes, (<ClassDeclaration>node).heritageClauses) ||
+                    visitNodes(cbNodes, (<InterfaceDeclaration>node).members);
+            case SyntaxKind.TypeAliasDeclaration:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<TypeAliasDeclaration>node).name) ||
+                    visitNode(cbNode, (<TypeAliasDeclaration>node).type);
+            case SyntaxKind.EnumDeclaration:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<EnumDeclaration>node).name) ||
+                    visitNodes(cbNodes, (<EnumDeclaration>node).members);
+            case SyntaxKind.EnumMember:
+                return visitNode(cbNode, (<EnumMember>node).name) ||
+                    visitNode(cbNode, (<EnumMember>node).initializer);
+            case SyntaxKind.ModuleDeclaration:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<ModuleDeclaration>node).name) ||
+                    visitNode(cbNode, (<ModuleDeclaration>node).body);
+            case SyntaxKind.ImportEqualsDeclaration:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<ImportEqualsDeclaration>node).name) ||
+                    visitNode(cbNode, (<ImportEqualsDeclaration>node).moduleReference);
+            case SyntaxKind.ImportDeclaration:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<ImportDeclaration>node).importClause) ||
+                    visitNode(cbNode, (<ImportDeclaration>node).moduleSpecifier);
+            case SyntaxKind.ImportClause:
+                return visitNode(cbNode, (<ImportClause>node).name) ||
+                    visitNode(cbNode, (<ImportClause>node).namedBindings);
+            case SyntaxKind.NamespaceImport:
+                return visitNode(cbNode, (<NamespaceImport>node).name);
+            case SyntaxKind.NamedImports:
+            case SyntaxKind.NamedExports:
+                return visitNodes(cbNodes, (<NamedImportsOrExports>node).elements);
+            case SyntaxKind.ExportDeclaration:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<ExportDeclaration>node).exportClause) ||
+                    visitNode(cbNode, (<ExportDeclaration>node).moduleSpecifier);
+            case SyntaxKind.ImportSpecifier:
+            case SyntaxKind.ExportSpecifier:
+                return visitNode(cbNode, (<ImportOrExportSpecifier>node).propertyName) ||
+                    visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
+            case SyntaxKind.ExportAssignment:
+                return visitNodes(cbNodes, node.decorators) ||
+                    visitNodes(cbNodes, node.modifiers) ||
+                    visitNode(cbNode, (<ExportAssignment>node).expression);
+            case SyntaxKind.TemplateExpression:
+                return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNodes, (<TemplateExpression>node).templateSpans);
+            case SyntaxKind.TemplateSpan:
+                return visitNode(cbNode, (<TemplateSpan>node).expression) || visitNode(cbNode, (<TemplateSpan>node).literal);
+            case SyntaxKind.ComputedPropertyName:
+                return visitNode(cbNode, (<ComputedPropertyName>node).expression);
+            case SyntaxKind.HeritageClause:
+                return visitNodes(cbNodes, (<HeritageClause>node).types);
+            case SyntaxKind.HeritageClauseElement:
+                return visitNode(cbNode, (<HeritageClauseElement>node).expression) ||
+                    visitNodes(cbNodes, (<HeritageClauseElement>node).typeArguments);
+            case SyntaxKind.ExternalModuleReference:
+                return visitNode(cbNode, (<ExternalModuleReference>node).expression);
+            case SyntaxKind.MissingDeclaration:
+                return visitNodes(cbNodes, node.decorators);
+        }
+    }
+
+    export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false): SourceFile {
+        let start = new Date().getTime();
+        let result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes);
+
+        parseTime += new Date().getTime() - start;
+        return result;
+    }
+
+    // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
+    // indicates what changed between the 'text' that this SourceFile has and the 'newText'.
+    // The SourceFile will be created with the compiler attempting to reuse as many nodes from
+    // this file as possible.
+    //
+    // Note: this function mutates nodes from this SourceFile. That means any existing nodes
+    // from this SourceFile that are being held onto may change as a result (including
+    // becoming detached from any SourceFile).  It is recommended that this SourceFile not
+    // be used once 'update' is called on it.
+    export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
+        return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
+    }
+
+    // Implement the parser as a singleton module.  We do this for perf reasons because creating
+    // parser instances can actually be expensive enough to impact us on projects with many source
+    // files.
+    module Parser {
+        // Share a single scanner across all calls to parse a source file.  This helps speed things
+        // up by avoiding the cost of creating/compiling scanners over and over again.
+        const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ true);
+        const disallowInAndDecoratorContext = ParserContextFlags.DisallowIn | ParserContextFlags.Decorator;
+
+        let sourceFile: SourceFile;
+        let syntaxCursor: IncrementalParser.SyntaxCursor;
+
+        let token: SyntaxKind;
+        let sourceText: string;
+        let nodeCount: number;
+        let identifiers: Map<string>;
+        let identifierCount: number;
+
+        let parsingContext: ParsingContext;
+
+        // Flags that dictate what parsing context we're in.  For example:
+        // Whether or not we are in strict parsing mode.  All that changes in strict parsing mode is
+        // that some tokens that would be considered identifiers may be considered keywords.
+        //
+        // When adding more parser context flags, consider which is the more common case that the
+        // flag will be in.  This should be the 'false' state for that flag.  The reason for this is
+        // that we don't store data in our nodes unless the value is in the *non-default* state.  So,
+        // for example, more often than code 'allows-in' (or doesn't 'disallow-in').  We opt for
+        // 'disallow-in' set to 'false'.  Otherwise, if we had 'allowsIn' set to 'true', then almost
+        // all nodes would need extra state on them to store this info.
+        //
+        // Note:  'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6
+        // grammar specification.
+        //
+        // An important thing about these context concepts.  By default they are effectively inherited
+        // while parsing through every grammar production.  i.e. if you don't change them, then when
+        // you parse a sub-production, it will have the same context values as the parent production.
+        // This is great most of the time.  After all, consider all the 'expression' grammar productions
+        // and how nearly all of them pass along the 'in' and 'yield' context values:
+        //
+        // EqualityExpression[In, Yield] :
+        //      RelationalExpression[?In, ?Yield]
+        //      EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield]
+        //      EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield]
+        //      EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield]
+        //      EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield]
+        //
+        // Where you have to be careful is then understanding what the points are in the grammar
+        // where the values are *not* passed along.  For example:
+        //
+        // SingleNameBinding[Yield,GeneratorParameter]
+        //      [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt
+        //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
+        //
+        // Here this is saying that if the GeneratorParameter context flag is set, that we should
+        // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier
+        // and we should explicitly unset the 'yield' context flag before calling into the Initializer.
+        // production.  Conversely, if the GeneratorParameter context flag is not set, then we
+        // should leave the 'yield' context flag alone.
+        //
+        // Getting this all correct is tricky and requires careful reading of the grammar to
+        // understand when these values should be changed versus when they should be inherited.
+        //
+        // Note: it should not be necessary to save/restore these flags during speculative/lookahead
+        // parsing.  These context flags are naturally stored and restored through normal recursive
+        // descent parsing and unwinding.
+        let contextFlags: ParserContextFlags = 0;
+
+        // Whether or not we've had a parse error since creating the last AST node.  If we have
+        // encountered an error, it will be stored on the next AST node we create.  Parse errors
+        // can be broken down into three categories:
+        //
+        // 1) An error that occurred during scanning.  For example, an unterminated literal, or a
+        //    character that was completely not understood.
+        //
+        // 2) A token was expected, but was not present.  This type of error is commonly produced
+        //    by the 'parseExpected' function.
+        //
+        // 3) A token was present that no parsing function was able to consume.  This type of error
+        //    only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser
+        //    decides to skip the token.
+        //
+        // In all of these cases, we want to mark the next node as having had an error before it.
+        // With this mark, we can know in incremental settings if this node can be reused, or if
+        // we have to reparse it.  If we don't keep this information around, we may just reuse the
+        // node.  in that event we would then not produce the same errors as we did before, causing
+        // significant confusion problems.
+        //
+        // Note: it is necessary that this value be saved/restored during speculative/lookahead
+        // parsing.  During lookahead parsing, we will often create a node.  That node will have
+        // this value attached, and then this value will be set back to 'false'.  If we decide to
+        // rewind, we must get back to the same value we had prior to the lookahead.
+        //
+        // Note: any errors at the end of the file that do not precede a regular node, should get
+        // attached to the EOF token.
+        let parseErrorBeforeNextFinishedNode: boolean = false;
+
+        export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): SourceFile {
+            sourceText = _sourceText;
+            syntaxCursor = _syntaxCursor;
+
+            parsingContext = 0;
+            identifiers = {};
+            identifierCount = 0;
+            nodeCount = 0;
+
+            contextFlags = 0;
+            parseErrorBeforeNextFinishedNode = false;
+
+            createSourceFile(fileName, languageVersion);
+
+            // Initialize and prime the scanner before parsing the source elements.
+            scanner.setText(sourceText);
+            scanner.setOnError(scanError);
+            scanner.setScriptTarget(languageVersion);
+            token = nextToken();
+
+            processReferenceComments(sourceFile);
+
+            sourceFile.statements = parseList(ParsingContext.SourceElements, /*checkForStrictMode*/ true, parseSourceElement);
+            Debug.assert(token === SyntaxKind.EndOfFileToken);
+            sourceFile.endOfFileToken = parseTokenNode();
+
+            setExternalModuleIndicator(sourceFile);
+
+            sourceFile.nodeCount = nodeCount;
+            sourceFile.identifierCount = identifierCount;
+            sourceFile.identifiers = identifiers;
+
+            if (setParentNodes) {
+                fixupParentReferences(sourceFile);
+            }
+
+            syntaxCursor = undefined;
+
+            // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily.
+            scanner.setText("");
+            scanner.setOnError(undefined);
+
+            let result = sourceFile;
+
+            // Clear any data.  We don't want to accidently hold onto it for too long.
+            sourceFile = undefined;
+            identifiers = undefined;
+            syntaxCursor = undefined;
+            sourceText = undefined;
+
+            return result;
+        }
+
+        function fixupParentReferences(sourceFile: SourceFile) {
+            // normally parent references are set during binding. However, for clients that only need
+            // a syntax tree, and no semantic features, then the binding process is an unnecessary
+            // overhead.  This functions allows us to set all the parents, without all the expense of
+            // binding.
+
+            let parent: Node = sourceFile;
+            forEachChild(sourceFile, visitNode);
+            return;
+
+            function visitNode(n: Node): void {
+                // walk down setting parents that differ from the parent we think it should be.  This
+                // allows us to quickly bail out of setting parents for subtrees during incremental
+                // parsing
+                if (n.parent !== parent) {
+                    n.parent = parent;
+
+                    let saveParent = parent;
+                    parent = n;
+                    forEachChild(n, visitNode);
+                    parent = saveParent;
+                }
+            }
+        }
+
+        function createSourceFile(fileName: string, languageVersion: ScriptTarget) {
+            sourceFile = <SourceFile>createNode(SyntaxKind.SourceFile, /*pos*/ 0);
+
+            sourceFile.pos = 0;
+            sourceFile.end = sourceText.length;
+            sourceFile.text = sourceText;
+
+            sourceFile.parseDiagnostics = [];
+            sourceFile.bindDiagnostics = [];
+            sourceFile.languageVersion = languageVersion;
+            sourceFile.fileName = normalizePath(fileName);
+            sourceFile.flags = fileExtensionIs(sourceFile.fileName, ".d.ts") ? NodeFlags.DeclarationFile : 0;
+        }
+
+        function setContextFlag(val: Boolean, flag: ParserContextFlags) {
+            if (val) {
+                contextFlags |= flag;
+            }
+            else {
+                contextFlags &= ~flag;
+            }
+        }
+
+        function setStrictModeContext(val: boolean) {
+            setContextFlag(val, ParserContextFlags.StrictMode);
+        }
+
+        function setDisallowInContext(val: boolean) {
+            setContextFlag(val, ParserContextFlags.DisallowIn);
+        }
+
+        function setYieldContext(val: boolean) {
+            setContextFlag(val, ParserContextFlags.Yield);
+        }
+
+        function setGeneratorParameterContext(val: boolean) {
+            setContextFlag(val, ParserContextFlags.GeneratorParameter);
+        }
+
+        function setDecoratorContext(val: boolean) {
+            setContextFlag(val, ParserContextFlags.Decorator);
+        }
+
+        function doOutsideOfContext<T>(flags: ParserContextFlags, func: () => T): T {
+            let currentContextFlags = contextFlags & flags;
+            if (currentContextFlags) {
+                setContextFlag(false, currentContextFlags);
+                let result = func();
+                setContextFlag(true, currentContextFlags);
+                return result;
+            }
+
+            // no need to do anything special as we are not in any of the requested contexts
+            return func();
+        }
+
+        function allowInAnd<T>(func: () => T): T {
+            if (contextFlags & ParserContextFlags.DisallowIn) {
+                setDisallowInContext(false);
+                let result = func();
+                setDisallowInContext(true);
+                return result;
+            }
+
+            // no need to do anything special if 'in' is already allowed.
+            return func();
+        }
+
+        function disallowInAnd<T>(func: () => T): T {
+            if (contextFlags & ParserContextFlags.DisallowIn) {
+                // no need to do anything special if 'in' is already disallowed.
+                return func();
+            }
+
+            setDisallowInContext(true);
+            let result = func();
+            setDisallowInContext(false);
+            return result;
+        }
+
+        function doInYieldContext<T>(func: () => T): T {
+            if (contextFlags & ParserContextFlags.Yield) {
+                // no need to do anything special if we're already in the [Yield] context.
+                return func();
+            }
+
+            setYieldContext(true);
+            let result = func();
+            setYieldContext(false);
+            return result;
+        }
+
+        function doOutsideOfYieldContext<T>(func: () => T): T {
+            if (contextFlags & ParserContextFlags.Yield) {
+                setYieldContext(false);
+                let result = func();
+                setYieldContext(true);
+                return result;
+            }
+
+            // no need to do anything special if we're not in the [Yield] context.
+            return func();
+        }
+
+        function doInDecoratorContext<T>(func: () => T): T {
+            if (contextFlags & ParserContextFlags.Decorator) {
+                // no need to do anything special if we're already in the [Decorator] context.
+                return func();
+            }
+
+            setDecoratorContext(true);
+            let result = func();
+            setDecoratorContext(false);
+            return result;
+        }
+
+        function inYieldContext() {
+            return (contextFlags & ParserContextFlags.Yield) !== 0;
+        }
+
+        function inStrictModeContext() {
+            return (contextFlags & ParserContextFlags.StrictMode) !== 0;
+        }
+
+        function inGeneratorParameterContext() {
+            return (contextFlags & ParserContextFlags.GeneratorParameter) !== 0;
+        }
+
+        function inDisallowInContext() {
+            return (contextFlags & ParserContextFlags.DisallowIn) !== 0;
+        }
+
+        function inDecoratorContext() {
+            return (contextFlags & ParserContextFlags.Decorator) !== 0;
+        }
+
+        function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): void {
+            let start = scanner.getTokenPos();
+            let length = scanner.getTextPos() - start;
+
+            parseErrorAtPosition(start, length, message, arg0);
+        }
+
+        function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): void {
+            // Don't report another error if it would just be at the same position as the last error.
+            let lastError = lastOrUndefined(sourceFile.parseDiagnostics);
+            if (!lastError || start !== lastError.start) {
+                sourceFile.parseDiagnostics.push(createFileDiagnostic(sourceFile, start, length, message, arg0));
+            }
+
+            // Mark that we've encountered an error.  We'll set an appropriate bit on the next
+            // node we finish so that it can't be reused incrementally.
+            parseErrorBeforeNextFinishedNode = true;
+        }
+
+        function scanError(message: DiagnosticMessage, length?: number) {
+            let pos = scanner.getTextPos();
+            parseErrorAtPosition(pos, length || 0, message);
+        }
+
+        function getNodePos(): number {
+            return scanner.getStartPos();
+        }
+
+        function getNodeEnd(): number {
+            return scanner.getStartPos();
+        }
+
+        function nextToken(): SyntaxKind {
+            return token = scanner.scan();
+        }
+
+        function getTokenPos(pos: number): number {
+            return skipTrivia(sourceText, pos);
+        }
+
+        function reScanGreaterToken(): SyntaxKind {
+            return token = scanner.reScanGreaterToken();
+        }
+
+        function reScanSlashToken(): SyntaxKind {
+            return token = scanner.reScanSlashToken();
+        }
+
+        function reScanTemplateToken(): SyntaxKind {
+            return token = scanner.reScanTemplateToken();
+        }
+
+        function speculationHelper<T>(callback: () => T, isLookAhead: boolean): T {
+            // Keep track of the state we'll need to rollback to if lookahead fails (or if the
+            // caller asked us to always reset our state).
+            let saveToken = token;
+            let saveParseDiagnosticsLength = sourceFile.parseDiagnostics.length;
+            let saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
+
+            // Note: it is not actually necessary to save/restore the context flags here.  That's
+            // because the saving/restorating of these flags happens naturally through the recursive
+            // descent nature of our parser.  However, we still store this here just so we can
+            // assert that that invariant holds.
+            let saveContextFlags = contextFlags;
+
+            // If we're only looking ahead, then tell the scanner to only lookahead as well.
+            // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the
+            // same.
+            let result = isLookAhead
+                ? scanner.lookAhead(callback)
+                : scanner.tryScan(callback);
+
+            Debug.assert(saveContextFlags === contextFlags);
+
+            // If our callback returned something 'falsy' or we're just looking ahead,
+            // then unconditionally restore us to where we were.
+            if (!result || isLookAhead) {
+                token = saveToken;
+                sourceFile.parseDiagnostics.length = saveParseDiagnosticsLength;
+                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
+            }
+
+            return result;
+        }
+
+        // Invokes the provided callback then unconditionally restores the parser to the state it
+        // was in immediately prior to invoking the callback.  The result of invoking the callback
+        // is returned from this function.
+        function lookAhead<T>(callback: () => T): T {
+            return speculationHelper(callback, /*isLookAhead:*/ true);
+        }
+
+        // Invokes the provided callback.  If the callback returns something falsy, then it restores
+        // the parser to the state it was in immediately prior to invoking the callback.  If the
+        // callback returns something truthy, then the parser state is not rolled back.  The result
+        // of invoking the callback is returned from this function.
+        function tryParse<T>(callback: () => T): T {
+            return speculationHelper(callback, /*isLookAhead:*/ false);
+        }
+
+        // Ignore strict mode flag because we will report an error in type checker instead.
+        function isIdentifier(): boolean {
+            if (token === SyntaxKind.Identifier) {
+                return true;
+            }
+
+            // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is
+            // considered a keyword and is not an identifier.
+            if (token === SyntaxKind.YieldKeyword && inYieldContext()) {
+                return false;
+            }
+
+            return token > SyntaxKind.LastReservedWord;
+        }
+
+        function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage): boolean {
+            if (token === kind) {
+                nextToken();
+                return true;
+            }
+
+            // Report specific message if provided with one.  Otherwise, report generic fallback message.
+            if (diagnosticMessage) {
+                parseErrorAtCurrentToken(diagnosticMessage);
+            }
+            else {
+                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
+            }
+            return false;
+        }
+
+        function parseOptional(t: SyntaxKind): boolean {
+            if (token === t) {
+                nextToken();
+                return true;
+            }
+            return false;
+        }
+
+        function parseOptionalToken(t: SyntaxKind): Node {
+            if (token === t) {
+                return parseTokenNode();
+            }
+            return undefined;
+        }
+
+        function parseExpectedToken(t: SyntaxKind, reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): Node {
+            return parseOptionalToken(t) ||
+                createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0);
+        }
+
+        function parseTokenNode<T extends Node>(): T {
+            let node = <T>createNode(token);
+            nextToken();
+            return finishNode(node);
+        }
+
+        function canParseSemicolon() {
+            // If there's a real semicolon, then we can always parse it out.
+            if (token === SyntaxKind.SemicolonToken) {
+                return true;
+            }
+
+            // We can parse out an optional semicolon in ASI cases in the following cases.
+            return token === SyntaxKind.CloseBraceToken || token === SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak();
+        }
+
+        function parseSemicolon(): boolean {
+            if (canParseSemicolon()) {
+                if (token === SyntaxKind.SemicolonToken) {
+                    // consume the semicolon if it was explicitly provided.
+                    nextToken();
+                }
+
+                return true;
+            }
+            else {
+                return parseExpected(SyntaxKind.SemicolonToken);
+            }
+        }
+
+        function createNode(kind: SyntaxKind, pos?: number): Node {
+            nodeCount++;
+            let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))();
+            if (!(pos >= 0)) {
+                pos = scanner.getStartPos();
+            }
+
+            node.pos = pos;
+            node.end = pos;
+            return node;
+        }
+
+        function finishNode<T extends Node>(node: T): T {
+            node.end = scanner.getStartPos();
+
+            if (contextFlags) {
+                node.parserContextFlags = contextFlags;
+            }
+
+            // Keep track on the node if we encountered an error while parsing it.  If we did, then
+            // we cannot reuse the node incrementally.  Once we've marked this node, clear out the
+            // flag so that we don't mark any subsequent nodes.
+            if (parseErrorBeforeNextFinishedNode) {
+                parseErrorBeforeNextFinishedNode = false;
+                node.parserContextFlags |= ParserContextFlags.ThisNodeHasError;
+            }
+
+            return node;
+        }
+
+        function createMissingNode(kind: SyntaxKind, reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): Node {
+            if (reportAtCurrentPosition) {
+                parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0);
+            }
+            else {
+                parseErrorAtCurrentToken(diagnosticMessage, arg0);
+            }
+
+            let result = createNode(kind, scanner.getStartPos());
+            (<Identifier>result).text = "";
+            return finishNode(result);
+        }
+
+        function internIdentifier(text: string): string {
+            text = escapeIdentifier(text);
+            return hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
+        }
+
+        // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
+        // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for
+        // each identifier in order to reduce memory consumption.
+        function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage): Identifier {
+            identifierCount++;
+            if (isIdentifier) {
+                let node = <Identifier>createNode(SyntaxKind.Identifier);
+
+                // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker
+                if (token !== SyntaxKind.Identifier) {
+                    node.originalKeywordKind = token;
+                }
+                node.text = internIdentifier(scanner.getTokenValue());
+                nextToken();
+                return finishNode(node);
+            }
+
+            return <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition:*/ false, diagnosticMessage || Diagnostics.Identifier_expected);
+        }
+
+        function parseIdentifier(diagnosticMessage?: DiagnosticMessage): Identifier {
+            return createIdentifier(isIdentifier(), diagnosticMessage);
+        }
+
+        function parseIdentifierName(): Identifier {
+            return createIdentifier(isIdentifierOrKeyword());
+        }
+
+        function isLiteralPropertyName(): boolean {
+            return isIdentifierOrKeyword() ||
+                token === SyntaxKind.StringLiteral ||
+                token === SyntaxKind.NumericLiteral;
+        }
+
+        function parsePropertyName(): DeclarationName {
+            if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) {
+                return parseLiteralNode(/*internName:*/ true);
+            }
+            if (token === SyntaxKind.OpenBracketToken) {
+                return parseComputedPropertyName();
+            }
+            return parseIdentifierName();
+        }
+
+        function parseComputedPropertyName(): ComputedPropertyName {
+            // PropertyName[Yield,GeneratorParameter] :
+            //     LiteralPropertyName
+            //     [+GeneratorParameter] ComputedPropertyName
+            //     [~GeneratorParameter] ComputedPropertyName[?Yield]
+            //
+            // ComputedPropertyName[Yield] :
+            //     [ AssignmentExpression[In, ?Yield] ]
+            //
+            let node = <ComputedPropertyName>createNode(SyntaxKind.ComputedPropertyName);
+            parseExpected(SyntaxKind.OpenBracketToken);
+
+            // We parse any expression (including a comma expression). But the grammar
+            // says that only an assignment expression is allowed, so the grammar checker
+            // will error if it sees a comma expression.
+            let yieldContext = inYieldContext();
+            if (inGeneratorParameterContext()) {
+                setYieldContext(false);
+            }
+
+            node.expression = allowInAnd(parseExpression);
+            if (inGeneratorParameterContext()) {
+                setYieldContext(yieldContext);
+            }
+
+            parseExpected(SyntaxKind.CloseBracketToken);
+            return finishNode(node);
+        }
+
+        function parseContextualModifier(t: SyntaxKind): boolean {
+            return token === t && tryParse(nextTokenCanFollowModifier);
+        }
+
+        function nextTokenCanFollowModifier() {
+            nextToken();
+            return canFollowModifier();
+        }
+
+        function parseAnyContextualModifier(): boolean {
+            return isModifier(token) && tryParse(nextTokenCanFollowContextualModifier);
+        }
+
+        function nextTokenCanFollowContextualModifier() {
+            if (token === SyntaxKind.ConstKeyword) {
+                // 'const' is only a modifier if followed by 'enum'.
+                return nextToken() === SyntaxKind.EnumKeyword;
+            }
+            if (token === SyntaxKind.ExportKeyword) {
+                nextToken();
+                if (token === SyntaxKind.DefaultKeyword) {
+                    return lookAhead(nextTokenIsClassOrFunction);
+                }
+                return token !== SyntaxKind.AsteriskToken && token !== SyntaxKind.OpenBraceToken && canFollowModifier();
+            }
+            if (token === SyntaxKind.DefaultKeyword) {
+                return nextTokenIsClassOrFunction();
+            }
+            nextToken();
+            return canFollowModifier();
+        }
+
+        function canFollowModifier(): boolean {
+            return token === SyntaxKind.OpenBracketToken
+                || token === SyntaxKind.OpenBraceToken
+                || token === SyntaxKind.AsteriskToken
+                || isLiteralPropertyName();
+        }
+
+        function nextTokenIsClassOrFunction(): boolean {
+            nextToken();
+            return token === SyntaxKind.ClassKeyword || token === SyntaxKind.FunctionKeyword;
+        }
+
+        // True if positioned at the start of a list element
+        function isListElement(parsingContext: ParsingContext, inErrorRecovery: boolean): boolean {
+            let node = currentNode(parsingContext);
+            if (node) {
+                return true;
+            }
+
+            switch (parsingContext) {
+                case ParsingContext.SourceElements:
+                case ParsingContext.ModuleElements:
+                    return isSourceElement(inErrorRecovery);
+                case ParsingContext.BlockStatements:
+                case ParsingContext.SwitchClauseStatements:
+                    return isStartOfStatement(inErrorRecovery);
+                case ParsingContext.SwitchClauses:
+                    return token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
+                case ParsingContext.TypeMembers:
+                    return isStartOfTypeMember();
+                case ParsingContext.ClassMembers:
+                    // We allow semicolons as class elements (as specified by ES6) as long as we're
+                    // not in error recovery.  If we're in error recovery, we don't want an errant
+                    // semicolon to be treated as a class member (since they're almost always used
+                    // for statements.
+                    return lookAhead(isClassMemberStart) || (token === SyntaxKind.SemicolonToken && !inErrorRecovery);
+                case ParsingContext.EnumMembers:
+                    // Include open bracket computed properties. This technically also lets in indexers,
+                    // which would be a candidate for improved error reporting.
+                    return token === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
+                case ParsingContext.ObjectLiteralMembers:
+                    return token === SyntaxKind.OpenBracketToken || token === SyntaxKind.AsteriskToken || isLiteralPropertyName();
+                case ParsingContext.ObjectBindingElements:
+                    return isLiteralPropertyName();
+                case ParsingContext.HeritageClauseElement:
+                    // If we see { } then only consume it as an expression if it is followed by , or {
+                    // That way we won't consume the body of a class in its heritage clause.
+                    if (token === SyntaxKind.OpenBraceToken) {
+                        return lookAhead(isValidHeritageClauseObjectLiteral);
+                    }
+
+                    if (!inErrorRecovery) {
+                        return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
+                    }
+                    else {
+                        // If we're in error recovery we tighten up what we're willing to match.
+                        // That way we don't treat something like "this" as a valid heritage clause
+                        // element during recovery.
+                        return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
+                    }
+                case ParsingContext.VariableDeclarations:
+                    return isIdentifierOrPattern();
+                case ParsingContext.ArrayBindingElements:
+                    return token === SyntaxKind.CommaToken || token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern();
+                case ParsingContext.TypeParameters:
+                    return isIdentifier();
+                case ParsingContext.ArgumentExpressions:
+                case ParsingContext.ArrayLiteralMembers:
+                    return token === SyntaxKind.CommaToken || token === SyntaxKind.DotDotDotToken || isStartOfExpression();
+                case ParsingContext.Parameters:
+                    return isStartOfParameter();
+                case ParsingContext.TypeArguments:
+                case ParsingContext.TupleElementTypes:
+                    return token === SyntaxKind.CommaToken || isStartOfType();
+                case ParsingContext.HeritageClauses:
+                    return isHeritageClause();
+                case ParsingContext.ImportOrExportSpecifiers:
+                    return isIdentifierOrKeyword();
+            }
+
+            Debug.fail("Non-exhaustive case in 'isListElement'.");
+        }
+
+        function isValidHeritageClauseObjectLiteral() {
+            Debug.assert(token === SyntaxKind.OpenBraceToken);
+            if (nextToken() === SyntaxKind.CloseBraceToken) {
+                // if we see  "extends {}" then only treat the {} as what we're extending (and not
+                // the class body) if we have:
+                //
+                //      extends {} { 
+                //      extends {},
+                //      extends {} extends
+                //      extends {} implements
+
+                let next = nextToken();
+                return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword;
+            }
+
+            return true;
+        }
+
+        function nextTokenIsIdentifier() {
+            nextToken();
+            return isIdentifier();
+        }
+
+        function isHeritageClauseExtendsOrImplementsKeyword(): boolean {
+            if (token === SyntaxKind.ImplementsKeyword ||
+                token === SyntaxKind.ExtendsKeyword) {
+
+                return lookAhead(nextTokenIsStartOfExpression);
+            }
+
+            return false;
+        }
+
+        function nextTokenIsStartOfExpression() {
+            nextToken();
+            return isStartOfExpression();
+        }
+
+        // True if positioned at a list terminator
+        function isListTerminator(kind: ParsingContext): boolean {
+            if (token === SyntaxKind.EndOfFileToken) {
+                // Being at the end of the file ends all lists.
+                return true;
+            }
+
+            switch (kind) {
+                case ParsingContext.ModuleElements:
+                case ParsingContext.BlockStatements:
+                case ParsingContext.SwitchClauses:
+                case ParsingContext.TypeMembers:
+                case ParsingContext.ClassMembers:
+                case ParsingContext.EnumMembers:
+                case ParsingContext.ObjectLiteralMembers:
+                case ParsingContext.ObjectBindingElements:
+                case ParsingContext.ImportOrExportSpecifiers:
+                    return token === SyntaxKind.CloseBraceToken;
+                case ParsingContext.SwitchClauseStatements:
+                    return token === SyntaxKind.CloseBraceToken || token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
+                case ParsingContext.HeritageClauseElement:
+                    return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.ExtendsKeyword || token === SyntaxKind.ImplementsKeyword;
+                case ParsingContext.VariableDeclarations:
+                    return isVariableDeclaratorListTerminator();
+                case ParsingContext.TypeParameters:
+                    // Tokens other than '>' are here for better error recovery
+                    return token === SyntaxKind.GreaterThanToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.OpenBraceToken || token === SyntaxKind.ExtendsKeyword || token === SyntaxKind.ImplementsKeyword;
+                case ParsingContext.ArgumentExpressions:
+                    // Tokens other than ')' are here for better error recovery
+                    return token === SyntaxKind.CloseParenToken || token === SyntaxKind.SemicolonToken;
+                case ParsingContext.ArrayLiteralMembers:
+                case ParsingContext.TupleElementTypes:
+                case ParsingContext.ArrayBindingElements:
+                    return token === SyntaxKind.CloseBracketToken;
+                case ParsingContext.Parameters:
+                    // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
+                    return token === SyntaxKind.CloseParenToken || token === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/;
+                case ParsingContext.TypeArguments:
+                    // Tokens other than '>' are here for better error recovery
+                    return token === SyntaxKind.GreaterThanToken || token === SyntaxKind.OpenParenToken;
+                case ParsingContext.HeritageClauses:
+                    return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.CloseBraceToken;
+            }
+        }
+
+        function isVariableDeclaratorListTerminator(): boolean {
+            // If we can consume a semicolon (either explicitly, or with ASI), then consider us done
+            // with parsing the list of  variable declarators.
+            if (canParseSemicolon()) {
+                return true;
+            }
+
+            // in the case where we're parsing the variable declarator of a 'for-in' statement, we
+            // are done if we see an 'in' keyword in front of us. Same with for-of
+            if (isInOrOfKeyword(token)) {
+                return true;
+            }
+
+            // ERROR RECOVERY TWEAK:
+            // For better error recovery, if we see an '=>' then we just stop immediately.  We've got an
+            // arrow function here and it's going to be very unlikely that we'll resynchronize and get
+            // another variable declaration.
+            if (token === SyntaxKind.EqualsGreaterThanToken) {
+                return true;
+            }
+
+            // Keep trying to parse out variable declarators.
+            return false;
+        }
+
+        // True if positioned at element or terminator of the current list or any enclosing list
+        function isInSomeParsingContext(): boolean {
+            for (let kind = 0; kind < ParsingContext.Count; kind++) {
+                if (parsingContext & (1 << kind)) {
+                    if (isListElement(kind, /* inErrorRecovery */ true) || isListTerminator(kind)) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        // Parses a list of elements
+        function parseList<T extends Node>(kind: ParsingContext, checkForStrictMode: boolean, parseElement: () => T): NodeArray<T> {
+            let saveParsingContext = parsingContext;
+            parsingContext |= 1 << kind;
+            let result = <NodeArray<T>>[];
+            result.pos = getNodePos();
+            let savedStrictModeContext = inStrictModeContext();
+
+            while (!isListTerminator(kind)) {
+                if (isListElement(kind, /* inErrorRecovery */ false)) {
+                    let element = parseListElement(kind, parseElement);
+                    result.push(element);
+
+                    // test elements only if we are not already in strict mode
+                    if (checkForStrictMode && !inStrictModeContext()) {
+                        if (isPrologueDirective(element)) {
+                            if (isUseStrictPrologueDirective(sourceFile, element)) {
+                                setStrictModeContext(true);
+                                checkForStrictMode = false;
+                            }
+                        }
+                        else {
+                            checkForStrictMode = false;
+                        }
+                    }
+
+                    continue;
+                }
+
+                if (abortParsingListOrMoveToNextToken(kind)) {
+                    break;
+                }
+            }
+
+            setStrictModeContext(savedStrictModeContext);
+            result.end = getNodeEnd();
+            parsingContext = saveParsingContext;
+            return result;
+        }
+
+        /// Should be called only on prologue directives (isPrologueDirective(node) should be true)
+        function isUseStrictPrologueDirective(sourceFile: SourceFile, node: Node): boolean {
+            Debug.assert(isPrologueDirective(node));
+            let nodeText = getSourceTextOfNodeFromSourceFile(sourceFile, (<ExpressionStatement>node).expression);
+
+            // Note: the node text must be exactly "use strict" or 'use strict'.  It is not ok for the
+            // string to contain unicode escapes (as per ES5).
+            return nodeText === '"use strict"' || nodeText === "'use strict'";
+        }
+
+        function parseListElement<T extends Node>(parsingContext: ParsingContext, parseElement: () => T): T {
+            let node = currentNode(parsingContext);
+            if (node) {
+                return <T>consumeNode(node);
+            }
+
+            return parseElement();
+        }
+
+        function currentNode(parsingContext: ParsingContext): Node {
+            // If there is an outstanding parse error that we've encountered, but not attached to
+            // some node, then we cannot get a node from the old source tree.  This is because we
+            // want to mark the next node we encounter as being unusable.
+            //
+            // Note: This may be too conservative.  Perhaps we could reuse the node and set the bit
+            // on it (or its leftmost child) as having the error.  For now though, being conservative
+            // is nice and likely won't ever affect perf.
+            if (parseErrorBeforeNextFinishedNode) {
+                return undefined;
+            }
+
+            if (!syntaxCursor) {
+                // if we don't have a cursor, we could never return a node from the old tree.
+                return undefined;
+            }
+
+            let node = syntaxCursor.currentNode(scanner.getStartPos());
+
+            // Can't reuse a missing node.
+            if (nodeIsMissing(node)) {
+                return undefined;
+            }
+
+            // Can't reuse a node that intersected the change range.
+            if (node.intersectsChange) {
+                return undefined;
+            }
+
+            // Can't reuse a node that contains a parse error.  This is necessary so that we
+            // produce the same set of errors again.
+            if (containsParseError(node)) {
+                return undefined;
+            }
+
+            // We can only reuse a node if it was parsed under the same strict mode that we're
+            // currently in.  i.e. if we originally parsed a node in non-strict mode, but then
+            // the user added 'using strict' at the top of the file, then we can't use that node
+            // again as the presense of strict mode may cause us to parse the tokens in the file
+            // differetly.
+            //
+            // Note: we *can* reuse tokens when the strict mode changes.  That's because tokens
+            // are unaffected by strict mode.  It's just the parser will decide what to do with it
+            // differently depending on what mode it is in.
+            //
+            // This also applies to all our other context flags as well.
+            let nodeContextFlags = node.parserContextFlags & ParserContextFlags.ParserGeneratedFlags;
+            if (nodeContextFlags !== contextFlags) {
+                return undefined;
+            }
+
+            // Ok, we have a node that looks like it could be reused.  Now verify that it is valid
+            // in the currest list parsing context that we're currently at.
+            if (!canReuseNode(node, parsingContext)) {
+                return undefined;
+            }
+
+            return node;
+        }
+
+        function consumeNode(node: Node) {
+            // Move the scanner so it is after the node we just consumed.
+            scanner.setTextPos(node.end);
+            nextToken();
+            return node;
+        }
+
+        function canReuseNode(node: Node, parsingContext: ParsingContext): boolean {
+            switch (parsingContext) {
+                case ParsingContext.ModuleElements:
+                    return isReusableModuleElement(node);
+
+                case ParsingContext.ClassMembers:
+                    return isReusableClassMember(node);
+
+                case ParsingContext.SwitchClauses:
+                    return isReusableSwitchClause(node);
+
+                case ParsingContext.BlockStatements:
+                case ParsingContext.SwitchClauseStatements:
+                    return isReusableStatement(node);
+
+                case ParsingContext.EnumMembers:
+                    return isReusableEnumMember(node);
+
+                case ParsingContext.TypeMembers:
+                    return isReusableTypeMember(node);
+
+                case ParsingContext.VariableDeclarations:
+                    return isReusableVariableDeclaration(node);
+
+                case ParsingContext.Parameters:
+                    return isReusableParameter(node);
+
+                // Any other lists we do not care about reusing nodes in.  But feel free to add if
+                // you can do so safely.  Danger areas involve nodes that may involve speculative
+                // parsing.  If speculative parsing is involved with the node, then the range the
+                // parser reached while looking ahead might be in the edited range (see the example
+                // in canReuseVariableDeclaratorNode for a good case of this).
+                case ParsingContext.HeritageClauses:
+                // This would probably be safe to reuse.  There is no speculative parsing with
+                // heritage clauses.
+
+                case ParsingContext.TypeParameters:
+                // This would probably be safe to reuse.  There is no speculative parsing with
+                // type parameters.  Note that that's because type *parameters* only occur in
+                // unambiguous *type* contexts.  While type *arguments* occur in very ambiguous
+                // *expression* contexts.
+
+                case ParsingContext.TupleElementTypes:
+                // This would probably be safe to reuse.  There is no speculative parsing with
+                // tuple types.
+
+                // Technically, type argument list types are probably safe to reuse.  While
+                // speculative parsing is involved with them (since type argument lists are only
+                // produced from speculative parsing a < as a type argument list), we only have
+                // the types because speculative parsing succeeded.  Thus, the lookahead never
+                // went past the end of the list and rewound.
+                case ParsingContext.TypeArguments:
+
+                // Note: these are almost certainly not safe to ever reuse.  Expressions commonly
+                // need a large amount of lookahead, and we should not reuse them as they may
+                // have actually intersected the edit.
+                case ParsingContext.ArgumentExpressions:
+
+                // This is not safe to reuse for the same reason as the 'AssignmentExpression'
+                // cases.  i.e. a property assignment may end with an expression, and thus might
+                // have lookahead far beyond it's old node.
+                case ParsingContext.ObjectLiteralMembers:
+
+                // This is probably not safe to reuse.  There can be speculative parsing with
+                // type names in a heritage clause.  There can be generic names in the type
+                // name list, and there can be left hand side expressions (which can have type
+                // arguments.)
+                case ParsingContext.HeritageClauseElement:
+            }
+
+            return false;
+        }
+
+        function isReusableModuleElement(node: Node) {
+            if (node) {
+                switch (node.kind) {
+                    case SyntaxKind.ImportDeclaration:
+                    case SyntaxKind.ImportEqualsDeclaration:
+                    case SyntaxKind.ExportDeclaration:
+                    case SyntaxKind.ExportAssignment:
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.ModuleDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                        return true;
+                }
+
+                return isReusableStatement(node);
+            }
+
+            return false;
+        }
+
+        function isReusableClassMember(node: Node) {
+            if (node) {
+                switch (node.kind) {
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.IndexSignature:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.SemicolonClassElement:
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        function isReusableSwitchClause(node: Node) {
+            if (node) {
+                switch (node.kind) {
+                    case SyntaxKind.CaseClause:
+                    case SyntaxKind.DefaultClause:
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        function isReusableStatement(node: Node) {
+            if (node) {
+                switch (node.kind) {
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.VariableStatement:
+                    case SyntaxKind.Block:
+                    case SyntaxKind.IfStatement:
+                    case SyntaxKind.ExpressionStatement:
+                    case SyntaxKind.ThrowStatement:
+                    case SyntaxKind.ReturnStatement:
+                    case SyntaxKind.SwitchStatement:
+                    case SyntaxKind.BreakStatement:
+                    case SyntaxKind.ContinueStatement:
+                    case SyntaxKind.ForInStatement:
+                    case SyntaxKind.ForOfStatement:
+                    case SyntaxKind.ForStatement:
+                    case SyntaxKind.WhileStatement:
+                    case SyntaxKind.WithStatement:
+                    case SyntaxKind.EmptyStatement:
+                    case SyntaxKind.TryStatement:
+                    case SyntaxKind.LabeledStatement:
+                    case SyntaxKind.DoStatement:
+                    case SyntaxKind.DebuggerStatement:
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        function isReusableEnumMember(node: Node) {
+            return node.kind === SyntaxKind.EnumMember;
+        }
+
+        function isReusableTypeMember(node: Node) {
+            if (node) {
+                switch (node.kind) {
+                    case SyntaxKind.ConstructSignature:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.IndexSignature:
+                    case SyntaxKind.PropertySignature:
+                    case SyntaxKind.CallSignature:
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        function isReusableVariableDeclaration(node: Node) {
+            if (node.kind !== SyntaxKind.VariableDeclaration) {
+                return false;
+            }
+
+            // Very subtle incremental parsing bug.  Consider the following code:
+            //
+            //      let v = new List < A, B
+            //
+            // This is actually legal code.  It's a list of variable declarators "v = new List<A"
+            // on one side and "B" on the other. If you then change that to:
+            //
+            //      let v = new List < A, B >()
+            //
+            // then we have a problem.  "v = new List<A" doesn't intersect the change range, so we
+            // start reparsing at "B" and we completely fail to handle this properly.
+            //
+            // In order to prevent this, we do not allow a variable declarator to be reused if it
+            // has an initializer.
+            let variableDeclarator = <VariableDeclaration>node;
+            return variableDeclarator.initializer === undefined;
+        }
+
+        function isReusableParameter(node: Node) {
+            if (node.kind !== SyntaxKind.Parameter) {
+                return false;
+            }
+
+            // See the comment in isReusableVariableDeclaration for why we do this.
+            let parameter = <ParameterDeclaration>node;
+            return parameter.initializer === undefined;
+        }
+
+        // Returns true if we should abort parsing.
+        function abortParsingListOrMoveToNextToken(kind: ParsingContext) {
+            parseErrorAtCurrentToken(parsingContextErrors(kind));
+            if (isInSomeParsingContext()) {
+                return true;
+            }
+
+            nextToken();
+            return false;
+        }
+
+        function parsingContextErrors(context: ParsingContext): DiagnosticMessage {
+            switch (context) {
+                case ParsingContext.SourceElements: return Diagnostics.Declaration_or_statement_expected;
+                case ParsingContext.ModuleElements: return Diagnostics.Declaration_or_statement_expected;
+                case ParsingContext.BlockStatements: return Diagnostics.Statement_expected;
+                case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
+                case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
+                case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
+                case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
+                case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
+                case ParsingContext.HeritageClauseElement: return Diagnostics.Expression_expected;
+                case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected;
+                case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected;
+                case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected;
+                case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected;
+                case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected;
+                case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected;
+                case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected;
+                case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected;
+                case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected;
+                case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected;
+                case ParsingContext.HeritageClauses: return Diagnostics.Unexpected_token_expected;
+                case ParsingContext.ImportOrExportSpecifiers: return Diagnostics.Identifier_expected;
+            }
+        };
+
+        // Parses a comma-delimited list of elements
+        function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimeter?: boolean): NodeArray<T> {
+            let saveParsingContext = parsingContext;
+            parsingContext |= 1 << kind;
+            let result = <NodeArray<T>>[];
+            result.pos = getNodePos();
+
+            let commaStart = -1; // Meaning the previous token was not a comma
+            while (true) {
+                if (isListElement(kind, /* inErrorRecovery */ false)) {
+                    result.push(parseListElement(kind, parseElement));
+                    commaStart = scanner.getTokenPos();
+                    if (parseOptional(SyntaxKind.CommaToken)) {
+                        continue;
+                    }
+
+                    commaStart = -1; // Back to the state where the last token was not a comma
+                    if (isListTerminator(kind)) {
+                        break;
+                    }
+
+                    // We didn't get a comma, and the list wasn't terminated, explicitly parse
+                    // out a comma so we give a good error message.
+                    parseExpected(SyntaxKind.CommaToken);
+
+                    // If the token was a semicolon, and the caller allows that, then skip it and
+                    // continue.  This ensures we get back on track and don't result in tons of
+                    // parse errors.  For example, this can happen when people do things like use
+                    // a semicolon to delimit object literal members.   Note: we'll have already
+                    // reported an error when we called parseExpected above.
+                    if (considerSemicolonAsDelimeter && token === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) {
+                        nextToken();
+                    }
+                    continue;
+                }
+
+                if (isListTerminator(kind)) {
+                    break;
+                }
+
+                if (abortParsingListOrMoveToNextToken(kind)) {
+                    break;
+                }
+            }
+
+            // Recording the trailing comma is deliberately done after the previous
+            // loop, and not just if we see a list terminator. This is because the list
+            // may have ended incorrectly, but it is still important to know if there
+            // was a trailing comma.
+            // Check if the last token was a comma.
+            if (commaStart >= 0) {
+                // Always preserve a trailing comma by marking it on the NodeArray
+                result.hasTrailingComma = true;
+            }
+
+            result.end = getNodeEnd();
+            parsingContext = saveParsingContext;
+            return result;
+        }
+
+        function createMissingList<T>(): NodeArray<T> {
+            let pos = getNodePos();
+            let result = <NodeArray<T>>[];
+            result.pos = pos;
+            result.end = pos;
+            return result;
+        }
+
+        function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray<T> {
+            if (parseExpected(open)) {
+                let result = parseDelimitedList(kind, parseElement);
+                parseExpected(close);
+                return result;
+            }
+
+            return createMissingList<T>();
+        }
+
+        // The allowReservedWords parameter controls whether reserved words are permitted after the first dot
+        function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName {
+            let entity: EntityName = parseIdentifier(diagnosticMessage);
+            while (parseOptional(SyntaxKind.DotToken)) {
+                let node = <QualifiedName>createNode(SyntaxKind.QualifiedName, entity.pos);
+                node.left = entity;
+                node.right = parseRightSideOfDot(allowReservedWords);
+                entity = finishNode(node);
+            }
+            return entity;
+        }
+
+        function parseRightSideOfDot(allowIdentifierNames: boolean): Identifier {
+            // Technically a keyword is valid here as all keywords are identifier names.
+            // However, often we'll encounter this in error situations when the keyword
+            // is actually starting another valid construct.
+            //
+            // So, we check for the following specific case:
+            //
+            //      name.
+            //      keyword identifierNameOrKeyword
+            //
+            // Note: the newlines are important here.  For example, if that above code
+            // were rewritten into:
+            //
+            //      name.keyword
+            //      identifierNameOrKeyword
+            //
+            // Then we would consider it valid.  That's because ASI would take effect and
+            // the code would be implicitly: "name.keyword; identifierNameOrKeyword".
+            // In the first case though, ASI will not take effect because there is not a
+            // line terminator after the keyword.
+            if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord()) {
+                let matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
+
+                if (matchesPattern) {
+                    // Report that we need an identifier.  However, report it right after the dot,
+                    // and not on the next token.  This is because the next token might actually
+                    // be an identifier and the error woudl be quite confusing.
+                    return <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentToken:*/ true, Diagnostics.Identifier_expected);
+                }
+            }
+
+            return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
+        }
+
+        function parseTemplateExpression(): TemplateExpression {
+            let template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
+
+            template.head = parseLiteralNode();
+            Debug.assert(template.head.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
+
+            let templateSpans = <NodeArray<TemplateSpan>>[];
+            templateSpans.pos = getNodePos();
+
+            do {
+                templateSpans.push(parseTemplateSpan());
+            }
+            while (templateSpans[templateSpans.length - 1].literal.kind === SyntaxKind.TemplateMiddle)
+
+            templateSpans.end = getNodeEnd();
+            template.templateSpans = templateSpans;
+
+            return finishNode(template);
+        }
+
+        function parseTemplateSpan(): TemplateSpan {
+            let span = <TemplateSpan>createNode(SyntaxKind.TemplateSpan);
+            span.expression = allowInAnd(parseExpression);
+
+            let literal: LiteralExpression;
+
+            if (token === SyntaxKind.CloseBraceToken) {
+                reScanTemplateToken()
+                literal = parseLiteralNode();
+            }
+            else {
+                literal = <LiteralExpression>parseExpectedToken(SyntaxKind.TemplateTail, /*reportAtCurrentPosition:*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken));
+            }
+
+            span.literal = literal;
+            return finishNode(span);
+        }
+
+        function parseLiteralNode(internName?: boolean): LiteralExpression {
+            let node = <LiteralExpression>createNode(token);
+            let text = scanner.getTokenValue();
+            node.text = internName ? internIdentifier(text) : text;
+
+            if (scanner.hasExtendedUnicodeEscape()) {
+                node.hasExtendedUnicodeEscape = true;
+            }
+
+            if (scanner.isUnterminated()) {
+                node.isUnterminated = true;
+            }
+
+            let tokenPos = scanner.getTokenPos();
+            nextToken();
+            finishNode(node);
+
+            // Octal literals are not allowed in strict mode or ES5
+            // Note that theoretically the following condition would hold true literals like 009,
+            // which is not octal.But because of how the scanner separates the tokens, we would
+            // never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
+            // We also do not need to check for negatives because any prefix operator would be part of a
+            // parent unary expression.
+            if (node.kind === SyntaxKind.NumericLiteral
+                && sourceText.charCodeAt(tokenPos) === CharacterCodes._0
+                && isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) {
+
+                node.flags |= NodeFlags.OctalLiteral;
+            }
+
+            return node;
+        }
+
+        // TYPES
+
+        function parseTypeReference(): TypeReferenceNode {
+            let node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
+            node.typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected);
+            if (!scanner.hasPrecedingLineBreak() && token === SyntaxKind.LessThanToken) {
+                node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
+            }
+            return finishNode(node);
+        }
+
+        function parseTypeQuery(): TypeQueryNode {
+            let node = <TypeQueryNode>createNode(SyntaxKind.TypeQuery);
+            parseExpected(SyntaxKind.TypeOfKeyword);
+            node.exprName = parseEntityName(/*allowReservedWords*/ true);
+            return finishNode(node);
+        }
+
+        function parseTypeParameter(): TypeParameterDeclaration {
+            let node = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
+            node.name = parseIdentifier();
+            if (parseOptional(SyntaxKind.ExtendsKeyword)) {
+                // It's not uncommon for people to write improper constraints to a generic.  If the
+                // user writes a constraint that is an expression and not an actual type, then parse
+                // it out as an expression (so we can recover well), but report that a type is needed
+                // instead.
+                if (isStartOfType() || !isStartOfExpression()) {
+                    node.constraint = parseType();
+                }
+                else {
+                    // It was not a type, and it looked like an expression.  Parse out an expression
+                    // here so we recover well.  Note: it is important that we call parseUnaryExpression
+                    // and not parseExpression here.  If the user has:
+                    //
+                    //      <T extends "">
+                    //
+                    // We do *not* want to consume the  >  as we're consuming the expression for "".
+                    node.expression = parseUnaryExpressionOrHigher();
+                }
+            }
+
+            return finishNode(node);
+        }
+
+        function parseTypeParameters(): NodeArray<TypeParameterDeclaration> {
+            if (token === SyntaxKind.LessThanToken) {
+                return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
+            }
+        }
+
+        function parseParameterType(): TypeNode {
+            if (parseOptional(SyntaxKind.ColonToken)) {
+                return token === SyntaxKind.StringLiteral
+                    ? <StringLiteral>parseLiteralNode(/*internName:*/ true)
+                    : parseType();
+            }
+
+            return undefined;
+        }
+
+        function isStartOfParameter(): boolean {
+            return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifier(token) || token === SyntaxKind.AtToken;
+        }
+
+        function setModifiers(node: Node, modifiers: ModifiersArray) {
+            if (modifiers) {
+                node.flags |= modifiers.flags;
+                node.modifiers = modifiers;
+            }
+        }
+
+        function parseParameter(): ParameterDeclaration {
+            let node = <ParameterDeclaration>createNode(SyntaxKind.Parameter);
+            node.decorators = parseDecorators();
+            setModifiers(node, parseModifiers());
+            node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
+
+            // SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3
+            //      [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
+            //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
+
+            node.name = inGeneratorParameterContext() ? doInYieldContext(parseIdentifierOrPattern) : parseIdentifierOrPattern();
+
+            if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) {
+                // in cases like
+                // 'use strict'
+                // function foo(static)
+                // isParameter('static') === true, because of isModifier('static')
+                // however 'static' is not a legal identifier in a strict mode.
+                // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined)
+                // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM)
+                // to avoid this we'll advance cursor to the next token.
+                nextToken();
+            }
+
+            node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
+            node.type = parseParameterType();
+            node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) : parseParameterInitializer();
+
+            // Do not check for initializers in an ambient context for parameters. This is not
+            // a grammar error because the grammar allows arbitrary call signatures in
+            // an ambient context.
+            // It is actually not necessary for this to be an error at all. The reason is that
+            // function/constructor implementations are syntactically disallowed in ambient
+            // contexts. In addition, parameter initializers are semantically disallowed in
+            // overload signatures. So parameter initializers are transitively disallowed in
+            // ambient contexts.
+            return finishNode(node);
+        }
+
+        function parseParameterInitializer() {
+            return parseInitializer(/*inParameter*/ true);
+        }
+
+        function fillSignature(
+            returnToken: SyntaxKind,
+            yieldAndGeneratorParameterContext: boolean,
+            requireCompleteParameterList: boolean,
+            signature: SignatureDeclaration): void {
+            let returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken;
+            signature.typeParameters = parseTypeParameters();
+            signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList);
+
+            if (returnTokenRequired) {
+                parseExpected(returnToken);
+                signature.type = parseType();
+            }
+            else if (parseOptional(returnToken)) {
+                signature.type = parseType();
+            }
+        }
+
+        // Note: after careful analysis of the grammar, it does not appear to be possible to
+        // have 'Yield' And 'GeneratorParameter' not in sync.  i.e. any production calling
+        // this FormalParameters production either always sets both to true, or always sets
+        // both to false.  As such we only have a single parameter to represent both.
+        function parseParameterList(yieldAndGeneratorParameterContext: boolean, requireCompleteParameterList: boolean) {
+            // FormalParameters[Yield,GeneratorParameter] :
+            //      ...
+            //
+            // FormalParameter[Yield,GeneratorParameter] :
+            //      BindingElement[?Yield, ?GeneratorParameter]
+            //
+            // BindingElement[Yield, GeneratorParameter ] : See 13.2.3
+            //      SingleNameBinding[?Yield, ?GeneratorParameter]
+            //      [+GeneratorParameter]BindingPattern[?Yield, GeneratorParameter]Initializer[In]opt
+            //      [~GeneratorParameter]BindingPattern[?Yield]Initializer[In, ?Yield]opt
+            //
+            // SingleNameBinding[Yield, GeneratorParameter] : See 13.2.3
+            //      [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
+            //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
+            if (parseExpected(SyntaxKind.OpenParenToken)) {
+                let savedYieldContext = inYieldContext();
+                let savedGeneratorParameterContext = inGeneratorParameterContext();
+
+                setYieldContext(yieldAndGeneratorParameterContext);
+                setGeneratorParameterContext(yieldAndGeneratorParameterContext);
+
+                let result = parseDelimitedList(ParsingContext.Parameters, parseParameter);
+
+                setYieldContext(savedYieldContext);
+                setGeneratorParameterContext(savedGeneratorParameterContext);
+
+                if (!parseExpected(SyntaxKind.CloseParenToken) && requireCompleteParameterList) {
+                    // Caller insisted that we had to end with a )   We didn't.  So just return
+                    // undefined here.
+                    return undefined;
+                }
+
+                return result;
+            }
+
+            // We didn't even have an open paren.  If the caller requires a complete parameter list,
+            // we definitely can't provide that.  However, if they're ok with an incomplete one,
+            // then just return an empty set of parameters.
+            return requireCompleteParameterList ? undefined : createMissingList<ParameterDeclaration>();
+        }
+
+        function parseTypeMemberSemicolon() {
+            // We allow type members to be separated by commas or (possibly ASI) semicolons.
+            // First check if it was a comma.  If so, we're done with the member.
+            if (parseOptional(SyntaxKind.CommaToken)) {
+                return;
+            }
+
+            // Didn't have a comma.  We must have a (possible ASI) semicolon.
+            parseSemicolon();
+        }
+
+        function parseSignatureMember(kind: SyntaxKind): SignatureDeclaration {
+            let node = <SignatureDeclaration>createNode(kind);
+            if (kind === SyntaxKind.ConstructSignature) {
+                parseExpected(SyntaxKind.NewKeyword);
+            }
+            fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
+            parseTypeMemberSemicolon();
+            return finishNode(node);
+        }
+
+        function isIndexSignature(): boolean {
+            if (token !== SyntaxKind.OpenBracketToken) {
+                return false;
+            }
+
+            return lookAhead(isUnambiguouslyIndexSignature);
+        }
+
+        function isUnambiguouslyIndexSignature() {
+            // The only allowed sequence is:
+            //
+            //   [id:
+            //
+            // However, for error recovery, we also check the following cases:
+            //
+            //   [...
+            //   [id,
+            //   [id?,
+            //   [id?:
+            //   [id?]
+            //   [public id
+            //   [private id
+            //   [protected id
+            //   []
+            //
+            nextToken();
+            if (token === SyntaxKind.DotDotDotToken || token === SyntaxKind.CloseBracketToken) {
+                return true;
+            }
+
+            if (isModifier(token)) {
+                nextToken();
+                if (isIdentifier()) {
+                    return true;
+                }
+            }
+            else if (!isIdentifier()) {
+                return false;
+            }
+            else {
+                // Skip the identifier
+                nextToken();
+            }
+
+            // A colon signifies a well formed indexer
+            // A comma should be a badly formed indexer because comma expressions are not allowed
+            // in computed properties.
+            if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken) {
+                return true;
+            }
+
+            // Question mark could be an indexer with an optional property,
+            // or it could be a conditional expression in a computed property.
+            if (token !== SyntaxKind.QuestionToken) {
+                return false;
+            }
+
+            // If any of the following tokens are after the question mark, it cannot
+            // be a conditional expression, so treat it as an indexer.
+            nextToken();
+            return token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBracketToken;
+        }
+
+        function parseIndexSignatureDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): IndexSignatureDeclaration {
+            let node = <IndexSignatureDeclaration>createNode(SyntaxKind.IndexSignature, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
+            node.type = parseTypeAnnotation();
+            parseTypeMemberSemicolon();
+            return finishNode(node)
+        }
+
+        function parsePropertyOrMethodSignature(): Declaration {
+            let fullStart = scanner.getStartPos();
+            let name = parsePropertyName();
+            let questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
+
+            if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
+                let method = <MethodDeclaration>createNode(SyntaxKind.MethodSignature, fullStart);
+                method.name = name;
+                method.questionToken = questionToken;
+
+                // Method signatues don't exist in expression contexts.  So they have neither
+                // [Yield] nor [GeneratorParameter]
+                fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, method);
+                parseTypeMemberSemicolon();
+                return finishNode(method);
+            }
+            else {
+                let property = <PropertyDeclaration>createNode(SyntaxKind.PropertySignature, fullStart);
+                property.name = name;
+                property.questionToken = questionToken;
+                property.type = parseTypeAnnotation();
+                parseTypeMemberSemicolon();
+                return finishNode(property);
+            }
+        }
+
+        function isStartOfTypeMember(): boolean {
+            switch (token) {
+                case SyntaxKind.OpenParenToken:
+                case SyntaxKind.LessThanToken:
+                case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties
+                    return true;
+                default:
+                    if (isModifier(token)) {
+                        let result = lookAhead(isStartOfIndexSignatureDeclaration);
+                        if (result) {
+                            return result;
+                        }
+                    }
+
+                    return isLiteralPropertyName() && lookAhead(isTypeMemberWithLiteralPropertyName);
+            }
+        }
+
+        function isStartOfIndexSignatureDeclaration() {
+            while (isModifier(token)) {
+                nextToken();
+            }
+
+            return isIndexSignature();
+        }
+
+        function isTypeMemberWithLiteralPropertyName() {
+            nextToken();
+            return token === SyntaxKind.OpenParenToken ||
+                token === SyntaxKind.LessThanToken ||
+                token === SyntaxKind.QuestionToken ||
+                token === SyntaxKind.ColonToken ||
+                canParseSemicolon();
+        }
+
+        function parseTypeMember(): Declaration {
+            switch (token) {
+                case SyntaxKind.OpenParenToken:
+                case SyntaxKind.LessThanToken:
+                    return parseSignatureMember(SyntaxKind.CallSignature);
+                case SyntaxKind.OpenBracketToken:
+                    // Indexer or computed property
+                    return isIndexSignature()
+                        ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined)
+                        : parsePropertyOrMethodSignature();
+                case SyntaxKind.NewKeyword:
+                    if (lookAhead(isStartOfConstructSignature)) {
+                        return parseSignatureMember(SyntaxKind.ConstructSignature);
+                    }
+                // fall through.
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.NumericLiteral:
+                    return parsePropertyOrMethodSignature();
+                default:
+                    // Index declaration as allowed as a type member.  But as per the grammar,
+                    // they also allow modifiers. So we have to check for an index declaration
+                    // that might be following modifiers. This ensures that things work properly
+                    // when incrementally parsing as the parser will produce the Index declaration
+                    // if it has the same text regardless of whether it is inside a class or an
+                    // object type.
+                    if (isModifier(token)) {
+                        let result = tryParse(parseIndexSignatureWithModifiers);
+                        if (result) {
+                            return result;
+                        }
+                    }
+
+                    if (isIdentifierOrKeyword()) {
+                        return parsePropertyOrMethodSignature();
+                    }
+            }
+        }
+
+        function parseIndexSignatureWithModifiers() {
+            let fullStart = scanner.getStartPos();
+            let decorators = parseDecorators();
+            let modifiers = parseModifiers();
+            return isIndexSignature()
+                ? parseIndexSignatureDeclaration(fullStart, decorators, modifiers)
+                : undefined;
+        }
+
+        function isStartOfConstructSignature() {
+            nextToken();
+            return token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken;
+        }
+
+        function parseTypeLiteral(): TypeLiteralNode {
+            let node = <TypeLiteralNode>createNode(SyntaxKind.TypeLiteral);
+            node.members = parseObjectTypeMembers();
+            return finishNode(node);
+        }
+
+        function parseObjectTypeMembers(): NodeArray<Declaration> {
+            let members: NodeArray<Declaration>;
+            if (parseExpected(SyntaxKind.OpenBraceToken)) {
+                members = parseList(ParsingContext.TypeMembers, /*checkForStrictMode*/ false, parseTypeMember);
+                parseExpected(SyntaxKind.CloseBraceToken);
+            }
+            else {
+                members = createMissingList<Declaration>();
+            }
+
+            return members;
+        }
+
+        function parseTupleType(): TupleTypeNode {
+            let node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
+            node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
+            return finishNode(node);
+        }
+
+        function parseParenthesizedType(): ParenthesizedTypeNode {
+            let node = <ParenthesizedTypeNode>createNode(SyntaxKind.ParenthesizedType);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.type = parseType();
+            parseExpected(SyntaxKind.CloseParenToken);
+            return finishNode(node);
+        }
+
+        function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode {
+            let node = <FunctionOrConstructorTypeNode>createNode(kind);
+            if (kind === SyntaxKind.ConstructorType) {
+                parseExpected(SyntaxKind.NewKeyword);
+            }
+            fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
+            return finishNode(node);
+        }
+
+        function parseKeywordAndNoDot(): TypeNode {
+            let node = parseTokenNode<TypeNode>();
+            return token === SyntaxKind.DotToken ? undefined : node;
+        }
+
+        function parseNonArrayType(): TypeNode {
+            switch (token) {
+                case SyntaxKind.AnyKeyword:
+                case SyntaxKind.StringKeyword:
+                case SyntaxKind.NumberKeyword:
+                case SyntaxKind.BooleanKeyword:
+                case SyntaxKind.SymbolKeyword:
+                    // If these are followed by a dot, then parse these out as a dotted type reference instead.
+                    let node = tryParse(parseKeywordAndNoDot);
+                    return node || parseTypeReference();
+                case SyntaxKind.VoidKeyword:
+                    return parseTokenNode<TypeNode>();
+                case SyntaxKind.TypeOfKeyword:
+                    return parseTypeQuery();
+                case SyntaxKind.OpenBraceToken:
+                    return parseTypeLiteral();
+                case SyntaxKind.OpenBracketToken:
+                    return parseTupleType();
+                case SyntaxKind.OpenParenToken:
+                    return parseParenthesizedType();
+                default:
+                    return parseTypeReference();
+            }
+        }
+
+        function isStartOfType(): boolean {
+            switch (token) {
+                case SyntaxKind.AnyKeyword:
+                case SyntaxKind.StringKeyword:
+                case SyntaxKind.NumberKeyword:
+                case SyntaxKind.BooleanKeyword:
+                case SyntaxKind.SymbolKeyword:
+                case SyntaxKind.VoidKeyword:
+                case SyntaxKind.TypeOfKeyword:
+                case SyntaxKind.OpenBraceToken:
+                case SyntaxKind.OpenBracketToken:
+                case SyntaxKind.LessThanToken:
+                case SyntaxKind.NewKeyword:
+                    return true;
+                case SyntaxKind.OpenParenToken:
+                    // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
+                    // or something that starts a type. We don't want to consider things like '(1)' a type.
+                    return lookAhead(isStartOfParenthesizedOrFunctionType);
+                default:
+                    return isIdentifier();
+            }
+        }
+
+        function isStartOfParenthesizedOrFunctionType() {
+            nextToken();
+            return token === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType();
+        }
+
+        function parseArrayTypeOrHigher(): TypeNode {
+            let type = parseNonArrayType();
+            while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
+                parseExpected(SyntaxKind.CloseBracketToken);
+                let node = <ArrayTypeNode>createNode(SyntaxKind.ArrayType, type.pos);
+                node.elementType = type;
+                type = finishNode(node);
+            }
+            return type;
+        }
+
+        function parseUnionTypeOrHigher(): TypeNode {
+            let type = parseArrayTypeOrHigher();
+            if (token === SyntaxKind.BarToken) {
+                let types = <NodeArray<TypeNode>>[type];
+                types.pos = type.pos;
+                while (parseOptional(SyntaxKind.BarToken)) {
+                    types.push(parseArrayTypeOrHigher());
+                }
+                types.end = getNodeEnd();
+                let node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
+                node.types = types;
+                type = finishNode(node);
+            }
+            return type;
+        }
+
+        function isStartOfFunctionType(): boolean {
+            if (token === SyntaxKind.LessThanToken) {
+                return true;
+            }
+
+            return token === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType);
+        }
+
+        function isUnambiguouslyStartOfFunctionType() {
+            nextToken();
+            if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) {
+                // ( )
+                // ( ...
+                return true;
+            }
+            if (isIdentifier() || isModifier(token)) {
+                nextToken();
+                if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken ||
+                    token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken ||
+                    isIdentifier() || isModifier(token)) {
+                    // ( id :
+                    // ( id ,
+                    // ( id ?
+                    // ( id =
+                    // ( modifier id
+                    return true;
+                }
+                if (token === SyntaxKind.CloseParenToken) {
+                    nextToken();
+                    if (token === SyntaxKind.EqualsGreaterThanToken) {
+                        // ( id ) =>
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        function parseType(): TypeNode {
+            // The rules about 'yield' only apply to actual code/expression contexts.  They don't
+            // apply to 'type' contexts.  So we disable these parameters here before moving on.
+            let savedYieldContext = inYieldContext();
+            let savedGeneratorParameterContext = inGeneratorParameterContext();
+
+            setYieldContext(false);
+            setGeneratorParameterContext(false);
+
+            let result = parseTypeWorker();
+
+            setYieldContext(savedYieldContext);
+            setGeneratorParameterContext(savedGeneratorParameterContext);
+
+            return result;
+        }
+
+        function parseTypeWorker(): TypeNode {
+            if (isStartOfFunctionType()) {
+                return parseFunctionOrConstructorType(SyntaxKind.FunctionType);
+            }
+            if (token === SyntaxKind.NewKeyword) {
+                return parseFunctionOrConstructorType(SyntaxKind.ConstructorType);
+            }
+            return parseUnionTypeOrHigher();
+        }
+
+        function parseTypeAnnotation(): TypeNode {
+            return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
+        }
+
+        // EXPRESSIONS
+        function isStartOfLeftHandSideExpression(): boolean {
+            switch (token) {
+                case SyntaxKind.ThisKeyword:
+                case SyntaxKind.SuperKeyword:
+                case SyntaxKind.NullKeyword:
+                case SyntaxKind.TrueKeyword:
+                case SyntaxKind.FalseKeyword:
+                case SyntaxKind.NumericLiteral:
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.NoSubstitutionTemplateLiteral:
+                case SyntaxKind.TemplateHead:
+                case SyntaxKind.OpenParenToken:
+                case SyntaxKind.OpenBracketToken:
+                case SyntaxKind.OpenBraceToken:
+                case SyntaxKind.FunctionKeyword:
+                case SyntaxKind.ClassKeyword:
+                case SyntaxKind.NewKeyword:
+                case SyntaxKind.SlashToken:
+                case SyntaxKind.SlashEqualsToken:
+                case SyntaxKind.Identifier:
+                    return true;
+                default:
+                    return isIdentifier();
+            }
+        }
+
+        function isStartOfExpression(): boolean {
+            if (isStartOfLeftHandSideExpression()) {
+                return true;
+            }
+
+            switch (token) {
+                case SyntaxKind.PlusToken:
+                case SyntaxKind.MinusToken:
+                case SyntaxKind.TildeToken:
+                case SyntaxKind.ExclamationToken:
+                case SyntaxKind.DeleteKeyword:
+                case SyntaxKind.TypeOfKeyword:
+                case SyntaxKind.VoidKeyword:
+                case SyntaxKind.PlusPlusToken:
+                case SyntaxKind.MinusMinusToken:
+                case SyntaxKind.LessThanToken:
+                case SyntaxKind.YieldKeyword:
+                    // Yield always starts an expression.  Either it is an identifier (in which case
+                    // it is definitely an expression).  Or it's a keyword (either because we're in
+                    // a generator, or in strict mode (or both)) and it started a yield expression.
+                    return true;
+                default:
+                    // Error tolerance.  If we see the start of some binary operator, we consider
+                    // that the start of an expression.  That way we'll parse out a missing identifier,
+                    // give a good message about an identifier being missing, and then consume the
+                    // rest of the binary expression.
+                    if (isBinaryOperator()) {
+                        return true;
+                    }
+
+                    return isIdentifier();
+            }
+        }
+
+        function isStartOfExpressionStatement(): boolean {
+            // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement.
+            return token !== SyntaxKind.OpenBraceToken &&
+                token !== SyntaxKind.FunctionKeyword &&
+                token !== SyntaxKind.ClassKeyword &&
+                token !== SyntaxKind.AtToken &&
+                isStartOfExpression();
+        }
+
+        function parseExpression(): Expression {
+            // Expression[in]:
+            //      AssignmentExpression[in]
+            //      Expression[in] , AssignmentExpression[in]
+
+            // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator
+            let saveDecoratorContext = inDecoratorContext();
+            if (saveDecoratorContext) {
+                setDecoratorContext(false);
+            }
+
+            let expr = parseAssignmentExpressionOrHigher();
+            let operatorToken: Node;
+            while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) {
+                expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher());
+            }
+
+            if (saveDecoratorContext) {
+                setDecoratorContext(true);
+            }
+            return expr;
+        }
+
+        function parseInitializer(inParameter: boolean): Expression {
+            if (token !== SyntaxKind.EqualsToken) {
+                // It's not uncommon during typing for the user to miss writing the '=' token.  Check if
+                // there is no newline after the last token and if we're on an expression.  If so, parse
+                // this as an equals-value clause with a missing equals.
+                // NOTE: There are two places where we allow equals-value clauses.  The first is in a
+                // variable declarator.  The second is with a parameter.  For variable declarators
+                // it's more likely that a { would be a allowed (as an object literal).  While this
+                // is also allowed for parameters, the risk is that we consume the { as an object
+                // literal when it really will be for the block following the parameter.
+                if (scanner.hasPrecedingLineBreak() || (inParameter && token === SyntaxKind.OpenBraceToken) || !isStartOfExpression()) {
+                    // preceding line break, open brace in a parameter (likely a function body) or current token is not an expression -
+                    // do not try to parse initializer
+                    return undefined;
+                }
+            }
+
+            // Initializer[In, Yield] :
+            //     = AssignmentExpression[?In, ?Yield]
+
+            parseExpected(SyntaxKind.EqualsToken);
+            return parseAssignmentExpressionOrHigher();
+        }
+
+        function parseAssignmentExpressionOrHigher(): Expression {
+            //  AssignmentExpression[in,yield]:
+            //      1) ConditionalExpression[?in,?yield]
+            //      2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
+            //      3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
+            //      4) ArrowFunctionExpression[?in,?yield]
+            //      5) [+Yield] YieldExpression[?In]
+            //
+            // Note: for ease of implementation we treat productions '2' and '3' as the same thing.
+            // (i.e. they're both BinaryExpressions with an assignment operator in it).
+
+            // First, do the simple check if we have a YieldExpression (production '5').
+            if (isYieldExpression()) {
+                return parseYieldExpression();
+            }
+
+            // Then, check if we have an arrow function (production '4') that starts with a parenthesized
+            // parameter list. If we do, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
+            // not a  LeftHandSideExpression, nor does it start a ConditionalExpression.  So we are done
+            // with AssignmentExpression if we see one.
+            let arrowExpression = tryParseParenthesizedArrowFunctionExpression();
+            if (arrowExpression) {
+                return arrowExpression;
+            }
+
+            // Now try to see if we're in production '1', '2' or '3'.  A conditional expression can
+            // start with a LogicalOrExpression, while the assignment productions can only start with
+            // LeftHandSideExpressions.
+            //
+            // So, first, we try to just parse out a BinaryExpression.  If we get something that is a
+            // LeftHandSide or higher, then we can try to parse out the assignment expression part.
+            // Otherwise, we try to parse out the conditional expression bit.  We want to allow any
+            // binary expression here, so we pass in the 'lowest' precedence here so that it matches
+            // and consumes anything.
+            let expr = parseBinaryExpressionOrHigher(/*precedence:*/ 0);
+
+            // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized
+            // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single
+            // identifier and the current token is an arrow.
+            if (expr.kind === SyntaxKind.Identifier && token === SyntaxKind.EqualsGreaterThanToken) {
+                return parseSimpleArrowFunctionExpression(<Identifier>expr);
+            }
+
+            // Now see if we might be in cases '2' or '3'.
+            // If the expression was a LHS expression, and we have an assignment operator, then
+            // we're in '2' or '3'. Consume the assignment and return.
+            //
+            // Note: we call reScanGreaterToken so that we get an appropriately merged token
+            // for cases like > > =  becoming >>=
+            if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
+                return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher());
+            }
+
+            // It wasn't an assignment or a lambda.  This is a conditional expression:
+            return parseConditionalExpressionRest(expr);
+        }
+
+        function isYieldExpression(): boolean {
+            if (token === SyntaxKind.YieldKeyword) {
+                // If we have a 'yield' keyword, and htis is a context where yield expressions are
+                // allowed, then definitely parse out a yield expression.
+                if (inYieldContext()) {
+                    return true;
+                }
+
+                if (inStrictModeContext()) {
+                    // If we're in strict mode, then 'yield' is a keyword, could only ever start
+                    // a yield expression.
+                    return true;
+                }
+
+                // We're in a context where 'yield expr' is not allowed.  However, if we can
+                // definitely tell that the user was trying to parse a 'yield expr' and not
+                // just a normal expr that start with a 'yield' identifier, then parse out
+                // a 'yield expr'.  We can then report an error later that they are only
+                // allowed in generator expressions.
+                //
+                // for example, if we see 'yield(foo)', then we'll have to treat that as an
+                // invocation expression of something called 'yield'.  However, if we have
+                // 'yield foo' then that is not legal as a normal expression, so we can
+                // definitely recognize this as a yield expression.
+                //
+                // for now we just check if the next token is an identifier.  More heuristics
+                // can be added here later as necessary.  We just need to make sure that we
+                // don't accidently consume something legal.
+                return lookAhead(nextTokenIsIdentifierOnSameLine);
+            }
+
+            return false;
+        }
+
+        function nextTokenIsIdentifierOnSameLine() {
+            nextToken();
+            return !scanner.hasPrecedingLineBreak() && isIdentifier()
+        }
+
+        function nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine() {
+            nextToken();
+            return !scanner.hasPrecedingLineBreak() &&
+                (isIdentifier() || token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken);
+        }
+
+        function parseYieldExpression(): YieldExpression {
+            let node = <YieldExpression>createNode(SyntaxKind.YieldExpression);
+
+            // YieldExpression[In] :
+            //      yield
+            //      yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
+            //      yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
+            nextToken();
+
+            if (!scanner.hasPrecedingLineBreak() &&
+                (token === SyntaxKind.AsteriskToken || isStartOfExpression())) {
+                node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
+                node.expression = parseAssignmentExpressionOrHigher();
+                return finishNode(node);
+            }
+            else {
+                // if the next token is not on the same line as yield.  or we don't have an '*' or
+                // the start of an expressin, then this is just a simple "yield" expression.
+                return finishNode(node);
+            }
+        }
+
+        function parseSimpleArrowFunctionExpression(identifier: Identifier): Expression {
+            Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
+
+            let node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, identifier.pos);
+
+            let parameter = <ParameterDeclaration>createNode(SyntaxKind.Parameter, identifier.pos);
+            parameter.name = identifier;
+            finishNode(parameter);
+
+            node.parameters = <NodeArray<ParameterDeclaration>>[parameter];
+            node.parameters.pos = parameter.pos;
+            node.parameters.end = parameter.end;
+
+            node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, false, Diagnostics._0_expected, "=>");
+            node.body = parseArrowFunctionExpressionBody();
+
+            return finishNode(node);
+        }
+
+        function tryParseParenthesizedArrowFunctionExpression(): Expression {
+            let triState = isParenthesizedArrowFunctionExpression();
+
+            if (triState === Tristate.False) {
+                // It's definitely not a parenthesized arrow function expression.
+                return undefined;
+            }
+
+            // If we definitely have an arrow function, then we can just parse one, not requiring a
+            // following => or { token. Otherwise, we *might* have an arrow function.  Try to parse
+            // it out, but don't allow any ambiguity, and return 'undefined' if this could be an
+            // expression instead.
+            let arrowFunction = triState === Tristate.True
+                ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity:*/ true)
+                : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead);
+
+            if (!arrowFunction) {
+                // Didn't appear to actually be a parenthesized arrow function.  Just bail out.
+                return undefined;
+            }
+
+            // If we have an arrow, then try to parse the body. Even if not, try to parse if we
+            // have an opening brace, just in case we're in an error state.
+            var lastToken = token;
+            arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition:*/false, Diagnostics._0_expected, "=>");
+            arrowFunction.body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken)
+                ? parseArrowFunctionExpressionBody()
+                : parseIdentifier();
+
+            return finishNode(arrowFunction);
+        }
+
+        //  True        -> We definitely expect a parenthesized arrow function here.
+        //  False       -> There *cannot* be a parenthesized arrow function here.
+        //  Unknown     -> There *might* be a parenthesized arrow function here.
+        //                 Speculatively look ahead to be sure, and rollback if not.
+        function isParenthesizedArrowFunctionExpression(): Tristate {
+            if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
+                return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
+            }
+
+            if (token === SyntaxKind.EqualsGreaterThanToken) {
+                // ERROR RECOVERY TWEAK:
+                // If we see a standalone => try to parse it as an arrow function expression as that's
+                // likely what the user intended to write.
+                return Tristate.True;
+            }
+            // Definitely not a parenthesized arrow function.
+            return Tristate.False;
+        }
+
+        function isParenthesizedArrowFunctionExpressionWorker() {
+            let first = token;
+            let second = nextToken();
+
+            if (first === SyntaxKind.OpenParenToken) {
+                if (second === SyntaxKind.CloseParenToken) {
+                    // Simple cases: "() =>", "(): ", and  "() {".
+                    // This is an arrow function with no parameters.
+                    // The last one is not actually an arrow function,
+                    // but this is probably what the user intended.
+                    let third = nextToken();
+                    switch (third) {
+                        case SyntaxKind.EqualsGreaterThanToken:
+                        case SyntaxKind.ColonToken:
+                        case SyntaxKind.OpenBraceToken:
+                            return Tristate.True;
+                        default:
+                            return Tristate.False;
+                    }
+                }
+
+                // If encounter "([" or "({", this could be the start of a binding pattern.
+                // Examples:
+                //      ([ x ]) => { }
+                //      ({ x }) => { }
+                //      ([ x ])
+                //      ({ x })
+                if (second === SyntaxKind.OpenBracketToken || second === SyntaxKind.OpenBraceToken) {
+                    return Tristate.Unknown;
+                }
+
+                // Simple case: "(..."
+                // This is an arrow function with a rest parameter.
+                if (second === SyntaxKind.DotDotDotToken) {
+                    return Tristate.True;
+                }
+
+                // If we had "(" followed by something that's not an identifier,
+                // then this definitely doesn't look like a lambda.
+                // Note: we could be a little more lenient and allow
+                // "(public" or "(private". These would not ever actually be allowed,
+                // but we could provide a good error message instead of bailing out.
+                if (!isIdentifier()) {
+                    return Tristate.False;
+                }
+
+                // If we have something like "(a:", then we must have a
+                // type-annotated parameter in an arrow function expression.
+                if (nextToken() === SyntaxKind.ColonToken) {
+                    return Tristate.True;
+                }
+
+                // This *could* be a parenthesized arrow function.
+                // Return Unknown to let the caller know.
+                return Tristate.Unknown;
+            }
+            else {
+                Debug.assert(first === SyntaxKind.LessThanToken);
+
+                // If we have "<" not followed by an identifier,
+                // then this definitely is not an arrow function.
+                if (!isIdentifier()) {
+                    return Tristate.False;
+                }
+
+                // This *could* be a parenthesized arrow function.
+                return Tristate.Unknown;
+            }
+        }
+
+        function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction {
+            return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity:*/ false);
+        }
+
+        function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
+            let node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction);
+            // Arrow functions are never generators.
+            //
+            // If we're speculatively parsing a signature for a parenthesized arrow function, then
+            // we have to have a complete parameter list.  Otherwise we might see something like
+            // a => (b => c)
+            // And think that "(b =>" was actually a parenthesized arrow function with a missing
+            // close paren.
+            fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ !allowAmbiguity, node);
+
+            // If we couldn't get parameters, we definitely could not parse out an arrow function.
+            if (!node.parameters) {
+                return undefined;
+            }
+
+            // Parsing a signature isn't enough.
+            // Parenthesized arrow signatures often look like other valid expressions.
+            // For instance:
+            //  - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
+            //  - "(x,y)" is a comma expression parsed as a signature with two parameters.
+            //  - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
+            //
+            // So we need just a bit of lookahead to ensure that it can only be a signature.
+            if (!allowAmbiguity && token !== SyntaxKind.EqualsGreaterThanToken && token !== SyntaxKind.OpenBraceToken) {
+                // Returning undefined here will cause our caller to rewind to where we started from.
+                return undefined;
+            }
+
+            return node;
+        }
+
+        function parseArrowFunctionExpressionBody(): Block | Expression {
+            if (token === SyntaxKind.OpenBraceToken) {
+                return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
+            }
+
+            if (isStartOfStatement(/*inErrorRecovery:*/ true) &&
+                !isStartOfExpressionStatement() &&
+                token !== SyntaxKind.FunctionKeyword &&
+                token !== SyntaxKind.ClassKeyword) {
+
+                // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations)
+                //
+                // Here we try to recover from a potential error situation in the case where the
+                // user meant to supply a block. For example, if the user wrote:
+                //
+                //  a =>
+                //      let v = 0;
+                //  }
+                //
+                // they may be missing an open brace.  Check to see if that's the case so we can
+                // try to recover better.  If we don't do this, then the next close curly we see may end
+                // up preemptively closing the containing construct.
+                //
+                // Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error.
+                return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ true);
+            }
+
+            return parseAssignmentExpressionOrHigher();
+        }
+
+        function parseConditionalExpressionRest(leftOperand: Expression): Expression {
+            // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher.
+            let questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
+            if (!questionToken) {
+                return leftOperand;
+            }
+
+            // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
+            // we do not that for the 'whenFalse' part.
+            let node = <ConditionalExpression>createNode(SyntaxKind.ConditionalExpression, leftOperand.pos);
+            node.condition = leftOperand;
+            node.questionToken = questionToken;
+            node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher);
+            node.colonToken = parseExpectedToken(SyntaxKind.ColonToken, /*reportAtCurrentPosition:*/ false,
+                Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
+            node.whenFalse = parseAssignmentExpressionOrHigher();
+            return finishNode(node);
+        }
+
+        function parseBinaryExpressionOrHigher(precedence: number): Expression {
+            let leftOperand = parseUnaryExpressionOrHigher();
+            return parseBinaryExpressionRest(precedence, leftOperand);
+        }
+
+        function isInOrOfKeyword(t: SyntaxKind) {
+            return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword;
+        }
+
+        function parseBinaryExpressionRest(precedence: number, leftOperand: Expression): Expression {
+            while (true) {
+                // We either have a binary operator here, or we're finished.  We call
+                // reScanGreaterToken so that we merge token sequences like > and = into >=
+
+                reScanGreaterToken();
+                let newPrecedence = getBinaryOperatorPrecedence();
+
+                // Check the precedence to see if we should "take" this operator
+                if (newPrecedence <= precedence) {
+                    break;
+                }
+
+                if (token === SyntaxKind.InKeyword && inDisallowInContext()) {
+                    break;
+                }
+
+                leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
+            }
+
+            return leftOperand;
+        }
+
+        function isBinaryOperator() {
+            if (inDisallowInContext() && token === SyntaxKind.InKeyword) {
+                return false;
+            }
+
+            return getBinaryOperatorPrecedence() > 0;
+        }
+
+        function getBinaryOperatorPrecedence(): number {
+            switch (token) {
+                case SyntaxKind.BarBarToken:
+                    return 1;
+                case SyntaxKind.AmpersandAmpersandToken:
+                    return 2;
+                case SyntaxKind.BarToken:
+                    return 3;
+                case SyntaxKind.CaretToken:
+                    return 4;
+                case SyntaxKind.AmpersandToken:
+                    return 5;
+                case SyntaxKind.EqualsEqualsToken:
+                case SyntaxKind.ExclamationEqualsToken:
+                case SyntaxKind.EqualsEqualsEqualsToken:
+                case SyntaxKind.ExclamationEqualsEqualsToken:
+                    return 6;
+                case SyntaxKind.LessThanToken:
+                case SyntaxKind.GreaterThanToken:
+                case SyntaxKind.LessThanEqualsToken:
+                case SyntaxKind.GreaterThanEqualsToken:
+                case SyntaxKind.InstanceOfKeyword:
+                case SyntaxKind.InKeyword:
+                    return 7;
+                case SyntaxKind.LessThanLessThanToken:
+                case SyntaxKind.GreaterThanGreaterThanToken:
+                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
+                    return 8;
+                case SyntaxKind.PlusToken:
+                case SyntaxKind.MinusToken:
+                    return 9;
+                case SyntaxKind.AsteriskToken:
+                case SyntaxKind.SlashToken:
+                case SyntaxKind.PercentToken:
+                    return 10;
+            }
+
+            // -1 is lower than all other precedences.  Returning it will cause binary expression
+            // parsing to stop.
+            return -1;
+        }
+
+        function makeBinaryExpression(left: Expression, operatorToken: Node, right: Expression): BinaryExpression {
+            let node = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, left.pos);
+            node.left = left;
+            node.operatorToken = operatorToken;
+            node.right = right;
+            return finishNode(node);
+        }
+
+        function parsePrefixUnaryExpression() {
+            let node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
+            node.operator = token;
+            nextToken();
+            node.operand = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+
+        function parseDeleteExpression() {
+            let node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
+            nextToken();
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+
+        function parseTypeOfExpression() {
+            let node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
+            nextToken();
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+
+        function parseVoidExpression() {
+            let node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
+            nextToken();
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+
+        function parseUnaryExpressionOrHigher(): UnaryExpression {
+            switch (token) {
+                case SyntaxKind.PlusToken:
+                case SyntaxKind.MinusToken:
+                case SyntaxKind.TildeToken:
+                case SyntaxKind.ExclamationToken:
+                case SyntaxKind.PlusPlusToken:
+                case SyntaxKind.MinusMinusToken:
+                    return parsePrefixUnaryExpression();
+                case SyntaxKind.DeleteKeyword:
+                    return parseDeleteExpression();
+                case SyntaxKind.TypeOfKeyword:
+                    return parseTypeOfExpression();
+                case SyntaxKind.VoidKeyword:
+                    return parseVoidExpression();
+                case SyntaxKind.LessThanToken:
+                    return parseTypeAssertion();
+                default:
+                    return parsePostfixExpressionOrHigher();
+            }
+        }
+
+        function parsePostfixExpressionOrHigher(): PostfixExpression {
+            let expression = parseLeftHandSideExpressionOrHigher();
+
+            Debug.assert(isLeftHandSideExpression(expression));
+            if ((token === SyntaxKind.PlusPlusToken || token === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) {
+                let node = <PostfixUnaryExpression>createNode(SyntaxKind.PostfixUnaryExpression, expression.pos);
+                node.operand = expression;
+                node.operator = token;
+                nextToken();
+                return finishNode(node);
+            }
+
+            return expression;
+        }
+
+        function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression {
+            // Original Ecma:
+            // LeftHandSideExpression: See 11.2
+            //      NewExpression
+            //      CallExpression
+            //
+            // Our simplification:
+            //
+            // LeftHandSideExpression: See 11.2
+            //      MemberExpression
+            //      CallExpression
+            //
+            // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with
+            // MemberExpression to make our lives easier.
+            //
+            // to best understand the below code, it's important to see how CallExpression expands
+            // out into its own productions:
+            //
+            // CallExpression:
+            //      MemberExpression Arguments
+            //      CallExpression Arguments
+            //      CallExpression[Expression]
+            //      CallExpression.IdentifierName
+            //      super   (   ArgumentListopt   )
+            //      super.IdentifierName
+            //
+            // Because of the recursion in these calls, we need to bottom out first.  There are two
+            // bottom out states we can run into.  Either we see 'super' which must start either of
+            // the last two CallExpression productions.  Or we have a MemberExpression which either
+            // completes the LeftHandSideExpression, or starts the beginning of the first four
+            // CallExpression productions.
+            let expression = token === SyntaxKind.SuperKeyword
+                ? parseSuperExpression()
+                : parseMemberExpressionOrHigher();
+
+            // Now, we *may* be complete.  However, we might have consumed the start of a
+            // CallExpression.  As such, we need to consume the rest of it here to be complete.
+            return parseCallExpressionRest(expression);
+        }
+
+        function parseMemberExpressionOrHigher(): MemberExpression {
+            // Note: to make our lives simpler, we decompose the the NewExpression productions and
+            // place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
+            // like so:
+            //
+            //   PrimaryExpression : See 11.1
+            //      this
+            //      Identifier
+            //      Literal
+            //      ArrayLiteral
+            //      ObjectLiteral
+            //      (Expression)
+            //      FunctionExpression
+            //      new MemberExpression Arguments?
+            //
+            //   MemberExpression : See 11.2
+            //      PrimaryExpression
+            //      MemberExpression[Expression]
+            //      MemberExpression.IdentifierName
+            //
+            //   CallExpression : See 11.2
+            //      MemberExpression
+            //      CallExpression Arguments
+            //      CallExpression[Expression]
+            //      CallExpression.IdentifierName
+            //
+            // Technically this is ambiguous.  i.e. CallExpression defines:
+            //
+            //   CallExpression:
+            //      CallExpression Arguments
+            //
+            // If you see: "new Foo()"
+            //
+            // Then that could be treated as a single ObjectCreationExpression, or it could be
+            // treated as the invocation of "new Foo".  We disambiguate that in code (to match
+            // the original grammar) by making sure that if we see an ObjectCreationExpression
+            // we always consume arguments if they are there. So we treat "new Foo()" as an
+            // object creation only, and not at all as an invocation)  Another way to think
+            // about this is that for every "new" that we see, we will consume an argument list if
+            // it is there as part of the *associated* object creation node.  Any additional
+            // argument lists we see, will become invocation expressions.
+            //
+            // Because there are no other places in the grammar now that refer to FunctionExpression
+            // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression
+            // production.
+            //
+            // Because CallExpression and MemberExpression are left recursive, we need to bottom out
+            // of the recursion immediately.  So we parse out a primary expression to start with.
+            let expression = parsePrimaryExpression();
+            return parseMemberExpressionRest(expression);
+        }
+
+        function parseSuperExpression(): MemberExpression {
+            let expression = parseTokenNode<PrimaryExpression>();
+            if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken) {
+                return expression;
+            }
+
+            // If we have seen "super" it must be followed by '(' or '.'.
+            // If it wasn't then just try to parse out a '.' and report an error.
+            let node = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
+            node.expression = expression;
+            node.dotToken = parseExpectedToken(SyntaxKind.DotToken, /*reportAtCurrentPosition:*/ false, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
+            node.name = parseRightSideOfDot(/*allowIdentifierNames:*/ true);
+            return finishNode(node);
+        }
+
+        function parseTypeAssertion(): TypeAssertion {
+            let node = <TypeAssertion>createNode(SyntaxKind.TypeAssertionExpression);
+            parseExpected(SyntaxKind.LessThanToken);
+            node.type = parseType();
+            parseExpected(SyntaxKind.GreaterThanToken);
+            node.expression = parseUnaryExpressionOrHigher();
+            return finishNode(node);
+        }
+
+        function parseMemberExpressionRest(expression: LeftHandSideExpression): MemberExpression {
+            while (true) {
+                let dotToken = parseOptionalToken(SyntaxKind.DotToken);
+                if (dotToken) {
+                    let propertyAccess = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
+                    propertyAccess.expression = expression;
+                    propertyAccess.dotToken = dotToken;
+                    propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames:*/ true);
+                    expression = finishNode(propertyAccess);
+                    continue;
+                }
+
+                // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName                
+                if (!inDecoratorContext() && parseOptional(SyntaxKind.OpenBracketToken)) {
+                    let indexedAccess = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, expression.pos);
+                    indexedAccess.expression = expression;
+
+                    // It's not uncommon for a user to write: "new Type[]".
+                    // Check for that common pattern and report a better error message.
+                    if (token !== SyntaxKind.CloseBracketToken) {
+                        indexedAccess.argumentExpression = allowInAnd(parseExpression);
+                        if (indexedAccess.argumentExpression.kind === SyntaxKind.StringLiteral || indexedAccess.argumentExpression.kind === SyntaxKind.NumericLiteral) {
+                            let literal = <LiteralExpression>indexedAccess.argumentExpression;
+                            literal.text = internIdentifier(literal.text);
+                        }
+                    }
+
+                    parseExpected(SyntaxKind.CloseBracketToken);
+                    expression = finishNode(indexedAccess);
+                    continue;
+                }
+
+                if (token === SyntaxKind.NoSubstitutionTemplateLiteral || token === SyntaxKind.TemplateHead) {
+                    let tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, expression.pos);
+                    tagExpression.tag = expression;
+                    tagExpression.template = token === SyntaxKind.NoSubstitutionTemplateLiteral
+                        ? parseLiteralNode()
+                        : parseTemplateExpression();
+                    expression = finishNode(tagExpression);
+                    continue;
+                }
+
+                return <MemberExpression>expression;
+            }
+        }
+
+        function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
+            while (true) {
+                expression = parseMemberExpressionRest(expression);
+                if (token === SyntaxKind.LessThanToken) {
+                    // See if this is the start of a generic invocation.  If so, consume it and
+                    // keep checking for postfix expressions.  Otherwise, it's just a '<' that's
+                    // part of an arithmetic expression.  Break out so we consume it higher in the
+                    // stack.
+                    let typeArguments = tryParse(parseTypeArgumentsInExpression);
+                    if (!typeArguments) {
+                        return expression;
+                    }
+
+                    let callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
+                    callExpr.expression = expression;
+                    callExpr.typeArguments = typeArguments;
+                    callExpr.arguments = parseArgumentList();
+                    expression = finishNode(callExpr);
+                    continue;
+                }
+                else if (token === SyntaxKind.OpenParenToken) {
+                    let callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
+                    callExpr.expression = expression;
+                    callExpr.arguments = parseArgumentList();
+                    expression = finishNode(callExpr);
+                    continue;
+                }
+
+                return expression;
+            }
+        }
+
+        function parseArgumentList() {
+            parseExpected(SyntaxKind.OpenParenToken);
+            let result = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
+            parseExpected(SyntaxKind.CloseParenToken);
+            return result;
+        }
+
+        function parseTypeArgumentsInExpression() {
+            if (!parseOptional(SyntaxKind.LessThanToken)) {
+                return undefined;
+            }
+
+            let typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
+            if (!parseExpected(SyntaxKind.GreaterThanToken)) {
+                // If it doesn't have the closing >  then it's definitely not an type argument list.
+                return undefined;
+            }
+
+            // If we have a '<', then only parse this as a arugment list if the type arguments
+            // are complete and we have an open paren.  if we don't, rewind and return nothing.
+            return typeArguments && canFollowTypeArgumentsInExpression()
+                ? typeArguments
+                : undefined;
+        }
+
+        function canFollowTypeArgumentsInExpression(): boolean {
+            switch (token) {
+                case SyntaxKind.OpenParenToken:                 // foo<x>(
+                // this case are the only case where this token can legally follow a type argument
+                // list.  So we definitely want to treat this as a type arg list.
+
+                case SyntaxKind.DotToken:                       // foo<x>.
+                case SyntaxKind.CloseParenToken:                // foo<x>)
+                case SyntaxKind.CloseBracketToken:              // foo<x>]
+                case SyntaxKind.ColonToken:                     // foo<x>:
+                case SyntaxKind.SemicolonToken:                 // foo<x>;
+                case SyntaxKind.QuestionToken:                  // foo<x>?
+                case SyntaxKind.EqualsEqualsToken:              // foo<x> ==
+                case SyntaxKind.EqualsEqualsEqualsToken:        // foo<x> ===
+                case SyntaxKind.ExclamationEqualsToken:         // foo<x> !=
+                case SyntaxKind.ExclamationEqualsEqualsToken:   // foo<x> !==
+                case SyntaxKind.AmpersandAmpersandToken:        // foo<x> &&
+                case SyntaxKind.BarBarToken:                    // foo<x> ||
+                case SyntaxKind.CaretToken:                     // foo<x> ^
+                case SyntaxKind.AmpersandToken:                 // foo<x> &
+                case SyntaxKind.BarToken:                       // foo<x> |
+                case SyntaxKind.CloseBraceToken:                // foo<x> }
+                case SyntaxKind.EndOfFileToken:                 // foo<x>
+                    // these cases can't legally follow a type arg list.  However, they're not legal
+                    // expressions either.  The user is probably in the middle of a generic type. So
+                    // treat it as such.
+                    return true;
+
+                case SyntaxKind.CommaToken:                     // foo<x>,
+                case SyntaxKind.OpenBraceToken:                 // foo<x> {
+                // We don't want to treat these as type arguments.  Otherwise we'll parse this
+                // as an invocation expression.  Instead, we want to parse out the expression 
+                // in isolation from the type arguments.
+
+                default:
+                    // Anything else treat as an expression.
+                    return false;
+            }
+        }
+
+        function parsePrimaryExpression(): PrimaryExpression {
+            switch (token) {
+                case SyntaxKind.NumericLiteral:
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.NoSubstitutionTemplateLiteral:
+                    return parseLiteralNode();
+                case SyntaxKind.ThisKeyword:
+                case SyntaxKind.SuperKeyword:
+                case SyntaxKind.NullKeyword:
+                case SyntaxKind.TrueKeyword:
+                case SyntaxKind.FalseKeyword:
+                    return parseTokenNode<PrimaryExpression>();
+                case SyntaxKind.OpenParenToken:
+                    return parseParenthesizedExpression();
+                case SyntaxKind.OpenBracketToken:
+                    return parseArrayLiteralExpression();
+                case SyntaxKind.OpenBraceToken:
+                    return parseObjectLiteralExpression();
+                case SyntaxKind.ClassKeyword:
+                    return parseClassExpression();
+                case SyntaxKind.FunctionKeyword:
+                    return parseFunctionExpression();
+                case SyntaxKind.NewKeyword:
+                    return parseNewExpression();
+                case SyntaxKind.SlashToken:
+                case SyntaxKind.SlashEqualsToken:
+                    if (reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
+                        return parseLiteralNode();
+                    }
+                    break;
+                case SyntaxKind.TemplateHead:
+                    return parseTemplateExpression();
+            }
+
+            return parseIdentifier(Diagnostics.Expression_expected);
+        }
+
+        function parseParenthesizedExpression(): ParenthesizedExpression {
+            let node = <ParenthesizedExpression>createNode(SyntaxKind.ParenthesizedExpression);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(SyntaxKind.CloseParenToken);
+            return finishNode(node);
+        }
+
+        function parseSpreadElement(): Expression {
+            let node = <SpreadElementExpression>createNode(SyntaxKind.SpreadElementExpression);
+            parseExpected(SyntaxKind.DotDotDotToken);
+            node.expression = parseAssignmentExpressionOrHigher();
+            return finishNode(node);
+        }
+
+        function parseArgumentOrArrayLiteralElement(): Expression {
+            return token === SyntaxKind.DotDotDotToken ? parseSpreadElement() :
+                token === SyntaxKind.CommaToken ? <Expression>createNode(SyntaxKind.OmittedExpression) :
+                    parseAssignmentExpressionOrHigher();
+        }
+
+        function parseArgumentExpression(): Expression {
+            return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
+        }
+
+        function parseArrayLiteralExpression(): ArrayLiteralExpression {
+            let node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
+            parseExpected(SyntaxKind.OpenBracketToken);
+            if (scanner.hasPrecedingLineBreak()) node.flags |= NodeFlags.MultiLine;
+            node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement);
+            parseExpected(SyntaxKind.CloseBracketToken);
+            return finishNode(node);
+        }
+
+        function tryParseAccessorDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): AccessorDeclaration {
+            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
+                return parseAccessorDeclaration(SyntaxKind.GetAccessor, fullStart, decorators, modifiers);
+            }
+            else if (parseContextualModifier(SyntaxKind.SetKeyword)) {
+                return parseAccessorDeclaration(SyntaxKind.SetAccessor, fullStart, decorators, modifiers);
+            }
+
+            return undefined;
+        }
+
+        function parseObjectLiteralElement(): ObjectLiteralElement {
+            let fullStart = scanner.getStartPos();
+            let decorators = parseDecorators();
+            let modifiers = parseModifiers();
+
+            let accessor = tryParseAccessorDeclaration(fullStart, decorators, modifiers);
+            if (accessor) {
+                return accessor;
+            }
+
+            let asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
+            let tokenIsIdentifier = isIdentifier();
+            let nameToken = token;
+            let propertyName = parsePropertyName();
+
+            // Disallowing of optional property assignments happens in the grammar checker.
+            let questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
+            if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
+                return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, propertyName, questionToken);
+            }
+
+            // Parse to check if it is short-hand property assignment or normal property assignment
+            if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) {
+                let shorthandDeclaration = <ShorthandPropertyAssignment>createNode(SyntaxKind.ShorthandPropertyAssignment, fullStart);
+                shorthandDeclaration.name = <Identifier>propertyName;
+                shorthandDeclaration.questionToken = questionToken;
+                return finishNode(shorthandDeclaration);
+            }
+            else {
+                let propertyAssignment = <PropertyAssignment>createNode(SyntaxKind.PropertyAssignment, fullStart);
+                propertyAssignment.name = propertyName;
+                propertyAssignment.questionToken = questionToken;
+                parseExpected(SyntaxKind.ColonToken);
+                propertyAssignment.initializer = allowInAnd(parseAssignmentExpressionOrHigher);
+                return finishNode(propertyAssignment);
+            }
+        }
+
+        function parseObjectLiteralExpression(): ObjectLiteralExpression {
+            let node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression);
+            parseExpected(SyntaxKind.OpenBraceToken);
+            if (scanner.hasPrecedingLineBreak()) {
+                node.flags |= NodeFlags.MultiLine;
+            }
+
+            node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimeter:*/ true);
+            parseExpected(SyntaxKind.CloseBraceToken);
+            return finishNode(node);
+        }
+
+        function parseFunctionExpression(): FunctionExpression {
+            // GeneratorExpression :
+            //      function * BindingIdentifier[Yield]opt (FormalParameters[Yield, GeneratorParameter]) { GeneratorBody[Yield] }
+            // FunctionExpression:
+            //      function BindingIdentifieropt(FormalParameters) { FunctionBody }
+            let saveDecoratorContext = inDecoratorContext();
+            if (saveDecoratorContext) {
+                setDecoratorContext(false);
+            }
+            let node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression);
+            parseExpected(SyntaxKind.FunctionKeyword);
+            node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
+            node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
+            fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
+            node.body = parseFunctionBlock(/*allowYield:*/ !!node.asteriskToken, /* ignoreMissingOpenBrace */ false);
+            if (saveDecoratorContext) {
+                setDecoratorContext(true);
+            }
+            return finishNode(node);
+        }
+
+        function parseOptionalIdentifier() {
+            return isIdentifier() ? parseIdentifier() : undefined;
+        }
+
+        function parseNewExpression(): NewExpression {
+            let node = <NewExpression>createNode(SyntaxKind.NewExpression);
+            parseExpected(SyntaxKind.NewKeyword);
+            node.expression = parseMemberExpressionOrHigher();
+            node.typeArguments = tryParse(parseTypeArgumentsInExpression);
+            if (node.typeArguments || token === SyntaxKind.OpenParenToken) {
+                node.arguments = parseArgumentList();
+            }
+
+            return finishNode(node);
+        }
+
+        // STATEMENTS
+        function parseBlock(ignoreMissingOpenBrace: boolean, checkForStrictMode: boolean, diagnosticMessage?: DiagnosticMessage): Block {
+            let node = <Block>createNode(SyntaxKind.Block);
+            if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) {
+                node.statements = parseList(ParsingContext.BlockStatements, checkForStrictMode, parseStatement);
+                parseExpected(SyntaxKind.CloseBraceToken);
+            }
+            else {
+                node.statements = createMissingList<Statement>();
+            }
+            return finishNode(node);
+        }
+
+        function parseFunctionBlock(allowYield: boolean, ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
+            let savedYieldContext = inYieldContext();
+            setYieldContext(allowYield);
+
+            // We may be in a [Decorator] context when parsing a function expression or 
+            // arrow function. The body of the function is not in [Decorator] context.
+            let saveDecoratorContext = inDecoratorContext();
+            if (saveDecoratorContext) {
+                setDecoratorContext(false);
+            }
+
+            let block = parseBlock(ignoreMissingOpenBrace, /*checkForStrictMode*/ true, diagnosticMessage);
+
+            if (saveDecoratorContext) {
+                setDecoratorContext(true);
+            }
+
+            setYieldContext(savedYieldContext);
+
+            return block;
+        }
+
+        function parseEmptyStatement(): Statement {
+            let node = <Statement>createNode(SyntaxKind.EmptyStatement);
+            parseExpected(SyntaxKind.SemicolonToken);
+            return finishNode(node);
+        }
+
+        function parseIfStatement(): IfStatement {
+            let node = <IfStatement>createNode(SyntaxKind.IfStatement);
+            parseExpected(SyntaxKind.IfKeyword);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(SyntaxKind.CloseParenToken);
+            node.thenStatement = parseStatement();
+            node.elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined;
+            return finishNode(node);
+        }
+
+        function parseDoStatement(): DoStatement {
+            let node = <DoStatement>createNode(SyntaxKind.DoStatement);
+            parseExpected(SyntaxKind.DoKeyword);
+            node.statement = parseStatement();
+            parseExpected(SyntaxKind.WhileKeyword);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(SyntaxKind.CloseParenToken);
+
+            // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html
+            // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in
+            // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby
+            //  do;while(0)x will have a semicolon inserted before x.
+            parseOptional(SyntaxKind.SemicolonToken);
+            return finishNode(node);
+        }
+
+        function parseWhileStatement(): WhileStatement {
+            let node = <WhileStatement>createNode(SyntaxKind.WhileStatement);
+            parseExpected(SyntaxKind.WhileKeyword);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(SyntaxKind.CloseParenToken);
+            node.statement = parseStatement();
+            return finishNode(node);
+        }
+
+        function parseForOrForInOrForOfStatement(): Statement {
+            let pos = getNodePos();
+            parseExpected(SyntaxKind.ForKeyword);
+            parseExpected(SyntaxKind.OpenParenToken);
+
+            let initializer: VariableDeclarationList | Expression = undefined;
+            if (token !== SyntaxKind.SemicolonToken) {
+                if (token === SyntaxKind.VarKeyword || token === SyntaxKind.LetKeyword || token === SyntaxKind.ConstKeyword) {
+                    initializer = parseVariableDeclarationList(/*inForStatementInitializer:*/ true);
+                }
+                else {
+                    initializer = disallowInAnd(parseExpression);
+                }
+            }
+            let forOrForInOrForOfStatement: IterationStatement;
+            if (parseOptional(SyntaxKind.InKeyword)) {
+                let forInStatement = <ForInStatement>createNode(SyntaxKind.ForInStatement, pos);
+                forInStatement.initializer = initializer;
+                forInStatement.expression = allowInAnd(parseExpression);
+                parseExpected(SyntaxKind.CloseParenToken);
+                forOrForInOrForOfStatement = forInStatement;
+            }
+            else if (parseOptional(SyntaxKind.OfKeyword)) {
+                let forOfStatement = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, pos);
+                forOfStatement.initializer = initializer;
+                forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
+                parseExpected(SyntaxKind.CloseParenToken);
+                forOrForInOrForOfStatement = forOfStatement;
+            } else {
+                let forStatement = <ForStatement>createNode(SyntaxKind.ForStatement, pos);
+                forStatement.initializer = initializer;
+                parseExpected(SyntaxKind.SemicolonToken);
+                if (token !== SyntaxKind.SemicolonToken && token !== SyntaxKind.CloseParenToken) {
+                    forStatement.condition = allowInAnd(parseExpression);
+                }
+                parseExpected(SyntaxKind.SemicolonToken);
+                if (token !== SyntaxKind.CloseParenToken) {
+                    forStatement.incrementor = allowInAnd(parseExpression);
+                }
+                parseExpected(SyntaxKind.CloseParenToken);
+                forOrForInOrForOfStatement = forStatement;
+            }
+
+            forOrForInOrForOfStatement.statement = parseStatement();
+
+            return finishNode(forOrForInOrForOfStatement);
+        }
+
+        function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement {
+            let node = <BreakOrContinueStatement>createNode(kind);
+
+            parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword);
+            if (!canParseSemicolon()) {
+                node.label = parseIdentifier();
+            }
+
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        function parseReturnStatement(): ReturnStatement {
+            let node = <ReturnStatement>createNode(SyntaxKind.ReturnStatement);
+
+            parseExpected(SyntaxKind.ReturnKeyword);
+            if (!canParseSemicolon()) {
+                node.expression = allowInAnd(parseExpression);
+            }
+
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        function parseWithStatement(): WithStatement {
+            let node = <WithStatement>createNode(SyntaxKind.WithStatement);
+            parseExpected(SyntaxKind.WithKeyword);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(SyntaxKind.CloseParenToken);
+            node.statement = parseStatement();
+            return finishNode(node);
+        }
+
+        function parseCaseClause(): CaseClause {
+            let node = <CaseClause>createNode(SyntaxKind.CaseClause);
+            parseExpected(SyntaxKind.CaseKeyword);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(SyntaxKind.ColonToken);
+            node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatement);
+            return finishNode(node);
+        }
+
+        function parseDefaultClause(): DefaultClause {
+            let node = <DefaultClause>createNode(SyntaxKind.DefaultClause);
+            parseExpected(SyntaxKind.DefaultKeyword);
+            parseExpected(SyntaxKind.ColonToken);
+            node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatement);
+            return finishNode(node);
+        }
+
+        function parseCaseOrDefaultClause(): CaseOrDefaultClause {
+            return token === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause();
+        }
+
+        function parseSwitchStatement(): SwitchStatement {
+            let node = <SwitchStatement>createNode(SyntaxKind.SwitchStatement);
+            parseExpected(SyntaxKind.SwitchKeyword);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.expression = allowInAnd(parseExpression);
+            parseExpected(SyntaxKind.CloseParenToken);
+            let caseBlock = <CaseBlock>createNode(SyntaxKind.CaseBlock, scanner.getStartPos());
+            parseExpected(SyntaxKind.OpenBraceToken);
+            caseBlock.clauses = parseList(ParsingContext.SwitchClauses, /*checkForStrictMode*/ false, parseCaseOrDefaultClause);
+            parseExpected(SyntaxKind.CloseBraceToken);
+            node.caseBlock = finishNode(caseBlock);
+            return finishNode(node);
+        }
+
+        function parseThrowStatement(): ThrowStatement {
+            // ThrowStatement[Yield] :
+            //      throw [no LineTerminator here]Expression[In, ?Yield];
+
+            // Because of automatic semicolon insertion, we need to report error if this
+            // throw could be terminated with a semicolon.  Note: we can't call 'parseExpression'
+            // directly as that might consume an expression on the following line.
+            // We just return 'undefined' in that case.  The actual error will be reported in the
+            // grammar walker.
+            let node = <ThrowStatement>createNode(SyntaxKind.ThrowStatement);
+            parseExpected(SyntaxKind.ThrowKeyword);
+            node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression);
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        // TODO: Review for error recovery
+        function parseTryStatement(): TryStatement {
+            let node = <TryStatement>createNode(SyntaxKind.TryStatement);
+
+            parseExpected(SyntaxKind.TryKeyword);
+            node.tryBlock = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode*/ false);
+            node.catchClause = token === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined;
+
+            // If we don't have a catch clause, then we must have a finally clause.  Try to parse
+            // one out no matter what.
+            if (!node.catchClause || token === SyntaxKind.FinallyKeyword) {
+                parseExpected(SyntaxKind.FinallyKeyword);
+                node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode*/ false);
+            }
+
+            return finishNode(node);
+        }
+
+        function parseCatchClause(): CatchClause {
+            let result = <CatchClause>createNode(SyntaxKind.CatchClause);
+            parseExpected(SyntaxKind.CatchKeyword);
+            if (parseExpected(SyntaxKind.OpenParenToken)) {
+                result.variableDeclaration = parseVariableDeclaration();
+            }
+
+            parseExpected(SyntaxKind.CloseParenToken);
+            result.block = parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode:*/ false);
+            return finishNode(result);
+        }
+
+        function parseDebuggerStatement(): Statement {
+            let node = <Statement>createNode(SyntaxKind.DebuggerStatement);
+            parseExpected(SyntaxKind.DebuggerKeyword);
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement {
+            // Avoiding having to do the lookahead for a labeled statement by just trying to parse
+            // out an expression, seeing if it is identifier and then seeing if it is followed by
+            // a colon.
+            let fullStart = scanner.getStartPos();
+            let expression = allowInAnd(parseExpression);
+
+            if (expression.kind === SyntaxKind.Identifier && parseOptional(SyntaxKind.ColonToken)) {
+                let labeledStatement = <LabeledStatement>createNode(SyntaxKind.LabeledStatement, fullStart);
+                labeledStatement.label = <Identifier>expression;
+                labeledStatement.statement = parseStatement();
+                return finishNode(labeledStatement);
+            }
+            else {
+                let expressionStatement = <ExpressionStatement>createNode(SyntaxKind.ExpressionStatement, fullStart);
+                expressionStatement.expression = expression;
+                parseSemicolon();
+                return finishNode(expressionStatement);
+            }
+        }
+
+        function isStartOfStatement(inErrorRecovery: boolean): boolean {
+            // Functions, variable statements and classes are allowed as a statement.  But as per
+            // the grammar, they also allow modifiers.  So we have to check for those statements 
+            // that might be following modifiers.This ensures that things work properly when
+            // incrementally parsing as the parser will produce the same FunctionDeclaraiton, 
+            // VariableStatement or ClassDeclaration, if it has the same text regardless of whether 
+            // it is inside a block or not.
+            if (isModifier(token)) {
+                let result = lookAhead(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers);
+                if (result) {
+                    return true;
+                }
+            }
+
+            switch (token) {
+                case SyntaxKind.SemicolonToken:
+                    // If we're in error recovery, then we don't want to treat ';' as an empty statement.
+                    // The problem is that ';' can show up in far too many contexts, and if we see one
+                    // and assume it's a statement, then we may bail out inappropriately from whatever
+                    // we're parsing.  For example, if we have a semicolon in the middle of a class, then
+                    // we really don't want to assume the class is over and we're on a statement in the
+                    // outer module.  We just want to consume and move on.
+                    return !inErrorRecovery;
+                case SyntaxKind.OpenBraceToken:
+                case SyntaxKind.VarKeyword:
+                case SyntaxKind.LetKeyword:
+                case SyntaxKind.FunctionKeyword:
+                case SyntaxKind.ClassKeyword:
+                case SyntaxKind.IfKeyword:
+                case SyntaxKind.DoKeyword:
+                case SyntaxKind.WhileKeyword:
+                case SyntaxKind.ForKeyword:
+                case SyntaxKind.ContinueKeyword:
+                case SyntaxKind.BreakKeyword:
+                case SyntaxKind.ReturnKeyword:
+                case SyntaxKind.WithKeyword:
+                case SyntaxKind.SwitchKeyword:
+                case SyntaxKind.ThrowKeyword:
+                case SyntaxKind.TryKeyword:
+                case SyntaxKind.DebuggerKeyword:
+                // 'catch' and 'finally' do not actually indicate that the code is part of a statement,
+                // however, we say they are here so that we may gracefully parse them and error later.
+                case SyntaxKind.CatchKeyword:
+                case SyntaxKind.FinallyKeyword:
+                    return true;
+                case SyntaxKind.ConstKeyword:
+                    // const keyword can precede enum keyword when defining constant enums
+                    // 'const enum' do not start statement.
+                    // In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier
+                    let isConstEnum = lookAhead(nextTokenIsEnumKeyword);
+                    return !isConstEnum;
+                case SyntaxKind.InterfaceKeyword:
+                case SyntaxKind.ModuleKeyword:
+                case SyntaxKind.EnumKeyword:
+                case SyntaxKind.TypeKeyword:
+                    // When followed by an identifier, these do not start a statement but might
+                    // instead be following declarations
+                    if (isDeclarationStart()) {
+                        return false;
+                    }
+
+                case SyntaxKind.PublicKeyword:
+                case SyntaxKind.PrivateKeyword:
+                case SyntaxKind.ProtectedKeyword:
+                case SyntaxKind.StaticKeyword:
+                    // When followed by an identifier or keyword, these do not start a statement but
+                    // might instead be following type members
+                    if (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine)) {
+                        return false;
+                    }
+                default:
+                    return isStartOfExpression();
+            }
+        }
+
+        function nextTokenIsEnumKeyword() {
+            nextToken();
+            return token === SyntaxKind.EnumKeyword
+        }
+
+        function nextTokenIsIdentifierOrKeywordOnSameLine() {
+            nextToken();
+            return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();
+        }
+
+        function parseStatement(): Statement {
+            switch (token) {
+                case SyntaxKind.OpenBraceToken:
+                    return parseBlock(/*ignoreMissingOpenBrace:*/ false, /*checkForStrictMode:*/ false);
+                case SyntaxKind.VarKeyword:
+                case SyntaxKind.ConstKeyword:
+                    // const here should always be parsed as const declaration because of check in 'isStatement'
+                    return parseVariableStatement(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined);
+                case SyntaxKind.FunctionKeyword:
+                    return parseFunctionDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined);
+                case SyntaxKind.ClassKeyword:
+                    return parseClassDeclaration(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined);
+                case SyntaxKind.SemicolonToken:
+                    return parseEmptyStatement();
+                case SyntaxKind.IfKeyword:
+                    return parseIfStatement();
+                case SyntaxKind.DoKeyword:
+                    return parseDoStatement();
+                case SyntaxKind.WhileKeyword:
+                    return parseWhileStatement();
+                case SyntaxKind.ForKeyword:
+                    return parseForOrForInOrForOfStatement();
+                case SyntaxKind.ContinueKeyword:
+                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);
+                case SyntaxKind.BreakKeyword:
+                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);
+                case SyntaxKind.ReturnKeyword:
+                    return parseReturnStatement();
+                case SyntaxKind.WithKeyword:
+                    return parseWithStatement();
+                case SyntaxKind.SwitchKeyword:
+                    return parseSwitchStatement();
+                case SyntaxKind.ThrowKeyword:
+                    return parseThrowStatement();
+                case SyntaxKind.TryKeyword:
+                // Include the next two for error recovery.
+                case SyntaxKind.CatchKeyword:
+                case SyntaxKind.FinallyKeyword:
+                    return parseTryStatement();
+                case SyntaxKind.DebuggerKeyword:
+                    return parseDebuggerStatement();
+                case SyntaxKind.LetKeyword:
+                    // If let follows identifier on the same line, it is declaration parse it as variable statement
+                    if (isLetDeclaration()) {
+                        return parseVariableStatement(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers:*/ undefined);
+                    }
+                // Else parse it like identifier - fall through
+                default:
+                    // Functions and variable statements are allowed as a statement.  But as per
+                    // the grammar, they also allow modifiers.  So we have to check for those
+                    // statements that might be following modifiers.  This ensures that things
+                    // work properly when incrementally parsing as the parser will produce the
+                    // same FunctionDeclaraiton or VariableStatement if it has the same text
+                    // regardless of whether it is inside a block or not.
+                    // Even though variable statements and function declarations cannot have decorators, 
+                    // we parse them here to provide better error recovery.
+                    if (isModifier(token) || token === SyntaxKind.AtToken) {
+                        let result = tryParse(parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers);
+                        if (result) {
+                            return result;
+                        }
+                    }
+
+                    return parseExpressionOrLabeledStatement();
+            }
+        }
+
+        function parseVariableStatementOrFunctionDeclarationOrClassDeclarationWithDecoratorsOrModifiers(): FunctionDeclaration | VariableStatement | ClassDeclaration {
+            let start = scanner.getStartPos();
+            let decorators = parseDecorators();
+            let modifiers = parseModifiers();
+            switch (token) {
+                case SyntaxKind.ConstKeyword:
+                    let nextTokenIsEnum = lookAhead(nextTokenIsEnumKeyword)
+                    if (nextTokenIsEnum) {
+                        return undefined;
+                    }
+                    return parseVariableStatement(start, decorators, modifiers);
+
+                case SyntaxKind.LetKeyword:
+                    if (!isLetDeclaration()) {
+                        return undefined;
+                    }
+                    return parseVariableStatement(start, decorators, modifiers);
+
+                case SyntaxKind.VarKeyword:
+                    return parseVariableStatement(start, decorators, modifiers);
+
+                case SyntaxKind.FunctionKeyword:
+                    return parseFunctionDeclaration(start, decorators, modifiers);
+
+                case SyntaxKind.ClassKeyword:
+                    return parseClassDeclaration(start, decorators, modifiers);
+            }
+
+            return undefined;
+        }
+
+        function parseFunctionBlockOrSemicolon(isGenerator: boolean, diagnosticMessage?: DiagnosticMessage): Block {
+            if (token !== SyntaxKind.OpenBraceToken && canParseSemicolon()) {
+                parseSemicolon();
+                return;
+            }
+
+            return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false, diagnosticMessage);
+        }
+
+        // DECLARATIONS
+
+        function parseArrayBindingElement(): BindingElement {
+            if (token === SyntaxKind.CommaToken) {
+                return <BindingElement>createNode(SyntaxKind.OmittedExpression);
+            }
+            let node = <BindingElement>createNode(SyntaxKind.BindingElement);
+            node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
+            node.name = parseIdentifierOrPattern();
+            node.initializer = parseInitializer(/*inParameter*/ false);
+            return finishNode(node);
+        }
+
+        function parseObjectBindingElement(): BindingElement {
+            let node = <BindingElement>createNode(SyntaxKind.BindingElement);
+            // TODO(andersh): Handle computed properties
+            let tokenIsIdentifier = isIdentifier();
+            let propertyName = parsePropertyName();
+            if (tokenIsIdentifier && token !== SyntaxKind.ColonToken) {
+                node.name = <Identifier>propertyName;
+            }
+            else {
+                parseExpected(SyntaxKind.ColonToken);
+                node.propertyName = <Identifier>propertyName;
+                node.name = parseIdentifierOrPattern();
+            }
+            node.initializer = parseInitializer(/*inParameter*/ false);
+            return finishNode(node);
+        }
+
+        function parseObjectBindingPattern(): BindingPattern {
+            let node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);
+            parseExpected(SyntaxKind.OpenBraceToken);
+            node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);
+            parseExpected(SyntaxKind.CloseBraceToken);
+            return finishNode(node);
+        }
+
+        function parseArrayBindingPattern(): BindingPattern {
+            let node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);
+            parseExpected(SyntaxKind.OpenBracketToken);
+            node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);
+            parseExpected(SyntaxKind.CloseBracketToken);
+            return finishNode(node);
+        }
+
+        function isIdentifierOrPattern() {
+            return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken || isIdentifier();
+        }
+
+        function parseIdentifierOrPattern(): Identifier | BindingPattern {
+            if (token === SyntaxKind.OpenBracketToken) {
+                return parseArrayBindingPattern();
+            }
+            if (token === SyntaxKind.OpenBraceToken) {
+                return parseObjectBindingPattern();
+            }
+            return parseIdentifier();
+        }
+
+        function parseVariableDeclaration(): VariableDeclaration {
+            let node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);
+            node.name = parseIdentifierOrPattern();
+            node.type = parseTypeAnnotation();
+            if (!isInOrOfKeyword(token)) {
+                node.initializer = parseInitializer(/*inParameter*/ false);
+            }
+            return finishNode(node);
+        }
+
+        function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList {
+            let node = <VariableDeclarationList>createNode(SyntaxKind.VariableDeclarationList);
+
+            switch (token) {
+                case SyntaxKind.VarKeyword:
+                    break;
+                case SyntaxKind.LetKeyword:
+                    node.flags |= NodeFlags.Let;
+                    break;
+                case SyntaxKind.ConstKeyword:
+                    node.flags |= NodeFlags.Const;
+                    break;
+                default:
+                    Debug.fail();
+            }
+
+            nextToken();
+
+            // The user may have written the following:
+            //
+            //    for (let of X) { }
+            //
+            // In this case, we want to parse an empty declaration list, and then parse 'of'
+            // as a keyword. The reason this is not automatic is that 'of' is a valid identifier.
+            // So we need to look ahead to determine if 'of' should be treated as a keyword in
+            // this context.
+            // The checker will then give an error that there is an empty declaration list.
+            if (token === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) {
+                node.declarations = createMissingList<VariableDeclaration>();
+            }
+            else {
+                let savedDisallowIn = inDisallowInContext();
+                setDisallowInContext(inForStatementInitializer);
+
+                node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations, parseVariableDeclaration);
+
+                setDisallowInContext(savedDisallowIn);
+            }
+
+            return finishNode(node);
+        }
+
+        function canFollowContextualOfKeyword(): boolean {
+            return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken;
+        }
+
+        function parseVariableStatement(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): VariableStatement {
+            let node = <VariableStatement>createNode(SyntaxKind.VariableStatement, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer:*/ false);
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        function parseFunctionDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): FunctionDeclaration {
+            let node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(SyntaxKind.FunctionKeyword);
+            node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
+            node.name = node.flags & NodeFlags.Default ? parseOptionalIdentifier() : parseIdentifier();
+            fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
+            node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken, Diagnostics.or_expected);
+            return finishNode(node);
+        }
+
+        function parseConstructorDeclaration(pos: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ConstructorDeclaration {
+            let node = <ConstructorDeclaration>createNode(SyntaxKind.Constructor, pos);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(SyntaxKind.ConstructorKeyword);
+            fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
+            node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false, Diagnostics.or_expected);
+            return finishNode(node);
+        }
+
+        function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, asteriskToken: Node, name: DeclarationName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
+            let method = <MethodDeclaration>createNode(SyntaxKind.MethodDeclaration, fullStart);
+            method.decorators = decorators;
+            setModifiers(method, modifiers);
+            method.asteriskToken = asteriskToken;
+            method.name = name;
+            method.questionToken = questionToken;
+            fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, /*requireCompleteParameterList:*/ false, method);
+            method.body = parseFunctionBlockOrSemicolon(!!asteriskToken, diagnosticMessage);
+            return finishNode(method);
+        }
+
+        function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, name: DeclarationName, questionToken: Node): ClassElement {
+            let property = <PropertyDeclaration>createNode(SyntaxKind.PropertyDeclaration, fullStart);
+            property.decorators = decorators;
+            setModifiers(property, modifiers);
+            property.name = name;
+            property.questionToken = questionToken;
+            property.type = parseTypeAnnotation();
+            property.initializer = allowInAnd(parseNonParameterInitializer);
+            parseSemicolon();
+            return finishNode(property);
+        }
+
+        function parsePropertyOrMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ClassElement {
+            let asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
+            let name = parsePropertyName();
+            
+            // Note: this is not legal as per the grammar.  But we allow it in the parser and
+            // report an error in the grammar checker.
+            let questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
+            if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
+                return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, Diagnostics.or_expected);
+            }
+            else {
+                return parsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken);
+            }
+        }
+
+        function parseNonParameterInitializer() {
+            return parseInitializer(/*inParameter*/ false);
+        }
+
+        function parseAccessorDeclaration(kind: SyntaxKind, fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): AccessorDeclaration {
+            let node = <AccessorDeclaration>createNode(kind, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.name = parsePropertyName();
+            fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
+            node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false);
+            return finishNode(node);
+        }
+
+        function isClassMemberModifier(idToken: SyntaxKind) {
+            switch (idToken) {
+                case SyntaxKind.PublicKeyword:
+                case SyntaxKind.PrivateKeyword:
+                case SyntaxKind.ProtectedKeyword:
+                case SyntaxKind.StaticKeyword:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        function isClassMemberStart(): boolean {
+            let idToken: SyntaxKind;
+
+            if (token === SyntaxKind.AtToken) {
+                return true;
+            }
+
+            // Eat up all modifiers, but hold on to the last one in case it is actually an identifier.
+            while (isModifier(token)) {
+                idToken = token;
+                // If the idToken is a class modifier (protected, private, public, and static), it is
+                // certain that we are starting to parse class member. This allows better error recovery
+                // Example:
+                //      public foo() ...     // true
+                //      public @dec blah ... // true; we will then report an error later
+                //      export public ...    // true; we will then report an error later
+                if (isClassMemberModifier(idToken)) {
+                    return true;
+                }
+
+                nextToken();
+            }
+
+            if (token === SyntaxKind.AsteriskToken) {
+                return true;
+            }
+
+            // Try to get the first property-like token following all modifiers.
+            // This can either be an identifier or the 'get' or 'set' keywords.
+            if (isLiteralPropertyName()) {
+                idToken = token;
+                nextToken();
+            }
+
+            // Index signatures and computed properties are class members; we can parse.
+            if (token === SyntaxKind.OpenBracketToken) {
+                return true;
+            }
+
+            // If we were able to get any potential identifier...
+            if (idToken !== undefined) {
+                // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse.
+                if (!isKeyword(idToken) || idToken === SyntaxKind.SetKeyword || idToken === SyntaxKind.GetKeyword) {
+                    return true;
+                }
+
+                // If it *is* a keyword, but not an accessor, check a little farther along
+                // to see if it should actually be parsed as a class member.
+                switch (token) {
+                    case SyntaxKind.OpenParenToken:     // Method declaration
+                    case SyntaxKind.LessThanToken:      // Generic Method declaration
+                    case SyntaxKind.ColonToken:         // Type Annotation for declaration
+                    case SyntaxKind.EqualsToken:        // Initializer for declaration
+                    case SyntaxKind.QuestionToken:      // Not valid, but permitted so that it gets caught later on.
+                        return true;
+                    default:
+                        // Covers
+                        //  - Semicolons     (declaration termination)
+                        //  - Closing braces (end-of-class, must be declaration)
+                        //  - End-of-files   (not valid, but permitted so that it gets caught later on)
+                        //  - Line-breaks    (enabling *automatic semicolon insertion*)
+                        return canParseSemicolon();
+                }
+            }
+
+            return false;
+        }
+
+        function parseDecorators(): NodeArray<Decorator> {
+            let decorators: NodeArray<Decorator>;
+            while (true) {
+                let decoratorStart = getNodePos();
+                if (!parseOptional(SyntaxKind.AtToken)) {
+                    break;
+                }
+
+                if (!decorators) {
+                    decorators = <NodeArray<Decorator>>[];
+                    decorators.pos = scanner.getStartPos();
+                }
+
+                let decorator = <Decorator>createNode(SyntaxKind.Decorator, decoratorStart);
+                decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher);
+                decorators.push(finishNode(decorator));
+            }
+            if (decorators) {
+                decorators.end = getNodeEnd();
+            }
+            return decorators;
+        }
+
+        function parseModifiers(): ModifiersArray {
+            let flags = 0;
+            let modifiers: ModifiersArray;
+            while (true) {
+                let modifierStart = scanner.getStartPos();
+                let modifierKind = token;
+
+                if (!parseAnyContextualModifier()) {
+                    break;
+                }
+
+                if (!modifiers) {
+                    modifiers = <ModifiersArray>[];
+                    modifiers.pos = modifierStart;
+                }
+                flags |= modifierToFlag(modifierKind);
+                modifiers.push(finishNode(createNode(modifierKind, modifierStart)));
+            }
+            if (modifiers) {
+                modifiers.flags = flags;
+                modifiers.end = scanner.getStartPos();
+            }
+            return modifiers;
+        }
+
+        function parseClassElement(): ClassElement {
+            if (token === SyntaxKind.SemicolonToken) {
+                let result = <SemicolonClassElement>createNode(SyntaxKind.SemicolonClassElement);
+                nextToken();
+                return finishNode(result);
+            }
+
+            let fullStart = getNodePos();
+            let decorators = parseDecorators();
+            let modifiers = parseModifiers();
+
+            let accessor = tryParseAccessorDeclaration(fullStart, decorators, modifiers);
+            if (accessor) {
+                return accessor;
+            }
+
+            if (token === SyntaxKind.ConstructorKeyword) {
+                return parseConstructorDeclaration(fullStart, decorators, modifiers);
+            }
+
+            if (isIndexSignature()) {
+                return parseIndexSignatureDeclaration(fullStart, decorators, modifiers);
+            }
+
+            // It is very important that we check this *after* checking indexers because
+            // the [ token can start an index signature or a computed property name
+            if (isIdentifierOrKeyword() ||
+                token === SyntaxKind.StringLiteral ||
+                token === SyntaxKind.NumericLiteral ||
+                token === SyntaxKind.AsteriskToken ||
+                token === SyntaxKind.OpenBracketToken) {
+
+                return parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers);
+            }
+
+            if (decorators) {
+                // treat this as a property declaration with a missing name.
+                let name = <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
+                return parsePropertyDeclaration(fullStart, decorators, modifiers, name, /*questionToken*/ undefined);
+            }
+
+            // 'isClassMemberStart' should have hinted not to attempt parsing.
+            Debug.fail("Should not have attempted to parse class member declaration.");
+        }
+
+        function parseClassExpression(): ClassExpression {
+            return <ClassExpression>parseClassDeclarationOrExpression(
+                /*fullStart:*/ scanner.getStartPos(),
+                /*decorators:*/ undefined,
+                /*modifiers:*/ undefined,
+                SyntaxKind.ClassExpression);
+        }
+
+        function parseClassDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ClassDeclaration {
+            return <ClassDeclaration>parseClassDeclarationOrExpression(fullStart, decorators, modifiers, SyntaxKind.ClassDeclaration);
+        }
+
+        function parseClassDeclarationOrExpression(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, kind: SyntaxKind): ClassLikeDeclaration {
+            // In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
+            let savedStrictModeContext = inStrictModeContext();
+            setStrictModeContext(true);
+
+            var node = <ClassLikeDeclaration>createNode(kind, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(SyntaxKind.ClassKeyword);
+            node.name = parseOptionalIdentifier();
+            node.typeParameters = parseTypeParameters();
+            node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ true);
+
+            if (parseExpected(SyntaxKind.OpenBraceToken)) {
+                // ClassTail[Yield,GeneratorParameter] : See 14.5
+                //      [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
+                //      [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
+
+                node.members = inGeneratorParameterContext()
+                    ? doOutsideOfYieldContext(parseClassMembers)
+                    : parseClassMembers();
+                parseExpected(SyntaxKind.CloseBraceToken);
+            }
+            else {
+                node.members = createMissingList<ClassElement>();
+            }
+
+            var finishedNode = finishNode(node);
+            setStrictModeContext(savedStrictModeContext);
+            return finishedNode;
+        }
+
+        function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {
+            // ClassTail[Yield,GeneratorParameter] : See 14.5
+            //      [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
+            //      [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
+
+            if (isHeritageClause()) {
+                return isClassHeritageClause && inGeneratorParameterContext()
+                    ? doOutsideOfYieldContext(parseHeritageClausesWorker)
+                    : parseHeritageClausesWorker();
+            }
+
+            return undefined;
+        }
+
+        function parseHeritageClausesWorker() {
+            return parseList(ParsingContext.HeritageClauses, /*checkForStrictMode:*/ false, parseHeritageClause);
+        }
+
+        function parseHeritageClause() {
+            if (token === SyntaxKind.ExtendsKeyword || token === SyntaxKind.ImplementsKeyword) {
+                let node = <HeritageClause>createNode(SyntaxKind.HeritageClause);
+                node.token = token;
+                nextToken();
+                node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseHeritageClauseElement);
+                return finishNode(node);
+            }
+
+            return undefined;
+        }
+
+        function parseHeritageClauseElement(): HeritageClauseElement {
+            let node = <HeritageClauseElement>createNode(SyntaxKind.HeritageClauseElement);
+            node.expression = parseLeftHandSideExpressionOrHigher();
+            if (token === SyntaxKind.LessThanToken) {
+                node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
+            }
+
+            return finishNode(node);
+        }
+
+        function isHeritageClause(): boolean {
+            return token === SyntaxKind.ExtendsKeyword || token === SyntaxKind.ImplementsKeyword;
+        }
+
+        function parseClassMembers() {
+            return parseList(ParsingContext.ClassMembers, /*checkForStrictMode*/ false, parseClassElement);
+        }
+
+        function parseInterfaceDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): InterfaceDeclaration {
+            let node = <InterfaceDeclaration>createNode(SyntaxKind.InterfaceDeclaration, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(SyntaxKind.InterfaceKeyword);
+            node.name = parseIdentifier();
+            node.typeParameters = parseTypeParameters();
+            node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ false);
+            node.members = parseObjectTypeMembers();
+            return finishNode(node);
+        }
+
+        function parseTypeAliasDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): TypeAliasDeclaration {
+            let node = <TypeAliasDeclaration>createNode(SyntaxKind.TypeAliasDeclaration, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(SyntaxKind.TypeKeyword);
+            node.name = parseIdentifier();
+            parseExpected(SyntaxKind.EqualsToken);
+            node.type = parseType();
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        // In an ambient declaration, the grammar only allows integer literals as initializers.
+        // In a non-ambient declaration, the grammar allows uninitialized members only in a
+        // ConstantEnumMemberSection, which starts at the beginning of an enum declaration
+        // or any time an integer literal initializer is encountered.
+        function parseEnumMember(): EnumMember {
+            let node = <EnumMember>createNode(SyntaxKind.EnumMember, scanner.getStartPos());
+            node.name = parsePropertyName();
+            node.initializer = allowInAnd(parseNonParameterInitializer);
+            return finishNode(node);
+        }
+
+        function parseEnumDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): EnumDeclaration {
+            let node = <EnumDeclaration>createNode(SyntaxKind.EnumDeclaration, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            parseExpected(SyntaxKind.EnumKeyword);
+            node.name = parseIdentifier();
+            if (parseExpected(SyntaxKind.OpenBraceToken)) {
+                node.members = parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember);
+                parseExpected(SyntaxKind.CloseBraceToken);
+            }
+            else {
+                node.members = createMissingList<EnumMember>();
+            }
+            return finishNode(node);
+        }
+
+        function parseModuleBlock(): ModuleBlock {
+            let node = <ModuleBlock>createNode(SyntaxKind.ModuleBlock, scanner.getStartPos());
+            if (parseExpected(SyntaxKind.OpenBraceToken)) {
+                node.statements = parseList(ParsingContext.ModuleElements, /*checkForStrictMode*/false, parseModuleElement);
+                parseExpected(SyntaxKind.CloseBraceToken);
+            }
+            else {
+                node.statements = createMissingList<Statement>();
+            }
+            return finishNode(node);
+        }
+
+        function parseInternalModuleTail(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, flags: NodeFlags): ModuleDeclaration {
+            let node = <ModuleDeclaration>createNode(SyntaxKind.ModuleDeclaration, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.flags |= flags;
+            node.name = parseIdentifier();
+            node.body = parseOptional(SyntaxKind.DotToken)
+                ? parseInternalModuleTail(getNodePos(), /*decorators*/ undefined, /*modifiers:*/undefined, NodeFlags.Export)
+                : parseModuleBlock();
+            return finishNode(node);
+        }
+
+        function parseAmbientExternalModuleDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ModuleDeclaration {
+            let node = <ModuleDeclaration>createNode(SyntaxKind.ModuleDeclaration, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            node.name = parseLiteralNode(/*internName:*/ true);
+            node.body = parseModuleBlock();
+            return finishNode(node);
+        }
+
+        function parseModuleDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ModuleDeclaration {
+            parseExpected(SyntaxKind.ModuleKeyword);
+            return token === SyntaxKind.StringLiteral
+                ? parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers)
+                : parseInternalModuleTail(fullStart, decorators, modifiers, modifiers ? modifiers.flags : 0);
+        }
+
+        function isExternalModuleReference() {
+            return token === SyntaxKind.RequireKeyword &&
+                lookAhead(nextTokenIsOpenParen);
+        }
+
+        function nextTokenIsOpenParen() {
+            return nextToken() === SyntaxKind.OpenParenToken;
+        }
+
+        function nextTokenIsCommaOrFromKeyword() {
+            nextToken();
+            return token === SyntaxKind.CommaToken ||
+                token === SyntaxKind.FromKeyword;
+        }
+
+        function parseImportDeclarationOrImportEqualsDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ImportEqualsDeclaration | ImportDeclaration {
+            parseExpected(SyntaxKind.ImportKeyword);
+            let afterImportPos = scanner.getStartPos();
+
+            let identifier: Identifier;
+            if (isIdentifier()) {
+                identifier = parseIdentifier();
+                if (token !== SyntaxKind.CommaToken && token !== SyntaxKind.FromKeyword) {
+                    // ImportEquals declaration of type:
+                    // import x = require("mod"); or
+                    // import x = M.x;
+                    let importEqualsDeclaration = <ImportEqualsDeclaration>createNode(SyntaxKind.ImportEqualsDeclaration, fullStart);
+                    importEqualsDeclaration.decorators = decorators;
+                    setModifiers(importEqualsDeclaration, modifiers);
+                    importEqualsDeclaration.name = identifier;
+                    parseExpected(SyntaxKind.EqualsToken);
+                    importEqualsDeclaration.moduleReference = parseModuleReference();
+                    parseSemicolon();
+                    return finishNode(importEqualsDeclaration);
+                }
+            }
+
+            // Import statement
+            let importDeclaration = <ImportDeclaration>createNode(SyntaxKind.ImportDeclaration, fullStart);
+            importDeclaration.decorators = decorators;
+            setModifiers(importDeclaration, modifiers);
+
+            // ImportDeclaration:
+            //  import ImportClause from ModuleSpecifier ;
+            //  import ModuleSpecifier;
+            if (identifier || // import id
+                token === SyntaxKind.AsteriskToken || // import *
+                token === SyntaxKind.OpenBraceToken) { // import {
+                importDeclaration.importClause = parseImportClause(identifier, afterImportPos);
+                parseExpected(SyntaxKind.FromKeyword);
+            }
+
+            importDeclaration.moduleSpecifier = parseModuleSpecifier();
+            parseSemicolon();
+            return finishNode(importDeclaration);
+        }
+
+        function parseImportClause(identifier: Identifier, fullStart: number) {
+            //ImportClause:
+            //  ImportedDefaultBinding
+            //  NameSpaceImport
+            //  NamedImports
+            //  ImportedDefaultBinding, NameSpaceImport
+            //  ImportedDefaultBinding, NamedImports
+
+            let importClause = <ImportClause>createNode(SyntaxKind.ImportClause, fullStart);
+            if (identifier) {
+                // ImportedDefaultBinding:
+                //  ImportedBinding
+                importClause.name = identifier;
+            }
+
+            // If there was no default import or if there is comma token after default import
+            // parse namespace or named imports
+            if (!importClause.name ||
+                parseOptional(SyntaxKind.CommaToken)) {
+                importClause.namedBindings = token === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
+            }
+
+            return finishNode(importClause);
+        }
+
+        function parseModuleReference() {
+            return isExternalModuleReference()
+                ? parseExternalModuleReference()
+                : parseEntityName(/*allowReservedWords*/ false);
+        }
+
+        function parseExternalModuleReference() {
+            let node = <ExternalModuleReference>createNode(SyntaxKind.ExternalModuleReference);
+            parseExpected(SyntaxKind.RequireKeyword);
+            parseExpected(SyntaxKind.OpenParenToken);
+            node.expression = parseModuleSpecifier();
+            parseExpected(SyntaxKind.CloseParenToken);
+            return finishNode(node);
+        }
+
+        function parseModuleSpecifier(): Expression {
+            // We allow arbitrary expressions here, even though the grammar only allows string
+            // literals.  We check to ensure that it is only a string literal later in the grammar
+            // walker.
+            let result = parseExpression();
+            // Ensure the string being required is in our 'identifier' table.  This will ensure
+            // that features like 'find refs' will look inside this file when search for its name.
+            if (result.kind === SyntaxKind.StringLiteral) {
+                internIdentifier((<LiteralExpression>result).text);
+            }
+            return result;
+        }
+
+        function parseNamespaceImport(): NamespaceImport {
+            // NameSpaceImport:
+            //  * as ImportedBinding
+            let namespaceImport = <NamespaceImport>createNode(SyntaxKind.NamespaceImport);
+            parseExpected(SyntaxKind.AsteriskToken);
+            parseExpected(SyntaxKind.AsKeyword);
+            namespaceImport.name = parseIdentifier();
+            return finishNode(namespaceImport);
+        }
+
+        function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports {
+            let node = <NamedImports>createNode(kind);
+
+            // NamedImports:
+            //  { }
+            //  { ImportsList }
+            //  { ImportsList, }
+
+            // ImportsList:
+            //  ImportSpecifier
+            //  ImportsList, ImportSpecifier
+            node.elements = parseBracketedList(ParsingContext.ImportOrExportSpecifiers,
+                kind === SyntaxKind.NamedImports ? parseImportSpecifier : parseExportSpecifier,
+                SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken);
+            return finishNode(node);
+        }
+
+        function parseExportSpecifier() {
+            return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier);
+        }
+
+        function parseImportSpecifier() {
+            return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier);
+        }
+
+        function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier {
+            let node = <ImportSpecifier>createNode(kind);
+            // ImportSpecifier:
+            //   BindingIdentifier
+            //   IdentifierName as BindingIdentifier
+            // ExportSpecififer:
+            //   IdentifierName
+            //   IdentifierName as IdentifierName
+            let checkIdentifierIsKeyword = isKeyword(token) && !isIdentifier();
+            let checkIdentifierStart = scanner.getTokenPos();
+            let checkIdentifierEnd = scanner.getTextPos();
+            let identifierName = parseIdentifierName();
+            if (token === SyntaxKind.AsKeyword) {
+                node.propertyName = identifierName;
+                parseExpected(SyntaxKind.AsKeyword);
+                checkIdentifierIsKeyword = isKeyword(token) && !isIdentifier();
+                checkIdentifierStart = scanner.getTokenPos();
+                checkIdentifierEnd = scanner.getTextPos();
+                node.name = parseIdentifierName();
+            }
+            else {
+                node.name = identifierName;
+            }
+            if (kind === SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) {
+                // Report error identifier expected
+                parseErrorAtPosition(checkIdentifierStart, checkIdentifierEnd - checkIdentifierStart, Diagnostics.Identifier_expected);
+            }
+            return finishNode(node);
+        }
+
+        function parseExportDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ExportDeclaration {
+            let node = <ExportDeclaration>createNode(SyntaxKind.ExportDeclaration, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            if (parseOptional(SyntaxKind.AsteriskToken)) {
+                parseExpected(SyntaxKind.FromKeyword);
+                node.moduleSpecifier = parseModuleSpecifier();
+            }
+            else {
+                node.exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports);
+                if (parseOptional(SyntaxKind.FromKeyword)) {
+                    node.moduleSpecifier = parseModuleSpecifier();
+                }
+            }
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        function parseExportAssignment(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ExportAssignment {
+            let node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment, fullStart);
+            node.decorators = decorators;
+            setModifiers(node, modifiers);
+            if (parseOptional(SyntaxKind.EqualsToken)) {
+                node.isExportEquals = true;
+            }
+            else {
+                parseExpected(SyntaxKind.DefaultKeyword);
+            }
+            node.expression = parseAssignmentExpressionOrHigher();
+            parseSemicolon();
+            return finishNode(node);
+        }
+
+        function isLetDeclaration() {
+            // It is let declaration if in strict mode or next token is identifier\open bracket\open curly on same line.
+            // otherwise it needs to be treated like identifier
+            return inStrictModeContext() || lookAhead(nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine);
+        }
+
+        function isDeclarationStart(followsModifier?: boolean): boolean {
+            switch (token) {
+                case SyntaxKind.VarKeyword:
+                case SyntaxKind.ConstKeyword:
+                case SyntaxKind.FunctionKeyword:
+                    return true;
+                case SyntaxKind.LetKeyword:
+                    return isLetDeclaration();
+                case SyntaxKind.ClassKeyword:
+                case SyntaxKind.InterfaceKeyword:
+                case SyntaxKind.EnumKeyword:
+                case SyntaxKind.TypeKeyword:
+                    // Not true keywords so ensure an identifier follows
+                    return lookAhead(nextTokenIsIdentifierOrKeyword);
+                case SyntaxKind.ImportKeyword:
+                    // Not true keywords so ensure an identifier follows or is string literal or asterisk or open brace
+                    return lookAhead(nextTokenCanFollowImportKeyword);
+                case SyntaxKind.ModuleKeyword:
+                    // Not a true keyword so ensure an identifier or string literal follows
+                    return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral);
+                case SyntaxKind.ExportKeyword:
+                    // Check for export assignment or modifier on source element
+                    return lookAhead(nextTokenCanFollowExportKeyword);
+                case SyntaxKind.DeclareKeyword:
+                case SyntaxKind.PublicKeyword:
+                case SyntaxKind.PrivateKeyword:
+                case SyntaxKind.ProtectedKeyword:
+                case SyntaxKind.StaticKeyword:
+                    // Check for modifier on source element
+                    return lookAhead(nextTokenIsDeclarationStart);
+                case SyntaxKind.AtToken:
+                    // a lookahead here is too costly, and decorators are only valid on a declaration. 
+                    // We will assume we are parsing a declaration here and report an error later
+                    return !followsModifier;
+            }
+        }
+
+        function isIdentifierOrKeyword() {
+            return token >= SyntaxKind.Identifier;
+        }
+
+        function nextTokenIsIdentifierOrKeyword() {
+            nextToken();
+            return isIdentifierOrKeyword();
+        }
+
+        function nextTokenIsIdentifierOrKeywordOrStringLiteral() {
+            nextToken();
+            return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral;
+        }
+
+        function nextTokenCanFollowImportKeyword() {
+            nextToken();
+            return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral ||
+                token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken;
+        }
+
+        function nextTokenCanFollowExportKeyword() {
+            nextToken();
+            return token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken ||
+                token === SyntaxKind.OpenBraceToken || token === SyntaxKind.DefaultKeyword || isDeclarationStart(/*followsModifier*/ true);
+        }
+
+        function nextTokenIsDeclarationStart() {
+            nextToken();
+            return isDeclarationStart(/*followsModifier*/ true);
+        }
+
+        function nextTokenIsAsKeyword() {
+            return nextToken() === SyntaxKind.AsKeyword;
+        }
+
+        function parseDeclaration(): ModuleElement {
+            let fullStart = getNodePos();
+            let decorators = parseDecorators();
+            let modifiers = parseModifiers();
+            if (token === SyntaxKind.ExportKeyword) {
+                nextToken();
+                if (token === SyntaxKind.DefaultKeyword || token === SyntaxKind.EqualsToken) {
+                    return parseExportAssignment(fullStart, decorators, modifiers);
+                }
+                if (token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken) {
+                    return parseExportDeclaration(fullStart, decorators, modifiers);
+                }
+            }
+
+            switch (token) {
+                case SyntaxKind.VarKeyword:
+                case SyntaxKind.LetKeyword:
+                case SyntaxKind.ConstKeyword:
+                    return parseVariableStatement(fullStart, decorators, modifiers);
+                case SyntaxKind.FunctionKeyword:
+                    return parseFunctionDeclaration(fullStart, decorators, modifiers);
+                case SyntaxKind.ClassKeyword:
+                    return parseClassDeclaration(fullStart, decorators, modifiers);
+                case SyntaxKind.InterfaceKeyword:
+                    return parseInterfaceDeclaration(fullStart, decorators, modifiers);
+                case SyntaxKind.TypeKeyword:
+                    return parseTypeAliasDeclaration(fullStart, decorators, modifiers);
+                case SyntaxKind.EnumKeyword:
+                    return parseEnumDeclaration(fullStart, decorators, modifiers);
+                case SyntaxKind.ModuleKeyword:
+                    return parseModuleDeclaration(fullStart, decorators, modifiers);
+                case SyntaxKind.ImportKeyword:
+                    return parseImportDeclarationOrImportEqualsDeclaration(fullStart, decorators, modifiers);
+                default:
+                    if (decorators) {
+                        // We reached this point because we encountered an AtToken and assumed a declaration would
+                        // follow. For recovery and error reporting purposes, return an incomplete declaration.                        
+                        let node = <ModuleElement>createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
+                        node.pos = fullStart;
+                        node.decorators = decorators;
+                        setModifiers(node, modifiers);
+                        return finishNode(node);
+                    }
+                    Debug.fail("Mismatch between isDeclarationStart and parseDeclaration");
+            }
+        }
+
+        function isSourceElement(inErrorRecovery: boolean): boolean {
+            return isDeclarationStart() || isStartOfStatement(inErrorRecovery);
+        }
+
+        function parseSourceElement() {
+            return parseSourceElementOrModuleElement();
+        }
+
+        function parseModuleElement() {
+            return parseSourceElementOrModuleElement();
+        }
+
+        function parseSourceElementOrModuleElement(): ModuleElement {
+            return isDeclarationStart()
+                ? parseDeclaration()
+                : parseStatement();
+        }
+
+        function processReferenceComments(sourceFile: SourceFile): void {
+            let triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/false, sourceText);
+            let referencedFiles: FileReference[] = [];
+            let amdDependencies: { path: string; name: string }[] = [];
+            let amdModuleName: string;
+
+            // Keep scanning all the leading trivia in the file until we get to something that
+            // isn't trivia.  Any single line comment will be analyzed to see if it is a
+            // reference comment.
+            while (true) {
+                let kind = triviaScanner.scan();
+                if (kind === SyntaxKind.WhitespaceTrivia || kind === SyntaxKind.NewLineTrivia || kind === SyntaxKind.MultiLineCommentTrivia) {
+                    continue;
+                }
+                if (kind !== SyntaxKind.SingleLineCommentTrivia) {
+                    break;
+                }
+
+                let range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
+
+                let comment = sourceText.substring(range.pos, range.end);
+                let referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
+                if (referencePathMatchResult) {
+                    let fileReference = referencePathMatchResult.fileReference;
+                    sourceFile.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
+                    let diagnosticMessage = referencePathMatchResult.diagnosticMessage;
+                    if (fileReference) {
+                        referencedFiles.push(fileReference);
+                    }
+                    if (diagnosticMessage) {
+                        sourceFile.parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, diagnosticMessage));
+                    }
+                }
+                else {
+                    let amdModuleNameRegEx = /^\/\/\/\s*<amd-module\s+name\s*=\s*('|")(.+?)\1/gim;
+                    let amdModuleNameMatchResult = amdModuleNameRegEx.exec(comment);
+                    if (amdModuleNameMatchResult) {
+                        if (amdModuleName) {
+                            sourceFile.parseDiagnostics.push(createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments));
+                        }
+                        amdModuleName = amdModuleNameMatchResult[2];
+                    }
+
+                    let amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s/gim;
+                    let pathRegex = /\spath\s*=\s*('|")(.+?)\1/gim;
+                    let nameRegex = /\sname\s*=\s*('|")(.+?)\1/gim;
+                    let amdDependencyMatchResult = amdDependencyRegEx.exec(comment);
+                    if (amdDependencyMatchResult) {
+                        let pathMatchResult = pathRegex.exec(comment);
+                        let nameMatchResult = nameRegex.exec(comment);
+                        if (pathMatchResult) {
+                            let amdDependency = { path: pathMatchResult[2], name: nameMatchResult ? nameMatchResult[2] : undefined };
+                            amdDependencies.push(amdDependency);
+                        }
+                    }
+                }
+            }
+
+            sourceFile.referencedFiles = referencedFiles;
+            sourceFile.amdDependencies = amdDependencies;
+            sourceFile.amdModuleName = amdModuleName;
+        }
+
+        function setExternalModuleIndicator(sourceFile: SourceFile) {
+            sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node =>
+                node.flags & NodeFlags.Export
+                    || node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference
+                    || node.kind === SyntaxKind.ImportDeclaration
+                    || node.kind === SyntaxKind.ExportAssignment
+                    || node.kind === SyntaxKind.ExportDeclaration
+                    ? node
+                    : undefined);
+        }
+
+        const enum ParsingContext {
+            SourceElements,            // Elements in source file
+            ModuleElements,            // Elements in module declaration
+            BlockStatements,           // Statements in block
+            SwitchClauses,             // Clauses in switch statement
+            SwitchClauseStatements,    // Statements in switch clause
+            TypeMembers,               // Members in interface or type literal
+            ClassMembers,              // Members in class declaration
+            EnumMembers,               // Members in enum declaration
+            HeritageClauseElement,     // Elements in a heritage clause
+            VariableDeclarations,      // Variable declarations in variable statement
+            ObjectBindingElements,     // Binding elements in object binding list
+            ArrayBindingElements,      // Binding elements in array binding list
+            ArgumentExpressions,       // Expressions in argument list
+            ObjectLiteralMembers,      // Members in object literal
+            ArrayLiteralMembers,       // Members in array literal
+            Parameters,                // Parameters in parameter list
+            TypeParameters,            // Type parameters in type parameter list
+            TypeArguments,             // Type arguments in type argument list
+            TupleElementTypes,         // Element types in tuple element type list
+            HeritageClauses,           // Heritage clauses for a class or interface declaration.
+            ImportOrExportSpecifiers,  // Named import clause's import specifier list
+            Count                      // Number of parsing contexts
+        }
+
+        const enum Tristate {
+            False,
+            True,
+            Unknown
+        }
+    }
+
+    module IncrementalParser {
+        export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile {
+            aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive);
+
+            checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
+            if (textChangeRangeIsUnchanged(textChangeRange)) {
+                // if the text didn't change, then we can just return our current source file as-is.
+                return sourceFile;
+            }
+
+            if (sourceFile.statements.length === 0) {
+                // If we don't have any statements in the current source file, then there's no real
+                // way to incrementally parse.  So just do a full parse instead.
+                return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setNodeParents*/ true)
+            }
+
+            // Make sure we're not trying to incrementally update a source file more than once.  Once
+            // we do an update the original source file is considered unusbale from that point onwards.
+            //
+            // This is because we do incremental parsing in-place.  i.e. we take nodes from the old
+            // tree and give them new positions and parents.  From that point on, trusting the old
+            // tree at all is not possible as far too much of it may violate invariants.
+            let incrementalSourceFile = <IncrementalNode><Node>sourceFile;
+            Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
+            incrementalSourceFile.hasBeenIncrementallyParsed = true;
+
+            let oldText = sourceFile.text;
+            let syntaxCursor = createSyntaxCursor(sourceFile);
+
+            // Make the actual change larger so that we know to reparse anything whose lookahead
+            // might have intersected the change.
+            let changeRange = extendToAffectedRange(sourceFile, textChangeRange);
+            checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
+
+            // Ensure that extending the affected range only moved the start of the change range
+            // earlier in the file.
+            Debug.assert(changeRange.span.start <= textChangeRange.span.start);
+            Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span));
+            Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange)));
+
+            // The is the amount the nodes after the edit range need to be adjusted.  It can be
+            // positive (if the edit added characters), negative (if the edit deleted characters)
+            // or zero (if this was a pure overwrite with nothing added/removed).
+            let delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
+
+            // If we added or removed characters during the edit, then we need to go and adjust all
+            // the nodes after the edit.  Those nodes may move forward (if we inserted chars) or they
+            // may move backward (if we deleted chars).
+            //
+            // Doing this helps us out in two ways.  First, it means that any nodes/tokens we want
+            // to reuse are already at the appropriate position in the new text.  That way when we
+            // reuse them, we don't have to figure out if they need to be adjusted.  Second, it makes
+            // it very easy to determine if we can reuse a node.  If the node's position is at where
+            // we are in the text, then we can reuse it.  Otherwise we can't.  If the node's position
+            // is ahead of us, then we'll need to rescan tokens.  If the node's position is behind
+            // us, then we'll need to skip it or crumble it as appropriate
+            //
+            // We will also adjust the positions of nodes that intersect the change range as well.
+            // By doing this, we ensure that all the positions in the old tree are consistent, not
+            // just the positions of nodes entirely before/after the change range.  By being
+            // consistent, we can then easily map from positions to nodes in the old tree easily.
+            //
+            // Also, mark any syntax elements that intersect the changed span.  We know, up front,
+            // that we cannot reuse these elements.
+            updateTokenPositionsAndMarkElements(incrementalSourceFile,
+                changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
+
+            // Now that we've set up our internal incremental state just proceed and parse the
+            // source file in the normal fashion.  When possible the parser will retrieve and
+            // reuse nodes from the old tree.
+            //
+            // Note: passing in 'true' for setNodeParents is very important.  When incrementally
+            // parsing, we will be reusing nodes from the old tree, and placing it into new
+            // parents.  If we don't set the parents now, we'll end up with an observably
+            // inconsistent tree.  Setting the parents on the new tree should be very fast.  We
+            // will immediately bail out of walking any subtrees when we can see that their parents
+            // are already correct.
+            let result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /* setParentNode */ true)
+
+            return result;
+        }
+
+        function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
+            if (isArray) {
+                visitArray(<IncrementalNodeArray>element);
+            }
+            else {
+                visitNode(<IncrementalNode>element);
+            }
+            return;
+
+            function visitNode(node: IncrementalNode) {
+                if (aggressiveChecks && shouldCheckNode(node)) {
+                    var text = oldText.substring(node.pos, node.end);
+                }
+
+                // Ditch any existing LS children we may have created.  This way we can avoid
+                // moving them forward.
+                node._children = undefined;
+                node.pos += delta;
+                node.end += delta;
+
+                if (aggressiveChecks && shouldCheckNode(node)) {
+                    Debug.assert(text === newText.substring(node.pos, node.end));
+                }
+
+                forEachChild(node, visitNode, visitArray);
+                checkNodePositions(node, aggressiveChecks);
+            }
+
+            function visitArray(array: IncrementalNodeArray) {
+                array._children = undefined;
+                array.pos += delta;
+                array.end += delta;
+
+                for (let node of array) {
+                    visitNode(node);
+                }
+            }
+        }
+
+        function shouldCheckNode(node: Node) {
+            switch (node.kind) {
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.NumericLiteral:
+                case SyntaxKind.Identifier:
+                    return true;
+            }
+
+            return false;
+        }
+
+        function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) {
+            Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
+            Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
+            Debug.assert(element.pos <= element.end);
+
+            // We have an element that intersects the change range in some way.  It may have its
+            // start, or its end (or both) in the changed range.  We want to adjust any part
+            // that intersects such that the final tree is in a consistent state.  i.e. all
+            // chlidren have spans within the span of their parent, and all siblings are ordered
+            // properly.
+
+            // We may need to update both the 'pos' and the 'end' of the element.
+
+            // If the 'pos' is before the start of the change, then we don't need to touch it.
+            // If it isn't, then the 'pos' must be inside the change.  How we update it will
+            // depend if delta is  positive or negative.  If delta is positive then we have
+            // something like:
+            //
+            //  -------------------AAA-----------------
+            //  -------------------BBBCCCCCCC-----------------
+            //
+            // In this case, we consider any node that started in the change range to still be
+            // starting at the same position.
+            //
+            // however, if the delta is negative, then we instead have something like this:
+            //
+            //  -------------------XXXYYYYYYY-----------------
+            //  -------------------ZZZ-----------------
+            //
+            // In this case, any element that started in the 'X' range will keep its position.
+            // However any element htat started after that will have their pos adjusted to be
+            // at the end of the new range.  i.e. any node that started in the 'Y' range will
+            // be adjusted to have their start at the end of the 'Z' range.
+            //
+            // The element will keep its position if possible.  Or Move backward to the new-end
+            // if it's in the 'Y' range.
+            element.pos = Math.min(element.pos, changeRangeNewEnd);
+
+            // If the 'end' is after the change range, then we always adjust it by the delta
+            // amount.  However, if the end is in the change range, then how we adjust it
+            // will depend on if delta is  positive or negative.  If delta is positive then we
+            // have something like:
+            //
+            //  -------------------AAA-----------------
+            //  -------------------BBBCCCCCCC-----------------
+            //
+            // In this case, we consider any node that ended inside the change range to keep its
+            // end position.
+            //
+            // however, if the delta is negative, then we instead have something like this:
+            //
+            //  -------------------XXXYYYYYYY-----------------
+            //  -------------------ZZZ-----------------
+            //
+            // In this case, any element that ended in the 'X' range will keep its position.
+            // However any element htat ended after that will have their pos adjusted to be
+            // at the end of the new range.  i.e. any node that ended in the 'Y' range will
+            // be adjusted to have their end at the end of the 'Z' range.
+            if (element.end >= changeRangeOldEnd) {
+                // Element ends after the change range.  Always adjust the end pos.
+                element.end += delta;
+            }
+            else {
+                // Element ends in the change range.  The element will keep its position if
+                // possible. Or Move backward to the new-end if it's in the 'Y' range.
+                element.end = Math.min(element.end, changeRangeNewEnd);
+            }
+
+            Debug.assert(element.pos <= element.end);
+            if (element.parent) {
+                Debug.assert(element.pos >= element.parent.pos);
+                Debug.assert(element.end <= element.parent.end);
+            }
+        }
+
+        function checkNodePositions(node: Node, aggressiveChecks: boolean) {
+            if (aggressiveChecks) {
+                let pos = node.pos;
+                forEachChild(node, child => {
+                    Debug.assert(child.pos >= pos);
+                    pos = child.end;
+                });
+                Debug.assert(pos <= node.end);
+            }
+        }
+
+        function updateTokenPositionsAndMarkElements(
+            sourceFile: IncrementalNode,
+            changeStart: number,
+            changeRangeOldEnd: number,
+            changeRangeNewEnd: number,
+            delta: number,
+            oldText: string,
+            newText: string,
+            aggressiveChecks: boolean): void {
+
+            visitNode(sourceFile);
+            return;
+
+            function visitNode(child: IncrementalNode) {
+                Debug.assert(child.pos <= child.end);
+                if (child.pos > changeRangeOldEnd) {
+                    // Node is entirely past the change range.  We need to move both its pos and
+                    // end, forward or backward appropriately.
+                    moveElementEntirelyPastChangeRange(child, /*isArray:*/ false, delta, oldText, newText, aggressiveChecks);
+                    return;
+                }
+
+                // Check if the element intersects the change range.  If it does, then it is not
+                // reusable.  Also, we'll need to recurse to see what constituent portions we may
+                // be able to use.
+                let fullEnd = child.end;
+                if (fullEnd >= changeStart) {
+                    child.intersectsChange = true;
+                    child._children = undefined;
+
+                    // Adjust the pos or end (or both) of the intersecting element accordingly.
+                    adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
+                    forEachChild(child, visitNode, visitArray);
+
+                    checkNodePositions(child, aggressiveChecks);
+                    return;
+                }
+
+                // Otherwise, the node is entirely before the change range.  No need to do anything with it.
+                Debug.assert(fullEnd < changeStart);
+            }
+
+            function visitArray(array: IncrementalNodeArray) {
+                Debug.assert(array.pos <= array.end);
+                if (array.pos > changeRangeOldEnd) {
+                    // Array is entirely after the change range.  We need to move it, and move any of
+                    // its children.
+                    moveElementEntirelyPastChangeRange(array, /*isArray:*/ true, delta, oldText, newText, aggressiveChecks);
+                    return;
+                }
+
+                // Check if the element intersects the change range.  If it does, then it is not
+                // reusable.  Also, we'll need to recurse to see what constituent portions we may
+                // be able to use.
+                let fullEnd = array.end;
+                if (fullEnd >= changeStart) {
+                    array.intersectsChange = true;
+                    array._children = undefined;
+
+                    // Adjust the pos or end (or both) of the intersecting array accordingly.
+                    adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
+                    for (let node of array) {
+                        visitNode(node);
+                    }
+                    return;
+                }
+
+                // Otherwise, the array is entirely before the change range.  No need to do anything with it.
+                Debug.assert(fullEnd < changeStart);
+            }
+        }
+
+        function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange {
+            // Consider the following code:
+            //      void foo() { /; }
+            //
+            // If the text changes with an insertion of / just before the semicolon then we end up with:
+            //      void foo() { //; }
+            //
+            // If we were to just use the changeRange a is, then we would not rescan the { token
+            // (as it does not intersect the actual original change range).  Because an edit may
+            // change the token touching it, we actually need to look back *at least* one token so
+            // that the prior token sees that change.
+            let maxLookahead = 1;
+
+            let start = changeRange.span.start;
+
+            // the first iteration aligns us with the change start. subsequent iteration move us to
+            // the left by maxLookahead tokens.  We only need to do this as long as we're not at the
+            // start of the tree.
+            for (let i = 0; start > 0 && i <= maxLookahead; i++) {
+                let nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
+                Debug.assert(nearestNode.pos <= start);
+                let position = nearestNode.pos;
+
+                start = Math.max(0, position - 1);
+            }
+
+            let finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span));
+            let finalLength = changeRange.newLength + (changeRange.span.start - start);
+
+            return createTextChangeRange(finalSpan, finalLength);
+        }
+
+        function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node {
+            let bestResult: Node = sourceFile;
+            let lastNodeEntirelyBeforePosition: Node;
+
+            forEachChild(sourceFile, visit);
+
+            if (lastNodeEntirelyBeforePosition) {
+                let lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition);
+                if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
+                    bestResult = lastChildOfLastEntireNodeBeforePosition;
+                }
+            }
+
+            return bestResult;
+
+            function getLastChild(node: Node): Node {
+                while (true) {
+                    let lastChild = getLastChildWorker(node);
+                    if (lastChild) {
+                        node = lastChild;
+                    }
+                    else {
+                        return node;
+                    }
+                }
+            }
+
+            function getLastChildWorker(node: Node): Node {
+                let last: Node = undefined;
+                forEachChild(node, child => {
+                    if (nodeIsPresent(child)) {
+                        last = child;
+                    }
+                });
+                return last;
+            }
+
+            function visit(child: Node) {
+                if (nodeIsMissing(child)) {
+                    // Missing nodes are effectively invisible to us.  We never even consider them
+                    // When trying to find the nearest node before us.
+                    return;
+                }
+
+                // If the child intersects this position, then this node is currently the nearest
+                // node that starts before the position.
+                if (child.pos <= position) {
+                    if (child.pos >= bestResult.pos) {
+                        // This node starts before the position, and is closer to the position than
+                        // the previous best node we found.  It is now the new best node.
+                        bestResult = child;
+                    }
+
+                    // Now, the node may overlap the position, or it may end entirely before the
+                    // position.  If it overlaps with the position, then either it, or one of its
+                    // children must be the nearest node before the position.  So we can just
+                    // recurse into this child to see if we can find something better.
+                    if (position < child.end) {
+                        // The nearest node is either this child, or one of the children inside
+                        // of it.  We've already marked this child as the best so far.  Recurse
+                        // in case one of the children is better.
+                        forEachChild(child, visit);
+
+                        // Once we look at the children of this node, then there's no need to
+                        // continue any further.
+                        return true;
+                    }
+                    else {
+                        Debug.assert(child.end <= position);
+                        // The child ends entirely before this position.  Say you have the following
+                        // (where $ is the position)
+                        //
+                        //      <complex expr 1> ? <complex expr 2> $ : <...> <...>
+                        //
+                        // We would want to find the nearest preceding node in "complex expr 2".
+                        // To support that, we keep track of this node, and once we're done searching
+                        // for a best node, we recurse down this node to see if we can find a good
+                        // result in it.
+                        //
+                        // This approach allows us to quickly skip over nodes that are entirely
+                        // before the position, while still allowing us to find any nodes in the
+                        // last one that might be what we want.
+                        lastNodeEntirelyBeforePosition = child;
+                    }
+                }
+                else {
+                    Debug.assert(child.pos > position);
+                    // We're now at a node that is entirely past the position we're searching for.
+                    // This node (and all following nodes) could never contribute to the result,
+                    // so just skip them by returning 'true' here.
+                    return true;
+                }
+            }
+        }
+
+        function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) {
+            let oldText = sourceFile.text;
+            if (textChangeRange) {
+                Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length);
+
+                if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) {
+                    let oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
+                    let newTextPrefix = newText.substr(0, textChangeRange.span.start);
+                    Debug.assert(oldTextPrefix === newTextPrefix);
+
+                    let oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length);
+                    let newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length);
+                    Debug.assert(oldTextSuffix === newTextSuffix);
+                }
+            }
+        }
+
+        interface IncrementalElement extends TextRange {
+            parent?: Node;
+            intersectsChange: boolean
+            length?: number;
+            _children: Node[];
+        }
+
+        export interface IncrementalNode extends Node, IncrementalElement {
+            hasBeenIncrementallyParsed: boolean
+        }
+
+        interface IncrementalNodeArray extends NodeArray<IncrementalNode>, IncrementalElement {
+            length: number
+        }
+
+        // Allows finding nodes in the source file at a certain position in an efficient manner.
+        // The implementation takes advantage of the calling pattern it knows the parser will
+        // make in order to optimize finding nodes as quickly as possible.
+        export interface SyntaxCursor {
+            currentNode(position: number): IncrementalNode;
+        }
+
+        function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor {
+            let currentArray: NodeArray<Node> = sourceFile.statements;
+            let currentArrayIndex = 0;
+
+            Debug.assert(currentArrayIndex < currentArray.length);
+            let current = currentArray[currentArrayIndex];
+            let lastQueriedPosition = InvalidPosition.Value;
+
+            return {
+                currentNode(position: number) {
+                    // Only compute the current node if the position is different than the last time
+                    // we were asked.  The parser commonly asks for the node at the same position
+                    // twice.  Once to know if can read an appropriate list element at a certain point,
+                    // and then to actually read and consume the node.
+                    if (position !== lastQueriedPosition) {
+                        // Much of the time the parser will need the very next node in the array that
+                        // we just returned a node from.So just simply check for that case and move
+                        // forward in the array instead of searching for the node again.
+                        if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
+                            currentArrayIndex++;
+                            current = currentArray[currentArrayIndex];
+                        }
+
+                        // If we don't have a node, or the node we have isn't in the right position,
+                        // then try to find a viable node at the position requested.
+                        if (!current || current.pos !== position) {
+                            findHighestListElementThatStartsAtPosition(position);
+                        }
+                    }
+
+                    // Cache this query so that we don't do any extra work if the parser calls back
+                    // into us.  Note: this is very common as the parser will make pairs of calls like
+                    // 'isListElement -> parseListElement'.  If we were unable to find a node when
+                    // called with 'isListElement', we don't want to redo the work when parseListElement
+                    // is called immediately after.
+                    lastQueriedPosition = position;
+
+                    // Either we don'd have a node, or we have a node at the position being asked for.
+                    Debug.assert(!current || current.pos === position);
+                    return <IncrementalNode>current;
+                }
+            };
+
+            // Finds the highest element in the tree we can find that starts at the provided position.
+            // The element must be a direct child of some node list in the tree.  This way after we
+            // return it, we can easily return its next sibling in the list.
+            function findHighestListElementThatStartsAtPosition(position: number) {
+                // Clear out any cached state about the last node we found.
+                currentArray = undefined;
+                currentArrayIndex = InvalidPosition.Value;
+                current = undefined;
+
+                // Recurse into the source file to find the highest node at this position.
+                forEachChild(sourceFile, visitNode, visitArray);
+                return;
+
+                function visitNode(node: Node) {
+                    if (position >= node.pos && position < node.end) {
+                        // Position was within this node.  Keep searching deeper to find the node.
+                        forEachChild(node, visitNode, visitArray);
+
+                        // don't procede any futher in the search.
+                        return true;
+                    }
+
+                    // position wasn't in this node, have to keep searching.
+                    return false;
+                }
+
+                function visitArray(array: NodeArray<Node>) {
+                    if (position >= array.pos && position < array.end) {
+                        // position was in this array.  Search through this array to see if we find a
+                        // viable element.
+                        for (let i = 0, n = array.length; i < n; i++) {
+                            let child = array[i];
+                            if (child) {
+                                if (child.pos === position) {
+                                    // Found the right node.  We're done.
+                                    currentArray = array;
+                                    currentArrayIndex = i;
+                                    current = child;
+                                    return true;
+                                }
+                                else {
+                                    if (child.pos < position && position < child.end) {
+                                        // Position in somewhere within this child.  Search in it and
+                                        // stop searching in this array.
+                                        forEachChild(child, visitNode, visitArray);
+                                        return true;
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                    // position wasn't in this array, have to keep searching.
+                    return false;
+                }
+            }
+        }
+
+        const enum InvalidPosition {
+            Value = -1
+        }
+    }
+}
diff --git a/lib/typescript/compiler/program.ts b/lib/typescript/compiler/program.ts
new file mode 100644
index 000000000..29baecb7e
--- /dev/null
+++ b/lib/typescript/compiler/program.ts
@@ -0,0 +1,608 @@
+/// <reference path="sys.ts" />
+/// <reference path="emitter.ts" />
+
+module ts {
+    /* @internal */ export let programTime = 0;
+    /* @internal */ export let emitTime = 0;
+    /* @internal */ export let ioReadTime = 0;
+    /* @internal */ export let ioWriteTime = 0;
+
+    /** The version of the TypeScript compiler release */
+    export const version = "1.5.0";
+
+    export function findConfigFile(searchPath: string): string {
+        var fileName = "tsconfig.json";
+        while (true) {
+            if (sys.fileExists(fileName)) {
+                return fileName;
+            }
+            var parentPath = getDirectoryPath(searchPath);
+            if (parentPath === searchPath) {
+                break;
+            }
+            searchPath = parentPath;
+            fileName = "../" + fileName;
+        }
+        return undefined;
+    }
+
+    export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
+        let currentDirectory: string;
+        let existingDirectories: Map<boolean> = {};
+
+        function getCanonicalFileName(fileName: string): string {
+            // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
+            // otherwise use toLowerCase as a canonical form.
+            return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
+        }
+        
+        // returned by CScript sys environment
+        let unsupportedFileEncodingErrorCode = -2147024809;
+
+        function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
+            let text: string;
+            try {
+                let start = new Date().getTime();
+                text = sys.readFile(fileName, options.charset);
+                ioReadTime += new Date().getTime() - start;
+            }
+            catch (e) {
+                if (onError) {
+                    onError(e.number === unsupportedFileEncodingErrorCode
+                        ? createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText
+                        : e.message);
+                }
+                text = "";
+            }
+
+            return text !== undefined ? createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined;
+        }
+
+        function directoryExists(directoryPath: string): boolean {
+            if (hasProperty(existingDirectories, directoryPath)) {
+                return true;
+            }
+            if (sys.directoryExists(directoryPath)) {
+                existingDirectories[directoryPath] = true;
+                return true;
+            }
+            return false;
+        }
+
+        function ensureDirectoriesExist(directoryPath: string) {
+            if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
+                let parentDirectory = getDirectoryPath(directoryPath);
+                ensureDirectoriesExist(parentDirectory);
+                sys.createDirectory(directoryPath);
+            }
+        }
+
+        function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
+            try {
+                var start = new Date().getTime();
+                ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
+                sys.writeFile(fileName, data, writeByteOrderMark);
+                ioWriteTime += new Date().getTime() - start;
+            }
+            catch (e) {
+                if (onError) {
+                    onError(e.message);
+                }
+            }
+        }
+
+        return {
+            getSourceFile,
+            getDefaultLibFileName: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)),
+            writeFile,
+            getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
+            useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
+            getCanonicalFileName,
+            getNewLine: () => sys.newLine
+        };
+    }
+
+    export function getPreEmitDiagnostics(program: Program): Diagnostic[] {
+        let diagnostics = program.getSyntacticDiagnostics().concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics());
+
+        if (program.getCompilerOptions().declaration) {
+            diagnostics.concat(program.getDeclarationDiagnostics());
+        }
+
+        return sortAndDeduplicateDiagnostics(diagnostics);
+    }
+
+    export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string {
+        if (typeof messageText === "string") {
+            return messageText;
+        }
+        else {
+            let diagnosticChain = messageText;
+            let result = "";
+
+            let indent = 0;
+            while (diagnosticChain) {
+                if (indent) {
+                    result += newLine;
+
+                    for (let i = 0; i < indent; i++) {
+                        result += "  ";
+                    }
+                }
+                result += diagnosticChain.messageText;
+                indent++;
+                diagnosticChain = diagnosticChain.next;
+            }
+
+            return result;
+        }
+    }
+
+    export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost): Program {
+        let program: Program;
+        let files: SourceFile[] = [];
+        let filesByName: Map<SourceFile> = {};
+        let diagnostics = createDiagnosticCollection();
+        let seenNoDefaultLib = options.noLib;
+        let commonSourceDirectory: string;
+        let diagnosticsProducingTypeChecker: TypeChecker;
+        let noDiagnosticsTypeChecker: TypeChecker;
+
+        let start = new Date().getTime();
+
+        host = host || createCompilerHost(options);
+        forEach(rootNames, name => processRootFile(name, false));
+        if (!seenNoDefaultLib) {
+            processRootFile(host.getDefaultLibFileName(options), true);
+        }
+        verifyCompilerOptions();
+
+        programTime += new Date().getTime() - start;
+
+        program = {
+            getSourceFile: getSourceFile,
+            getSourceFiles: () => files,
+            getCompilerOptions: () => options,
+            getSyntacticDiagnostics,
+            getGlobalDiagnostics,
+            getSemanticDiagnostics,
+            getDeclarationDiagnostics,
+            getTypeChecker,
+            getDiagnosticsProducingTypeChecker,
+            getCommonSourceDirectory: () => commonSourceDirectory,
+            emit,
+            getCurrentDirectory: () => host.getCurrentDirectory(),
+            getNodeCount: () => getDiagnosticsProducingTypeChecker().getNodeCount(),
+            getIdentifierCount: () => getDiagnosticsProducingTypeChecker().getIdentifierCount(),
+            getSymbolCount: () => getDiagnosticsProducingTypeChecker().getSymbolCount(),
+            getTypeCount: () => getDiagnosticsProducingTypeChecker().getTypeCount(),
+        };
+        return program;
+
+        function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost {
+            return {
+                getCanonicalFileName: fileName => host.getCanonicalFileName(fileName),
+                getCommonSourceDirectory: program.getCommonSourceDirectory,
+                getCompilerOptions: program.getCompilerOptions,
+                getCurrentDirectory: () => host.getCurrentDirectory(),
+                getNewLine: () => host.getNewLine(),
+                getSourceFile: program.getSourceFile,
+                getSourceFiles: program.getSourceFiles,
+                writeFile: writeFileCallback || (
+                    (fileName, data, writeByteOrderMark, onError) => host.writeFile(fileName, data, writeByteOrderMark, onError)),
+            };
+        }
+
+        function getDiagnosticsProducingTypeChecker() {
+            return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ true));
+        }
+
+        function getTypeChecker() {
+            return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false));
+        }
+
+        function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback): EmitResult {
+            // If the noEmitOnError flag is set, then check if we have any errors so far.  If so,
+            // immediately bail out.
+            if (options.noEmitOnError && getPreEmitDiagnostics(this).length > 0) {
+                return { diagnostics: [], sourceMaps: undefined, emitSkipped: true };
+            }
+
+            // Create the emit resolver outside of the "emitTime" tracking code below.  That way
+            // any cost associated with it (like type checking) are appropriate associated with
+            // the type-checking counter.
+            let emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
+
+            let start = new Date().getTime();
+
+            let emitResult = emitFiles(
+                emitResolver,
+                getEmitHost(writeFileCallback),
+                sourceFile);
+
+            emitTime += new Date().getTime() - start;
+            return emitResult;
+        }
+
+        function getSourceFile(fileName: string) {
+            fileName = host.getCanonicalFileName(fileName);
+            return hasProperty(filesByName, fileName) ? filesByName[fileName] : undefined;
+        }
+
+        function getDiagnosticsHelper(sourceFile: SourceFile, getDiagnostics: (sourceFile: SourceFile) => Diagnostic[]): Diagnostic[] {
+            if (sourceFile) {
+                return getDiagnostics(sourceFile);
+            }
+
+            let allDiagnostics: Diagnostic[] = [];
+            forEach(program.getSourceFiles(), sourceFile => {
+                addRange(allDiagnostics, getDiagnostics(sourceFile));
+            });
+
+            return sortAndDeduplicateDiagnostics(allDiagnostics);
+        }
+
+        function getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
+            return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile);
+        }
+
+        function getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
+            return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile);
+        }
+
+        function getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
+            return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile);
+        }
+
+        function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
+            return sourceFile.parseDiagnostics;
+        }
+
+        function getSemanticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
+            let typeChecker = getDiagnosticsProducingTypeChecker();
+
+            Debug.assert(!!sourceFile.bindDiagnostics);
+            let bindDiagnostics = sourceFile.bindDiagnostics;
+            let checkDiagnostics = typeChecker.getDiagnostics(sourceFile);
+            let programDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
+
+            return bindDiagnostics.concat(checkDiagnostics).concat(programDiagnostics);
+        }
+
+        function getDeclarationDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
+            if (!isDeclarationFile(sourceFile)) {
+                let resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile);
+                // Don't actually write any files since we're just getting diagnostics.
+                var writeFile: WriteFileCallback = () => { };
+                return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile);
+            }
+        }
+
+        function getGlobalDiagnostics(): Diagnostic[] {
+            let typeChecker = getDiagnosticsProducingTypeChecker();
+
+            let allDiagnostics: Diagnostic[] = [];
+            addRange(allDiagnostics, typeChecker.getGlobalDiagnostics());
+            addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
+
+            return sortAndDeduplicateDiagnostics(allDiagnostics);
+        }
+
+        function hasExtension(fileName: string): boolean {
+            return getBaseFileName(fileName).indexOf(".") >= 0;
+        }
+
+        function processRootFile(fileName: string, isDefaultLib: boolean) {
+            processSourceFile(normalizePath(fileName), isDefaultLib);
+        }
+
+        function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
+            let start: number;
+            let length: number;
+            if (refEnd !== undefined && refPos !== undefined) {
+                start = refPos;
+                length = refEnd - refPos;
+            }
+            let diagnostic: DiagnosticMessage;
+            if (hasExtension(fileName)) {
+                if (!options.allowNonTsExtensions && !fileExtensionIs(host.getCanonicalFileName(fileName), ".ts")) {
+                    diagnostic = Diagnostics.File_0_must_have_extension_ts_or_d_ts;
+                }
+                else if (!findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
+                    diagnostic = Diagnostics.File_0_not_found;
+                }
+                else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
+                    diagnostic = Diagnostics.A_file_cannot_have_a_reference_to_itself;
+                }
+            }
+            else {
+                if (options.allowNonTsExtensions && !findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
+                    diagnostic = Diagnostics.File_0_not_found;
+                }
+                else if (!findSourceFile(fileName + ".ts", isDefaultLib, refFile, refPos, refEnd) && !findSourceFile(fileName + ".d.ts", isDefaultLib, refFile, refPos, refEnd)) {
+                    diagnostic = Diagnostics.File_0_not_found;
+                    fileName += ".ts";
+                }
+            }
+
+            if (diagnostic) {
+                if (refFile) {
+                    diagnostics.add(createFileDiagnostic(refFile, start, length, diagnostic, fileName));
+                }
+                else {
+                    diagnostics.add(createCompilerDiagnostic(diagnostic, fileName));
+                }
+            }
+        }
+
+        // Get source file from normalized fileName
+        function findSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refStart?: number, refLength?: number): SourceFile {
+            let canonicalName = host.getCanonicalFileName(fileName);
+            if (hasProperty(filesByName, canonicalName)) {
+                // We've already looked for this file, use cached result
+                return getSourceFileFromCache(fileName, canonicalName, /*useAbsolutePath*/ false);
+            }
+            else {
+                let normalizedAbsolutePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
+                let canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
+                if (hasProperty(filesByName, canonicalAbsolutePath)) {
+                    return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, /*useAbsolutePath*/ true);
+                }
+
+                // We haven't looked for this file, do so now and cache result
+                let file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, hostErrorMessage => {
+                    if (refFile) {
+                        diagnostics.add(createFileDiagnostic(refFile, refStart, refLength,
+                            Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
+                    }
+                    else {
+                        diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
+                    }
+                });
+                if (file) {
+                    seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
+
+                    // Set the source file for normalized absolute path
+                    filesByName[canonicalAbsolutePath] = file;
+
+                    if (!options.noResolve) {
+                        let basePath = getDirectoryPath(fileName);
+                        processReferencedFiles(file, basePath);
+                        processImportedModules(file, basePath);
+                    }
+                    if (isDefaultLib) {
+                        files.unshift(file);
+                    }
+                    else {
+                        files.push(file);
+                    }
+                }
+
+                return file;
+            }
+
+            function getSourceFileFromCache(fileName: string, canonicalName: string, useAbsolutePath: boolean): SourceFile {
+                let file = filesByName[canonicalName];
+                if (file && host.useCaseSensitiveFileNames()) {
+                    let sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
+                    if (canonicalName !== sourceFileName) {
+                        diagnostics.add(createFileDiagnostic(refFile, refStart, refLength,
+                            Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, sourceFileName));
+                    }
+                }
+                return file;
+            }
+        }
+
+        function processReferencedFiles(file: SourceFile, basePath: string) {
+            forEach(file.referencedFiles, ref => {
+                let referencedFileName = isRootedDiskPath(ref.fileName) ? ref.fileName : combinePaths(basePath, ref.fileName);
+                processSourceFile(normalizePath(referencedFileName), /* isDefaultLib */ false, file, ref.pos, ref.end);
+            });
+        }
+
+        function processImportedModules(file: SourceFile, basePath: string) {
+            forEach(file.statements, node => {
+                if (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration || node.kind === SyntaxKind.ExportDeclaration) {
+                    let moduleNameExpr = getExternalModuleName(node);
+                    if (moduleNameExpr && moduleNameExpr.kind === SyntaxKind.StringLiteral) {
+                        let moduleNameText = (<LiteralExpression>moduleNameExpr).text;
+                        if (moduleNameText) {
+                            let searchPath = basePath;
+                            while (true) {
+                                let searchName = normalizePath(combinePaths(searchPath, moduleNameText));
+                                if (findModuleSourceFile(searchName + ".ts", moduleNameExpr) || findModuleSourceFile(searchName + ".d.ts", moduleNameExpr)) {
+                                    break;
+                                }
+                                let parentPath = getDirectoryPath(searchPath);
+                                if (parentPath === searchPath) {
+                                    break;
+                                }
+                                searchPath = parentPath;
+                            }
+                        }
+                    }
+                }
+                else if (node.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || isDeclarationFile(file))) {
+                    // TypeScript 1.0 spec (April 2014): 12.1.6
+                    // An AmbientExternalModuleDeclaration declares an external module. 
+                    // This type of declaration is permitted only in the global module.
+                    // The StringLiteral must specify a top - level external module name.
+                    // Relative external module names are not permitted
+                    forEachChild((<ModuleDeclaration>node).body, node => {
+                        if (isExternalModuleImportEqualsDeclaration(node) &&
+                            getExternalModuleImportEqualsDeclarationExpression(node).kind === SyntaxKind.StringLiteral) {
+
+                            let nameLiteral = <LiteralExpression>getExternalModuleImportEqualsDeclarationExpression(node);
+                            let moduleName = nameLiteral.text;
+                            if (moduleName) {
+                                // TypeScript 1.0 spec (April 2014): 12.1.6
+                                // An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules 
+                                // only through top - level external module names. Relative external module names are not permitted.
+                                let searchName = normalizePath(combinePaths(basePath, moduleName));
+                                let tsFile = findModuleSourceFile(searchName + ".ts", nameLiteral);
+                                if (!tsFile) {
+                                    findModuleSourceFile(searchName + ".d.ts", nameLiteral);
+                                }
+                            }
+                        }
+                    });
+                }
+            });
+
+            function findModuleSourceFile(fileName: string, nameLiteral: Expression) {
+                return findSourceFile(fileName, /* isDefaultLib */ false, file, nameLiteral.pos, nameLiteral.end - nameLiteral.pos);
+            }
+        }
+
+        function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string {
+            let commonPathComponents: string[];
+            let currentDirectory = host.getCurrentDirectory();
+            forEach(files, sourceFile => {
+                // Each file contributes into common source file path
+                if (isDeclarationFile(sourceFile)) {
+                    return;
+                }
+
+                let sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, currentDirectory);
+                sourcePathComponents.pop(); // The base file name is not part of the common directory path
+
+                if (!commonPathComponents) {
+                    // first file
+                    commonPathComponents = sourcePathComponents;
+                    return;
+                }
+
+                for (let i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) {
+                    if (commonPathComponents[i] !== sourcePathComponents[i]) {
+                        if (i === 0) {
+                            diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
+                            return;
+                        }
+
+                        // New common path found that is 0 -> i-1
+                        commonPathComponents.length = i;
+                        break;
+                    }
+                }
+
+                // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents
+                if (sourcePathComponents.length < commonPathComponents.length) {
+                    commonPathComponents.length = sourcePathComponents.length;
+                }
+            });
+
+            return getNormalizedPathFromPathComponents(commonPathComponents);
+        }
+
+        function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean {
+            let allFilesBelongToPath = true;
+            if (sourceFiles) {
+                let currentDirectory = host.getCurrentDirectory();
+                let absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));
+
+                for (var sourceFile of sourceFiles) {
+                    if (!isDeclarationFile(sourceFile)) {
+                        let absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
+                        if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) {
+                            diagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir));
+                            allFilesBelongToPath = false;
+                        }
+                    }
+                }
+            }
+
+            return allFilesBelongToPath;
+        }
+
+        function verifyCompilerOptions() {
+            if (options.separateCompilation) {
+                if (options.sourceMap) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_sourceMap_cannot_be_specified_with_option_separateCompilation));
+                }
+
+                if (options.declaration) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_declaration_cannot_be_specified_with_option_separateCompilation));
+                }
+
+                if (options.noEmitOnError) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_noEmitOnError_cannot_be_specified_with_option_separateCompilation));
+                }
+
+                if (options.out) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_out_cannot_be_specified_with_option_separateCompilation));
+                }
+            }
+
+            if (!options.sourceMap && (options.mapRoot || options.sourceRoot)) {
+                // Error to specify --mapRoot or --sourceRoot without mapSourceFiles
+                if (options.mapRoot) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_mapRoot_cannot_be_specified_without_specifying_sourcemap_option));
+                }
+                if (options.sourceRoot) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_sourceRoot_cannot_be_specified_without_specifying_sourcemap_option));
+                }
+                return;
+            }
+
+            let languageVersion = options.target || ScriptTarget.ES3;
+
+            let firstExternalModuleSourceFile = forEach(files, f => isExternalModule(f) ? f : undefined);
+            if (options.separateCompilation) {
+                if (!options.module && languageVersion < ScriptTarget.ES6) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_separateCompilation_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_or_higher));
+                }
+
+                let firstNonExternalModuleSourceFile = forEach(files, f => !isExternalModule(f) && !isDeclarationFile(f) ? f : undefined);
+                if (firstNonExternalModuleSourceFile) {
+                    let span = getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile);
+                    diagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided));
+                }
+            }
+            else if (firstExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && !options.module) {
+                // We cannot use createDiagnosticFromNode because nodes do not have parents yet 
+                let span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
+                diagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
+            }
+
+            // Cannot specify module gen target when in es6 or above
+            if (options.module && languageVersion >= ScriptTarget.ES6) {
+                diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_compile_external_modules_into_amd_commonjs_or_umd_when_targeting_ES6_or_higher));
+            }
+
+            // there has to be common source directory if user specified --outdir || --sourceRoot
+            // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted
+            if (options.outDir || // there is --outDir specified
+                options.sourceRoot || // there is --sourceRoot specified
+                (options.mapRoot &&  // there is --mapRoot specified and there would be multiple js files generated
+                    (!options.out || firstExternalModuleSourceFile !== undefined))) {
+
+                if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) {
+                    // If a rootDir is specified and is valid use it as the commonSourceDirectory
+                    commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory());
+                }
+                else {
+                    // Compute the commonSourceDirectory from the input files
+                    commonSourceDirectory = computeCommonSourceDirectory(files);
+                }
+
+                if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) {
+                    // Make sure directory path ends with directory separator so this string can directly 
+                    // used to replace with "" to get the relative path of the source file and the relative path doesn't
+                    // start with / making it rooted path
+                    commonSourceDirectory += directorySeparator;
+                }
+            }
+
+            if (options.noEmit) {
+                if (options.out || options.outDir) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_out_or_outDir));
+                }
+
+                if (options.declaration) {
+                    diagnostics.add(createCompilerDiagnostic(Diagnostics.Option_noEmit_cannot_be_specified_with_option_declaration));
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/compiler/scanner.ts b/lib/typescript/compiler/scanner.ts
new file mode 100644
index 000000000..f7a51cd8e
--- /dev/null
+++ b/lib/typescript/compiler/scanner.ts
@@ -0,0 +1,1505 @@
+/// <reference path="core.ts"/>
+/// <reference path="diagnosticInformationMap.generated.ts"/>
+
+module ts {
+    /* @internal */ 
+    export interface ErrorCallback {
+        (message: DiagnosticMessage, length: number): void;
+    }
+
+    /* @internal */ 
+    export interface Scanner {
+        getStartPos(): number;
+        getToken(): SyntaxKind;
+        getTextPos(): number;
+        getTokenPos(): number;
+        getTokenText(): string;
+        getTokenValue(): string;
+        hasExtendedUnicodeEscape(): boolean;
+        hasPrecedingLineBreak(): boolean;
+        isIdentifier(): boolean;
+        isReservedWord(): boolean;
+        isUnterminated(): boolean;
+        reScanGreaterToken(): SyntaxKind;
+        reScanSlashToken(): SyntaxKind;
+        reScanTemplateToken(): SyntaxKind;
+        scan(): SyntaxKind;
+        // Sets the text for the scanner to scan.  An optional subrange starting point and length
+        // can be provided to have the scanner only scan a portion of the text.
+        setText(text: string, start?: number, length?: number): void;
+        setOnError(onError: ErrorCallback): void;
+        setScriptTarget(scriptTarget: ScriptTarget): void;
+        setTextPos(textPos: number): void;
+        // Invokes the provided callback then unconditionally restores the scanner to the state it 
+        // was in immediately prior to invoking the callback.  The result of invoking the callback
+        // is returned from this function.
+        lookAhead<T>(callback: () => T): T;
+
+        // Invokes the provided callback.  If the callback returns something falsy, then it restores
+        // the scanner to the state it was in immediately prior to invoking the callback.  If the 
+        // callback returns something truthy, then the scanner state is not rolled back.  The result
+        // of invoking the callback is returned from this function.
+        tryScan<T>(callback: () => T): T;
+    }
+
+    let textToToken: Map<SyntaxKind> = {
+        "any": SyntaxKind.AnyKeyword,
+        "as": SyntaxKind.AsKeyword,
+        "boolean": SyntaxKind.BooleanKeyword,
+        "break": SyntaxKind.BreakKeyword,
+        "case": SyntaxKind.CaseKeyword,
+        "catch": SyntaxKind.CatchKeyword,
+        "class": SyntaxKind.ClassKeyword,
+        "continue": SyntaxKind.ContinueKeyword,
+        "const": SyntaxKind.ConstKeyword,
+        "constructor": SyntaxKind.ConstructorKeyword,
+        "debugger": SyntaxKind.DebuggerKeyword,
+        "declare": SyntaxKind.DeclareKeyword,
+        "default": SyntaxKind.DefaultKeyword,
+        "delete": SyntaxKind.DeleteKeyword,
+        "do": SyntaxKind.DoKeyword,
+        "else": SyntaxKind.ElseKeyword,
+        "enum": SyntaxKind.EnumKeyword,
+        "export": SyntaxKind.ExportKeyword,
+        "extends": SyntaxKind.ExtendsKeyword,
+        "false": SyntaxKind.FalseKeyword,
+        "finally": SyntaxKind.FinallyKeyword,
+        "for": SyntaxKind.ForKeyword,
+        "from": SyntaxKind.FromKeyword,
+        "function": SyntaxKind.FunctionKeyword,
+        "get": SyntaxKind.GetKeyword,
+        "if": SyntaxKind.IfKeyword,
+        "implements": SyntaxKind.ImplementsKeyword,
+        "import": SyntaxKind.ImportKeyword,
+        "in": SyntaxKind.InKeyword,
+        "instanceof": SyntaxKind.InstanceOfKeyword,
+        "interface": SyntaxKind.InterfaceKeyword,
+        "let": SyntaxKind.LetKeyword,
+        "module": SyntaxKind.ModuleKeyword,
+        "new": SyntaxKind.NewKeyword,
+        "null": SyntaxKind.NullKeyword,
+        "number": SyntaxKind.NumberKeyword,
+        "package": SyntaxKind.PackageKeyword,
+        "private": SyntaxKind.PrivateKeyword,
+        "protected": SyntaxKind.ProtectedKeyword,
+        "public": SyntaxKind.PublicKeyword,
+        "require": SyntaxKind.RequireKeyword,
+        "return": SyntaxKind.ReturnKeyword,
+        "set": SyntaxKind.SetKeyword,
+        "static": SyntaxKind.StaticKeyword,
+        "string": SyntaxKind.StringKeyword,
+        "super": SyntaxKind.SuperKeyword,
+        "switch": SyntaxKind.SwitchKeyword,
+        "symbol": SyntaxKind.SymbolKeyword,
+        "this": SyntaxKind.ThisKeyword,
+        "throw": SyntaxKind.ThrowKeyword,
+        "true": SyntaxKind.TrueKeyword,
+        "try": SyntaxKind.TryKeyword,
+        "type": SyntaxKind.TypeKeyword,
+        "typeof": SyntaxKind.TypeOfKeyword,
+        "var": SyntaxKind.VarKeyword,
+        "void": SyntaxKind.VoidKeyword,
+        "while": SyntaxKind.WhileKeyword,
+        "with": SyntaxKind.WithKeyword,
+        "yield": SyntaxKind.YieldKeyword,
+        "of": SyntaxKind.OfKeyword,
+        "{": SyntaxKind.OpenBraceToken,
+        "}": SyntaxKind.CloseBraceToken,
+        "(": SyntaxKind.OpenParenToken,
+        ")": SyntaxKind.CloseParenToken,
+        "[": SyntaxKind.OpenBracketToken,
+        "]": SyntaxKind.CloseBracketToken,
+        ".": SyntaxKind.DotToken,
+        "...": SyntaxKind.DotDotDotToken,
+        ";": SyntaxKind.SemicolonToken,
+        ",": SyntaxKind.CommaToken,
+        "<": SyntaxKind.LessThanToken,
+        ">": SyntaxKind.GreaterThanToken,
+        "<=": SyntaxKind.LessThanEqualsToken,
+        ">=": SyntaxKind.GreaterThanEqualsToken,
+        "==": SyntaxKind.EqualsEqualsToken,
+        "!=": SyntaxKind.ExclamationEqualsToken,
+        "===": SyntaxKind.EqualsEqualsEqualsToken,
+        "!==": SyntaxKind.ExclamationEqualsEqualsToken,
+        "=>": SyntaxKind.EqualsGreaterThanToken,
+        "+": SyntaxKind.PlusToken,
+        "-": SyntaxKind.MinusToken,
+        "*": SyntaxKind.AsteriskToken,
+        "/": SyntaxKind.SlashToken,
+        "%": SyntaxKind.PercentToken,
+        "++": SyntaxKind.PlusPlusToken,
+        "--": SyntaxKind.MinusMinusToken,
+        "<<": SyntaxKind.LessThanLessThanToken,
+        ">>": SyntaxKind.GreaterThanGreaterThanToken,
+        ">>>": SyntaxKind.GreaterThanGreaterThanGreaterThanToken,
+        "&": SyntaxKind.AmpersandToken,
+        "|": SyntaxKind.BarToken,
+        "^": SyntaxKind.CaretToken,
+        "!": SyntaxKind.ExclamationToken,
+        "~": SyntaxKind.TildeToken,
+        "&&": SyntaxKind.AmpersandAmpersandToken,
+        "||": SyntaxKind.BarBarToken,
+        "?": SyntaxKind.QuestionToken,
+        ":": SyntaxKind.ColonToken,
+        "=": SyntaxKind.EqualsToken,
+        "+=": SyntaxKind.PlusEqualsToken,
+        "-=": SyntaxKind.MinusEqualsToken,
+        "*=": SyntaxKind.AsteriskEqualsToken,
+        "/=": SyntaxKind.SlashEqualsToken,
+        "%=": SyntaxKind.PercentEqualsToken,
+        "<<=": SyntaxKind.LessThanLessThanEqualsToken,
+        ">>=": SyntaxKind.GreaterThanGreaterThanEqualsToken,
+        ">>>=": SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
+        "&=": SyntaxKind.AmpersandEqualsToken,
+        "|=": SyntaxKind.BarEqualsToken,
+        "^=": SyntaxKind.CaretEqualsToken,
+        "@": SyntaxKind.AtToken,
+    };
+
+    /*
+        As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
+        IdentifierStart ::
+            Can contain Unicode 3.0.0  categories:
+            Uppercase letter (Lu),
+            Lowercase letter (Ll),
+            Titlecase letter (Lt),
+            Modifier letter (Lm),
+            Other letter (Lo), or
+            Letter number (Nl).
+        IdentifierPart :: =
+            Can contain IdentifierStart + Unicode 3.0.0  categories:
+            Non-spacing mark (Mn),
+            Combining spacing mark (Mc),
+            Decimal number (Nd), or
+            Connector punctuation (Pc).
+
+        Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at:
+        http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt
+    */
+    let unicodeES3IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
+    let unicodeES3IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
+
+    /*
+        As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers
+        IdentifierStart ::
+            Can contain Unicode 6.2  categories:
+            Uppercase letter (Lu),
+            Lowercase letter (Ll),
+            Titlecase letter (Lt),
+            Modifier letter (Lm),
+            Other letter (Lo), or
+            Letter number (Nl).
+        IdentifierPart ::
+            Can contain IdentifierStart + Unicode 6.2  categories:
+            Non-spacing mark (Mn),
+            Combining spacing mark (Mc),
+            Decimal number (Nd),
+            Connector punctuation (Pc),
+            <ZWNJ>, or
+            <ZWJ>.
+
+        Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at:
+        http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt
+    */
+    let unicodeES5IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
+    let unicodeES5IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, ];
+
+    function lookupInUnicodeMap(code: number, map: number[]): boolean {
+        // Bail out quickly if it couldn't possibly be in the map.
+        if (code < map[0]) {
+            return false;
+        }
+
+        // Perform binary search in one of the Unicode range maps
+        let lo: number = 0;
+        let hi: number = map.length;
+        let mid: number;
+
+        while (lo + 1 < hi) {
+            mid = lo + (hi - lo) / 2;
+            // mid has to be even to catch a range's beginning
+            mid -= mid % 2;
+            if (map[mid] <= code && code <= map[mid + 1]) {
+                return true;
+            }
+
+            if (code < map[mid]) {
+                hi = mid;
+            }
+            else {
+                lo = mid + 2;
+            }
+        }
+
+        return false;
+    }
+
+    /* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget) {
+        return languageVersion >= ScriptTarget.ES5 ?
+            lookupInUnicodeMap(code, unicodeES5IdentifierStart) :
+            lookupInUnicodeMap(code, unicodeES3IdentifierStart);
+    }
+
+    function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget) {
+        return languageVersion >= ScriptTarget.ES5 ?
+            lookupInUnicodeMap(code, unicodeES5IdentifierPart) :
+            lookupInUnicodeMap(code, unicodeES3IdentifierPart);
+    }
+
+    function makeReverseMap(source: Map<number>): string[] {
+        let result: string[] = [];
+        for (let name in source) {
+            if (source.hasOwnProperty(name)) {
+                result[source[name]] = name;
+            }
+        }
+        return result;
+    }
+
+    let tokenStrings = makeReverseMap(textToToken);
+
+    export function tokenToString(t: SyntaxKind): string {
+        return tokenStrings[t];
+    }
+
+    /* @internal */
+    export function stringToToken(s: string): SyntaxKind {
+        return textToToken[s];
+    }
+
+    /* @internal */ 
+    export function computeLineStarts(text: string): number[] {
+        let result: number[] = new Array();
+        let pos = 0;
+        let lineStart = 0;
+        while (pos < text.length) {
+           let ch = text.charCodeAt(pos++);
+           switch (ch) {
+                case CharacterCodes.carriageReturn:
+                    if (text.charCodeAt(pos) === CharacterCodes.lineFeed) {
+                        pos++;
+                    }
+                case CharacterCodes.lineFeed:
+                    result.push(lineStart);
+                    lineStart = pos;
+                    break;
+                default:
+                    if (ch > CharacterCodes.maxAsciiCharacter && isLineBreak(ch)) {
+                        result.push(lineStart);
+                        lineStart = pos;
+                    }
+                    break;
+            }
+        }
+        result.push(lineStart);
+        return result;
+    }
+
+    export function getPositionOfLineAndCharacter(sourceFile: SourceFile, line: number, character: number): number {
+        return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character);
+    }
+
+    /* @internal */ 
+    export function computePositionOfLineAndCharacter(lineStarts: number[], line: number, character: number): number {
+        Debug.assert(line >= 0 && line < lineStarts.length);
+        return lineStarts[line] + character;
+    }
+
+    /* @internal */ 
+    export function getLineStarts(sourceFile: SourceFile): number[] {
+        return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
+    }
+
+    /* @internal */ 
+    export function computeLineAndCharacterOfPosition(lineStarts: number[], position: number) {
+        let lineNumber = binarySearch(lineStarts, position);
+        if (lineNumber < 0) {
+            // If the actual position was not found, 
+            // the binary search returns the negative value of the next line start
+            // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20
+            // then the search will return -2
+            lineNumber = ~lineNumber - 1;
+        }
+        return {
+            line: lineNumber,
+            character: position - lineStarts[lineNumber]
+        };
+    }
+
+    export function getLineAndCharacterOfPosition(sourceFile: SourceFile, position: number): LineAndCharacter {
+        return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
+    }
+
+    let hasOwnProperty = Object.prototype.hasOwnProperty;
+
+    export function isWhiteSpace(ch: number): boolean {
+        // Note: nextLine is in the Zs space, and should be considered to be a whitespace.
+        // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript.
+        return ch === CharacterCodes.space ||
+            ch === CharacterCodes.tab ||
+            ch === CharacterCodes.verticalTab ||
+            ch === CharacterCodes.formFeed ||
+            ch === CharacterCodes.nonBreakingSpace ||
+            ch === CharacterCodes.nextLine ||
+            ch === CharacterCodes.ogham ||
+            ch >= CharacterCodes.enQuad && ch <= CharacterCodes.zeroWidthSpace ||
+            ch === CharacterCodes.narrowNoBreakSpace ||
+            ch === CharacterCodes.mathematicalSpace ||
+            ch === CharacterCodes.ideographicSpace ||
+            ch === CharacterCodes.byteOrderMark;
+    }
+
+    export function isLineBreak(ch: number): boolean {
+        // ES5 7.3:
+        // The ECMAScript line terminator characters are listed in Table 3.
+        //     Table 3: Line Terminator Characters
+        //     Code Unit Value     Name                    Formal Name
+        //     \u000A              Line Feed               <LF>
+        //     \u000D              Carriage Return         <CR>
+        //     \u2028              Line separator          <LS>
+        //     \u2029              Paragraph separator     <PS>
+        // Only the characters in Table 3 are treated as line terminators. Other new line or line 
+        // breaking characters are treated as white space but not as line terminators. 
+
+        return ch === CharacterCodes.lineFeed ||
+            ch === CharacterCodes.carriageReturn ||
+            ch === CharacterCodes.lineSeparator ||
+            ch === CharacterCodes.paragraphSeparator;
+    }
+
+    function isDigit(ch: number): boolean {
+        return ch >= CharacterCodes._0 && ch <= CharacterCodes._9;
+    }
+
+    /* @internal */ 
+    export function isOctalDigit(ch: number): boolean {
+        return ch >= CharacterCodes._0 && ch <= CharacterCodes._7;
+    }
+
+    /* @internal */ 
+    export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
+        while (true) {
+            let ch = text.charCodeAt(pos);
+            switch (ch) {
+                case CharacterCodes.carriageReturn:
+                    if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
+                        pos++;
+                    }
+                case CharacterCodes.lineFeed:
+                    pos++;
+                    if (stopAfterLineBreak) {
+                        return pos;
+                    }
+                    continue;
+                case CharacterCodes.tab:
+                case CharacterCodes.verticalTab:
+                case CharacterCodes.formFeed:
+                case CharacterCodes.space:
+                    pos++;
+                    continue;
+                case CharacterCodes.slash:
+                    if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
+                        pos += 2;
+                        while (pos < text.length) {
+                            if (isLineBreak(text.charCodeAt(pos))) {
+                                break;
+                            }
+                            pos++;
+                        }
+                        continue;
+                    }
+                    if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
+                        pos += 2;
+                        while (pos < text.length) {
+                            if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
+                                pos += 2;
+                                break;
+                            }
+                            pos++;
+                        }
+                        continue;
+                    }
+                    break;
+
+                case CharacterCodes.lessThan:
+                case CharacterCodes.equals:
+                case CharacterCodes.greaterThan:
+                    if (isConflictMarkerTrivia(text, pos)) {
+                        pos = scanConflictMarkerTrivia(text, pos);
+                        continue;
+                    }
+                    break;
+
+                default:
+                    if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) {
+                        pos++;
+                        continue;
+                    }
+                    break;
+            }
+            return pos;
+        }
+    }
+
+    // All conflict markers consist of the same character repeated seven times.  If it is 
+    // a <<<<<<< or >>>>>>> marker then it is also followd by a space.
+    let mergeConflictMarkerLength = "<<<<<<<".length;
+
+    function isConflictMarkerTrivia(text: string, pos: number) {
+        Debug.assert(pos >= 0);
+
+        // Conflict markers must be at the start of a line.
+        if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) {
+            let ch = text.charCodeAt(pos);
+
+            if ((pos + mergeConflictMarkerLength) < text.length) {
+                for (let i = 0, n = mergeConflictMarkerLength; i < n; i++) {
+                    if (text.charCodeAt(pos + i) !== ch) {
+                        return false;
+                    }
+                }
+
+                return ch === CharacterCodes.equals ||
+                    text.charCodeAt(pos + mergeConflictMarkerLength) === CharacterCodes.space;
+            }
+        }
+
+        return false;
+    }
+
+    function scanConflictMarkerTrivia(text: string, pos: number, error?: ErrorCallback) {
+        if (error) {
+            error(Diagnostics.Merge_conflict_marker_encountered, mergeConflictMarkerLength);
+        }
+
+        let ch = text.charCodeAt(pos);
+        let len = text.length;
+
+        if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
+            while (pos < len && !isLineBreak(text.charCodeAt(pos))) {
+                pos++;
+            }
+        }
+        else {
+            Debug.assert(ch === CharacterCodes.equals);
+            // Consume everything from the start of the mid-conlict marker to the start of the next
+            // end-conflict marker.
+            while (pos < len) {
+                let ch = text.charCodeAt(pos);
+                if (ch === CharacterCodes.greaterThan && isConflictMarkerTrivia(text, pos)) {
+                    break;
+                }
+
+                pos++;
+            }
+        }
+
+        return pos;
+    }
+
+    // Extract comments from the given source text starting at the given position. If trailing is 
+    // false, whitespace is skipped until the first line break and comments between that location 
+    // and the next token are returned.If trailing is true, comments occurring between the given 
+    // position and the next line break are returned.The return value is an array containing a 
+    // TextRange for each comment. Single-line comment ranges include the beginning '//' characters 
+    // but not the ending line break. Multi - line comment ranges include the beginning '/* and 
+    // ending '*/' characters.The return value is undefined if no comments were found.
+    function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] {
+        let result: CommentRange[];
+        let collecting = trailing || pos === 0;
+        while (true) {
+            let ch = text.charCodeAt(pos);
+            switch (ch) {
+                case CharacterCodes.carriageReturn:
+                    if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
+                        pos++;
+                    }
+                case CharacterCodes.lineFeed:
+                    pos++;
+                    if (trailing) {
+                        return result;
+                    }
+                    collecting = true;
+                    if (result && result.length) {
+                        result[result.length - 1].hasTrailingNewLine = true;
+                    }
+                    continue;
+                case CharacterCodes.tab:
+                case CharacterCodes.verticalTab:
+                case CharacterCodes.formFeed:
+                case CharacterCodes.space:
+                    pos++;
+                    continue;
+                case CharacterCodes.slash:
+                    let nextChar = text.charCodeAt(pos + 1);
+                    let hasTrailingNewLine = false;
+                    if (nextChar === CharacterCodes.slash || nextChar === CharacterCodes.asterisk) {
+                        let kind = nextChar === CharacterCodes.slash ? SyntaxKind.SingleLineCommentTrivia : SyntaxKind.MultiLineCommentTrivia;
+                        let startPos = pos;
+                        pos += 2;
+                        if (nextChar === CharacterCodes.slash) {
+                            while (pos < text.length) {
+                                if (isLineBreak(text.charCodeAt(pos))) {
+                                    hasTrailingNewLine = true;
+                                    break;
+                                }
+                                pos++;
+                            }
+                        }
+                        else {
+                            while (pos < text.length) {
+                                if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
+                                    pos += 2;
+                                    break;
+                                }
+                                pos++;
+                            }
+                        }
+                        if (collecting) {
+                            if (!result) {
+                                result = [];
+                            }
+
+                            result.push({ pos: startPos, end: pos, hasTrailingNewLine, kind });
+                        }
+                        continue;
+                    }
+                    break;
+                default:
+                    if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) {
+                        if (result && result.length && isLineBreak(ch)) {
+                            result[result.length - 1].hasTrailingNewLine = true;
+                        }
+                        pos++;
+                        continue;
+                    }
+                    break;
+            }
+            return result;
+        }
+    }
+
+    export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] {
+        return getCommentRanges(text, pos, /*trailing*/ false);
+    }
+
+    export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] {
+        return getCommentRanges(text, pos, /*trailing*/ true);
+    }
+
+    export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean {
+        return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
+            ch === CharacterCodes.$ || ch === CharacterCodes._ ||
+            ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion);
+    }
+
+    export function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean {
+        return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
+            ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ ||
+            ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
+    }
+
+    // Creates a scanner over a (possibly unspecified) range of a piece of text.
+    /* @internal */ 
+    export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, text?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner {
+        let pos: number;       // Current position (end position of text of current token)
+        let end: number;       // end of text
+        let startPos: number;  // Start position of whitespace before current token
+        let tokenPos: number;  // Start position of text of current token
+        let token: SyntaxKind;
+        let tokenValue: string;
+        let precedingLineBreak: boolean;
+        let hasExtendedUnicodeEscape: boolean;
+        let tokenIsUnterminated: boolean;
+
+        setText(text, start, length);
+
+        return {
+            getStartPos: () => startPos,
+            getTextPos: () => pos,
+            getToken: () => token,
+            getTokenPos: () => tokenPos,
+            getTokenText: () => text.substring(tokenPos, pos),
+            getTokenValue: () => tokenValue,
+            hasExtendedUnicodeEscape: () => hasExtendedUnicodeEscape,
+            hasPrecedingLineBreak: () => precedingLineBreak,
+            isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord,
+            isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
+            isUnterminated: () => tokenIsUnterminated,
+            reScanGreaterToken,
+            reScanSlashToken,
+            reScanTemplateToken,
+            scan,
+            setText,
+            setScriptTarget,
+            setOnError,
+            setTextPos,
+            tryScan,
+            lookAhead,
+        };
+
+        function error(message: DiagnosticMessage, length?: number): void {
+            if (onError) {
+                onError(message, length || 0);
+            }
+        }
+
+        function isIdentifierStart(ch: number): boolean {
+            return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
+                ch === CharacterCodes.$ || ch === CharacterCodes._ ||
+                ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion);
+        }
+
+        function isIdentifierPart(ch: number): boolean {
+            return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
+                ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ ||
+                ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
+        }
+
+        function scanNumber(): number {
+            let start = pos;
+            while (isDigit(text.charCodeAt(pos))) pos++;
+            if (text.charCodeAt(pos) === CharacterCodes.dot) {
+                pos++;
+                while (isDigit(text.charCodeAt(pos))) pos++;
+            }
+            let end = pos;
+            if (text.charCodeAt(pos) === CharacterCodes.E || text.charCodeAt(pos) === CharacterCodes.e) {
+                pos++;
+                if (text.charCodeAt(pos) === CharacterCodes.plus || text.charCodeAt(pos) === CharacterCodes.minus) pos++;
+                if (isDigit(text.charCodeAt(pos))) {
+                    pos++;
+                    while (isDigit(text.charCodeAt(pos))) pos++;
+                    end = pos;
+                }
+                else {
+                    error(Diagnostics.Digit_expected);
+                }
+            }
+            return +(text.substring(start, end));
+        }
+
+        function scanOctalDigits(): number {
+            let start = pos;
+            while (isOctalDigit(text.charCodeAt(pos))) {
+                pos++;
+            }
+            return +(text.substring(start, pos));
+        }
+        
+        /**
+         * Scans the given number of hexadecimal digits in the text,
+         * returning -1 if the given number is unavailable.
+         */
+        function scanExactNumberOfHexDigits(count: number): number {
+            return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false);
+        }
+        
+        /**
+         * Scans as many hexadecimal digits as are available in the text,
+         * returning -1 if the given number of digits was unavailable.
+         */
+        function scanMinimumNumberOfHexDigits(count: number): number {
+            return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ true);
+        }
+
+        function scanHexDigits(minCount: number, scanAsManyAsPossible: boolean): number {
+            let digits = 0;
+            let value = 0;
+            while (digits < minCount || scanAsManyAsPossible) {
+                let ch = text.charCodeAt(pos);
+                if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) {
+                    value = value * 16 + ch - CharacterCodes._0;
+                }
+                else if (ch >= CharacterCodes.A && ch <= CharacterCodes.F) {
+                    value = value * 16 + ch - CharacterCodes.A + 10;
+                }
+                else if (ch >= CharacterCodes.a && ch <= CharacterCodes.f) {
+                    value = value * 16 + ch - CharacterCodes.a + 10;
+                }
+                else {
+                    break;
+                }
+                pos++;
+                digits++;
+            }
+            if (digits < minCount) {
+                value = -1;
+            }
+            return value;
+        }
+
+        function scanString(): string {
+            let quote = text.charCodeAt(pos++);
+            let result = "";
+            let start = pos;
+            while (true) {
+                if (pos >= end) {
+                    result += text.substring(start, pos);
+                    tokenIsUnterminated = true;
+                    error(Diagnostics.Unterminated_string_literal);
+                    break;
+                }
+                let ch = text.charCodeAt(pos);
+                if (ch === quote) {
+                    result += text.substring(start, pos);
+                    pos++;
+                    break;
+                }
+                if (ch === CharacterCodes.backslash) {
+                    result += text.substring(start, pos);
+                    result += scanEscapeSequence();
+                    start = pos;
+                    continue;
+                }
+                if (isLineBreak(ch)) {
+                    result += text.substring(start, pos);
+                    tokenIsUnterminated = true;
+                    error(Diagnostics.Unterminated_string_literal);
+                    break;
+                }
+                pos++;
+            }
+            return result;
+        }
+
+        /**
+         * Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or
+         * a literal component of a TemplateExpression.
+         */
+        function scanTemplateAndSetTokenValue(): SyntaxKind {
+            let startedWithBacktick = text.charCodeAt(pos) === CharacterCodes.backtick;
+
+            pos++;
+            let start = pos;
+            let contents = ""
+            let resultingToken: SyntaxKind;
+
+            while (true) {
+                if (pos >= end) {
+                    contents += text.substring(start, pos);
+                    tokenIsUnterminated = true;
+                    error(Diagnostics.Unterminated_template_literal);
+                    resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
+                    break;
+                }
+
+                let currChar = text.charCodeAt(pos);
+
+                // '`'
+                if (currChar === CharacterCodes.backtick) {
+                    contents += text.substring(start, pos);
+                    pos++;
+                    resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
+                    break;
+                }
+
+                // '${'
+                if (currChar === CharacterCodes.$ && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) {
+                    contents += text.substring(start, pos);
+                    pos += 2;
+                    resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle;
+                    break;
+                }
+
+                // Escape character
+                if (currChar === CharacterCodes.backslash) {
+                    contents += text.substring(start, pos);
+                    contents += scanEscapeSequence();
+                    start = pos;
+                    continue;
+                }
+
+                // Speculated ECMAScript 6 Spec 11.8.6.1:
+                // <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for Template Values
+                if (currChar === CharacterCodes.carriageReturn) {
+                    contents += text.substring(start, pos);
+                    pos++;
+
+                    if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) {
+                        pos++;
+                    }
+
+                    contents += "\n";
+                    start = pos;
+                    continue;
+                }
+
+                pos++;
+            }
+
+            Debug.assert(resultingToken !== undefined);
+
+            tokenValue = contents;
+            return resultingToken;
+        }
+
+        function scanEscapeSequence(): string {
+            pos++;
+            if (pos >= end) {
+                error(Diagnostics.Unexpected_end_of_text);
+                return "";
+            }
+            let ch = text.charCodeAt(pos++);
+            switch (ch) {
+                case CharacterCodes._0:
+                    return "\0";
+                case CharacterCodes.b:
+                    return "\b";
+                case CharacterCodes.t:
+                    return "\t";
+                case CharacterCodes.n:
+                    return "\n";
+                case CharacterCodes.v:
+                    return "\v";
+                case CharacterCodes.f:
+                    return "\f";
+                case CharacterCodes.r:
+                    return "\r";
+                case CharacterCodes.singleQuote:
+                    return "\'";
+                case CharacterCodes.doubleQuote:
+                    return "\"";
+                case CharacterCodes.u:
+                    // '\u{DDDDDDDD}'
+                    if (pos < end && text.charCodeAt(pos) === CharacterCodes.openBrace) {
+                        hasExtendedUnicodeEscape = true;
+                        pos++;
+                        return scanExtendedUnicodeEscape();
+                    }
+                    
+                    // '\uDDDD'
+                    return scanHexadecimalEscape(/*numDigits*/ 4)
+                    
+                case CharacterCodes.x:
+                    // '\xDD'
+                    return scanHexadecimalEscape(/*numDigits*/ 2)
+
+                // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence),
+                // the line terminator is interpreted to be "the empty code unit sequence".
+                case CharacterCodes.carriageReturn:
+                    if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) {
+                        pos++;
+                    }
+                    // fall through
+                case CharacterCodes.lineFeed:
+                case CharacterCodes.lineSeparator:
+                case CharacterCodes.paragraphSeparator:
+                    return ""
+                default:
+                    return String.fromCharCode(ch);
+            }
+        }
+        
+        function scanHexadecimalEscape(numDigits: number): string {
+            let escapedValue = scanExactNumberOfHexDigits(numDigits);
+            
+            if (escapedValue >= 0) {
+                return String.fromCharCode(escapedValue);
+            }
+            else {
+                error(Diagnostics.Hexadecimal_digit_expected);
+                return ""
+            }
+        }
+        
+        function scanExtendedUnicodeEscape(): string {
+            let escapedValue = scanMinimumNumberOfHexDigits(1);
+            let isInvalidExtendedEscape = false;
+
+            // Validate the value of the digit
+            if (escapedValue < 0) {
+                error(Diagnostics.Hexadecimal_digit_expected)
+                isInvalidExtendedEscape = true;
+            }
+            else if (escapedValue > 0x10FFFF) {
+                error(Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive);
+                isInvalidExtendedEscape = true;
+            }
+
+            if (pos >= end) {
+                error(Diagnostics.Unexpected_end_of_text);
+                isInvalidExtendedEscape = true;
+            }
+            else if (text.charCodeAt(pos) == CharacterCodes.closeBrace) {
+                // Only swallow the following character up if it's a '}'.
+                pos++;
+            }
+            else {
+                error(Diagnostics.Unterminated_Unicode_escape_sequence);
+                isInvalidExtendedEscape = true;
+            }
+
+            if (isInvalidExtendedEscape) {
+                return "";
+            }
+
+            return utf16EncodeAsString(escapedValue);
+        }
+        
+        // Derived from the 10.1.1 UTF16Encoding of the ES6 Spec.
+        function utf16EncodeAsString(codePoint: number): string {
+            Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF);
+            
+            if (codePoint <= 65535) {
+                return String.fromCharCode(codePoint);
+            }
+            
+            let codeUnit1 = Math.floor((codePoint - 65536) / 1024) + 0xD800;
+            let codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00;
+            
+            return String.fromCharCode(codeUnit1, codeUnit2);
+        }
+
+        // Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX'
+        // and return code point value if valid Unicode escape is found. Otherwise return -1.
+        function peekUnicodeEscape(): number {
+            if (pos + 5 < end && text.charCodeAt(pos + 1) === CharacterCodes.u) {
+                let start = pos;
+                pos += 2;
+                let value = scanExactNumberOfHexDigits(4);
+                pos = start;
+                return value;
+            }
+            return -1;
+        }
+
+        function scanIdentifierParts(): string {
+            let result = "";
+            let start = pos;
+            while (pos < end) {
+                let ch = text.charCodeAt(pos);
+                if (isIdentifierPart(ch)) {
+                    pos++;
+                }
+                else if (ch === CharacterCodes.backslash) {
+                    ch = peekUnicodeEscape();
+                    if (!(ch >= 0 && isIdentifierPart(ch))) {
+                        break;
+                    }
+                    result += text.substring(start, pos);
+                    result += String.fromCharCode(ch);
+                    // Valid Unicode escape is always six characters
+                    pos += 6;
+                    start = pos;
+                }
+                else {
+                    break;
+                }
+            }
+            result += text.substring(start, pos);
+            return result;
+        }
+
+        function getIdentifierToken(): SyntaxKind {
+            // Reserved words are between 2 and 11 characters long and start with a lowercase letter
+            let len = tokenValue.length;
+            if (len >= 2 && len <= 11) {
+                let ch = tokenValue.charCodeAt(0);
+                if (ch >= CharacterCodes.a && ch <= CharacterCodes.z && hasOwnProperty.call(textToToken, tokenValue)) {
+                    return token = textToToken[tokenValue];
+                }
+            }
+            return token = SyntaxKind.Identifier;
+        }
+
+        function scanBinaryOrOctalDigits(base: number): number {
+            Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8");
+
+            let value = 0;
+            // For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b.
+            // Similarly valid octalIntegerLiteral must have at least one octal digit following o or O.
+            let numberOfDigits = 0;  
+            while (true) {
+                let ch = text.charCodeAt(pos);
+                let valueOfCh = ch - CharacterCodes._0;
+                if (!isDigit(ch) || valueOfCh >= base) {
+                    break;
+                }
+                value = value * base + valueOfCh;
+                pos++;
+                numberOfDigits++;
+            }
+            // Invalid binaryIntegerLiteral or octalIntegerLiteral
+            if (numberOfDigits === 0) {
+                return -1;
+            }
+            return value;
+        }
+
+        function scan(): SyntaxKind {
+            startPos = pos;
+            hasExtendedUnicodeEscape = false;
+            precedingLineBreak = false;
+            tokenIsUnterminated = false;
+            while (true) {
+                tokenPos = pos;
+                if (pos >= end) {
+                    return token = SyntaxKind.EndOfFileToken;
+                }
+                let ch = text.charCodeAt(pos);
+                switch (ch) {
+                    case CharacterCodes.lineFeed:
+                    case CharacterCodes.carriageReturn:
+                        precedingLineBreak = true;
+                        if (skipTrivia) {
+                            pos++;
+                            continue;
+                        }
+                        else {
+                            if (ch === CharacterCodes.carriageReturn && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
+                                // consume both CR and LF
+                                pos += 2;
+                            }
+                            else {
+                                pos++;
+                            }
+                            return token = SyntaxKind.NewLineTrivia;
+                        }
+                    case CharacterCodes.tab:
+                    case CharacterCodes.verticalTab:
+                    case CharacterCodes.formFeed:
+                    case CharacterCodes.space:
+                        if (skipTrivia) {
+                            pos++;
+                            continue;
+                        }
+                        else {
+                            while (pos < end && isWhiteSpace(text.charCodeAt(pos))) {
+                                pos++;
+                            }
+                            return token = SyntaxKind.WhitespaceTrivia;
+                        }
+                    case CharacterCodes.exclamation:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
+                                return pos += 3, token = SyntaxKind.ExclamationEqualsEqualsToken;
+                            }
+                            return pos += 2, token = SyntaxKind.ExclamationEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.ExclamationToken;
+                    case CharacterCodes.doubleQuote:
+                    case CharacterCodes.singleQuote:
+                        tokenValue = scanString();
+                        return token = SyntaxKind.StringLiteral;
+                    case CharacterCodes.backtick:
+                        return token = scanTemplateAndSetTokenValue()
+                    case CharacterCodes.percent:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.PercentEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.PercentToken;
+                    case CharacterCodes.ampersand:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.ampersand) {
+                            return pos += 2, token = SyntaxKind.AmpersandAmpersandToken;
+                        }
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.AmpersandEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.AmpersandToken;
+                    case CharacterCodes.openParen:
+                        return pos++, token = SyntaxKind.OpenParenToken;
+                    case CharacterCodes.closeParen:
+                        return pos++, token = SyntaxKind.CloseParenToken;
+                    case CharacterCodes.asterisk:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.AsteriskEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.AsteriskToken;
+                    case CharacterCodes.plus:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.plus) {
+                            return pos += 2, token = SyntaxKind.PlusPlusToken;
+                        }
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.PlusEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.PlusToken;
+                    case CharacterCodes.comma:
+                        return pos++, token = SyntaxKind.CommaToken;
+                    case CharacterCodes.minus:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.minus) {
+                            return pos += 2, token = SyntaxKind.MinusMinusToken;
+                        }
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.MinusEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.MinusToken;
+                    case CharacterCodes.dot:
+                        if (isDigit(text.charCodeAt(pos + 1))) {
+                            tokenValue = "" + scanNumber();
+                            return token = SyntaxKind.NumericLiteral;
+                        }
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) {
+                            return pos += 3, token = SyntaxKind.DotDotDotToken;
+                        }
+                        return pos++, token = SyntaxKind.DotToken;
+                    case CharacterCodes.slash:
+                        // Single-line comment
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
+                            pos += 2;
+
+                            while (pos < end) {
+                                if (isLineBreak(text.charCodeAt(pos))) {
+                                    break;
+                                }
+                                pos++;
+
+                            }
+
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = SyntaxKind.SingleLineCommentTrivia;
+                            }
+                        }
+                        // Multi-line comment
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) {
+                            pos += 2;
+
+                            let commentClosed = false;
+                            while (pos < end) {
+                                let ch = text.charCodeAt(pos);
+
+                                if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) {
+                                    pos += 2;
+                                    commentClosed = true;
+                                    break;
+                                }
+
+                                if (isLineBreak(ch)) {
+                                    precedingLineBreak = true;
+                                }
+                                pos++;
+                            }
+
+                            if (!commentClosed) {
+                                error(Diagnostics.Asterisk_Slash_expected);
+                            }
+
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                tokenIsUnterminated = !commentClosed;
+                                return token = SyntaxKind.MultiLineCommentTrivia;
+                            }
+                        }
+
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.SlashEqualsToken;
+                        }
+
+                        return pos++, token = SyntaxKind.SlashToken;
+
+                    case CharacterCodes._0:
+                        if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) {
+                            pos += 2;
+                            let value = scanMinimumNumberOfHexDigits(1);
+                            if (value < 0) {
+                                error(Diagnostics.Hexadecimal_digit_expected);
+                                value = 0;
+                            }
+                            tokenValue = "" + value;
+                            return token = SyntaxKind.NumericLiteral;
+                        }
+                        else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) {
+                            pos += 2;
+                            let value = scanBinaryOrOctalDigits(/* base */ 2);
+                            if (value < 0) {
+                                error(Diagnostics.Binary_digit_expected);
+                                value = 0;
+                            }
+                            tokenValue = "" + value;
+                            return token = SyntaxKind.NumericLiteral;
+                        }
+                        else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) {
+                            pos += 2;
+                            let value = scanBinaryOrOctalDigits(/* base */ 8);
+                            if (value < 0) {
+                                error(Diagnostics.Octal_digit_expected);
+                                value = 0;
+                            }
+                            tokenValue = "" + value;
+                            return token = SyntaxKind.NumericLiteral;
+                        }
+                        // Try to parse as an octal
+                        if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) {
+                            tokenValue = "" + scanOctalDigits();
+                            return token = SyntaxKind.NumericLiteral;
+                        }
+                        // This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero
+                        // can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being
+                        // permissive and allowing decimal digits of the form 08* and 09* (which many browsers also do).
+                    case CharacterCodes._1:
+                    case CharacterCodes._2:
+                    case CharacterCodes._3:
+                    case CharacterCodes._4:
+                    case CharacterCodes._5:
+                    case CharacterCodes._6:
+                    case CharacterCodes._7:
+                    case CharacterCodes._8:
+                    case CharacterCodes._9:
+                        tokenValue = "" + scanNumber();
+                        return token = SyntaxKind.NumericLiteral;
+                    case CharacterCodes.colon:
+                        return pos++, token = SyntaxKind.ColonToken;
+                    case CharacterCodes.semicolon:
+                        return pos++, token = SyntaxKind.SemicolonToken;
+                    case CharacterCodes.lessThan:
+                        if (isConflictMarkerTrivia(text, pos)) {
+                            pos = scanConflictMarkerTrivia(text, pos, error);
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = SyntaxKind.ConflictMarkerTrivia;
+                            }
+                        }
+
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.lessThan) {
+                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
+                                return pos += 3, token = SyntaxKind.LessThanLessThanEqualsToken;
+                            }
+                            return pos += 2, token = SyntaxKind.LessThanLessThanToken;
+                        }
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.LessThanEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.LessThanToken;
+                    case CharacterCodes.equals:
+                        if (isConflictMarkerTrivia(text, pos)) {
+                            pos = scanConflictMarkerTrivia(text, pos, error);
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = SyntaxKind.ConflictMarkerTrivia;
+                            }
+                        }
+
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
+                                return pos += 3, token = SyntaxKind.EqualsEqualsEqualsToken;
+                            }
+                            return pos += 2, token = SyntaxKind.EqualsEqualsToken;
+                        }
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
+                            return pos += 2, token = SyntaxKind.EqualsGreaterThanToken;
+                        }
+                        return pos++, token = SyntaxKind.EqualsToken;
+                    case CharacterCodes.greaterThan:
+                        if (isConflictMarkerTrivia(text, pos)) {
+                            pos = scanConflictMarkerTrivia(text, pos, error);
+                            if (skipTrivia) {
+                                continue;
+                            }
+                            else {
+                                return token = SyntaxKind.ConflictMarkerTrivia;
+                            }
+                        }
+
+                        return pos++, token = SyntaxKind.GreaterThanToken;
+                    case CharacterCodes.question:
+                        return pos++, token = SyntaxKind.QuestionToken;
+                    case CharacterCodes.openBracket:
+                        return pos++, token = SyntaxKind.OpenBracketToken;
+                    case CharacterCodes.closeBracket:
+                        return pos++, token = SyntaxKind.CloseBracketToken;
+                    case CharacterCodes.caret:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.CaretEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.CaretToken;
+                    case CharacterCodes.openBrace:
+                        return pos++, token = SyntaxKind.OpenBraceToken;
+                    case CharacterCodes.bar:
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.bar) {
+                            return pos += 2, token = SyntaxKind.BarBarToken;
+                        }
+                        if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                            return pos += 2, token = SyntaxKind.BarEqualsToken;
+                        }
+                        return pos++, token = SyntaxKind.BarToken;
+                    case CharacterCodes.closeBrace:
+                        return pos++, token = SyntaxKind.CloseBraceToken;
+                    case CharacterCodes.tilde:
+                        return pos++, token = SyntaxKind.TildeToken;
+                    case CharacterCodes.at:
+                        return pos++, token = SyntaxKind.AtToken;
+                    case CharacterCodes.backslash:
+                        let cookedChar = peekUnicodeEscape();
+                        if (cookedChar >= 0 && isIdentifierStart(cookedChar)) {
+                            pos += 6;
+                            tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts();
+                            return token = getIdentifierToken();
+                        }
+                        error(Diagnostics.Invalid_character);
+                        return pos++, token = SyntaxKind.Unknown;
+                    default:
+                        if (isIdentifierStart(ch)) {
+                            pos++;
+                            while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos))) pos++;
+                            tokenValue = text.substring(tokenPos, pos);
+                            if (ch === CharacterCodes.backslash) {
+                                tokenValue += scanIdentifierParts();
+                            }
+                            return token = getIdentifierToken();
+                        }
+                        else if (isWhiteSpace(ch)) {
+                            pos++;
+                            continue;
+                        }
+                        else if (isLineBreak(ch)) {
+                            precedingLineBreak = true;
+                            pos++;
+                            continue;
+                        }
+                        error(Diagnostics.Invalid_character);
+                        return pos++, token = SyntaxKind.Unknown;
+                }
+            }
+        }
+
+        function reScanGreaterToken(): SyntaxKind {
+            if (token === SyntaxKind.GreaterThanToken) {
+                if (text.charCodeAt(pos) === CharacterCodes.greaterThan) {
+                    if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
+                        if (text.charCodeAt(pos + 2) === CharacterCodes.equals) {
+                            return pos += 3, token = SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken;
+                        }
+                        return pos += 2, token = SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
+                    }
+                    if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
+                        return pos += 2, token = SyntaxKind.GreaterThanGreaterThanEqualsToken;
+                    }
+                    return pos++, token = SyntaxKind.GreaterThanGreaterThanToken;
+                }
+                if (text.charCodeAt(pos) === CharacterCodes.equals) {
+                    return pos++, token = SyntaxKind.GreaterThanEqualsToken;
+                }
+            }
+            return token;
+        }
+
+        function reScanSlashToken(): SyntaxKind {
+            if (token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) {
+                let p = tokenPos + 1;
+                let inEscape = false;
+                let inCharacterClass = false;
+                while (true) {
+                    // If we reach the end of a file, or hit a newline, then this is an unterminated
+                    // regex.  Report error and return what we have so far.
+                    if (p >= end) {
+                        tokenIsUnterminated = true;
+                        error(Diagnostics.Unterminated_regular_expression_literal)
+                        break;
+                    }
+
+                    let ch = text.charCodeAt(p);
+                    if (isLineBreak(ch)) {
+                        tokenIsUnterminated = true;
+                        error(Diagnostics.Unterminated_regular_expression_literal)
+                        break;
+                    }
+
+                    if (inEscape) {
+                        // Parsing an escape character;
+                        // reset the flag and just advance to the next char.
+                        inEscape = false;
+                    }
+                    else if (ch === CharacterCodes.slash && !inCharacterClass) {
+                        // A slash within a character class is permissible,
+                        // but in general it signals the end of the regexp literal.
+                        p++;
+                        break;
+                    }
+                    else if (ch === CharacterCodes.openBracket) {
+                        inCharacterClass = true;
+                    }
+                    else if (ch === CharacterCodes.backslash) {
+                        inEscape = true;
+                    }
+                    else if (ch === CharacterCodes.closeBracket) {
+                        inCharacterClass = false;
+                    }
+                    p++;
+                }
+
+                while (p < end && isIdentifierPart(text.charCodeAt(p))) {
+                    p++;
+                }
+                pos = p;
+                tokenValue = text.substring(tokenPos, pos);
+                token = SyntaxKind.RegularExpressionLiteral;
+            }
+            return token;
+        }
+
+        /**
+         * Unconditionally back up and scan a template expression portion.
+         */
+        function reScanTemplateToken(): SyntaxKind {
+            Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'");
+            pos = tokenPos;
+            return token = scanTemplateAndSetTokenValue();
+        }
+
+        function speculationHelper<T>(callback: () => T, isLookahead: boolean): T {
+            let savePos = pos;
+            let saveStartPos = startPos;
+            let saveTokenPos = tokenPos;
+            let saveToken = token;
+            let saveTokenValue = tokenValue;
+            let savePrecedingLineBreak = precedingLineBreak;
+            let result = callback();
+
+            // If our callback returned something 'falsy' or we're just looking ahead,
+            // then unconditionally restore us to where we were.
+            if (!result || isLookahead) {
+                pos = savePos;
+                startPos = saveStartPos;
+                tokenPos = saveTokenPos;
+                token = saveToken;
+                tokenValue = saveTokenValue;
+                precedingLineBreak = savePrecedingLineBreak;
+            }
+            return result;
+        }
+
+        function lookAhead<T>(callback: () => T): T {
+            return speculationHelper(callback, /*isLookahead:*/ true);
+        }
+
+        function tryScan<T>(callback: () => T): T {
+            return speculationHelper(callback, /*isLookahead:*/ false);
+        }
+
+        function setText(newText: string, start: number, length: number) {
+            text = newText || "";
+            end = length === undefined ? text.length : start + length;
+            setTextPos(start || 0);
+        }
+
+        function setOnError(errorCallback: ErrorCallback) {
+            onError = errorCallback;
+        }
+
+        function setScriptTarget(scriptTarget: ScriptTarget) {
+            languageVersion = scriptTarget;
+        }
+
+        function setTextPos(textPos: number) {
+            Debug.assert(textPos >= 0);
+            pos = textPos;
+            startPos = textPos;
+            tokenPos = textPos;
+            token = SyntaxKind.Unknown;
+            precedingLineBreak = false;
+
+            tokenValue = undefined;
+            hasExtendedUnicodeEscape = false;
+            tokenIsUnterminated = false;
+        }
+    }
+}
diff --git a/lib/typescript/compiler/sys.ts b/lib/typescript/compiler/sys.ts
new file mode 100644
index 000000000..92c26bf01
--- /dev/null
+++ b/lib/typescript/compiler/sys.ts
@@ -0,0 +1,318 @@
+/// <reference path="core.ts"/>
+
+module ts {
+    export interface System {
+        args: string[];
+        newLine: string;
+        useCaseSensitiveFileNames: boolean;
+        write(s: string): void;
+        readFile(path: string, encoding?: string): string;
+        writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
+        watchFile?(path: string, callback: (path: string) => void): FileWatcher;
+        resolvePath(path: string): string;
+        fileExists(path: string): boolean;
+        directoryExists(path: string): boolean;
+        createDirectory(path: string): void;
+        getExecutingFilePath(): string;
+        getCurrentDirectory(): string;
+        readDirectory(path: string, extension?: string): string[];
+        getMemoryUsage?(): number;
+        exit(exitCode?: number): void;
+    }
+
+    export interface FileWatcher {
+        close(): void;
+    }
+
+    declare var require: any;
+    declare var module: any;
+    declare var process: any;
+    declare var global: any;
+    declare var __filename: string;
+
+    declare class Enumerator {
+        public atEnd(): boolean;
+        public moveNext(): boolean;
+        public item(): any;
+        constructor(o: any);
+    }
+
+    export var sys: System = (function () {
+
+        function getWScriptSystem(): System {
+
+            var fso = new ActiveXObject("Scripting.FileSystemObject");
+
+            var fileStream = new ActiveXObject("ADODB.Stream");
+            fileStream.Type = 2 /*text*/;
+
+            var binaryStream = new ActiveXObject("ADODB.Stream");
+            binaryStream.Type = 1 /*binary*/;
+
+            var args: string[] = [];
+            for (var i = 0; i < WScript.Arguments.length; i++) {
+                args[i] = WScript.Arguments.Item(i);
+            }
+
+            function readFile(fileName: string, encoding?: string): string {
+                if (!fso.FileExists(fileName)) {
+                    return undefined;
+                }
+                fileStream.Open();
+                try {
+                    if (encoding) {
+                        fileStream.Charset = encoding;
+                        fileStream.LoadFromFile(fileName);
+                    }
+                    else {
+                        // Load file and read the first two bytes into a string with no interpretation
+                        fileStream.Charset = "x-ansi";
+                        fileStream.LoadFromFile(fileName);
+                        var bom = fileStream.ReadText(2) || "";
+                        // Position must be at 0 before encoding can be changed
+                        fileStream.Position = 0;
+                        // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
+                        fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
+                    }
+                    // ReadText method always strips byte order mark from resulting string
+                    return fileStream.ReadText();
+                }
+                catch (e) {
+                    throw e;
+                }
+                finally {
+                    fileStream.Close();
+                }
+            }
+
+            function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
+                fileStream.Open();
+                binaryStream.Open();
+                try {
+                    // Write characters in UTF-8 encoding
+                    fileStream.Charset = "utf-8";
+                    fileStream.WriteText(data);
+                    // If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM).
+                    // If not, start from position 0, as the BOM will be added automatically when charset==utf8.
+                    if (writeByteOrderMark) {
+                        fileStream.Position = 0;
+                    }
+                    else {
+                        fileStream.Position = 3;
+                    }
+                    fileStream.CopyTo(binaryStream);
+                    binaryStream.SaveToFile(fileName, 2 /*overwrite*/);
+                }
+                finally {
+                    binaryStream.Close();
+                    fileStream.Close();
+                }
+            }
+
+            function getNames(collection: any): string[] {
+                var result: string[] = [];
+                for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
+                    result.push(e.item().Name);
+                }
+                return result.sort();
+            }
+
+            function readDirectory(path: string, extension?: string): string[] {
+                var result: string[] = [];
+                visitDirectory(path);
+                return result;
+                function visitDirectory(path: string) {
+                    var folder = fso.GetFolder(path || ".");
+                    var files = getNames(folder.files);
+                    for (let name of files) {
+                        if (!extension || fileExtensionIs(name, extension)) {
+                            result.push(combinePaths(path, name));
+                        }
+                    }
+                    var subfolders = getNames(folder.subfolders);
+                    for (let current of subfolders) {
+                        visitDirectory(combinePaths(path, current));
+                    }
+                }
+            }
+
+            return {
+                args,
+                newLine: "\r\n",
+                useCaseSensitiveFileNames: false,
+                write(s: string): void {
+                    WScript.StdOut.Write(s);
+                },
+                readFile,
+                writeFile,
+                resolvePath(path: string): string {
+                    return fso.GetAbsolutePathName(path);
+                },
+                fileExists(path: string): boolean {
+                    return fso.FileExists(path);
+                },
+                directoryExists(path: string) {
+                    return fso.FolderExists(path);
+                },
+                createDirectory(directoryName: string) {
+                    if (!this.directoryExists(directoryName)) {
+                        fso.CreateFolder(directoryName);
+                    }
+                },
+                getExecutingFilePath() {
+                    return WScript.ScriptFullName;
+                },
+                getCurrentDirectory() {
+                    return new ActiveXObject("WScript.Shell").CurrentDirectory;
+                },
+                readDirectory,
+                exit(exitCode?: number): void {
+                    try {
+                        WScript.Quit(exitCode);
+                    }
+                    catch (e) {
+                    }
+                }
+            };
+        }
+        function getNodeSystem(): System {
+            var _fs = require("fs");
+            var _path = require("path");
+            var _os = require('os');
+
+            var platform: string = _os.platform();
+            // win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive
+            var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin";
+
+            function readFile(fileName: string, encoding?: string): string {
+                if (!_fs.existsSync(fileName)) {
+                    return undefined;
+                }
+                var buffer = _fs.readFileSync(fileName);
+                var len = buffer.length;
+                if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
+                    // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
+                    // flip all byte pairs and treat as little endian.
+                    len &= ~1;
+                    for (var i = 0; i < len; i += 2) {
+                        var temp = buffer[i];
+                        buffer[i] = buffer[i + 1];
+                        buffer[i + 1] = temp;
+                    }
+                    return buffer.toString("utf16le", 2);
+                }
+                if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
+                    // Little endian UTF-16 byte order mark detected
+                    return buffer.toString("utf16le", 2);
+                }
+                if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
+                    // UTF-8 byte order mark detected
+                    return buffer.toString("utf8", 3);
+                }
+                // Default is UTF-8 with no byte order mark
+                return buffer.toString("utf8");
+            }
+
+            function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
+                // If a BOM is required, emit one
+                if (writeByteOrderMark) {
+                    data = '\uFEFF' + data;
+                }
+
+                _fs.writeFileSync(fileName, data, "utf8");
+            }
+
+            function readDirectory(path: string, extension?: string): string[] {
+                var result: string[] = [];
+                visitDirectory(path);
+                return result;
+                function visitDirectory(path: string) {
+                    var files = _fs.readdirSync(path || ".").sort();
+                    var directories: string[] = [];
+                    for (let current of files) {
+                        var name = combinePaths(path, current);
+                        var stat = _fs.lstatSync(name);
+                        if (stat.isFile()) {
+                            if (!extension || fileExtensionIs(name, extension)) {
+                                result.push(name);
+                            }
+                        }
+                        else if (stat.isDirectory()) {
+                            directories.push(name);
+                        }
+                    }
+                    for (let current of directories) {
+                        visitDirectory(current);
+                    }
+                }
+            }
+
+            return {
+                args: process.argv.slice(2),
+                newLine: _os.EOL,
+                useCaseSensitiveFileNames: useCaseSensitiveFileNames,
+                write(s: string): void {
+                    // 1 is a standard descriptor for stdout
+                    _fs.writeSync(1, s);
+                },
+                readFile,
+                writeFile,
+                watchFile: (fileName, callback) => {
+                    // watchFile polls a file every 250ms, picking up file notifications.
+                    _fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged);
+
+                    return {
+                        close() { _fs.unwatchFile(fileName, fileChanged); }
+                    };
+
+                    function fileChanged(curr: any, prev: any) {
+                        if (+curr.mtime <= +prev.mtime) {
+                            return;
+                        }
+
+                        callback(fileName);
+                    };
+                },
+                resolvePath: function (path: string): string {
+                    return _path.resolve(path);
+                },
+                fileExists(path: string): boolean {
+                    return _fs.existsSync(path);
+                },
+                directoryExists(path: string) {
+                    return _fs.existsSync(path) && _fs.statSync(path).isDirectory();
+                },
+                createDirectory(directoryName: string) {
+                    if (!this.directoryExists(directoryName)) {
+                        _fs.mkdirSync(directoryName);
+                    }
+                },
+                getExecutingFilePath() {
+                    return __filename;
+                },
+                getCurrentDirectory() {
+                    return process.cwd();
+                },
+                readDirectory,
+                getMemoryUsage() {
+                    if (global.gc) {
+                        global.gc();
+                    }
+                    return process.memoryUsage().heapUsed;
+                },
+                exit(exitCode?: number): void {
+                    process.exit(exitCode);
+                }
+            };
+        }
+        if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
+            return getWScriptSystem();
+        }
+        else if (typeof module !== "undefined" && module.exports) {
+            return getNodeSystem();
+        }
+        else {
+            return undefined; // Unsupported host
+        }
+    })();
+}
\ No newline at end of file
diff --git a/lib/typescript/compiler/types.ts b/lib/typescript/compiler/types.ts
new file mode 100644
index 000000000..09c389b31
--- /dev/null
+++ b/lib/typescript/compiler/types.ts
@@ -0,0 +1,1898 @@
+module ts {
+    export interface Map<T> {
+        [index: string]: T;
+    }
+
+    export interface TextRange {
+        pos: number;
+        end: number;
+    }
+
+    // token > SyntaxKind.Identifer => token is a keyword
+    export const enum SyntaxKind {
+        Unknown,
+        EndOfFileToken,
+        SingleLineCommentTrivia,
+        MultiLineCommentTrivia,
+        NewLineTrivia,
+        WhitespaceTrivia,
+        // We detect and provide better error recovery when we encounter a git merge marker.  This
+        // allows us to edit files with git-conflict markers in them in a much more pleasant manner.
+        ConflictMarkerTrivia,
+        // Literals
+        NumericLiteral,
+        StringLiteral,
+        RegularExpressionLiteral,
+        NoSubstitutionTemplateLiteral,
+        // Pseudo-literals
+        TemplateHead,
+        TemplateMiddle,
+        TemplateTail,
+        // Punctuation
+        OpenBraceToken,
+        CloseBraceToken,
+        OpenParenToken,
+        CloseParenToken,
+        OpenBracketToken,
+        CloseBracketToken,
+        DotToken,
+        DotDotDotToken,
+        SemicolonToken,
+        CommaToken,
+        LessThanToken,
+        GreaterThanToken,
+        LessThanEqualsToken,
+        GreaterThanEqualsToken,
+        EqualsEqualsToken,
+        ExclamationEqualsToken,
+        EqualsEqualsEqualsToken,
+        ExclamationEqualsEqualsToken,
+        EqualsGreaterThanToken,
+        PlusToken,
+        MinusToken,
+        AsteriskToken,
+        SlashToken,
+        PercentToken,
+        PlusPlusToken,
+        MinusMinusToken,
+        LessThanLessThanToken,
+        GreaterThanGreaterThanToken,
+        GreaterThanGreaterThanGreaterThanToken,
+        AmpersandToken,
+        BarToken,
+        CaretToken,
+        ExclamationToken,
+        TildeToken,
+        AmpersandAmpersandToken,
+        BarBarToken,
+        QuestionToken,
+        ColonToken,
+        AtToken,
+        // Assignments
+        EqualsToken,
+        PlusEqualsToken,
+        MinusEqualsToken,
+        AsteriskEqualsToken,
+        SlashEqualsToken,
+        PercentEqualsToken,
+        LessThanLessThanEqualsToken,
+        GreaterThanGreaterThanEqualsToken,
+        GreaterThanGreaterThanGreaterThanEqualsToken,
+        AmpersandEqualsToken,
+        BarEqualsToken,
+        CaretEqualsToken,
+        // Identifiers
+        Identifier,
+        // Reserved words
+        BreakKeyword,
+        CaseKeyword,
+        CatchKeyword,
+        ClassKeyword,
+        ConstKeyword,
+        ContinueKeyword,
+        DebuggerKeyword,
+        DefaultKeyword,
+        DeleteKeyword,
+        DoKeyword,
+        ElseKeyword,
+        EnumKeyword,
+        ExportKeyword,
+        ExtendsKeyword,
+        FalseKeyword,
+        FinallyKeyword,
+        ForKeyword,
+        FunctionKeyword,
+        IfKeyword,
+        ImportKeyword,
+        InKeyword,
+        InstanceOfKeyword,
+        NewKeyword,
+        NullKeyword,
+        ReturnKeyword,
+        SuperKeyword,
+        SwitchKeyword,
+        ThisKeyword,
+        ThrowKeyword,
+        TrueKeyword,
+        TryKeyword,
+        TypeOfKeyword,
+        VarKeyword,
+        VoidKeyword,
+        WhileKeyword,
+        WithKeyword,
+        // Strict mode reserved words
+        ImplementsKeyword,
+        InterfaceKeyword,
+        LetKeyword,
+        PackageKeyword,
+        PrivateKeyword,
+        ProtectedKeyword,
+        PublicKeyword,
+        StaticKeyword,
+        YieldKeyword,
+        // Contextual keywords
+        AsKeyword,
+        AnyKeyword,
+        BooleanKeyword,
+        ConstructorKeyword,
+        DeclareKeyword,
+        GetKeyword,
+        ModuleKeyword,
+        RequireKeyword,
+        NumberKeyword,
+        SetKeyword,
+        StringKeyword,
+        SymbolKeyword,
+        TypeKeyword,
+        FromKeyword,
+        OfKeyword, // LastKeyword and LastToken
+
+        // Parse tree nodes
+
+        // Names
+        QualifiedName,
+        ComputedPropertyName,
+        // Signature elements
+        TypeParameter,
+        Parameter,
+        Decorator,
+        // TypeMember
+        PropertySignature,
+        PropertyDeclaration,
+        MethodSignature,
+        MethodDeclaration,
+        Constructor,
+        GetAccessor,
+        SetAccessor,
+        CallSignature,
+        ConstructSignature,
+        IndexSignature,
+        // Type
+        TypeReference,
+        FunctionType,
+        ConstructorType,
+        TypeQuery,
+        TypeLiteral,
+        ArrayType,
+        TupleType,
+        UnionType,
+        ParenthesizedType,
+        // Binding patterns
+        ObjectBindingPattern,
+        ArrayBindingPattern,
+        BindingElement,
+        // Expression
+        ArrayLiteralExpression,
+        ObjectLiteralExpression,
+        PropertyAccessExpression,
+        ElementAccessExpression,
+        CallExpression,
+        NewExpression,
+        TaggedTemplateExpression,
+        TypeAssertionExpression,
+        ParenthesizedExpression,
+        FunctionExpression,
+        ArrowFunction,
+        DeleteExpression,
+        TypeOfExpression,
+        VoidExpression,
+        PrefixUnaryExpression,
+        PostfixUnaryExpression,
+        BinaryExpression,
+        ConditionalExpression,
+        TemplateExpression,
+        YieldExpression,
+        SpreadElementExpression,
+        ClassExpression,
+        OmittedExpression,
+        // Misc
+        TemplateSpan,
+        HeritageClauseElement,
+        SemicolonClassElement,
+        // Element
+        Block,
+        VariableStatement,
+        EmptyStatement,
+        ExpressionStatement,
+        IfStatement,
+        DoStatement,
+        WhileStatement,
+        ForStatement,
+        ForInStatement,
+        ForOfStatement,
+        ContinueStatement,
+        BreakStatement,
+        ReturnStatement,
+        WithStatement,
+        SwitchStatement,
+        LabeledStatement,
+        ThrowStatement,
+        TryStatement,
+        DebuggerStatement,
+        VariableDeclaration,
+        VariableDeclarationList,
+        FunctionDeclaration,
+        ClassDeclaration,
+        InterfaceDeclaration,
+        TypeAliasDeclaration,
+        EnumDeclaration,
+        ModuleDeclaration,
+        ModuleBlock,
+        CaseBlock,
+        ImportEqualsDeclaration,
+        ImportDeclaration,
+        ImportClause,
+        NamespaceImport,
+        NamedImports,
+        ImportSpecifier,
+        ExportAssignment,
+        ExportDeclaration,
+        NamedExports,
+        ExportSpecifier,
+        MissingDeclaration,
+
+        // Module references
+        ExternalModuleReference,
+
+        // Clauses
+        CaseClause,
+        DefaultClause,
+        HeritageClause,
+        CatchClause,
+
+        // Property assignments
+        PropertyAssignment,
+        ShorthandPropertyAssignment,
+
+        // Enum
+        EnumMember,
+        // Top-level nodes
+        SourceFile,
+
+        // Synthesized list
+        SyntaxList,
+        // Enum value count
+        Count,
+        // Markers
+        FirstAssignment = EqualsToken,
+        LastAssignment = CaretEqualsToken,
+        FirstReservedWord = BreakKeyword,
+        LastReservedWord = WithKeyword,
+        FirstKeyword = BreakKeyword,
+        LastKeyword = OfKeyword,
+        FirstFutureReservedWord = ImplementsKeyword,
+        LastFutureReservedWord = YieldKeyword,
+        FirstTypeNode = TypeReference,
+        LastTypeNode = ParenthesizedType,
+        FirstPunctuation = OpenBraceToken,
+        LastPunctuation = CaretEqualsToken,
+        FirstToken = Unknown,
+        LastToken = LastKeyword,
+        FirstTriviaToken = SingleLineCommentTrivia,
+        LastTriviaToken = ConflictMarkerTrivia,
+        FirstLiteralToken = NumericLiteral,
+        LastLiteralToken = NoSubstitutionTemplateLiteral,
+        FirstTemplateToken = NoSubstitutionTemplateLiteral,
+        LastTemplateToken = TemplateTail,
+        FirstBinaryOperator = LessThanToken,
+        LastBinaryOperator = CaretEqualsToken,
+        FirstNode = QualifiedName,
+    }
+
+    export const enum NodeFlags {
+        Export =            0x00000001,  // Declarations
+        Ambient =           0x00000002,  // Declarations
+        Public =            0x00000010,  // Property/Method
+        Private =           0x00000020,  // Property/Method
+        Protected =         0x00000040,  // Property/Method
+        Static =            0x00000080,  // Property/Method
+        Default =           0x00000100,  // Function/Class (export default declaration)
+        MultiLine =         0x00000200,  // Multi-line array or object literal
+        Synthetic =         0x00000400,  // Synthetic node (for full fidelity)
+        DeclarationFile =   0x00000800,  // Node is a .d.ts file
+        Let =               0x00001000,  // Variable declaration
+        Const =             0x00002000,  // Variable declaration
+        OctalLiteral =      0x00004000,
+        ExportContext =     0x00008000,  // Export context (initialized by binding)
+
+        Modifier = Export | Ambient | Public | Private | Protected | Static | Default,
+        AccessibilityModifier = Public | Private | Protected,
+        BlockScoped = Let | Const
+    }
+
+    /* @internal */
+    export const enum ParserContextFlags {
+        // Set if this node was parsed in strict mode.  Used for grammar error checks, as well as
+        // checking if the node can be reused in incremental settings.
+        StrictMode = 1 << 0,
+
+        // If this node was parsed in a context where 'in-expressions' are not allowed.
+        DisallowIn = 1 << 1,
+
+        // If this node was parsed in the 'yield' context created when parsing a generator.
+        Yield = 1 << 2,
+
+        // If this node was parsed in the parameters of a generator.
+        GeneratorParameter = 1 << 3,
+
+        // If this node was parsed as part of a decorator
+        Decorator = 1 << 4,
+
+        // If the parser encountered an error when parsing the code that created this node.  Note
+        // the parser only sets this directly on the node it creates right after encountering the
+        // error.
+        ThisNodeHasError = 1 << 5,
+
+        // Context flags set directly by the parser.
+        ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError,
+
+        // Context flags computed by aggregating child flags upwards.
+
+        // Used during incremental parsing to determine if this node or any of its children had an
+        // error.  Computed only once and then cached.
+        ThisNodeOrAnySubNodesHasError = 1 << 6,
+
+        // Used to know if we've computed data from children and cached it in this node.
+        HasAggregatedChildData = 1 << 7
+    }
+
+    /* @internal */
+    export const enum RelationComparisonResult {
+        Succeeded = 1, // Should be truthy
+        Failed = 2,
+        FailedAndReported = 3
+    }
+
+    export interface Node extends TextRange {
+        kind: SyntaxKind;
+        flags: NodeFlags;
+        // Specific context the parser was in when this node was created.  Normally undefined.
+        // Only set when the parser was in some interesting context (like async/yield).
+        /* @internal */ parserContextFlags?: ParserContextFlags;
+        decorators?: NodeArray<Decorator>;    // Array of decorators (in document order)
+        modifiers?: ModifiersArray;           // Array of modifiers
+        /* @internal */ id?: number;          // Unique id (used to look up NodeLinks)
+        parent?: Node;                        // Parent node (initialized by binding)
+        /* @internal */ symbol?: Symbol;      // Symbol declared by node (initialized by binding)
+        /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
+        /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
+        /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
+    }
+
+    export interface NodeArray<T> extends Array<T>, TextRange {
+        hasTrailingComma?: boolean;
+    }
+
+    export interface ModifiersArray extends NodeArray<Node> {
+        flags: number;
+    }
+
+    export interface Identifier extends PrimaryExpression {
+        text: string;                                  // Text of identifier (with escapes converted to characters)
+        originalKeywordKind?: SyntaxKind;              // Original syntaxKind which get set so that we can report an error later
+    }
+
+    export interface QualifiedName extends Node {
+        // Must have same layout as PropertyAccess
+        left: EntityName;
+        right: Identifier;
+    }
+
+    export type EntityName = Identifier | QualifiedName;
+
+    export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern;
+
+    export interface Declaration extends Node {
+        _declarationBrand: any;
+        name?: DeclarationName;
+    }
+
+    export interface ComputedPropertyName extends Node {
+        expression: Expression;
+    }
+
+    export interface Decorator extends Node {
+        expression: LeftHandSideExpression;
+    }
+
+    export interface TypeParameterDeclaration extends Declaration {
+        name: Identifier;
+        constraint?: TypeNode;
+
+        // For error recovery purposes.
+        expression?: Expression;
+    }
+
+    export interface SignatureDeclaration extends Declaration {
+        typeParameters?: NodeArray<TypeParameterDeclaration>;
+        parameters: NodeArray<ParameterDeclaration>;
+        type?: TypeNode;
+    }
+
+    // SyntaxKind.VariableDeclaration
+    export interface VariableDeclaration extends Declaration {
+        parent?: VariableDeclarationList;
+        name: Identifier | BindingPattern;  // Declared variable name
+        type?: TypeNode;                    // Optional type annotation
+        initializer?: Expression;           // Optional initializer
+    }
+
+    export interface VariableDeclarationList extends Node {
+        declarations: NodeArray<VariableDeclaration>;
+    }
+
+    // SyntaxKind.Parameter
+    export interface ParameterDeclaration extends Declaration {
+        dotDotDotToken?: Node;              // Present on rest parameter
+        name: Identifier | BindingPattern;  // Declared parameter name
+        questionToken?: Node;               // Present on optional parameter
+        type?: TypeNode;                    // Optional type annotation
+        initializer?: Expression;           // Optional initializer
+    }
+
+    // SyntaxKind.BindingElement
+    export interface BindingElement extends Declaration {
+        propertyName?: Identifier;          // Binding property name (in object binding pattern)
+        dotDotDotToken?: Node;              // Present on rest binding element
+        name: Identifier | BindingPattern;  // Declared binding element name
+        initializer?: Expression;           // Optional initializer
+    }
+
+    // SyntaxKind.Property
+    export interface PropertyDeclaration extends Declaration, ClassElement {
+        name: DeclarationName;              // Declared property name
+        questionToken?: Node;               // Present on optional property
+        type?: TypeNode;                    // Optional type annotation
+        initializer?: Expression;           // Optional initializer
+    }
+
+    export interface ObjectLiteralElement extends Declaration {
+        _objectLiteralBrandBrand: any;
+    }
+
+    // SyntaxKind.PropertyAssignment
+    export interface PropertyAssignment extends ObjectLiteralElement {
+        _propertyAssignmentBrand: any;
+        name: DeclarationName;
+        questionToken?: Node;
+        initializer: Expression;
+    }
+
+    // SyntaxKind.ShorthandPropertyAssignment
+    export interface ShorthandPropertyAssignment extends ObjectLiteralElement {
+        name: Identifier;
+        questionToken?: Node;
+    }
+
+    // SyntaxKind.VariableDeclaration
+    // SyntaxKind.Parameter
+    // SyntaxKind.BindingElement
+    // SyntaxKind.Property
+    // SyntaxKind.PropertyAssignment
+    // SyntaxKind.ShorthandPropertyAssignment
+    // SyntaxKind.EnumMember
+    export interface VariableLikeDeclaration extends Declaration {
+        propertyName?: Identifier;
+        dotDotDotToken?: Node;
+        name: DeclarationName;
+        questionToken?: Node;
+        type?: TypeNode;
+        initializer?: Expression;
+    }
+
+    export interface BindingPattern extends Node {
+        elements: NodeArray<BindingElement>;
+    }
+
+    /**
+     * Several node kinds share function-like features such as a signature,
+     * a name, and a body. These nodes should extend FunctionLikeDeclaration.
+     * Examples:
+     *  FunctionDeclaration
+     *  MethodDeclaration
+     *  AccessorDeclaration
+     */
+    export interface FunctionLikeDeclaration extends SignatureDeclaration {
+        _functionLikeDeclarationBrand: any;
+
+        asteriskToken?: Node;
+        questionToken?: Node;
+        body?: Block | Expression;
+    }
+
+    export interface FunctionDeclaration extends FunctionLikeDeclaration, Statement {
+        name?: Identifier;
+        body?: Block;
+    }
+
+    // Note that a MethodDeclaration is considered both a ClassElement and an ObjectLiteralElement.
+    // Both the grammars for ClassDeclaration and ObjectLiteralExpression allow for MethodDeclarations
+    // as child elements, and so a MethodDeclaration satisfies both interfaces.  This avoids the
+    // alternative where we would need separate kinds/types for ClassMethodDeclaration and
+    // ObjectLiteralMethodDeclaration, which would look identical.
+    //
+    // Because of this, it may be necessary to determine what sort of MethodDeclaration you have
+    // at later stages of the compiler pipeline.  In that case, you can either check the parent kind
+    // of the method, or use helpers like isObjectLiteralMethodDeclaration
+    export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
+        body?: Block;
+    }
+
+    export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement {
+        body?: Block;
+    }
+
+    // For when we encounter a semicolon in a class declaration.  ES6 allows these as class elements.
+    export interface SemicolonClassElement extends ClassElement {
+        _semicolonClassElementBrand: any;
+    }
+
+    // See the comment on MethodDeclaration for the intuition behind AccessorDeclaration being a
+    // ClassElement and an ObjectLiteralElement.
+    export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement {
+        _accessorDeclarationBrand: any;
+        body: Block;
+    }
+
+    export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement {
+        _indexSignatureDeclarationBrand: any;
+    }
+
+    export interface TypeNode extends Node {
+        _typeNodeBrand: any;
+    }
+
+    export interface FunctionOrConstructorTypeNode extends TypeNode, SignatureDeclaration {
+        _functionOrConstructorTypeNodeBrand: any;
+    }
+
+    export interface TypeReferenceNode extends TypeNode {
+        typeName: EntityName;
+        typeArguments?: NodeArray<TypeNode>;
+    }
+
+    export interface TypeQueryNode extends TypeNode {
+        exprName: EntityName;
+    }
+
+    // A TypeLiteral is the declaration node for an anonymous symbol.
+    export interface TypeLiteralNode extends TypeNode, Declaration {
+        members: NodeArray<Node>;
+    }
+
+    export interface ArrayTypeNode extends TypeNode {
+        elementType: TypeNode;
+    }
+
+    export interface TupleTypeNode extends TypeNode {
+        elementTypes: NodeArray<TypeNode>;
+    }
+
+    export interface UnionTypeNode extends TypeNode {
+        types: NodeArray<TypeNode>;
+    }
+
+    export interface ParenthesizedTypeNode extends TypeNode {
+        type: TypeNode;
+    }
+
+    // Note that a StringLiteral AST node is both an Expression and a TypeNode.  The latter is
+    // because string literals can appear in the type annotation of a parameter node.
+    export interface StringLiteral extends LiteralExpression, TypeNode {
+        _stringLiteralBrand: any;
+    }
+
+    // Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing.
+    // Consider 'Expression'.  Without the brand, 'Expression' is actually no different
+    // (structurally) than 'Node'.  Because of this you can pass any Node to a function that
+    // takes an Expression without any error.  By using the 'brands' we ensure that the type
+    // checker actually thinks you have something of the right type.  Note: the brands are
+    // never actually given values.  At runtime they have zero cost.
+
+    export interface Expression extends Node {
+        _expressionBrand: any;
+        contextualType?: Type;  // Used to temporarily assign a contextual type during overload resolution
+    }
+
+    export interface UnaryExpression extends Expression {
+        _unaryExpressionBrand: any;
+    }
+
+    export interface PrefixUnaryExpression extends UnaryExpression {
+        operator: SyntaxKind;
+        operand: UnaryExpression;
+    }
+
+    export interface PostfixUnaryExpression extends PostfixExpression {
+        operand: LeftHandSideExpression;
+        operator: SyntaxKind;
+    }
+
+    export interface PostfixExpression extends UnaryExpression {
+        _postfixExpressionBrand: any;
+    }
+
+    export interface LeftHandSideExpression extends PostfixExpression {
+        _leftHandSideExpressionBrand: any;
+    }
+
+    export interface MemberExpression extends LeftHandSideExpression {
+        _memberExpressionBrand: any;
+    }
+
+    export interface PrimaryExpression extends MemberExpression {
+        _primaryExpressionBrand: any;
+    }
+
+    export interface DeleteExpression extends UnaryExpression {
+        expression: UnaryExpression;
+    }
+
+    export interface TypeOfExpression extends UnaryExpression {
+        expression: UnaryExpression;
+    }
+
+    export interface VoidExpression extends UnaryExpression {
+        expression: UnaryExpression;
+    }
+
+    export interface YieldExpression extends Expression {
+        asteriskToken?: Node;
+        expression: Expression;
+    }
+
+    export interface BinaryExpression extends Expression {
+        left: Expression;
+        operatorToken: Node;
+        right: Expression;
+    }
+
+    export interface ConditionalExpression extends Expression {
+        condition: Expression;
+        questionToken: Node;
+        whenTrue: Expression;
+        colonToken: Node;
+        whenFalse: Expression;
+    }
+
+    export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration {
+        name?: Identifier;
+        body: Block | Expression;  // Required, whereas the member inherited from FunctionDeclaration is optional
+    }
+
+    export interface ArrowFunction extends Expression, FunctionLikeDeclaration {
+        equalsGreaterThanToken: Node;
+    }
+
+    // The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
+    // or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
+    // For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
+    export interface LiteralExpression extends PrimaryExpression {
+        text: string;
+        isUnterminated?: boolean;
+        hasExtendedUnicodeEscape?: boolean;
+    }
+
+    export interface TemplateExpression extends PrimaryExpression {
+        head: LiteralExpression;
+        templateSpans: NodeArray<TemplateSpan>;
+    }
+
+    // Each of these corresponds to a substitution expression and a template literal, in that order.
+    // The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral.
+    export interface TemplateSpan extends Node {
+        expression: Expression;
+        literal: LiteralExpression;
+    }
+
+    export interface ParenthesizedExpression extends PrimaryExpression {
+        expression: Expression;
+    }
+
+    export interface ArrayLiteralExpression extends PrimaryExpression {
+        elements: NodeArray<Expression>;
+    }
+
+    export interface SpreadElementExpression extends Expression {
+        expression: Expression;
+    }
+
+    // An ObjectLiteralExpression is the declaration node for an anonymous symbol.
+    export interface ObjectLiteralExpression extends PrimaryExpression, Declaration {
+        properties: NodeArray<ObjectLiteralElement>;
+    }
+
+    export interface PropertyAccessExpression extends MemberExpression {
+        expression: LeftHandSideExpression;
+        dotToken: Node;
+        name: Identifier;
+    }
+
+    export interface ElementAccessExpression extends MemberExpression {
+        expression: LeftHandSideExpression;
+        argumentExpression?: Expression;
+    }
+
+    export interface CallExpression extends LeftHandSideExpression {
+        expression: LeftHandSideExpression;
+        typeArguments?: NodeArray<TypeNode>;
+        arguments: NodeArray<Expression>;
+    }
+
+    export interface HeritageClauseElement extends TypeNode {
+        expression: LeftHandSideExpression;
+        typeArguments?: NodeArray<TypeNode>;
+    }
+
+    export interface NewExpression extends CallExpression, PrimaryExpression { }
+
+    export interface TaggedTemplateExpression extends MemberExpression {
+        tag: LeftHandSideExpression;
+        template: LiteralExpression | TemplateExpression;
+    }
+
+    export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression;
+
+    export interface TypeAssertion extends UnaryExpression {
+        type: TypeNode;
+        expression: UnaryExpression;
+    }
+
+    export interface Statement extends Node, ModuleElement {
+        _statementBrand: any;
+    }
+
+    export interface Block extends Statement {
+        statements: NodeArray<Statement>;
+    }
+
+    export interface VariableStatement extends Statement {
+        declarationList: VariableDeclarationList;
+    }
+
+    export interface ExpressionStatement extends Statement {
+        expression: Expression;
+    }
+
+    export interface IfStatement extends Statement {
+        expression: Expression;
+        thenStatement: Statement;
+        elseStatement?: Statement;
+    }
+
+    export interface IterationStatement extends Statement {
+        statement: Statement;
+    }
+
+    export interface DoStatement extends IterationStatement {
+        expression: Expression;
+    }
+
+    export interface WhileStatement extends IterationStatement {
+        expression: Expression;
+    }
+
+    export interface ForStatement extends IterationStatement {
+        initializer?: VariableDeclarationList | Expression;
+        condition?: Expression;
+        incrementor?: Expression;
+    }
+
+    export interface ForInStatement extends IterationStatement {
+        initializer: VariableDeclarationList | Expression;
+        expression: Expression;
+    }
+
+    export interface ForOfStatement extends IterationStatement {
+        initializer: VariableDeclarationList | Expression;
+        expression: Expression;
+    }
+
+    export interface BreakOrContinueStatement extends Statement {
+        label?: Identifier;
+    }
+
+    export interface ReturnStatement extends Statement {
+        expression?: Expression;
+    }
+
+    export interface WithStatement extends Statement {
+        expression: Expression;
+        statement: Statement;
+    }
+
+    export interface SwitchStatement extends Statement {
+        expression: Expression;
+        caseBlock: CaseBlock;
+    }
+
+    export interface CaseBlock extends Node {
+        clauses: NodeArray<CaseOrDefaultClause>;
+    }
+
+    export interface CaseClause extends Node {
+        expression?: Expression;
+        statements: NodeArray<Statement>;
+    }
+
+    export interface DefaultClause extends Node {
+        statements: NodeArray<Statement>;
+    }
+
+    export type CaseOrDefaultClause = CaseClause | DefaultClause;
+
+    export interface LabeledStatement extends Statement {
+        label: Identifier;
+        statement: Statement;
+    }
+
+    export interface ThrowStatement extends Statement {
+        expression: Expression;
+    }
+
+    export interface TryStatement extends Statement {
+        tryBlock: Block;
+        catchClause?: CatchClause;
+        finallyBlock?: Block;
+    }
+
+    export interface CatchClause extends Node {
+        variableDeclaration: VariableDeclaration;
+        block: Block;
+    }
+
+    export interface ModuleElement extends Node {
+        _moduleElementBrand: any;
+    }
+
+    export interface ClassLikeDeclaration extends Declaration {
+        name?: Identifier;
+        typeParameters?: NodeArray<TypeParameterDeclaration>;
+        heritageClauses?: NodeArray<HeritageClause>;
+        members: NodeArray<ClassElement>;
+    }
+
+    export interface ClassDeclaration extends ClassLikeDeclaration, Statement {
+    }
+
+    export interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression {
+    }
+
+    export interface ClassElement extends Declaration {
+        _classElementBrand: any;
+    }
+
+    export interface InterfaceDeclaration extends Declaration, ModuleElement {
+        name: Identifier;
+        typeParameters?: NodeArray<TypeParameterDeclaration>;
+        heritageClauses?: NodeArray<HeritageClause>;
+        members: NodeArray<Declaration>;
+    }
+
+    export interface HeritageClause extends Node {
+        token: SyntaxKind;
+        types?: NodeArray<HeritageClauseElement>;
+    }
+
+    export interface TypeAliasDeclaration extends Declaration, ModuleElement {
+        name: Identifier;
+        type: TypeNode;
+    }
+
+    export interface EnumMember extends Declaration {
+        // This does include ComputedPropertyName, but the parser will give an error
+        // if it parses a ComputedPropertyName in an EnumMember
+        name: DeclarationName;
+        initializer?: Expression;
+    }
+
+    export interface EnumDeclaration extends Declaration, ModuleElement {
+        name: Identifier;
+        members: NodeArray<EnumMember>;
+    }
+
+    export interface ModuleDeclaration extends Declaration, ModuleElement {
+        name: Identifier | LiteralExpression;
+        body: ModuleBlock | ModuleDeclaration;
+    }
+
+    export interface ModuleBlock extends Node, ModuleElement {
+        statements: NodeArray<ModuleElement>
+    }
+
+    export interface ImportEqualsDeclaration extends Declaration, ModuleElement {
+        name: Identifier;
+
+        // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external
+        // module reference.
+        moduleReference: EntityName | ExternalModuleReference;
+    }
+
+    export interface ExternalModuleReference extends Node {
+        expression?: Expression;
+    }
+
+    // In case of:
+    // import "mod"  => importClause = undefined, moduleSpecifier = "mod"
+    // In rest of the cases, module specifier is string literal corresponding to module
+    // ImportClause information is shown at its declaration below.
+    export interface ImportDeclaration extends ModuleElement {
+        importClause?: ImportClause;
+        moduleSpecifier: Expression;
+    }
+
+    // In case of:
+    // import d from "mod" => name = d, namedBinding = undefined
+    // import * as ns from "mod" => name = undefined, namedBinding: NamespaceImport = { name: ns }
+    // import d, * as ns from "mod" => name = d, namedBinding: NamespaceImport = { name: ns }
+    // import { a, b as x } from "mod" => name = undefined, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
+    // import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
+    export interface ImportClause extends Declaration {
+        name?: Identifier; // Default binding
+        namedBindings?: NamespaceImport | NamedImports;
+    }
+
+    export interface NamespaceImport extends Declaration {
+        name: Identifier;
+    }
+
+    export interface ExportDeclaration extends Declaration, ModuleElement {
+        exportClause?: NamedExports;
+        moduleSpecifier?: Expression;
+    }
+
+    export interface NamedImportsOrExports extends Node {
+        elements: NodeArray<ImportOrExportSpecifier>;
+    }
+
+    export type NamedImports = NamedImportsOrExports;
+    export type NamedExports = NamedImportsOrExports;
+
+    export interface ImportOrExportSpecifier extends Declaration {
+        propertyName?: Identifier;  // Name preceding "as" keyword (or undefined when "as" is absent)
+        name: Identifier;           // Declared name
+    }
+
+    export type ImportSpecifier = ImportOrExportSpecifier;
+    export type ExportSpecifier = ImportOrExportSpecifier;
+
+    export interface ExportAssignment extends Declaration, ModuleElement {
+        isExportEquals?: boolean;
+        expression: Expression;
+    }
+
+    export interface FileReference extends TextRange {
+        fileName: string;
+    }
+
+    export interface CommentRange extends TextRange {
+        hasTrailingNewLine?: boolean;
+        kind: SyntaxKind;
+    }
+
+    // Source files are declarations when they are external modules.
+    export interface SourceFile extends Declaration {
+        statements: NodeArray<ModuleElement>;
+        endOfFileToken: Node;
+
+        fileName: string;
+        text: string;
+
+        amdDependencies: {path: string; name: string}[];
+        amdModuleName: string;
+        referencedFiles: FileReference[];
+
+        hasNoDefaultLib: boolean;
+
+        languageVersion: ScriptTarget;
+
+        // The first node that causes this file to be an external module
+        /* @internal */ externalModuleIndicator: Node;
+        
+        /* @internal */ identifiers: Map<string>;
+        /* @internal */ nodeCount: number;
+        /* @internal */ identifierCount: number;
+        /* @internal */ symbolCount: number;
+
+        // File level diagnostics reported by the parser (includes diagnostics about /// references
+        // as well as code diagnostics).
+        /* @internal */ parseDiagnostics: Diagnostic[];
+
+        // File level diagnostics reported by the binder.
+        /* @internal */ bindDiagnostics: Diagnostic[];
+
+        // Stores a line map for the file.
+        // This field should never be used directly to obtain line map, use getLineMap function instead.
+        /* @internal */ lineMap: number[];
+    }
+
+    export interface ScriptReferenceHost {
+        getCompilerOptions(): CompilerOptions;
+        getSourceFile(fileName: string): SourceFile;
+        getCurrentDirectory(): string;
+    }
+
+    export interface ParseConfigHost {
+        readDirectory(rootDir: string, extension: string): string[];
+    }
+
+    export interface WriteFileCallback {
+        (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
+    }
+
+    export interface Program extends ScriptReferenceHost {
+        /**
+         * Get a list of files in the program
+         */
+        getSourceFiles(): SourceFile[];
+
+        /**
+         * Emits the JavaScript and declaration files.  If targetSourceFile is not specified, then
+         * the JavaScript and declaration files will be produced for all the files in this program.
+         * If targetSourceFile is specified, then only the JavaScript and declaration for that
+         * specific file will be generated.
+         *
+         * If writeFile is not specified then the writeFile callback from the compiler host will be
+         * used for writing the JavaScript and declaration files.  Otherwise, the writeFile parameter
+         * will be invoked when writing the JavaScript and declaration files.
+         */
+        emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
+
+        getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
+        getGlobalDiagnostics(): Diagnostic[];
+        getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
+        getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[];
+
+        /** 
+         * Gets a type checker that can be used to semantically analyze source fils in the program.
+         */
+        getTypeChecker(): TypeChecker;
+
+        /* @internal */ getCommonSourceDirectory(): string;
+
+        // For testing purposes only.  Should not be used by any other consumers (including the
+        // language service).
+        /* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker;
+
+        /* @internal */ getNodeCount(): number;
+        /* @internal */ getIdentifierCount(): number;
+        /* @internal */ getSymbolCount(): number;
+        /* @internal */ getTypeCount(): number;
+    }
+
+    export interface SourceMapSpan {
+        /** Line number in the .js file. */
+        emittedLine: number; 
+        /** Column number in the .js file. */
+        emittedColumn: number;  
+        /** Line number in the .ts file. */
+        sourceLine: number; 
+        /** Column number in the .ts file. */
+        sourceColumn: number; 
+        /** Optional name (index into names array) associated with this span. */
+        nameIndex?: number; 
+        /** .ts file (index into sources array) associated with this span */
+        sourceIndex: number;
+    }
+
+    export interface SourceMapData {
+        sourceMapFilePath: string;       // Where the sourcemap file is written
+        jsSourceMappingURL: string;      // source map URL written in the .js file
+        sourceMapFile: string;           // Source map's file field - .js file name
+        sourceMapSourceRoot: string;     // Source map's sourceRoot field - location where the sources will be present if not ""
+        sourceMapSources: string[];      // Source map's sources field - list of sources that can be indexed in this source map
+        inputSourceFileNames: string[];  // Input source file (which one can use on program to get the file), 1:1 mapping with the sourceMapSources list
+        sourceMapNames?: string[];       // Source map's names field - list of names that can be indexed in this source map
+        sourceMapMappings: string;       // Source map's mapping field - encoded source map spans
+        sourceMapDecodedMappings: SourceMapSpan[];  // Raw source map spans that were encoded into the sourceMapMappings
+    }
+
+    /** Return code used by getEmitOutput function to indicate status of the function */
+    export enum ExitStatus {
+        // Compiler ran successfully.  Either this was a simple do-nothing compilation (for example,
+        // when -version or -help was provided, or this was a normal compilation, no diagnostics
+        // were produced, and all outputs were generated successfully.
+        Success = 0,
+
+        // Diagnostics were produced and because of them no code was generated.
+        DiagnosticsPresent_OutputsSkipped = 1,
+
+        // Diagnostics were produced and outputs were generated in spite of them.
+        DiagnosticsPresent_OutputsGenerated = 2,
+    }
+
+    export interface EmitResult {
+        emitSkipped: boolean;
+        diagnostics: Diagnostic[];
+        /* @internal */ sourceMaps: SourceMapData[];  // Array of sourceMapData if compiler emitted sourcemaps
+    }
+
+    export interface TypeCheckerHost {
+        getCompilerOptions(): CompilerOptions;
+
+        getSourceFiles(): SourceFile[];
+        getSourceFile(fileName: string): SourceFile;
+    }
+
+    export interface TypeChecker {
+        getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type;
+        getDeclaredTypeOfSymbol(symbol: Symbol): Type;
+        getPropertiesOfType(type: Type): Symbol[];
+        getPropertyOfType(type: Type, propertyName: string): Symbol;
+        getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
+        getIndexTypeOfType(type: Type, kind: IndexKind): Type;
+        getReturnTypeOfSignature(signature: Signature): Type;
+
+        getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
+        getSymbolAtLocation(node: Node): Symbol;
+        getShorthandAssignmentValueSymbol(location: Node): Symbol;
+        getTypeAtLocation(node: Node): Type;
+        typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
+        symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
+        getSymbolDisplayBuilder(): SymbolDisplayBuilder;
+        getFullyQualifiedName(symbol: Symbol): string;
+        getAugmentedPropertiesOfType(type: Type): Symbol[];
+        getRootSymbols(symbol: Symbol): Symbol[];
+        getContextualType(node: Expression): Type;
+        getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature;
+        getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
+        isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
+        isUndefinedSymbol(symbol: Symbol): boolean;
+        isArgumentsSymbol(symbol: Symbol): boolean;
+
+        getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
+        isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
+        getAliasedSymbol(symbol: Symbol): Symbol;
+        getExportsOfModule(moduleSymbol: Symbol): Symbol[];
+
+        // Should not be called directly.  Should only be accessed through the Program instance.
+        /* @internal */ getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
+        /* @internal */ getGlobalDiagnostics(): Diagnostic[];
+        /* @internal */ getEmitResolver(sourceFile?: SourceFile): EmitResolver;
+
+        /* @internal */ getNodeCount(): number;
+        /* @internal */ getIdentifierCount(): number;
+        /* @internal */ getSymbolCount(): number;
+        /* @internal */ getTypeCount(): number;
+    }
+
+    export interface SymbolDisplayBuilder {
+        buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
+        buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
+        buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
+        buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
+        buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
+        buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
+        buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
+        buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
+        buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
+    }
+
+    export interface SymbolWriter {
+        writeKeyword(text: string): void;
+        writeOperator(text: string): void;
+        writePunctuation(text: string): void;
+        writeSpace(text: string): void;
+        writeStringLiteral(text: string): void;
+        writeParameter(text: string): void;
+        writeSymbol(text: string, symbol: Symbol): void;
+        writeLine(): void;
+        increaseIndent(): void;
+        decreaseIndent(): void;
+        clear(): void;
+
+        // Called when the symbol writer encounters a symbol to write.  Currently only used by the
+        // declaration emitter to help determine if it should patch up the final declaration file
+        // with import statements it previously saw (but chose not to emit).
+        trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
+    }
+
+    export const enum TypeFormatFlags {
+        None                            = 0x00000000,
+        WriteArrayAsGenericType         = 0x00000001,  // Write Array<T> instead T[]
+        UseTypeOfFunction               = 0x00000002,  // Write typeof instead of function type literal
+        NoTruncation                    = 0x00000004,  // Don't truncate typeToString result
+        WriteArrowStyleSignature        = 0x00000008,  // Write arrow style signature
+        WriteOwnNameForAnyLike          = 0x00000010,  // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc)
+        WriteTypeArgumentsOfSignature   = 0x00000020,  // Write the type arguments instead of type parameters of the signature
+        InElementType                   = 0x00000040,  // Writing an array or union element type
+        UseFullyQualifiedType           = 0x00000080,  // Write out the fully qualified type name (eg. Module.Type, instead of Type)
+    }
+
+    export const enum SymbolFormatFlags {
+        None = 0x00000000,
+
+        // Write symbols's type argument if it is instantiated symbol
+        // eg. class C<T> { p: T }   <-- Show p as C<T>.p here
+        //     var a: C<number>;
+        //     var p = a.p;  <--- Here p is property of C<number> so show it as C<number>.p instead of just C.p
+        WriteTypeParametersOrArguments = 0x00000001,
+
+        // Use only external alias information to get the symbol name in the given context
+        // eg.  module m { export class c { } } import x = m.c;
+        // When this flag is specified m.c will be used to refer to the class instead of alias symbol x
+        UseOnlyExternalAliasing = 0x00000002,
+    }
+
+    /* @internal */
+    export const enum SymbolAccessibility {
+        Accessible,
+        NotAccessible,
+        CannotBeNamed
+    }
+
+    /* @internal */
+    export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration;
+
+    /* @internal */
+    export interface SymbolVisibilityResult {
+        accessibility: SymbolAccessibility;
+        aliasesToMakeVisible?: AnyImportSyntax[]; // aliases that need to have this symbol visible
+        errorSymbolName?: string; // Optional symbol name that results in error
+        errorNode?: Node; // optional node that results in error
+    }
+
+    /* @internal */
+    export interface SymbolAccessiblityResult extends SymbolVisibilityResult {
+        errorModuleName?: string // If the symbol is not visible from module, module's name
+    }
+
+    /* @internal */
+    export interface EmitResolver {
+        hasGlobalName(name: string): boolean;
+        getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (node: Node) => string): string;
+        isValueAliasDeclaration(node: Node): boolean;
+        isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean;
+        isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
+        getNodeCheckFlags(node: Node): NodeCheckFlags;
+        isDeclarationVisible(node: Declaration): boolean;
+        collectLinkedAliases(node: Identifier): Node[];
+        isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
+        writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
+        writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
+        writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
+        isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
+        isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
+        // Returns the constant value this property access resolves to, or 'undefined' for a non-constant
+        getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
+        resolvesToSomeValue(location: Node, name: string): boolean;
+        getBlockScopedVariableId(node: Identifier): number;
+        serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
+        serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[];
+        serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
+    }
+
+    export const enum SymbolFlags {
+        FunctionScopedVariable  = 0x00000001,  // Variable (var) or parameter
+        BlockScopedVariable     = 0x00000002,  // A block-scoped variable (let or const)
+        Property                = 0x00000004,  // Property or enum member
+        EnumMember              = 0x00000008,  // Enum member
+        Function                = 0x00000010,  // Function
+        Class                   = 0x00000020,  // Class
+        Interface               = 0x00000040,  // Interface
+        ConstEnum               = 0x00000080,  // Const enum
+        RegularEnum             = 0x00000100,  // Enum
+        ValueModule             = 0x00000200,  // Instantiated module
+        NamespaceModule         = 0x00000400,  // Uninstantiated module
+        TypeLiteral             = 0x00000800,  // Type Literal
+        ObjectLiteral           = 0x00001000,  // Object Literal
+        Method                  = 0x00002000,  // Method
+        Constructor             = 0x00004000,  // Constructor
+        GetAccessor             = 0x00008000,  // Get accessor
+        SetAccessor             = 0x00010000,  // Set accessor
+        Signature               = 0x00020000,  // Call, construct, or index signature
+        TypeParameter           = 0x00040000,  // Type parameter
+        TypeAlias               = 0x00080000,  // Type alias
+        ExportValue             = 0x00100000,  // Exported value marker (see comment in declareModuleMember in binder)
+        ExportType              = 0x00200000,  // Exported type marker (see comment in declareModuleMember in binder)
+        ExportNamespace         = 0x00400000,  // Exported namespace marker (see comment in declareModuleMember in binder)
+        Alias                   = 0x00800000,  // An alias for another symbol (see comment in isAliasSymbolDeclaration in checker)
+        Instantiated            = 0x01000000,  // Instantiated symbol
+        Merged                  = 0x02000000,  // Merged symbol (created during program binding)
+        Transient               = 0x04000000,  // Transient symbol (created during type check)
+        Prototype               = 0x08000000,  // Prototype property (no source representation)
+        UnionProperty           = 0x10000000,  // Property in union type
+        Optional                = 0x20000000,  // Optional property
+        ExportStar              = 0x40000000,  // Export * declaration
+
+        Enum = RegularEnum | ConstEnum,
+        Variable = FunctionScopedVariable | BlockScopedVariable,
+        Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
+        Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
+        Namespace = ValueModule | NamespaceModule,
+        Module = ValueModule | NamespaceModule,
+        Accessor = GetAccessor | SetAccessor,
+
+        // Variables can be redeclared, but can not redeclare a block-scoped declaration with the
+        // same name, or any other value that is not a variable, e.g. ValueModule or Class
+        FunctionScopedVariableExcludes = Value & ~FunctionScopedVariable,
+
+        // Block-scoped declarations are not allowed to be re-declared
+        // they can not merge with anything in the value space
+        BlockScopedVariableExcludes = Value,
+
+        ParameterExcludes = Value,
+        PropertyExcludes = Value,
+        EnumMemberExcludes = Value,
+        FunctionExcludes = Value & ~(Function | ValueModule),
+        ClassExcludes = (Value | Type) & ~ValueModule,
+        InterfaceExcludes = Type & ~Interface,
+        RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules
+        ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums
+        ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule),
+        NamespaceModuleExcludes = 0,
+        MethodExcludes = Value & ~Method,
+        GetAccessorExcludes = Value & ~SetAccessor,
+        SetAccessorExcludes = Value & ~GetAccessor,
+        TypeParameterExcludes = Type & ~TypeParameter,
+        TypeAliasExcludes = Type,
+        AliasExcludes = Alias,
+
+        ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Alias,
+
+        ExportHasLocal = Function | Class | Enum | ValueModule,
+
+        HasLocals = Function | Module | Method | Constructor | Accessor | Signature,
+        HasExports = Class | Enum | Module,
+        HasMembers = Class | Interface | TypeLiteral | ObjectLiteral,
+
+        IsContainer = HasLocals | HasExports | HasMembers,
+        PropertyOrAccessor = Property | Accessor,
+        Export = ExportNamespace | ExportType | ExportValue,
+    }
+
+    export interface Symbol {
+        flags: SymbolFlags;                     // Symbol flags
+        name: string;                           // Name of symbol
+        /* @internal */ id?: number;            // Unique id (used to look up SymbolLinks)
+        /* @internal */ mergeId?: number;       // Merge id (used to look up merged symbol)
+        declarations?: Declaration[];           // Declarations associated with this symbol
+        /* @internal */ parent?: Symbol;        // Parent symbol
+        members?: SymbolTable;                  // Class, interface or literal instance members
+        exports?: SymbolTable;                  // Module exports
+        /* @internal */ exportSymbol?: Symbol;  // Exported symbol associated with this symbol
+        valueDeclaration?: Declaration;         // First value declaration of the symbol
+        /* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums
+    }
+
+    /* @internal */ 
+    export interface SymbolLinks {
+        target?: Symbol;                    // Resolved (non-alias) target of an alias
+        type?: Type;                        // Type of value symbol
+        declaredType?: Type;                // Type of class, interface, enum, or type parameter
+        mapper?: TypeMapper;                // Type mapper for instantiation alias
+        referenced?: boolean;               // True if alias symbol has been referenced as a value
+        unionType?: UnionType;              // Containing union type for union property
+        resolvedExports?: SymbolTable;      // Resolved exports of module
+        exportsChecked?: boolean;           // True if exports of external module have been checked
+    }
+
+    /* @internal */ 
+    export interface TransientSymbol extends Symbol, SymbolLinks { }
+
+    export interface SymbolTable {
+        [index: string]: Symbol;
+    }
+
+    /* @internal */ 
+    export const enum NodeCheckFlags {
+        TypeChecked                 = 0x00000001,  // Node has been type checked
+        LexicalThis                 = 0x00000002,  // Lexical 'this' reference
+        CaptureThis                 = 0x00000004,  // Lexical 'this' used in body
+        EmitExtends                 = 0x00000008,  // Emit __extends
+        SuperInstance               = 0x00000010,  // Instance 'super' reference
+        SuperStatic                 = 0x00000020,  // Static 'super' reference
+        ContextChecked              = 0x00000040,  // Contextual types have been assigned
+
+        // Values for enum members have been computed, and any errors have been reported for them.
+        EnumValuesComputed          = 0x00000080,
+        BlockScopedBindingInLoop    = 0x00000100,
+        EmitDecorate                = 0x00000200,  // Emit __decorate
+        EmitParam                   = 0x00000400,  // Emit __param helper for decorators
+        LexicalModuleMergesWithClass = 0x00000800,  // Instantiated lexical module declaration is merged with a previous class declaration.
+    }
+
+    /* @internal */ 
+    export interface NodeLinks {
+        resolvedType?: Type;              // Cached type of type node
+        resolvedSignature?: Signature;    // Cached signature of signature node or call expression
+        resolvedSymbol?: Symbol;          // Cached name resolution result
+        flags?: NodeCheckFlags;           // Set of flags specific to Node
+        enumMemberValue?: number;         // Constant value of enum member
+        isIllegalTypeReferenceInConstraint?: boolean; // Is type reference in constraint refers to the type parameter from the same list
+        isVisible?: boolean;              // Is this node visible
+        generatedName?: string;           // Generated name for module, enum, or import declaration
+        generatedNames?: Map<string>;     // Generated names table for source file
+        assignmentChecks?: Map<boolean>;  // Cache of assignment checks
+        hasReportedStatementInAmbientContext?: boolean;  // Cache boolean if we report statements in ambient context
+        importOnRightSide?: Symbol;       // for import declarations - import that appear on the right side
+    }
+
+    export const enum TypeFlags {
+        Any                     = 0x00000001,
+        String                  = 0x00000002,
+        Number                  = 0x00000004,
+        Boolean                 = 0x00000008,
+        Void                    = 0x00000010,
+        Undefined               = 0x00000020,
+        Null                    = 0x00000040,
+        Enum                    = 0x00000080,  // Enum type
+        StringLiteral           = 0x00000100,  // String literal type
+        TypeParameter           = 0x00000200,  // Type parameter
+        Class                   = 0x00000400,  // Class
+        Interface               = 0x00000800,  // Interface
+        Reference               = 0x00001000,  // Generic type reference
+        Tuple                   = 0x00002000,  // Tuple
+        Union                   = 0x00004000,  // Union
+        Anonymous               = 0x00008000,  // Anonymous
+        /* @internal */ 
+        FromSignature           = 0x00010000,  // Created for signature assignment check
+        ObjectLiteral           = 0x00020000,  // Originates in an object literal
+        /* @internal */ 
+        ContainsUndefinedOrNull = 0x00040000,  // Type is or contains Undefined or Null type
+        /* @internal */ 
+        ContainsObjectLiteral = 0x00080000,  // Type is or contains object literal type
+        ESSymbol                = 0x00100000,  // Type of symbol primitive introduced in ES6
+
+        /* @internal */ 
+        Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
+        /* @internal */ 
+        Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum,
+        StringLike = String | StringLiteral,
+        NumberLike = Number | Enum,
+        ObjectType = Class | Interface | Reference | Tuple | Anonymous,
+        /* @internal */ 
+        RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral
+    }
+
+    // Properties common to all types
+    export interface Type {
+        flags: TypeFlags;               // Flags
+        /* @internal */ id: number;     // Unique ID
+        symbol?: Symbol;                // Symbol associated with type (if any)
+    }
+
+    /* @internal */ 
+    // Intrinsic types (TypeFlags.Intrinsic)
+    export interface IntrinsicType extends Type {
+        intrinsicName: string;  // Name of intrinsic type
+    }
+
+    // String literal types (TypeFlags.StringLiteral)
+    export interface StringLiteralType extends Type {
+        text: string;  // Text of string literal
+    }
+
+    // Object types (TypeFlags.ObjectType)
+    export interface ObjectType extends Type { }
+
+    // Class and interface types (TypeFlags.Class and TypeFlags.Interface)
+    export interface InterfaceType extends ObjectType {
+        typeParameters: TypeParameter[];           // Type parameters (undefined if non-generic)
+    }
+
+    export interface InterfaceTypeWithBaseTypes extends InterfaceType {
+        baseTypes: ObjectType[];
+    }
+
+    export interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
+        declaredProperties: Symbol[];              // Declared members
+        declaredCallSignatures: Signature[];       // Declared call signatures
+        declaredConstructSignatures: Signature[];  // Declared construct signatures
+        declaredStringIndexType: Type;             // Declared string index type
+        declaredNumberIndexType: Type;             // Declared numeric index type
+    }
+
+    // Type references (TypeFlags.Reference)
+    export interface TypeReference extends ObjectType {
+        target: GenericType;    // Type reference target
+        typeArguments: Type[];  // Type reference type arguments
+    }
+
+    // Generic class and interface types
+    export interface GenericType extends InterfaceType, TypeReference {
+        /* @internal */
+        instantiations: Map<TypeReference>;   // Generic instantiation cache
+    }
+
+    export interface TupleType extends ObjectType {
+        elementTypes: Type[];          // Element types
+        baseArrayType: TypeReference;  // Array<T> where T is best common type of element types
+    }
+
+    export interface UnionType extends Type {
+        types: Type[];                    // Constituent types
+        /* @internal */
+        reducedType: Type;                // Reduced union type (all subtypes removed)
+        /* @internal */
+        resolvedProperties: SymbolTable;  // Cache of resolved properties
+    }
+
+    /* @internal */
+    // Resolved object or union type
+    export interface ResolvedType extends ObjectType, UnionType {
+        members: SymbolTable;              // Properties by name
+        properties: Symbol[];              // Properties
+        callSignatures: Signature[];       // Call signatures of type
+        constructSignatures: Signature[];  // Construct signatures of type
+        stringIndexType: Type;             // String index type
+        numberIndexType: Type;             // Numeric index type
+    }
+
+    // Type parameters (TypeFlags.TypeParameter)
+    export interface TypeParameter extends Type {
+        constraint: Type;        // Constraint
+        /* @internal */
+        target?: TypeParameter;  // Instantiation target
+        /* @internal */
+        mapper?: TypeMapper;     // Instantiation mapper
+    }
+
+    export const enum SignatureKind {
+        Call,
+        Construct,
+    }
+
+    export interface Signature {
+        declaration: SignatureDeclaration;  // Originating declaration
+        typeParameters: TypeParameter[];    // Type parameters (undefined if non-generic)
+        parameters: Symbol[];               // Parameters
+        /* @internal */
+        resolvedReturnType: Type;           // Resolved return type
+        /* @internal */
+        minArgumentCount: number;           // Number of non-optional parameters
+        /* @internal */
+        hasRestParameter: boolean;          // True if last parameter is rest parameter
+        /* @internal */
+        hasStringLiterals: boolean;         // True if specialized
+        /* @internal */
+        target?: Signature;                 // Instantiation target
+        /* @internal */
+        mapper?: TypeMapper;                // Instantiation mapper
+        /* @internal */
+        unionSignatures?: Signature[];      // Underlying signatures of a union signature
+        /* @internal */
+        erasedSignatureCache?: Signature;   // Erased version of signature (deferred)
+        /* @internal */
+        isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
+    }
+
+    export const enum IndexKind {
+        String,
+        Number,
+    }
+
+    /* @internal */
+    export interface TypeMapper {
+        (t: TypeParameter): Type;
+    }
+
+    /* @internal */
+    export interface TypeInferences {
+        primary: Type[];    // Inferences made directly to a type parameter
+        secondary: Type[];  // Inferences made to a type parameter in a union type
+        isFixed: boolean;   // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec
+                            // If a type parameter is fixed, no more inferences can be made for the type parameter
+    }
+
+    /* @internal */
+    export interface InferenceContext {
+        typeParameters: TypeParameter[];    // Type parameters for which inferences are made
+        inferUnionTypes: boolean;           // Infer union types for disjoint candidates (otherwise undefinedType)
+        inferences: TypeInferences[];       // Inferences made for each type parameter
+        inferredTypes: Type[];              // Inferred type for each type parameter
+        failedTypeParameterIndex?: number;  // Index of type parameter for which inference failed
+        // It is optional because in contextual signature instantiation, nothing fails
+    }
+
+    export interface DiagnosticMessage {
+        key: string;
+        category: DiagnosticCategory;
+        code: number;
+    }
+
+    /**
+     * A linked list of formatted diagnostic messages to be used as part of a multiline message.
+     * It is built from the bottom up, leaving the head to be the "main" diagnostic.
+     * While it seems that DiagnosticMessageChain is structurally similar to DiagnosticMessage,
+     * the difference is that messages are all preformatted in DMC.
+     */
+    export interface DiagnosticMessageChain {
+        messageText: string;
+        category: DiagnosticCategory;
+        code: number;
+        next?: DiagnosticMessageChain;
+    }
+
+    export interface Diagnostic {
+        file: SourceFile;
+        start: number;
+        length: number;
+        messageText: string | DiagnosticMessageChain;
+        category: DiagnosticCategory;
+        code: number;
+    }
+
+    export enum DiagnosticCategory {
+        Warning,
+        Error,
+        Message,
+    }
+
+    export interface CompilerOptions {
+        allowNonTsExtensions?: boolean;
+        charset?: string;
+        declaration?: boolean;
+        diagnostics?: boolean;
+        emitBOM?: boolean;
+        help?: boolean;
+        listFiles?: boolean;
+        locale?: string;
+        mapRoot?: string;
+        module?: ModuleKind;
+        noEmit?: boolean;
+        noEmitOnError?: boolean;
+        noErrorTruncation?: boolean;
+        noImplicitAny?: boolean;
+        noLib?: boolean;
+        noResolve?: boolean;
+        out?: string;
+        outDir?: string;
+        preserveConstEnums?: boolean;
+        project?: string;
+        removeComments?: boolean;
+        rootDir?: string;
+        sourceMap?: boolean;
+        sourceRoot?: string;
+        suppressImplicitAnyIndexErrors?: boolean;
+        target?: ScriptTarget;
+        version?: boolean;
+        watch?: boolean;
+        separateCompilation?: boolean;
+        emitDecoratorMetadata?: boolean;
+        /* @internal */ stripInternal?: boolean;
+        [option: string]: string | number | boolean;
+    }
+
+    export const enum ModuleKind {
+        None = 0,
+        CommonJS = 1,
+        AMD = 2,
+        UMD = 3,
+    }
+
+    export interface LineAndCharacter {
+        line: number;
+        /*
+         * This value denotes the character position in line and is different from the 'column' because of tab characters.
+         */
+        character: number;
+    }
+
+    export const enum ScriptTarget {
+        ES3 = 0,
+        ES5 = 1,
+        ES6 = 2,
+        Latest = ES6,
+    }
+
+    export interface ParsedCommandLine {
+        options: CompilerOptions;
+        fileNames: string[];
+        errors: Diagnostic[];
+    }
+
+    /* @internal */
+    export interface CommandLineOption {
+        name: string;
+        type: string | Map<number>;         // "string", "number", "boolean", or an object literal mapping named values to actual values
+        isFilePath?: boolean;               // True if option value is a path or fileName
+        shortName?: string;                 // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'
+        description?: DiagnosticMessage;    // The message describing what the command line switch does
+        paramType?: DiagnosticMessage;      // The name to be used for a non-boolean option's parameter
+        error?: DiagnosticMessage;          // The error given when the argument does not fit a customized 'type'
+        experimental?: boolean;
+    }
+
+    /* @internal */
+    export const enum CharacterCodes {
+        nullCharacter = 0,
+        maxAsciiCharacter = 0x7F,
+
+        lineFeed = 0x0A,              // \n
+        carriageReturn = 0x0D,        // \r
+        lineSeparator = 0x2028,
+        paragraphSeparator = 0x2029,
+        nextLine = 0x0085,
+
+        // Unicode 3.0 space characters
+        space = 0x0020,   // " "
+        nonBreakingSpace = 0x00A0,   //
+        enQuad = 0x2000,
+        emQuad = 0x2001,
+        enSpace = 0x2002,
+        emSpace = 0x2003,
+        threePerEmSpace = 0x2004,
+        fourPerEmSpace = 0x2005,
+        sixPerEmSpace = 0x2006,
+        figureSpace = 0x2007,
+        punctuationSpace = 0x2008,
+        thinSpace = 0x2009,
+        hairSpace = 0x200A,
+        zeroWidthSpace = 0x200B,
+        narrowNoBreakSpace = 0x202F,
+        ideographicSpace = 0x3000,
+        mathematicalSpace = 0x205F,
+        ogham = 0x1680,
+
+        _ = 0x5F,
+        $ = 0x24,
+
+        _0 = 0x30,
+        _1 = 0x31,
+        _2 = 0x32,
+        _3 = 0x33,
+        _4 = 0x34,
+        _5 = 0x35,
+        _6 = 0x36,
+        _7 = 0x37,
+        _8 = 0x38,
+        _9 = 0x39,
+
+        a = 0x61,
+        b = 0x62,
+        c = 0x63,
+        d = 0x64,
+        e = 0x65,
+        f = 0x66,
+        g = 0x67,
+        h = 0x68,
+        i = 0x69,
+        j = 0x6A,
+        k = 0x6B,
+        l = 0x6C,
+        m = 0x6D,
+        n = 0x6E,
+        o = 0x6F,
+        p = 0x70,
+        q = 0x71,
+        r = 0x72,
+        s = 0x73,
+        t = 0x74,
+        u = 0x75,
+        v = 0x76,
+        w = 0x77,
+        x = 0x78,
+        y = 0x79,
+        z = 0x7A,
+
+        A = 0x41,
+        B = 0x42,
+        C = 0x43,
+        D = 0x44,
+        E = 0x45,
+        F = 0x46,
+        G = 0x47,
+        H = 0x48,
+        I = 0x49,
+        J = 0x4A,
+        K = 0x4B,
+        L = 0x4C,
+        M = 0x4D,
+        N = 0x4E,
+        O = 0x4F,
+        P = 0x50,
+        Q = 0x51,
+        R = 0x52,
+        S = 0x53,
+        T = 0x54,
+        U = 0x55,
+        V = 0x56,
+        W = 0x57,
+        X = 0x58,
+        Y = 0x59,
+        Z = 0x5a,
+
+        ampersand = 0x26,             // &
+        asterisk = 0x2A,              // *
+        at = 0x40,                    // @
+        backslash = 0x5C,             // \
+        backtick = 0x60,              // `
+        bar = 0x7C,                   // |
+        caret = 0x5E,                 // ^
+        closeBrace = 0x7D,            // }
+        closeBracket = 0x5D,          // ]
+        closeParen = 0x29,            // )
+        colon = 0x3A,                 // :
+        comma = 0x2C,                 // ,
+        dot = 0x2E,                   // .
+        doubleQuote = 0x22,           // "
+        equals = 0x3D,                // =
+        exclamation = 0x21,           // !
+        greaterThan = 0x3E,           // >
+        hash = 0x23,                  // #
+        lessThan = 0x3C,              // <
+        minus = 0x2D,                 // -
+        openBrace = 0x7B,             // {
+        openBracket = 0x5B,           // [
+        openParen = 0x28,             // (
+        percent = 0x25,               // %
+        plus = 0x2B,                  // +
+        question = 0x3F,              // ?
+        semicolon = 0x3B,             // ;
+        singleQuote = 0x27,           // '
+        slash = 0x2F,                 // /
+        tilde = 0x7E,                 // ~
+
+        backspace = 0x08,             // \b
+        formFeed = 0x0C,              // \f
+        byteOrderMark = 0xFEFF,
+        tab = 0x09,                   // \t
+        verticalTab = 0x0B,           // \v
+    }
+
+    export interface CancellationToken {
+        isCancellationRequested(): boolean;
+    }
+
+    export interface CompilerHost {
+        getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
+        getDefaultLibFileName(options: CompilerOptions): string;
+        getCancellationToken? (): CancellationToken;
+        writeFile: WriteFileCallback;
+        getCurrentDirectory(): string;
+        getCanonicalFileName(fileName: string): string;
+        useCaseSensitiveFileNames(): boolean;
+        getNewLine(): string;
+    }
+
+    export interface TextSpan {
+        start: number;
+        length: number;
+    }
+
+    export interface TextChangeRange {
+        span: TextSpan;
+        newLength: number;
+    }
+
+    /* @internal */
+    export interface DiagnosticCollection {
+        // Adds a diagnostic to this diagnostic collection.
+        add(diagnostic: Diagnostic): void;
+
+        // Gets all the diagnostics that aren't associated with a file.
+        getGlobalDiagnostics(): Diagnostic[];
+
+        // If fileName is provided, gets all the diagnostics associated with that file name.
+        // Otherwise, returns all the diagnostics (global and file associated) in this colletion.
+        getDiagnostics(fileName?: string): Diagnostic[];
+
+        // Gets a count of how many times this collection has been modified.  This value changes
+        // each time 'add' is called (regardless of whether or not an equivalent diagnostic was
+        // already in the collection).  As such, it can be used as a simple way to tell if any
+        // operation caused diagnostics to be returned by storing and comparing the return value
+        // of this method before/after the operation is performed.
+        getModificationCount(): number;
+    }
+}
diff --git a/lib/typescript/compiler/utilities.ts b/lib/typescript/compiler/utilities.ts
new file mode 100644
index 000000000..6c17c6fc3
--- /dev/null
+++ b/lib/typescript/compiler/utilities.ts
@@ -0,0 +1,1915 @@
+/// <reference path="binder.ts" />
+
+/* @internal */
+module ts {
+    export interface ReferencePathMatchResult {
+        fileReference?: FileReference
+        diagnosticMessage?: DiagnosticMessage
+        isNoDefaultLib?: boolean
+    }
+
+    export interface SynthesizedNode extends Node {
+        leadingCommentRanges?: CommentRange[];
+        trailingCommentRanges?: CommentRange[];
+        startsOnNewLine: boolean;
+    }
+
+    export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
+        let declarations = symbol.declarations;
+        for (let declaration of declarations) {
+            if (declaration.kind === kind) {
+                return declaration;
+            }
+        }
+
+        return undefined;
+    }
+
+    export interface StringSymbolWriter extends SymbolWriter {
+        string(): string;
+    }
+
+    export interface EmitHost extends ScriptReferenceHost {
+        getSourceFiles(): SourceFile[];
+
+        getCommonSourceDirectory(): string;
+        getCanonicalFileName(fileName: string): string;
+        getNewLine(): string;
+
+        writeFile: WriteFileCallback;
+    }
+
+    // Pool writers to avoid needing to allocate them for every symbol we write.
+    let stringWriters: StringSymbolWriter[] = [];
+    export function getSingleLineStringWriter(): StringSymbolWriter {
+        if (stringWriters.length == 0) {
+            let str = "";
+
+            let writeText: (text: string) => void = text => str += text;
+            return {
+                string: () => str,
+                writeKeyword: writeText,
+                writeOperator: writeText,
+                writePunctuation: writeText,
+                writeSpace: writeText,
+                writeStringLiteral: writeText,
+                writeParameter: writeText,
+                writeSymbol: writeText,
+
+                // Completely ignore indentation for string writers.  And map newlines to
+                // a single space.
+                writeLine: () => str += " ",
+                increaseIndent: () => { },
+                decreaseIndent: () => { },
+                clear: () => str = "",
+                trackSymbol: () => { }
+            };
+        }
+
+        return stringWriters.pop();
+    }
+
+    export function releaseStringWriter(writer: StringSymbolWriter) {
+        writer.clear()
+        stringWriters.push(writer);
+    }
+
+    export function getFullWidth(node: Node) {
+        return node.end - node.pos;
+    }
+
+    // Returns true if this node contains a parse error anywhere underneath it.
+    export function containsParseError(node: Node): boolean {
+        aggregateChildData(node);
+        return (node.parserContextFlags & ParserContextFlags.ThisNodeOrAnySubNodesHasError) !== 0
+    }
+
+    function aggregateChildData(node: Node): void {
+        if (!(node.parserContextFlags & ParserContextFlags.HasAggregatedChildData)) {
+            // A node is considered to contain a parse error if:
+            //  a) the parser explicitly marked that it had an error
+            //  b) any of it's children reported that it had an error.
+            let thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & ParserContextFlags.ThisNodeHasError) !== 0) ||
+                forEachChild(node, containsParseError);
+
+            // If so, mark ourselves accordingly. 
+            if (thisNodeOrAnySubNodesHasError) {
+                node.parserContextFlags |= ParserContextFlags.ThisNodeOrAnySubNodesHasError;
+            }
+
+            // Also mark that we've propogated the child information to this node.  This way we can
+            // always consult the bit directly on this node without needing to check its children
+            // again.
+            node.parserContextFlags |= ParserContextFlags.HasAggregatedChildData;
+        }
+    }
+
+    export function getSourceFileOfNode(node: Node): SourceFile {
+        while (node && node.kind !== SyntaxKind.SourceFile) {
+            node = node.parent;
+        }
+        return <SourceFile>node;
+    }
+
+    export function getStartPositionOfLine(line: number, sourceFile: SourceFile): number {
+        Debug.assert(line >= 0);
+        return getLineStarts(sourceFile)[line];
+    }
+
+    // This is a useful function for debugging purposes.
+    export function nodePosToString(node: Node): string {
+        let file = getSourceFileOfNode(node);
+        let loc = getLineAndCharacterOfPosition(file, node.pos);
+        return `${ file.fileName }(${ loc.line + 1 },${ loc.character + 1 })`;
+    }
+
+    export function getStartPosOfNode(node: Node): number {
+        return node.pos;
+    }
+
+    // Returns true if this node is missing from the actual source code.  'missing' is different
+    // from 'undefined/defined'.  When a node is undefined (which can happen for optional nodes
+    // in the tree), it is definitel missing.  HOwever, a node may be defined, but still be 
+    // missing.  This happens whenever the parser knows it needs to parse something, but can't
+    // get anything in the source code that it expects at that location.  For example:
+    //
+    //          let a: ;
+    //
+    // Here, the Type in the Type-Annotation is not-optional (as there is a colon in the source 
+    // code).  So the parser will attempt to parse out a type, and will create an actual node.
+    // However, this node will be 'missing' in the sense that no actual source-code/tokens are
+    // contained within it.
+    export function nodeIsMissing(node: Node) {
+        if (!node) {
+            return true;
+        }
+
+        return node.pos === node.end && node.kind !== SyntaxKind.EndOfFileToken;
+    }
+
+    export function nodeIsPresent(node: Node) {
+        return !nodeIsMissing(node);
+    }
+
+    export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
+        // With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
+        // want to skip trivia because this will launch us forward to the next token.
+        if (nodeIsMissing(node)) {
+            return node.pos;
+        }
+
+        return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
+    }
+
+    export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
+        if (nodeIsMissing(node) || !node.decorators) {
+            return getTokenPosOfNode(node, sourceFile);
+        }
+
+        return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.decorators.end);        
+    }
+
+    export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string {
+        if (nodeIsMissing(node)) {
+            return "";
+        }
+
+        let text = sourceFile.text;
+        return text.substring(skipTrivia(text, node.pos), node.end);
+    }
+
+    export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string {
+        if (nodeIsMissing(node)) {
+            return "";
+        }
+
+        return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
+    }
+
+    export function getTextOfNode(node: Node): string {
+        return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node);
+    }
+
+    // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__'
+    export function escapeIdentifier(identifier: string): string {
+        return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier;
+    }
+
+    // Remove extra underscore from escaped identifier
+    export function unescapeIdentifier(identifier: string): string {
+        return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier;
+    }
+
+    // Make an identifier from an external module name by extracting the string after the last "/" and replacing
+    // all non-alphanumeric characters with underscores
+    export function makeIdentifierFromModuleName(moduleName: string): string {
+        return getBaseFileName(moduleName).replace(/\W/g, "_");
+    }
+
+    export function isBlockOrCatchScoped(declaration: Declaration) {
+        return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 ||
+            isCatchClauseVariableDeclaration(declaration);
+    }
+
+    // Gets the nearest enclosing block scope container that has the provided node 
+    // as a descendant, that is not the provided node.
+    export function getEnclosingBlockScopeContainer(node: Node): Node {
+        let current = node.parent;
+        while (current) {
+            if (isFunctionLike(current)) {
+                return current;
+            }
+            switch (current.kind) {
+                case SyntaxKind.SourceFile:
+                case SyntaxKind.CaseBlock:
+                case SyntaxKind.CatchClause:
+                case SyntaxKind.ModuleDeclaration:
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                    return current;
+                case SyntaxKind.Block:
+                    // function block is not considered block-scope container
+                    // see comment in binder.ts: bind(...), case for SyntaxKind.Block
+                    if (!isFunctionLike(current.parent)) {
+                        return current;
+                    }
+            }
+
+            current = current.parent;
+        }
+    }
+
+    export function isCatchClauseVariableDeclaration(declaration: Declaration) {
+        return declaration &&
+            declaration.kind === SyntaxKind.VariableDeclaration &&
+            declaration.parent &&
+            declaration.parent.kind === SyntaxKind.CatchClause;
+    }
+
+    // Return display name of an identifier
+    // Computed property names will just be emitted as "[<expr>]", where <expr> is the source
+    // text of the expression in the computed property.
+    export function declarationNameToString(name: DeclarationName) {
+        return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
+    }
+
+    export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
+        let sourceFile = getSourceFileOfNode(node);
+        let span = getErrorSpanForNode(sourceFile, node);
+        return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2);
+    }
+
+    export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic {
+        let sourceFile = getSourceFileOfNode(node);
+        let span = getErrorSpanForNode(sourceFile, node);
+        return {
+            file: sourceFile,
+            start: span.start,
+            length: span.length,
+            code: messageChain.code,
+            category: messageChain.category,
+            messageText: messageChain.next ? messageChain : messageChain.messageText
+        };
+    }
+
+    export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): TextSpan {
+        let scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.text, /*onError:*/ undefined, pos);
+        scanner.scan();
+        let start = scanner.getTokenPos();
+        return createTextSpanFromBounds(start, scanner.getTextPos());
+    }
+
+    export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpan {
+        let errorNode = node;
+        switch (node.kind) {
+            case SyntaxKind.SourceFile:
+                let pos = skipTrivia(sourceFile.text, 0, /*stopAfterLineBreak*/ false);
+                if (pos === sourceFile.text.length) {
+                    // file is empty - return span for the beginning of the file
+                    return createTextSpan(0, 0);
+                }
+                return getSpanOfTokenAtPosition(sourceFile, pos);
+            // This list is a work in progress. Add missing node kinds to improve their error
+            // spans.
+            case SyntaxKind.VariableDeclaration:
+            case SyntaxKind.BindingElement:
+            case SyntaxKind.ClassDeclaration:
+            case SyntaxKind.ClassExpression:
+            case SyntaxKind.InterfaceDeclaration:
+            case SyntaxKind.ModuleDeclaration:
+            case SyntaxKind.EnumDeclaration:
+            case SyntaxKind.EnumMember:
+            case SyntaxKind.FunctionDeclaration:
+            case SyntaxKind.FunctionExpression:
+                errorNode = (<Declaration>node).name;
+                break;
+        }
+
+        if (errorNode === undefined) {
+            // If we don't have a better node, then just set the error on the first token of 
+            // construct.
+            return getSpanOfTokenAtPosition(sourceFile, node.pos);
+        }
+
+        let pos = nodeIsMissing(errorNode)
+            ? errorNode.pos
+            : skipTrivia(sourceFile.text, errorNode.pos);
+
+        return createTextSpanFromBounds(pos, errorNode.end);
+    }
+
+    export function isExternalModule(file: SourceFile): boolean {
+        return file.externalModuleIndicator !== undefined;
+    }
+
+    export function isDeclarationFile(file: SourceFile): boolean {
+        return (file.flags & NodeFlags.DeclarationFile) !== 0;
+    }
+
+    export function isConstEnumDeclaration(node: Node): boolean {
+        return node.kind === SyntaxKind.EnumDeclaration && isConst(node);
+    }
+
+    function walkUpBindingElementsAndPatterns(node: Node): Node {
+        while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
+            node = node.parent;
+        }
+
+        return node;
+    }
+
+    // Returns the node flags for this node and all relevant parent nodes.  This is done so that 
+    // nodes like variable declarations and binding elements can returned a view of their flags
+    // that includes the modifiers from their container.  i.e. flags like export/declare aren't
+    // stored on the variable declaration directly, but on the containing variable statement 
+    // (if it has one).  Similarly, flags for let/const are store on the variable declaration
+    // list.  By calling this function, all those flags are combined so that the client can treat
+    // the node as if it actually had those flags.
+    export function getCombinedNodeFlags(node: Node): NodeFlags {
+        node = walkUpBindingElementsAndPatterns(node);
+
+        let flags = node.flags;
+        if (node.kind === SyntaxKind.VariableDeclaration) {
+            node = node.parent;
+        }
+
+        if (node && node.kind === SyntaxKind.VariableDeclarationList) {
+            flags |= node.flags;
+            node = node.parent;
+        }
+
+        if (node && node.kind === SyntaxKind.VariableStatement) {
+            flags |= node.flags;
+        }
+
+        return flags;
+    }
+
+    export function isConst(node: Node): boolean {
+        return !!(getCombinedNodeFlags(node) & NodeFlags.Const);
+    }
+
+    export function isLet(node: Node): boolean {
+        return !!(getCombinedNodeFlags(node) & NodeFlags.Let);
+    }
+
+    export function isPrologueDirective(node: Node): boolean {
+        return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
+    }
+
+    export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) {
+        // If parameter/type parameter, the prev token trailing comments are part of this node too
+        if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) {
+            // e.g.   (/** blah */ a, /** blah */ b);
+
+            // e.g.:     (
+            //            /** blah */ a,
+            //            /** blah */ b);
+            return concatenate(
+                getTrailingCommentRanges(sourceFileOfNode.text, node.pos),
+                getLeadingCommentRanges(sourceFileOfNode.text, node.pos));
+        }
+        else {
+            return getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
+        }
+    }
+
+    export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) {
+        return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment);
+
+        function isJsDocComment(comment: CommentRange) {
+            // True if the comment starts with '/**' but not if it is '/**/'
+            return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
+                sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
+                sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
+        }
+    }
+
+    export let fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)('|")(.+?)\2.*?\/>/
+
+    // Warning: This has the same semantics as the forEach family of functions,
+    //          in that traversal terminates in the event that 'visitor' supplies a truthy value.
+    export function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
+
+        return traverse(body);
+
+        function traverse(node: Node): T {
+            switch (node.kind) {
+                case SyntaxKind.ReturnStatement:
+                    return visitor(<ReturnStatement>node);
+                case SyntaxKind.CaseBlock:
+                case SyntaxKind.Block:
+                case SyntaxKind.IfStatement:
+                case SyntaxKind.DoStatement:
+                case SyntaxKind.WhileStatement:
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                case SyntaxKind.WithStatement:
+                case SyntaxKind.SwitchStatement:
+                case SyntaxKind.CaseClause:
+                case SyntaxKind.DefaultClause:
+                case SyntaxKind.LabeledStatement:
+                case SyntaxKind.TryStatement:
+                case SyntaxKind.CatchClause:
+                    return forEachChild(node, traverse);
+            }
+        }
+    }
+
+    export function isVariableLike(node: Node): boolean {
+        if (node) {
+            switch (node.kind) {
+                case SyntaxKind.BindingElement:
+                case SyntaxKind.EnumMember:
+                case SyntaxKind.Parameter:
+                case SyntaxKind.PropertyAssignment:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.ShorthandPropertyAssignment:
+                case SyntaxKind.VariableDeclaration:
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    export function isAccessor(node: Node): boolean {
+        if (node) {
+            switch (node.kind) {
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    export function isFunctionLike(node: Node): boolean {
+        if (node) {
+            switch (node.kind) {
+                case SyntaxKind.Constructor:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.ArrowFunction:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.ConstructSignature:
+                case SyntaxKind.IndexSignature:
+                case SyntaxKind.FunctionType:
+                case SyntaxKind.ConstructorType:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                case SyntaxKind.FunctionDeclaration:
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    export function isFunctionBlock(node: Node) {
+        return node && node.kind === SyntaxKind.Block && isFunctionLike(node.parent);
+    }
+
+    export function isObjectLiteralMethod(node: Node) {
+        return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression;
+    }
+
+    export function getContainingFunction(node: Node): FunctionLikeDeclaration {
+        while (true) {
+            node = node.parent;
+            if (!node || isFunctionLike(node)) {
+                return <FunctionLikeDeclaration>node;
+            }
+        }
+    }
+
+    export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
+        while (true) {
+            node = node.parent;
+            if (!node) {
+                return undefined;
+            }
+            switch (node.kind) {
+                case SyntaxKind.ComputedPropertyName:
+                    // If the grandparent node is an object literal (as opposed to a class),
+                    // then the computed property is not a 'this' container.
+                    // A computed property name in a class needs to be a this container
+                    // so that we can error on it.
+                    if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
+                        return node;
+                    }
+                    // If this is a computed property, then the parent should not
+                    // make it a this container. The parent might be a property
+                    // in an object literal, like a method or accessor. But in order for
+                    // such a parent to be a this container, the reference must be in
+                    // the *body* of the container.
+                    node = node.parent;
+                    break;
+                case SyntaxKind.Decorator:
+                    // Decorators are always applied outside of the body of a class or method. 
+                    if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) {
+                        // If the decorator's parent is a Parameter, we resolve the this container from
+                        // the grandparent class declaration.
+                        node = node.parent.parent;
+                    }
+                    else if (isClassElement(node.parent)) {
+                        // If the decorator's parent is a class element, we resolve the 'this' container
+                        // from the parent class declaration.
+                        node = node.parent;
+                    }
+                    break;
+                case SyntaxKind.ArrowFunction:
+                    if (!includeArrowFunctions) {
+                        continue;
+                    }
+                // Fall through
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ModuleDeclaration:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.Constructor:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.EnumDeclaration:
+                case SyntaxKind.SourceFile:
+                    return node;
+            }
+        }
+    }
+
+    export function getSuperContainer(node: Node, includeFunctions: boolean): Node {
+        while (true) {
+            node = node.parent;
+            if (!node) return node;
+            switch (node.kind) {
+                case SyntaxKind.ComputedPropertyName:
+                    // If the grandparent node is an object literal (as opposed to a class),
+                    // then the computed property is not a 'super' container.
+                    // A computed property name in a class needs to be a super container
+                    // so that we can error on it.
+                    if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
+                        return node;
+                    }
+                    // If this is a computed property, then the parent should not
+                    // make it a super container. The parent might be a property
+                    // in an object literal, like a method or accessor. But in order for
+                    // such a parent to be a super container, the reference must be in
+                    // the *body* of the container.
+                    node = node.parent;
+                    break;
+                case SyntaxKind.Decorator:
+                    // Decorators are always applied outside of the body of a class or method. 
+                    if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) {
+                        // If the decorator's parent is a Parameter, we resolve the this container from
+                        // the grandparent class declaration.
+                        node = node.parent.parent;
+                    }
+                    else if (isClassElement(node.parent)) {
+                        // If the decorator's parent is a class element, we resolve the 'this' container
+                        // from the parent class declaration.
+                        node = node.parent;
+                    }
+                    break;
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                    if (!includeFunctions) {
+                        continue;
+                    }
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.Constructor:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                    return node;
+            }
+        }
+    }
+
+    export function getInvokedExpression(node: CallLikeExpression): Expression {
+        if (node.kind === SyntaxKind.TaggedTemplateExpression) {
+            return (<TaggedTemplateExpression>node).tag;
+        }
+        
+        // Will either be a CallExpression or NewExpression.
+        return (<CallExpression>node).expression;
+    }
+
+    export function nodeCanBeDecorated(node: Node): boolean {
+        switch (node.kind) {
+            case SyntaxKind.ClassDeclaration:
+                // classes are valid targets
+                return true;
+
+            case SyntaxKind.PropertyDeclaration:
+                // property declarations are valid if their parent is a class declaration.
+                return node.parent.kind === SyntaxKind.ClassDeclaration;
+
+            case SyntaxKind.Parameter:
+                // if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target;
+                return (<FunctionLikeDeclaration>node.parent).body && node.parent.parent.kind === SyntaxKind.ClassDeclaration;
+
+            case SyntaxKind.GetAccessor:
+            case SyntaxKind.SetAccessor:
+            case SyntaxKind.MethodDeclaration:
+                // if this method has a body and its parent is a class declaration, this is a valid target.
+                return (<FunctionLikeDeclaration>node).body && node.parent.kind === SyntaxKind.ClassDeclaration;
+        }
+
+        return false;
+    }
+
+    export function nodeIsDecorated(node: Node): boolean {
+        switch (node.kind) {
+            case SyntaxKind.ClassDeclaration:
+                if (node.decorators) {
+                    return true;
+                }
+
+                return false;
+
+            case SyntaxKind.PropertyDeclaration:
+            case SyntaxKind.Parameter:
+                if (node.decorators) {
+                    return true;
+                }
+
+                return false;
+
+            case SyntaxKind.GetAccessor:
+                if ((<FunctionLikeDeclaration>node).body && node.decorators) {
+                    return true;
+                }
+
+                return false;
+
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.SetAccessor:
+                if ((<FunctionLikeDeclaration>node).body && node.decorators) {
+                    return true;
+                }
+
+                return false;
+        }
+
+        return false;
+    }
+
+    export function childIsDecorated(node: Node): boolean {
+        switch (node.kind) {
+            case SyntaxKind.ClassDeclaration:
+                return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);
+
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.SetAccessor:
+                return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
+        }
+
+        return false;
+    }
+
+    export function nodeOrChildIsDecorated(node: Node): boolean {
+        return nodeIsDecorated(node) || childIsDecorated(node);
+    }
+
+    export function isExpression(node: Node): boolean {
+        switch (node.kind) {
+            case SyntaxKind.ThisKeyword:
+            case SyntaxKind.SuperKeyword:
+            case SyntaxKind.NullKeyword:
+            case SyntaxKind.TrueKeyword:
+            case SyntaxKind.FalseKeyword:
+            case SyntaxKind.RegularExpressionLiteral:
+            case SyntaxKind.ArrayLiteralExpression:
+            case SyntaxKind.ObjectLiteralExpression:
+            case SyntaxKind.PropertyAccessExpression:
+            case SyntaxKind.ElementAccessExpression:
+            case SyntaxKind.CallExpression:
+            case SyntaxKind.NewExpression:
+            case SyntaxKind.TaggedTemplateExpression:
+            case SyntaxKind.TypeAssertionExpression:
+            case SyntaxKind.ParenthesizedExpression:
+            case SyntaxKind.FunctionExpression:
+            case SyntaxKind.ClassExpression:
+            case SyntaxKind.ArrowFunction:
+            case SyntaxKind.VoidExpression:
+            case SyntaxKind.DeleteExpression:
+            case SyntaxKind.TypeOfExpression:
+            case SyntaxKind.PrefixUnaryExpression:
+            case SyntaxKind.PostfixUnaryExpression:
+            case SyntaxKind.BinaryExpression:
+            case SyntaxKind.ConditionalExpression:
+            case SyntaxKind.SpreadElementExpression:
+            case SyntaxKind.TemplateExpression:
+            case SyntaxKind.NoSubstitutionTemplateLiteral:
+            case SyntaxKind.OmittedExpression:
+                return true;
+            case SyntaxKind.QualifiedName:
+                while (node.parent.kind === SyntaxKind.QualifiedName) {
+                    node = node.parent;
+                }
+
+                return node.parent.kind === SyntaxKind.TypeQuery;
+            case SyntaxKind.Identifier:
+                if (node.parent.kind === SyntaxKind.TypeQuery) {
+                    return true;
+                }
+            // fall through
+            case SyntaxKind.NumericLiteral:
+            case SyntaxKind.StringLiteral:
+                let parent = node.parent;
+                switch (parent.kind) {
+                    case SyntaxKind.VariableDeclaration:
+                    case SyntaxKind.Parameter:
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                    case SyntaxKind.EnumMember:
+                    case SyntaxKind.PropertyAssignment:
+                    case SyntaxKind.BindingElement:
+                        return (<VariableLikeDeclaration>parent).initializer === node;
+                    case SyntaxKind.ExpressionStatement:
+                    case SyntaxKind.IfStatement:
+                    case SyntaxKind.DoStatement:
+                    case SyntaxKind.WhileStatement:
+                    case SyntaxKind.ReturnStatement:
+                    case SyntaxKind.WithStatement:
+                    case SyntaxKind.SwitchStatement:
+                    case SyntaxKind.CaseClause:
+                    case SyntaxKind.ThrowStatement:
+                    case SyntaxKind.SwitchStatement:
+                        return (<ExpressionStatement>parent).expression === node;
+                    case SyntaxKind.ForStatement:
+                        let forStatement = <ForStatement>parent;
+                        return (forStatement.initializer === node && forStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) ||
+                            forStatement.condition === node ||
+                            forStatement.incrementor === node;
+                    case SyntaxKind.ForInStatement:
+                    case SyntaxKind.ForOfStatement:
+                        let forInStatement = <ForInStatement | ForOfStatement>parent;
+                        return (forInStatement.initializer === node && forInStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) ||
+                            forInStatement.expression === node;
+                    case SyntaxKind.TypeAssertionExpression:
+                        return node === (<TypeAssertion>parent).expression;
+                    case SyntaxKind.TemplateSpan:
+                        return node === (<TemplateSpan>parent).expression;
+                    case SyntaxKind.ComputedPropertyName:
+                        return node === (<ComputedPropertyName>parent).expression;
+                    case SyntaxKind.Decorator:
+                        return true;
+                    default:
+                        if (isExpression(parent)) {
+                            return true;
+                        }
+                }
+        }
+        return false;
+    }
+
+    export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) {
+        let moduleState = getModuleInstanceState(node)
+        return moduleState === ModuleInstanceState.Instantiated ||
+            (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly);
+    }
+
+    export function isExternalModuleImportEqualsDeclaration(node: Node) {
+        return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference;
+    }
+
+    export function getExternalModuleImportEqualsDeclarationExpression(node: Node) {
+        Debug.assert(isExternalModuleImportEqualsDeclaration(node));
+        return (<ExternalModuleReference>(<ImportEqualsDeclaration>node).moduleReference).expression;
+    }
+
+    export function isInternalModuleImportEqualsDeclaration(node: Node) {
+        return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
+    }
+
+    export function getExternalModuleName(node: Node): Expression {
+        if (node.kind === SyntaxKind.ImportDeclaration) {
+            return (<ImportDeclaration>node).moduleSpecifier;
+        }
+        if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
+            let reference = (<ImportEqualsDeclaration>node).moduleReference;
+            if (reference.kind === SyntaxKind.ExternalModuleReference) {
+                return (<ExternalModuleReference>reference).expression;
+            }
+        }
+        if (node.kind === SyntaxKind.ExportDeclaration) {
+            return (<ExportDeclaration>node).moduleSpecifier;
+        }
+    }
+
+    export function hasDotDotDotToken(node: Node) {
+        return node && node.kind === SyntaxKind.Parameter && (<ParameterDeclaration>node).dotDotDotToken !== undefined;
+    }
+
+    export function hasQuestionToken(node: Node) {
+        if (node) {
+            switch (node.kind) {
+                case SyntaxKind.Parameter:
+                    return (<ParameterDeclaration>node).questionToken !== undefined;
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                    return (<MethodDeclaration>node).questionToken !== undefined;
+                case SyntaxKind.ShorthandPropertyAssignment:
+                case SyntaxKind.PropertyAssignment:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    return (<PropertyDeclaration>node).questionToken !== undefined;
+            }
+        }
+
+        return false;
+    }
+
+    export function hasRestParameters(s: SignatureDeclaration): boolean {
+        return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined;
+    }
+
+    export function isLiteralKind(kind: SyntaxKind): boolean {
+        return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
+    }
+
+    export function isTextualLiteralKind(kind: SyntaxKind): boolean {
+        return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NoSubstitutionTemplateLiteral;
+    }
+
+    export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
+        return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
+    }
+
+    export function isBindingPattern(node: Node) {
+        return !!node && (node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern);
+    }
+
+    export function isInAmbientContext(node: Node): boolean {
+        while (node) {
+            if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) {
+                return true;
+            }
+
+            node = node.parent;
+        }
+        return false;
+    }
+
+    export function isDeclaration(node: Node): boolean {
+        switch (node.kind) {
+            case SyntaxKind.ArrowFunction:
+            case SyntaxKind.BindingElement:
+            case SyntaxKind.ClassDeclaration:
+            case SyntaxKind.Constructor:
+            case SyntaxKind.EnumDeclaration:
+            case SyntaxKind.EnumMember:
+            case SyntaxKind.ExportSpecifier:
+            case SyntaxKind.FunctionDeclaration:
+            case SyntaxKind.FunctionExpression:
+            case SyntaxKind.GetAccessor:
+            case SyntaxKind.ImportClause:
+            case SyntaxKind.ImportEqualsDeclaration:
+            case SyntaxKind.ImportSpecifier:
+            case SyntaxKind.InterfaceDeclaration:
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.MethodSignature:
+            case SyntaxKind.ModuleDeclaration:
+            case SyntaxKind.NamespaceImport:
+            case SyntaxKind.Parameter:
+            case SyntaxKind.PropertyAssignment:
+            case SyntaxKind.PropertyDeclaration:
+            case SyntaxKind.PropertySignature:
+            case SyntaxKind.SetAccessor:
+            case SyntaxKind.ShorthandPropertyAssignment:
+            case SyntaxKind.TypeAliasDeclaration:
+            case SyntaxKind.TypeParameter:
+            case SyntaxKind.VariableDeclaration:
+                return true;
+        }
+        return false;
+    }
+
+    export function isStatement(n: Node): boolean {
+        switch (n.kind) {
+            case SyntaxKind.BreakStatement:
+            case SyntaxKind.ContinueStatement:
+            case SyntaxKind.DebuggerStatement:
+            case SyntaxKind.DoStatement:
+            case SyntaxKind.ExpressionStatement:
+            case SyntaxKind.EmptyStatement:
+            case SyntaxKind.ForInStatement:
+            case SyntaxKind.ForOfStatement:
+            case SyntaxKind.ForStatement:
+            case SyntaxKind.IfStatement:
+            case SyntaxKind.LabeledStatement:
+            case SyntaxKind.ReturnStatement:
+            case SyntaxKind.SwitchStatement:
+            case SyntaxKind.ThrowKeyword:
+            case SyntaxKind.TryStatement:
+            case SyntaxKind.VariableStatement:
+            case SyntaxKind.WhileStatement:
+            case SyntaxKind.WithStatement:
+            case SyntaxKind.ExportAssignment:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    export function isClassElement(n: Node): boolean {
+        switch (n.kind) {
+            case SyntaxKind.Constructor:
+            case SyntaxKind.PropertyDeclaration:
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.GetAccessor:
+            case SyntaxKind.SetAccessor:
+            case SyntaxKind.MethodSignature:
+            case SyntaxKind.IndexSignature:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    // True if the given identifier, string literal, or number literal is the name of a declaration node
+    export function isDeclarationName(name: Node): boolean {
+        if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
+            return false;
+        }
+
+        let parent = name.parent;
+        if (parent.kind === SyntaxKind.ImportSpecifier || parent.kind === SyntaxKind.ExportSpecifier) {
+            if ((<ImportOrExportSpecifier>parent).propertyName) {
+                return true;
+            }
+        }
+
+        if (isDeclaration(parent)) {
+            return (<Declaration>parent).name === name;
+        }
+
+        return false;
+    }
+
+    // An alias symbol is created by one of the following declarations:
+    // import <symbol> = ...
+    // import <symbol> from ...
+    // import * as <symbol> from ...
+    // import { x as <symbol> } from ...
+    // export { x as <symbol> } from ...
+    // export = ...
+    // export default ...
+    export function isAliasSymbolDeclaration(node: Node): boolean {
+        return node.kind === SyntaxKind.ImportEqualsDeclaration ||
+            node.kind === SyntaxKind.ImportClause && !!(<ImportClause>node).name ||
+            node.kind === SyntaxKind.NamespaceImport ||
+            node.kind === SyntaxKind.ImportSpecifier ||
+            node.kind === SyntaxKind.ExportSpecifier ||
+            node.kind === SyntaxKind.ExportAssignment && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier;
+    }
+
+    export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration) {
+        let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
+        return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
+    }
+
+    export function getClassImplementsHeritageClauseElements(node: ClassDeclaration) {
+        let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword);
+        return heritageClause ? heritageClause.types : undefined;
+    }
+
+    export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) {
+        let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
+        return heritageClause ? heritageClause.types : undefined;
+    }
+
+    export function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind) {
+        if (clauses) {
+            for (let clause of clauses) {
+                if (clause.token === kind) {
+                    return clause;
+                }
+            }
+        }
+
+        return undefined;
+    }
+
+    export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference) {
+        if (!host.getCompilerOptions().noResolve) {
+            let referenceFileName = isRootedDiskPath(reference.fileName) ? reference.fileName : combinePaths(getDirectoryPath(sourceFile.fileName), reference.fileName);
+            referenceFileName = getNormalizedAbsolutePath(referenceFileName, host.getCurrentDirectory());
+            return host.getSourceFile(referenceFileName);
+        }
+    }
+
+    export function getAncestor(node: Node, kind: SyntaxKind): Node {
+        while (node) {
+            if (node.kind === kind) {
+                return node;
+            }
+            node = node.parent;
+        }
+        return undefined;
+    }
+
+    export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
+        let simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
+        let isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
+        if (simpleReferenceRegEx.exec(comment)) {
+            if (isNoDefaultLibRegEx.exec(comment)) {
+                return {
+                    isNoDefaultLib: true
+                }
+            }
+            else {
+                let matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
+                if (matchResult) {
+                    let start = commentRange.pos;
+                    let end = commentRange.end;
+                    return {
+                        fileReference: {
+                            pos: start,
+                            end: end,
+                            fileName: matchResult[3]
+                        },
+                        isNoDefaultLib: false
+                    };
+                }
+                else {
+                    return {
+                        diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax,
+                        isNoDefaultLib: false
+                    };
+                }
+            }
+        }
+
+        return undefined;
+    }
+
+    export function isKeyword(token: SyntaxKind): boolean {
+        return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
+    }
+
+    export function isTrivia(token: SyntaxKind) {
+        return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
+    }
+
+    /**
+     * A declaration has a dynamic name if both of the following are true:
+     *   1. The declaration has a computed property name
+     *   2. The computed name is *not* expressed as Symbol.<name>, where name
+     *      is a property of the Symbol constructor that denotes a built in
+     *      Symbol.
+     */
+    export function hasDynamicName(declaration: Declaration): boolean {
+        return declaration.name &&
+            declaration.name.kind === SyntaxKind.ComputedPropertyName &&
+            !isWellKnownSymbolSyntactically((<ComputedPropertyName>declaration.name).expression);
+    }
+
+    /**
+     * Checks if the expression is of the form:
+     *    Symbol.name
+     * where Symbol is literally the word "Symbol", and name is any identifierName
+     */
+    export function isWellKnownSymbolSyntactically(node: Expression): boolean {
+        return node.kind === SyntaxKind.PropertyAccessExpression && isESSymbolIdentifier((<PropertyAccessExpression>node).expression);
+    }
+
+    export function getPropertyNameForPropertyNameNode(name: DeclarationName): string {
+        if (name.kind === SyntaxKind.Identifier || name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral) {
+            return (<Identifier | LiteralExpression>name).text;
+        }
+        if (name.kind === SyntaxKind.ComputedPropertyName) {
+            let nameExpression = (<ComputedPropertyName>name).expression;
+            if (isWellKnownSymbolSyntactically(nameExpression)) {
+                let rightHandSideName = (<PropertyAccessExpression>nameExpression).name.text;
+                return getPropertyNameForKnownSymbolName(rightHandSideName);
+            }
+        }
+
+        return undefined;
+    }
+
+    export function getPropertyNameForKnownSymbolName(symbolName: string): string {
+        return "__@" + symbolName;
+    }
+
+    /**
+     * Includes the word "Symbol" with unicode escapes
+     */
+    export function isESSymbolIdentifier(node: Node): boolean {
+        return node.kind === SyntaxKind.Identifier && (<Identifier>node).text === "Symbol";
+    }
+
+    export function isModifier(token: SyntaxKind): boolean {
+        switch (token) {
+            case SyntaxKind.PublicKeyword:
+            case SyntaxKind.PrivateKeyword:
+            case SyntaxKind.ProtectedKeyword:
+            case SyntaxKind.StaticKeyword:
+            case SyntaxKind.ExportKeyword:
+            case SyntaxKind.DeclareKeyword:
+            case SyntaxKind.ConstKeyword:
+            case SyntaxKind.DefaultKeyword:
+                return true;
+        }
+        return false;
+    }
+        
+    export function nodeStartsNewLexicalEnvironment(n: Node): boolean {
+        return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile;
+    }
+
+    export function nodeIsSynthesized(node: Node): boolean {
+        return node.pos === -1;
+    }
+
+    export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node {
+        let node = <SynthesizedNode>createNode(kind);
+        node.pos = -1;
+        node.end = -1;
+        node.startsOnNewLine = startsOnNewLine;
+        return node;
+    }
+
+    export function createSynthesizedNodeArray(): NodeArray<any> {
+        var array = <NodeArray<any>>[];
+        array.pos = -1;
+        array.end = -1;
+        return array;
+    }
+
+    export function createDiagnosticCollection(): DiagnosticCollection {
+        let nonFileDiagnostics: Diagnostic[] = [];
+        let fileDiagnostics: Map<Diagnostic[]> = {};
+
+        let diagnosticsModified = false;
+        let modificationCount = 0;
+
+        return {
+            add,
+            getGlobalDiagnostics,
+            getDiagnostics,
+            getModificationCount
+        };
+
+        function getModificationCount() {
+            return modificationCount;
+        }
+
+        function add(diagnostic: Diagnostic): void {
+            let diagnostics: Diagnostic[];
+            if (diagnostic.file) {
+                diagnostics = fileDiagnostics[diagnostic.file.fileName];
+                if (!diagnostics) {
+                    diagnostics = [];
+                    fileDiagnostics[diagnostic.file.fileName] = diagnostics;
+                }
+            }
+            else {
+                diagnostics = nonFileDiagnostics;
+            }
+
+            diagnostics.push(diagnostic);
+            diagnosticsModified = true;
+            modificationCount++;
+        }
+
+        function getGlobalDiagnostics(): Diagnostic[] {
+            sortAndDeduplicate();
+            return nonFileDiagnostics;
+        }
+
+        function getDiagnostics(fileName?: string): Diagnostic[] {
+            sortAndDeduplicate();
+            if (fileName) {
+                return fileDiagnostics[fileName] || [];
+            }
+
+            let allDiagnostics: Diagnostic[] = [];
+            function pushDiagnostic(d: Diagnostic) {
+                allDiagnostics.push(d);
+            }
+
+            forEach(nonFileDiagnostics, pushDiagnostic);
+
+            for (let key in fileDiagnostics) {
+                if (hasProperty(fileDiagnostics, key)) {
+                    forEach(fileDiagnostics[key], pushDiagnostic);
+                }
+            }
+
+            return sortAndDeduplicateDiagnostics(allDiagnostics);
+        }
+
+        function sortAndDeduplicate() {
+            if (!diagnosticsModified) {
+                return;
+            }
+
+            diagnosticsModified = false;
+            nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
+
+            for (let key in fileDiagnostics) {
+                if (hasProperty(fileDiagnostics, key)) {
+                    fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
+                }
+            }
+        }
+    }
+    
+    // This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator,
+    // paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in
+    // the language service. These characters should be escaped when printing, and if any characters are added,
+    // the map below must be updated. Note that this regexp *does not* include the 'delete' character.
+    // There is no reason for this other than that JSON.stringify does not handle it either.
+    let escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
+    let escapedCharsMap: Map<string> = {
+        "\0": "\\0",
+        "\t": "\\t",
+        "\v": "\\v",
+        "\f": "\\f",
+        "\b": "\\b",
+        "\r": "\\r",
+        "\n": "\\n",
+        "\\": "\\\\",
+        "\"": "\\\"",
+        "\u2028": "\\u2028", // lineSeparator
+        "\u2029": "\\u2029", // paragraphSeparator
+        "\u0085": "\\u0085"  // nextLine
+    };
+
+    /**
+     * Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2),
+     * but augmented for a few select characters (e.g. lineSeparator, paragraphSeparator, nextLine)
+     * Note that this doesn't actually wrap the input in double quotes.
+     */
+    export function escapeString(s: string): string {
+        s = escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, getReplacement) : s;
+
+        return s;
+
+        function getReplacement(c: string) {
+            return escapedCharsMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
+        }
+    }
+
+    function get16BitUnicodeEscapeSequence(charCode: number): string {
+        let hexCharCode = charCode.toString(16).toUpperCase();
+        let paddedHexCode = ("0000" + hexCharCode).slice(-4);
+        return "\\u" + paddedHexCode;
+    }
+
+    let nonAsciiCharacters = /[^\u0000-\u007F]/g;
+    export function escapeNonAsciiCharacters(s: string): string {
+        // Replace non-ASCII characters with '\uNNNN' escapes if any exist.
+        // Otherwise just return the original string.
+        return nonAsciiCharacters.test(s) ?
+            s.replace(nonAsciiCharacters, c => get16BitUnicodeEscapeSequence(c.charCodeAt(0))) :
+            s;
+    }
+
+    export interface EmitTextWriter {
+        write(s: string): void;
+        writeTextOfNode(sourceFile: SourceFile, node: Node): void;
+        writeLine(): void;
+        increaseIndent(): void;
+        decreaseIndent(): void;
+        getText(): string;
+        rawWrite(s: string): void;
+        writeLiteral(s: string): void;
+        getTextPos(): number;
+        getLine(): number;
+        getColumn(): number;
+        getIndent(): number;
+    }
+
+    let indentStrings: string[] = ["", "    "];
+    export function getIndentString(level: number) {
+        if (indentStrings[level] === undefined) {
+            indentStrings[level] = getIndentString(level - 1) + indentStrings[1];
+        }
+        return indentStrings[level];
+    }
+
+    export function getIndentSize() {
+        return indentStrings[1].length;
+    }
+
+    export function createTextWriter(newLine: String): EmitTextWriter {
+        let output = "";
+        let indent = 0;
+        let lineStart = true;
+        let lineCount = 0;
+        let linePos = 0;
+
+        function write(s: string) {
+            if (s && s.length) {
+                if (lineStart) {
+                    output += getIndentString(indent);
+                    lineStart = false;
+                }
+                output += s;
+            }
+        }
+
+        function rawWrite(s: string) {
+            if (s !== undefined) {
+                if (lineStart) {
+                    lineStart = false;
+                }
+                output += s;
+            }
+        }
+
+        function writeLiteral(s: string) {
+            if (s && s.length) {
+                write(s);
+                let lineStartsOfS = computeLineStarts(s);
+                if (lineStartsOfS.length > 1) {
+                    lineCount = lineCount + lineStartsOfS.length - 1;
+                    linePos = output.length - s.length + lineStartsOfS[lineStartsOfS.length - 1];
+                }
+            }
+        }
+
+        function writeLine() {
+            if (!lineStart) {
+                output += newLine;
+                lineCount++;
+                linePos = output.length;
+                lineStart = true;
+            }
+        }
+
+        function writeTextOfNode(sourceFile: SourceFile, node: Node) {
+            write(getSourceTextOfNodeFromSourceFile(sourceFile, node));
+        }
+
+        return {
+            write,
+            rawWrite,
+            writeTextOfNode,
+            writeLiteral,
+            writeLine,
+            increaseIndent: () => indent++,
+            decreaseIndent: () => indent--,
+            getIndent: () => indent,
+            getTextPos: () => output.length,
+            getLine: () => lineCount + 1,
+            getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1,
+            getText: () => output,
+        };
+    }
+
+    export function getOwnEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost, extension: string) {
+        let compilerOptions = host.getCompilerOptions();
+        let emitOutputFilePathWithoutExtension: string;
+        if (compilerOptions.outDir) {
+            emitOutputFilePathWithoutExtension = removeFileExtension(getSourceFilePathInNewDir(sourceFile, host, compilerOptions.outDir));
+        }
+        else {
+            emitOutputFilePathWithoutExtension = removeFileExtension(sourceFile.fileName);
+        }
+
+        return emitOutputFilePathWithoutExtension + extension;
+    }
+
+    export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
+        let sourceFilePath = getNormalizedAbsolutePath(sourceFile.fileName, host.getCurrentDirectory());
+        sourceFilePath = sourceFilePath.replace(host.getCommonSourceDirectory(), "");
+        return combinePaths(newDirPath, sourceFilePath);
+    }
+
+    export function writeFile(host: EmitHost, diagnostics: Diagnostic[], fileName: string, data: string, writeByteOrderMark: boolean) {
+        host.writeFile(fileName, data, writeByteOrderMark, hostErrorMessage => {
+            diagnostics.push(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage));
+        });
+    }
+
+    export function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number) {
+        return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
+    }
+
+    export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration {
+        return forEach(node.members, member => {
+            if (member.kind === SyntaxKind.Constructor && nodeIsPresent((<ConstructorDeclaration>member).body)) {
+                return <ConstructorDeclaration>member;
+            }
+        });
+    }
+
+    export function shouldEmitToOwnFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean {
+        if (!isDeclarationFile(sourceFile)) {
+            if ((isExternalModule(sourceFile) || !compilerOptions.out) && !fileExtensionIs(sourceFile.fileName, ".js")) {
+                return true;
+            }
+            return false;
+        }
+        return false;
+    }
+
+    export function getAllAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration) {
+        let firstAccessor: AccessorDeclaration;
+        let secondAccessor: AccessorDeclaration;
+        let getAccessor: AccessorDeclaration;
+        let setAccessor: AccessorDeclaration;
+        if (hasDynamicName(accessor)) {
+            firstAccessor = accessor;
+            if (accessor.kind === SyntaxKind.GetAccessor) {
+                getAccessor = accessor;
+            }
+            else if (accessor.kind === SyntaxKind.SetAccessor) {
+                setAccessor = accessor;
+            }
+            else {
+                Debug.fail("Accessor has wrong kind");
+            }
+        }
+        else {
+            forEach(declarations, (member: Declaration) => {
+                if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor)
+                    && (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
+                    let memberName = getPropertyNameForPropertyNameNode(member.name);
+                    let accessorName = getPropertyNameForPropertyNameNode(accessor.name);
+                    if (memberName === accessorName) {
+                        if (!firstAccessor) {
+                            firstAccessor = <AccessorDeclaration>member;
+                        }
+                        else if (!secondAccessor) {
+                            secondAccessor = <AccessorDeclaration>member;
+                        }
+
+                        if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {
+                            getAccessor = <AccessorDeclaration>member;
+                        }
+
+                        if (member.kind === SyntaxKind.SetAccessor && !setAccessor) {
+                            setAccessor = <AccessorDeclaration>member;
+                        }
+                    }
+                }
+            });
+        }
+        return {
+            firstAccessor,
+            secondAccessor,
+            getAccessor,
+            setAccessor
+        };
+    }
+
+    export function emitNewLineBeforeLeadingComments(currentSourceFile: SourceFile, writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
+        // If the leading comments start on different line than the start of node, write new line
+        if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
+            getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) {
+            writer.writeLine();
+        }
+    }
+
+    export function emitComments(currentSourceFile: SourceFile, writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string,
+        writeComment: (currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) {
+        let emitLeadingSpace = !trailingSeparator;
+        forEach(comments, comment => {
+            if (emitLeadingSpace) {
+                writer.write(" ");
+                emitLeadingSpace = false;
+            }
+            writeComment(currentSourceFile, writer, comment, newLine);
+            if (comment.hasTrailingNewLine) {
+                writer.writeLine();
+            }
+            else if (trailingSeparator) {
+                writer.write(" ");
+            }
+            else {
+                // Emit leading space to separate comment during next comment emit
+                emitLeadingSpace = true;
+            }
+        });
+    }
+
+    export function writeCommentRange(currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) {
+        if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
+            let firstCommentLineAndCharacter = getLineAndCharacterOfPosition(currentSourceFile, comment.pos);
+            let lineCount = getLineStarts(currentSourceFile).length;
+            let firstCommentLineIndent: number;
+            for (let pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) {
+                let nextLineStart = (currentLine + 1) === lineCount
+                    ? currentSourceFile.text.length + 1
+                    : getStartPositionOfLine(currentLine + 1, currentSourceFile);
+
+                if (pos !== comment.pos) {
+                    // If we are not emitting first line, we need to write the spaces to adjust the alignment
+                    if (firstCommentLineIndent === undefined) {
+                        firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos);
+                    }
+
+                    // These are number of spaces writer is going to write at current indent
+                    let currentWriterIndentSpacing = writer.getIndent() * getIndentSize();
+
+                    // Number of spaces we want to be writing
+                    // eg: Assume writer indent
+                    // module m {
+                    //         /* starts at character 9 this is line 1
+                    //    * starts at character pos 4 line                        --1  = 8 - 8 + 3
+                    //   More left indented comment */                            --2  = 8 - 8 + 2
+                    //     class c { }
+                    // }
+                    // module m {
+                    //     /* this is line 1 -- Assume current writer indent 8
+                    //      * line                                                --3 = 8 - 4 + 5
+                    //            More right indented comment */                  --4 = 8 - 4 + 11
+                    //     class c { }
+                    // }
+                    let spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart);
+                    if (spacesToEmit > 0) {
+                        let numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize();
+                        let indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize());
+
+                        // Write indent size string ( in eg 1: = "", 2: "" , 3: string with 8 spaces 4: string with 12 spaces
+                        writer.rawWrite(indentSizeSpaceString);
+
+                        // Emit the single spaces (in eg: 1: 3 spaces, 2: 2 spaces, 3: 1 space, 4: 3 spaces)
+                        while (numberOfSingleSpacesToEmit) {
+                            writer.rawWrite(" ");
+                            numberOfSingleSpacesToEmit--;
+                        }
+                    }
+                    else {
+                        // No spaces to emit write empty string
+                        writer.rawWrite("");
+                    }
+                }
+
+                // Write the comment line text
+                writeTrimmedCurrentLine(pos, nextLineStart);
+
+                pos = nextLineStart;
+            }
+        }
+        else {
+            // Single line comment of style //....
+            writer.write(currentSourceFile.text.substring(comment.pos, comment.end));
+        }
+
+        function writeTrimmedCurrentLine(pos: number, nextLineStart: number) {
+            let end = Math.min(comment.end, nextLineStart - 1);
+            let currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, '');
+            if (currentLineText) {
+                // trimmed forward and ending spaces text
+                writer.write(currentLineText);
+                if (end !== comment.end) {
+                    writer.writeLine();
+                }
+            }
+            else {
+                // Empty string - make sure we write empty line
+                writer.writeLiteral(newLine);
+            }
+        }
+
+        function calculateIndent(pos: number, end: number) {
+            let currentLineIndent = 0;
+            for (; pos < end && isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) {
+                if (currentSourceFile.text.charCodeAt(pos) === CharacterCodes.tab) {
+                    // Tabs = TabSize = indent size and go to next tabStop
+                    currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
+                }
+                else {
+                    // Single space
+                    currentLineIndent++;
+                }
+            }
+
+            return currentLineIndent;
+        }
+    }
+
+    export function modifierToFlag(token: SyntaxKind): NodeFlags {
+        switch (token) {
+            case SyntaxKind.StaticKeyword: return NodeFlags.Static;
+            case SyntaxKind.PublicKeyword: return NodeFlags.Public;
+            case SyntaxKind.ProtectedKeyword: return NodeFlags.Protected;
+            case SyntaxKind.PrivateKeyword: return NodeFlags.Private;
+            case SyntaxKind.ExportKeyword: return NodeFlags.Export;
+            case SyntaxKind.DeclareKeyword: return NodeFlags.Ambient;
+            case SyntaxKind.ConstKeyword: return NodeFlags.Const;
+            case SyntaxKind.DefaultKeyword: return NodeFlags.Default;
+        }
+        return 0;
+    }
+
+    export function isLeftHandSideExpression(expr: Expression): boolean {
+        if (expr) {
+            switch (expr.kind) {
+                case SyntaxKind.PropertyAccessExpression:
+                case SyntaxKind.ElementAccessExpression:
+                case SyntaxKind.NewExpression:
+                case SyntaxKind.CallExpression:
+                case SyntaxKind.TaggedTemplateExpression:
+                case SyntaxKind.ArrayLiteralExpression:
+                case SyntaxKind.ParenthesizedExpression:
+                case SyntaxKind.ObjectLiteralExpression:
+                case SyntaxKind.ClassExpression:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.Identifier:
+                case SyntaxKind.RegularExpressionLiteral:
+                case SyntaxKind.NumericLiteral:
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.NoSubstitutionTemplateLiteral:
+                case SyntaxKind.TemplateExpression:
+                case SyntaxKind.FalseKeyword:
+                case SyntaxKind.NullKeyword:
+                case SyntaxKind.ThisKeyword:
+                case SyntaxKind.TrueKeyword:
+                case SyntaxKind.SuperKeyword:
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    export function isAssignmentOperator(token: SyntaxKind): boolean {
+        return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
+    }
+
+    // Returns false if this heritage clause element's expression contains something unsupported
+    // (i.e. not a name or dotted name).
+    export function isSupportedHeritageClauseElement(node: HeritageClauseElement): boolean {
+        return isSupportedHeritageClauseElementExpression(node.expression);
+    }
+
+    function isSupportedHeritageClauseElementExpression(node: Expression): boolean {
+        if (node.kind === SyntaxKind.Identifier) {
+            return true;
+        }
+        else if (node.kind === SyntaxKind.PropertyAccessExpression) {
+            return isSupportedHeritageClauseElementExpression((<PropertyAccessExpression>node).expression);
+        }
+        else {
+            return false;
+        }
+    }
+
+    export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
+        return (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node) ||
+            (node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
+    }
+
+    export function getLocalSymbolForExportDefault(symbol: Symbol) {
+            return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined;
+    }
+}
+
+module ts {
+    export function getDefaultLibFileName(options: CompilerOptions): string {
+        return options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts";
+    }
+
+    export function textSpanEnd(span: TextSpan) {
+        return span.start + span.length
+    }
+
+    export function textSpanIsEmpty(span: TextSpan) {
+        return span.length === 0
+    }
+
+    export function textSpanContainsPosition(span: TextSpan, position: number) {
+        return position >= span.start && position < textSpanEnd(span);
+    }
+
+    // Returns true if 'span' contains 'other'.
+    export function textSpanContainsTextSpan(span: TextSpan, other: TextSpan) {
+        return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span);
+    }
+
+    export function textSpanOverlapsWith(span: TextSpan, other: TextSpan) {
+        let overlapStart = Math.max(span.start, other.start);
+        let overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
+        return overlapStart < overlapEnd;
+    }
+
+    export function textSpanOverlap(span1: TextSpan, span2: TextSpan) {
+        let overlapStart = Math.max(span1.start, span2.start);
+        let overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
+        if (overlapStart < overlapEnd) {
+            return createTextSpanFromBounds(overlapStart, overlapEnd);
+        }
+        return undefined;
+    }
+
+    export function textSpanIntersectsWithTextSpan(span: TextSpan, other: TextSpan) {
+        return other.start <= textSpanEnd(span) && textSpanEnd(other) >= span.start
+    }
+
+    export function textSpanIntersectsWith(span: TextSpan, start: number, length: number) {
+        let end = start + length;
+        return start <= textSpanEnd(span) && end >= span.start;
+    }
+
+    export function textSpanIntersectsWithPosition(span: TextSpan, position: number) {
+        return position <= textSpanEnd(span) && position >= span.start;
+    }
+
+    export function textSpanIntersection(span1: TextSpan, span2: TextSpan) {
+        let intersectStart = Math.max(span1.start, span2.start);
+        let intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
+        if (intersectStart <= intersectEnd) {
+            return createTextSpanFromBounds(intersectStart, intersectEnd);
+        }
+        return undefined;
+    }
+
+    export function createTextSpan(start: number, length: number): TextSpan {
+        if (start < 0) {
+            throw new Error("start < 0");
+        }
+        if (length < 0) {
+            throw new Error("length < 0");
+        }
+
+        return { start, length };
+    }
+
+    export function createTextSpanFromBounds(start: number, end: number) {
+        return createTextSpan(start, end - start);
+    }
+
+    export function textChangeRangeNewSpan(range: TextChangeRange) {
+        return createTextSpan(range.span.start, range.newLength);
+    }
+
+    export function textChangeRangeIsUnchanged(range: TextChangeRange) {
+        return textSpanIsEmpty(range.span) && range.newLength === 0;
+    }
+
+    export function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange {
+        if (newLength < 0) {
+            throw new Error("newLength < 0");
+        }
+
+        return { span, newLength };
+    }
+
+    export let unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0);
+
+    /**
+     * Called to merge all the changes that occurred across several versions of a script snapshot 
+     * into a single change.  i.e. if a user keeps making successive edits to a script we will
+     * have a text change from V1 to V2, V2 to V3, ..., Vn.  
+     * 
+     * This function will then merge those changes into a single change range valid between V1 and
+     * Vn.
+     */
+    export function collapseTextChangeRangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange {
+        if (changes.length === 0) {
+            return unchangedTextChangeRange;
+        }
+
+        if (changes.length === 1) {
+            return changes[0];
+        }
+
+        // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd }
+        // as it makes things much easier to reason about.
+        let change0 = changes[0];
+
+        let oldStartN = change0.span.start;
+        let oldEndN = textSpanEnd(change0.span);
+        let newEndN = oldStartN + change0.newLength;
+
+        for (let i = 1; i < changes.length; i++) {
+            let nextChange = changes[i];
+
+            // Consider the following case:
+            // i.e. two edits.  The first represents the text change range { { 10, 50 }, 30 }.  i.e. The span starting
+            // at 10, with length 50 is reduced to length 30.  The second represents the text change range { { 30, 30 }, 40 }.
+            // i.e. the span starting at 30 with length 30 is increased to length 40.
+            //
+            //      0         10        20        30        40        50        60        70        80        90        100
+            //      -------------------------------------------------------------------------------------------------------
+            //                |                                                 /                                          
+            //                |                                            /----                                           
+            //  T1            |                                       /----                                                
+            //                |                                  /----                                                     
+            //                |                             /----                                                          
+            //      -------------------------------------------------------------------------------------------------------
+            //                                     |                            \                                          
+            //                                     |                               \                                       
+            //   T2                                |                                 \                                     
+            //                                     |                                   \                                   
+            //                                     |                                      \                                
+            //      -------------------------------------------------------------------------------------------------------
+            //
+            // Merging these turns out to not be too difficult.  First, determining the new start of the change is trivial
+            // it's just the min of the old and new starts.  i.e.:
+            //
+            //      0         10        20        30        40        50        60        70        80        90        100
+            //      ------------------------------------------------------------*------------------------------------------
+            //                |                                                 /                                          
+            //                |                                            /----                                           
+            //  T1            |                                       /----                                                
+            //                |                                  /----                                                     
+            //                |                             /----                                                          
+            //      ----------------------------------------$-------------------$------------------------------------------
+            //                .                    |                            \                                          
+            //                .                    |                               \                                       
+            //   T2           .                    |                                 \                                     
+            //                .                    |                                   \                                   
+            //                .                    |                                      \                                
+            //      ----------------------------------------------------------------------*--------------------------------
+            //
+            // (Note the dots represent the newly inferrred start.
+            // Determining the new and old end is also pretty simple.  Basically it boils down to paying attention to the
+            // absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see
+            // which if the two $'s precedes the other, and we move that one forward until they line up.  in this case that
+            // means:
+            //
+            //      0         10        20        30        40        50        60        70        80        90        100
+            //      --------------------------------------------------------------------------------*----------------------
+            //                |                                                                     /                      
+            //                |                                                                /----                       
+            //  T1            |                                                           /----                            
+            //                |                                                      /----                                 
+            //                |                                                 /----                                      
+            //      ------------------------------------------------------------$------------------------------------------
+            //                .                    |                            \                                          
+            //                .                    |                               \                                       
+            //   T2           .                    |                                 \                                     
+            //                .                    |                                   \                                   
+            //                .                    |                                      \                                
+            //      ----------------------------------------------------------------------*--------------------------------
+            //
+            // In other words (in this case), we're recognizing that the second edit happened after where the first edit
+            // ended with a delta of 20 characters (60 - 40).  Thus, if we go back in time to where the first edit started
+            // that's the same as if we started at char 80 instead of 60.  
+            //
+            // As it so happens, the same logic applies if the second edit precedes the first edit.  In that case rahter
+            // than pusing the first edit forward to match the second, we'll push the second edit forward to match the
+            // first.
+            //
+            // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange
+            // semantics: { { start: 10, length: 70 }, newLength: 60 }
+            //
+            // The math then works out as follows.
+            // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the 
+            // final result like so:
+            //
+            // {
+            //      oldStart3: Min(oldStart1, oldStart2),
+            //      oldEnd3  : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)),
+            //      newEnd3  : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
+            // }
+
+            let oldStart1 = oldStartN;
+            let oldEnd1 = oldEndN;
+            let newEnd1 = newEndN;
+
+            let oldStart2 = nextChange.span.start;
+            let oldEnd2 = textSpanEnd(nextChange.span);
+            let newEnd2 = oldStart2 + nextChange.newLength;
+
+            oldStartN = Math.min(oldStart1, oldStart2);
+            oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
+            newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
+        }
+
+        return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength:*/ newEndN - oldStartN);
+    }
+}
diff --git a/lib/typescript/makeTypeScriptGlobal.ts b/lib/typescript/makeTypeScriptGlobal.ts
new file mode 100644
index 000000000..d266987a1
--- /dev/null
+++ b/lib/typescript/makeTypeScriptGlobal.ts
@@ -0,0 +1,61 @@
+// Put the whole of `ts` namespace into the global `ts` variable
+// IMPORTANT!!!!!!!!!!!! `diagnosticInformationMap` needs to be before `commandLineParser`
+var servicesFiles = [
+    "../compiler/core.ts",
+    "../compiler/sys.ts",
+    "../compiler/types.ts",
+    "../compiler/scanner.ts",
+    "../compiler/parser.ts",
+    "../compiler/utilities.ts",
+    "../compiler/binder.ts",
+    "../compiler/checker.ts",
+    "../compiler/emitter.ts",
+    "../compiler/program.ts",
+    "../compiler/diagnosticInformationMap.generated.ts",
+    "../compiler/commandLineParser.ts",    
+    "breakpoints.ts",
+    "navigationBar.ts",
+    "outliningElementsCollector.ts",
+    "services.ts",
+    "shims.ts",
+    "signatureHelp.ts",
+    "utilities.ts",
+    "formatting/formatting.ts",
+    "formatting/formattingContext.ts",
+    "formatting/formattingRequestKind.ts",
+    "formatting/formattingScanner.ts",
+    "formatting/references.ts",
+    "formatting/rule.ts",
+    "formatting/ruleAction.ts",
+    "formatting/ruleDescriptor.ts",
+    "formatting/ruleFlag.ts",
+    "formatting/ruleOperation.ts",
+    "formatting/ruleOperationContext.ts",
+    "formatting/rules.ts",
+    "formatting/rulesMap.ts",
+    "formatting/rulesProvider.ts",
+    "formatting/smartIndenter.ts",
+    "formatting/tokenRange.ts"
+];
+
+
+var files = servicesFiles.map(f=> `./services/${f.replace('.ts', '.js') }`);
+
+////////////////////////////////// MAGIC
+import vm = require('vm');
+import fs = require('fs');
+import path = require('path');
+
+
+export function makeTsGlobal() {
+    // This is going to gather the ts module exports
+    var sandbox = { ts: {} };
+    vm.createContext(sandbox);
+
+    files.forEach(f=> {
+        vm.runInContext(fs.readFileSync(path.resolve(__dirname,f)).toString(), sandbox);
+    });
+    
+    // Finally export ts to the global namespace
+    global.ts = sandbox.ts;
+}
diff --git a/lib/typescript/readme.md b/lib/typescript/readme.md
new file mode 100644
index 000000000..f079b4eb0
--- /dev/null
+++ b/lib/typescript/readme.md
@@ -0,0 +1,22 @@
+# How to update the compiler source
+* get a copy of `microsoft/typescript` and checkout `master`.
+* Copy the `compiler` and `services` folders from the TypeScript `master` to here.
+* Delete the following: 
+  * `compiler/tsc.ts` as that is not a part of `services` proper and is used for command line handling which we don't need.
+  * `compiler/tsconfig.json`
+  * `services/tsconfig.json`
+
+
+# Magic
+Basically we run `makeTypeScriptGlobal.ts` (both in parent and child) to export `module ts` to the variable `global.ts` so we can just use `ts.` without any imports. 
+This isn't ideal but if you are willing to do more work to make it easier/safer to use the compiler source send a PR :P.
+
+# Notes
+We list the files in `makeTypeScriptGlobal.ts`, these are basically the `tsconfig.json` files from the `services` folder, with a minor change to preserve the order: 
+
+```ts
+"../compiler/diagnosticInformationMap.generated.ts",
+"../compiler/commandLineParser.ts",    
+```
+
+as `commandLineParser` depends on stuff from `compiler/diagnosticInformationMap.generated.ts`. We should report this to the TS team.
\ No newline at end of file
diff --git a/lib/typescript/services/breakpoints.ts b/lib/typescript/services/breakpoints.ts
new file mode 100644
index 000000000..36450fd49
--- /dev/null
+++ b/lib/typescript/services/breakpoints.ts
@@ -0,0 +1,529 @@
+// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. 
+// See LICENSE.txt in the project root for complete license information.
+
+/// <reference path='services.ts' />
+
+/* @internal */
+module ts.BreakpointResolver {
+    /**
+     * Get the breakpoint span in given sourceFile
+     */
+    export function spanInSourceFileAtLocation(sourceFile: SourceFile, position: number) {
+        // Cannot set breakpoint in dts file
+        if (sourceFile.flags & NodeFlags.DeclarationFile) {
+            return undefined;
+        }
+
+        let tokenAtLocation = getTokenAtPosition(sourceFile, position);
+        let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
+        if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
+            // Get previous token if the token is returned starts on new line
+            // eg: let x =10; |--- cursor is here
+            //     let y = 10; 
+            // token at position will return let keyword on second line as the token but we would like to use 
+            // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line
+            tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile);
+
+            // Its a blank line
+            if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) {
+                return undefined;
+            }
+        }
+
+        // Cannot set breakpoint in ambient declarations
+        if (isInAmbientContext(tokenAtLocation)) {
+            return undefined;
+        }
+
+        // Get the span in the node based on its syntax
+        return spanInNode(tokenAtLocation);
+
+        function textSpan(startNode: Node, endNode?: Node) {
+            return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
+        }
+
+        function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
+            if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
+                return spanInNode(node);
+            }
+            return spanInNode(otherwiseOnNode);
+        }
+
+        function spanInPreviousNode(node: Node): TextSpan {
+            return spanInNode(findPrecedingToken(node.pos, sourceFile));
+        }
+
+        function spanInNextNode(node: Node): TextSpan {
+            return spanInNode(findNextToken(node, node.parent));
+        }
+
+        function spanInNode(node: Node): TextSpan {
+            if (node) {
+                if (isExpression(node)) {
+                    if (node.parent.kind === SyntaxKind.DoStatement) {
+                        // Set span as if on while keyword
+                        return spanInPreviousNode(node);
+                    }
+
+                    if (node.parent.kind === SyntaxKind.ForStatement) {
+                        // For now lets set the span on this expression, fix it later
+                        return textSpan(node);
+                    }
+
+                    if (node.parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node.parent).operatorToken.kind === SyntaxKind.CommaToken) {
+                        // if this is comma expression, the breakpoint is possible in this expression
+                        return textSpan(node);
+                    }
+
+                    if (node.parent.kind == SyntaxKind.ArrowFunction && (<FunctionLikeDeclaration>node.parent).body == node) {
+                        // If this is body of arrow function, it is allowed to have the breakpoint
+                        return textSpan(node);
+                    }
+                }
+
+                switch (node.kind) {
+                    case SyntaxKind.VariableStatement:
+                        // Span on first variable declaration
+                        return spanInVariableDeclaration((<VariableStatement>node).declarationList.declarations[0]);
+
+                    case SyntaxKind.VariableDeclaration:
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                        return spanInVariableDeclaration(<VariableDeclaration>node);
+
+                    case SyntaxKind.Parameter:
+                        return spanInParameterDeclaration(<ParameterDeclaration>node);
+
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.ArrowFunction:
+                        return spanInFunctionDeclaration(<FunctionLikeDeclaration>node);
+
+                    case SyntaxKind.Block:
+                        if (isFunctionBlock(node)) {
+                            return spanInFunctionBlock(<Block>node);
+                        }
+                        // Fall through
+                    case SyntaxKind.ModuleBlock:
+                        return spanInBlock(<Block>node);
+
+                    case SyntaxKind.CatchClause:
+                        return spanInBlock((<CatchClause>node).block);
+
+                    case SyntaxKind.ExpressionStatement:
+                        // span on the expression
+                        return textSpan((<ExpressionStatement>node).expression);
+
+                    case SyntaxKind.ReturnStatement:
+                        // span on return keyword and expression if present
+                        return textSpan(node.getChildAt(0), (<ReturnStatement>node).expression);
+
+                    case SyntaxKind.WhileStatement:
+                        // Span on while(...)
+                        return textSpan(node, findNextToken((<WhileStatement>node).expression, node));
+
+                    case SyntaxKind.DoStatement:
+                        // span in statement of the do statement
+                        return spanInNode((<DoStatement>node).statement);
+
+                    case SyntaxKind.DebuggerStatement:
+                        // span on debugger keyword
+                        return textSpan(node.getChildAt(0));
+
+                    case SyntaxKind.IfStatement:
+                        // set on if(..) span
+                        return textSpan(node, findNextToken((<IfStatement>node).expression, node));
+
+                    case SyntaxKind.LabeledStatement:
+                        // span in statement
+                        return spanInNode((<LabeledStatement>node).statement);
+
+                    case SyntaxKind.BreakStatement:
+                    case SyntaxKind.ContinueStatement:
+                        // On break or continue keyword and label if present
+                        return textSpan(node.getChildAt(0), (<BreakOrContinueStatement>node).label);
+
+                    case SyntaxKind.ForStatement:
+                        return spanInForStatement(<ForStatement>node);
+
+                    case SyntaxKind.ForInStatement:
+                    case SyntaxKind.ForOfStatement:
+                        // span on for (a in ...)
+                        return textSpan(node, findNextToken((<ForInStatement | ForOfStatement>node).expression, node));
+
+                    case SyntaxKind.SwitchStatement:
+                        // span on switch(...)
+                        return textSpan(node, findNextToken((<SwitchStatement>node).expression, node));
+
+                    case SyntaxKind.CaseClause:
+                    case SyntaxKind.DefaultClause:
+                        // span in first statement of the clause
+                        return spanInNode((<CaseOrDefaultClause>node).statements[0]);
+
+                    case SyntaxKind.TryStatement:
+                        // span in try block
+                        return spanInBlock((<TryStatement>node).tryBlock);
+
+                    case SyntaxKind.ThrowStatement:
+                        // span in throw ...
+                        return textSpan(node, (<ThrowStatement>node).expression);
+
+                    case SyntaxKind.ExportAssignment:
+                        // span on export = id
+                        return textSpan(node, (<ExportAssignment>node).expression);
+
+                    case SyntaxKind.ImportEqualsDeclaration:
+                        // import statement without including semicolon
+                        return textSpan(node, (<ImportEqualsDeclaration>node).moduleReference);
+
+                    case SyntaxKind.ImportDeclaration:
+                        // import statement without including semicolon
+                        return textSpan(node, (<ImportDeclaration>node).moduleSpecifier);
+
+                    case SyntaxKind.ExportDeclaration:
+                        // import statement without including semicolon
+                        return textSpan(node, (<ExportDeclaration>node).moduleSpecifier);
+
+                    case SyntaxKind.ModuleDeclaration:
+                        // span on complete module if it is instantiated
+                        if (getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) {
+                            return undefined;
+                        }
+
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.EnumMember:
+                    case SyntaxKind.CallExpression:
+                    case SyntaxKind.NewExpression:
+                        // span on complete node
+                        return textSpan(node);
+
+                    case SyntaxKind.WithStatement:
+                        // span in statement
+                        return spanInNode((<WithStatement>node).statement);
+
+                    // No breakpoint in interface, type alias
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.TypeAliasDeclaration:
+                        return undefined;
+
+                    // Tokens:
+                    case SyntaxKind.SemicolonToken:
+                    case SyntaxKind.EndOfFileToken:
+                        return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile));
+
+                    case SyntaxKind.CommaToken:
+                        return spanInPreviousNode(node)
+                        
+                    case SyntaxKind.OpenBraceToken:
+                        return spanInOpenBraceToken(node);
+
+                    case SyntaxKind.CloseBraceToken:
+                        return spanInCloseBraceToken(node);
+
+                    case SyntaxKind.OpenParenToken: 
+                        return spanInOpenParenToken(node);
+
+                    case SyntaxKind.CloseParenToken:
+                        return spanInCloseParenToken(node);
+
+                    case SyntaxKind.ColonToken:
+                        return spanInColonToken(node);
+
+                    case SyntaxKind.GreaterThanToken:
+                    case SyntaxKind.LessThanToken:
+                        return spanInGreaterThanOrLessThanToken(node);
+
+                    // Keywords:
+                    case SyntaxKind.WhileKeyword:
+                        return spanInWhileKeyword(node);
+
+                    case SyntaxKind.ElseKeyword:
+                    case SyntaxKind.CatchKeyword:
+                    case SyntaxKind.FinallyKeyword:
+                        return spanInNextNode(node);
+
+                    default:
+                        // If this is name of property assignment, set breakpoint in the initializer
+                        if (node.parent.kind === SyntaxKind.PropertyAssignment && (<PropertyDeclaration>node.parent).name === node) {
+                            return spanInNode((<PropertyDeclaration>node.parent).initializer);
+                        }
+
+                        // Breakpoint in type assertion goes to its operand
+                        if (node.parent.kind === SyntaxKind.TypeAssertionExpression && (<TypeAssertion>node.parent).type === node) {
+                            return spanInNode((<TypeAssertion>node.parent).expression);
+                        }
+
+                        // return type of function go to previous token
+                        if (isFunctionLike(node.parent) && (<FunctionLikeDeclaration>node.parent).type === node) {
+                            return spanInPreviousNode(node);
+                        }
+
+                        // Default go to parent to set the breakpoint
+                        return spanInNode(node.parent);
+                }
+            }
+
+            function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan {
+                // If declaration of for in statement, just set the span in parent
+                if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement ||
+                    variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
+                    return spanInNode(variableDeclaration.parent.parent);
+                }
+
+                let isParentVariableStatement = variableDeclaration.parent.parent.kind === SyntaxKind.VariableStatement;
+                let isDeclarationOfForStatement = variableDeclaration.parent.parent.kind === SyntaxKind.ForStatement && contains((<VariableDeclarationList>(<ForStatement>variableDeclaration.parent.parent).initializer).declarations, variableDeclaration);
+                let declarations = isParentVariableStatement
+                    ? (<VariableStatement>variableDeclaration.parent.parent).declarationList.declarations
+                    : isDeclarationOfForStatement
+                        ? (<VariableDeclarationList>(<ForStatement>variableDeclaration.parent.parent).initializer).declarations
+                        : undefined;
+
+                // Breakpoint is possible in variableDeclaration only if there is initialization
+                if (variableDeclaration.initializer || (variableDeclaration.flags & NodeFlags.Export)) {
+                    if (declarations && declarations[0] === variableDeclaration) {
+                        if (isParentVariableStatement) {
+                            // First declaration - include let keyword
+                            return textSpan(variableDeclaration.parent, variableDeclaration);
+                        }
+                        else {
+                            Debug.assert(isDeclarationOfForStatement);
+                            // Include let keyword from for statement declarations in the span
+                            return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
+                        }
+                    }
+                    else {
+                        // Span only on this declaration
+                        return textSpan(variableDeclaration);
+                    }
+                }
+                else if (declarations && declarations[0] !== variableDeclaration) {
+                    // If we cant set breakpoint on this declaration, set it on previous one
+                    let indexOfCurrentDeclaration = indexOf(declarations, variableDeclaration);
+                    return spanInVariableDeclaration(declarations[indexOfCurrentDeclaration - 1]);
+                }
+            }
+
+            function canHaveSpanInParameterDeclaration(parameter: ParameterDeclaration): boolean {
+                // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier
+                return !!parameter.initializer || parameter.dotDotDotToken !== undefined ||
+                    !!(parameter.flags & NodeFlags.Public) || !!(parameter.flags & NodeFlags.Private);
+            }
+
+            function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan {
+                if (canHaveSpanInParameterDeclaration(parameter)) {
+                    return textSpan(parameter);
+                }
+                else {
+                    let functionDeclaration = <FunctionLikeDeclaration>parameter.parent;
+                    let indexOfParameter = indexOf(functionDeclaration.parameters, parameter);
+                    if (indexOfParameter) {
+                        // Not a first parameter, go to previous parameter
+                        return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
+                    }
+                    else {
+                        // Set breakpoint in the function declaration body
+                        return spanInNode(functionDeclaration.body);
+                    }
+                }
+            }
+
+            function canFunctionHaveSpanInWholeDeclaration(functionDeclaration: FunctionLikeDeclaration) {
+                return !!(functionDeclaration.flags & NodeFlags.Export) ||
+                    (functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor);
+            }
+
+            function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan {
+                // No breakpoints in the function signature
+                if (!functionDeclaration.body) {
+                    return undefined;
+                }
+
+                if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) {
+                    // Set the span on whole function declaration
+                    return textSpan(functionDeclaration);
+                }
+
+                // Set span in function body
+                return spanInNode(functionDeclaration.body);
+            }
+
+            function spanInFunctionBlock(block: Block): TextSpan {
+                let nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
+                if (canFunctionHaveSpanInWholeDeclaration(<FunctionLikeDeclaration>block.parent)) {
+                    return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
+                }
+
+                return spanInNode(nodeForSpanInBlock);
+            }
+
+            function spanInBlock(block: Block): TextSpan {
+                switch (block.parent.kind) {
+                    case SyntaxKind.ModuleDeclaration:
+                        if (getModuleInstanceState(block.parent) !== ModuleInstanceState.Instantiated) {
+                            return undefined;
+                        }
+
+                    // Set on parent if on same line otherwise on first statement
+                    case SyntaxKind.WhileStatement:
+                    case SyntaxKind.IfStatement:
+                    case SyntaxKind.ForInStatement:
+                    case SyntaxKind.ForOfStatement:
+                        return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]);
+
+                    // Set span on previous token if it starts on same line otherwise on the first statement of the block
+                    case SyntaxKind.ForStatement:
+                        return spanInNodeIfStartsOnSameLine(findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]);
+                }
+
+                // Default action is to set on first statement
+                return spanInNode(block.statements[0]);
+            }
+
+            function spanInForStatement(forStatement: ForStatement): TextSpan {
+                if (forStatement.initializer) {
+                    if (forStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
+                        let variableDeclarationList = <VariableDeclarationList>forStatement.initializer;
+                        if (variableDeclarationList.declarations.length > 0) {
+                            return spanInNode(variableDeclarationList.declarations[0]);
+                        }
+                    }
+                    else {
+                        return spanInNode(forStatement.initializer);
+                    }
+                }
+
+                if (forStatement.condition) {
+                    return textSpan(forStatement.condition);
+                }
+                if (forStatement.incrementor) {
+                    return textSpan(forStatement.incrementor);
+                }
+            }
+
+            // Tokens:
+            function spanInOpenBraceToken(node: Node): TextSpan {
+                switch (node.parent.kind) {
+                    case SyntaxKind.EnumDeclaration:
+                        let enumDeclaration = <EnumDeclaration>node.parent;
+                        return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile));
+
+                    case SyntaxKind.ClassDeclaration:
+                        let classDeclaration = <ClassDeclaration>node.parent;
+                        return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile));
+
+                    case SyntaxKind.CaseBlock:
+                        return spanInNodeIfStartsOnSameLine(node.parent.parent, (<CaseBlock>node.parent).clauses[0]);
+                }
+
+                // Default to parent node
+                return spanInNode(node.parent);
+            }
+
+            function spanInCloseBraceToken(node: Node): TextSpan {
+                switch (node.parent.kind) {
+                    case SyntaxKind.ModuleBlock:
+                        // If this is not instantiated module block no bp span
+                        if (getModuleInstanceState(node.parent.parent) !== ModuleInstanceState.Instantiated) {
+                            return undefined;
+                        }
+
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.ClassDeclaration:
+                        // Span on close brace token
+                        return textSpan(node);
+
+                    case SyntaxKind.Block:
+                        if (isFunctionBlock(node.parent)) {
+                            // Span on close brace token
+                            return textSpan(node);
+                        }
+                        // fall through.
+
+                    case SyntaxKind.CatchClause:
+                        return spanInNode((<Block>node.parent).statements[(<Block>node.parent).statements.length - 1]);;
+
+                    case SyntaxKind.CaseBlock:
+                        // breakpoint in last statement of the last clause
+                        let caseBlock = <CaseBlock>node.parent;
+                        let lastClause = caseBlock.clauses[caseBlock.clauses.length - 1];
+                        if (lastClause) {
+                            return spanInNode(lastClause.statements[lastClause.statements.length - 1]);
+                        }
+                        return undefined;
+
+                    // Default to parent node
+                    default:
+                        return spanInNode(node.parent);
+                }
+            }
+
+            function spanInOpenParenToken(node: Node): TextSpan {
+                if (node.parent.kind === SyntaxKind.DoStatement) {
+                    // Go to while keyword and do action instead
+                    return spanInPreviousNode(node);
+                }
+
+                // Default to parent node
+                return spanInNode(node.parent);
+            }
+
+            function spanInCloseParenToken(node: Node): TextSpan {
+                // Is this close paren token of parameter list, set span in previous token
+                switch (node.parent.kind) {
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.ArrowFunction:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.WhileStatement:
+                    case SyntaxKind.DoStatement:
+                    case SyntaxKind.ForStatement:
+                        return spanInPreviousNode(node);
+
+                    // Default to parent node
+                    default:
+                        return spanInNode(node.parent);
+                }
+
+                // Default to parent node
+                return spanInNode(node.parent);
+            }
+
+            function spanInColonToken(node: Node): TextSpan {
+                // Is this : specifying return annotation of the function declaration
+                if (isFunctionLike(node.parent) || node.parent.kind === SyntaxKind.PropertyAssignment) {
+                    return spanInPreviousNode(node);
+                }
+
+                return spanInNode(node.parent);
+            }
+
+            function spanInGreaterThanOrLessThanToken(node: Node): TextSpan {
+                if (node.parent.kind === SyntaxKind.TypeAssertionExpression) {
+                    return spanInNode((<TypeAssertion>node.parent).expression);
+                }
+
+                return spanInNode(node.parent);
+            }
+
+            function spanInWhileKeyword(node: Node): TextSpan {
+                if (node.parent.kind === SyntaxKind.DoStatement) {
+                    // Set span on while expression
+                    return textSpan(node, findNextToken((<DoStatement>node.parent).expression, node.parent));
+                }
+
+                // Default to parent node
+                return spanInNode(node.parent);
+            }
+        }
+   }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/formatting.ts b/lib/typescript/services/formatting/formatting.ts
new file mode 100644
index 000000000..408760231
--- /dev/null
+++ b/lib/typescript/services/formatting/formatting.ts
@@ -0,0 +1,1114 @@
+///<reference path='..\services.ts' />
+///<reference path='formattingScanner.ts' />
+///<reference path='rulesProvider.ts' />
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+
+    export interface TextRangeWithKind extends TextRange {
+        kind: SyntaxKind;
+    }
+
+    export interface TokenInfo {
+        leadingTrivia: TextRangeWithKind[];
+        token: TextRangeWithKind;
+        trailingTrivia: TextRangeWithKind[];
+    }
+
+    const enum Constants {
+        Unknown = -1
+    }
+
+    /* 
+     * Indentation for the scope that can be dynamically recomputed.
+     * i.e 
+     * while(true)
+     * { let x;
+     * }
+     * Normally indentation is applied only to the first token in line so at glance 'var' should not be touched. 
+     * However if some format rule adds new line between '}' and 'var' 'var' will become
+     * the first token in line so it should be indented
+     */
+    interface DynamicIndentation {
+        getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind): number;
+        getIndentationForComment(owningToken: SyntaxKind): number;
+        /**
+          * Indentation for open and close tokens of the node if it is block or another node that needs special indentation
+          * ... {
+          * .........<child>
+          * ....}
+          *  ____ - indentation
+          *      ____ - delta
+          **/
+        getIndentation(): number;
+        /**
+          * Prefered relative indentation for child nodes.
+          * Delta is used to carry the indentation info
+          * foo(bar({
+          *     $
+          * }))
+          * Both 'foo', 'bar' introduce new indentation with delta = 4, but total indentation in $ is not 8. 
+          * foo: { indentation: 0, delta: 4 }
+          * bar: { indentation: foo.indentation + foo.delta = 4, delta: 4} however 'foo' and 'bar' are on the same line
+          * so bar inherits indentation from foo and bar.delta will be 4
+          * 
+          */
+        getDelta(): number;
+        /**
+          * Formatter calls this function when rule adds or deletes new lines from the text 
+          * so indentation scope can adjust values of indentation and delta.
+          */
+        recomputeIndentation(lineAddedByFormatting: boolean): void;
+    }
+
+    interface Indentation {
+        indentation: number;
+        delta: number
+    }
+
+    export function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
+        let line = sourceFile.getLineAndCharacterOfPosition(position).line;
+        if (line === 0) {
+            return [];
+        }
+        // get the span for the previous\current line
+        let span = {
+            // get start position for the previous line
+            pos: getStartPositionOfLine(line - 1, sourceFile),
+            // get end position for the current line (end value is exclusive so add 1 to the result)
+            end: getEndLinePosition(line, sourceFile) + 1
+        }
+        return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnEnter);
+    }
+
+    export function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
+        return formatOutermostParent(position, SyntaxKind.SemicolonToken, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnSemicolon);
+    }
+
+    export function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
+        return formatOutermostParent(position, SyntaxKind.CloseBraceToken, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnClosingCurlyBrace);
+    }
+
+    export function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
+        let span = {
+            pos: 0,
+            end: sourceFile.text.length
+        };
+        return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatDocument);
+    }
+
+    export function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[] {
+        // format from the beginning of the line
+        let span = {
+            pos: getLineStartPositionForPosition(start, sourceFile),
+            end: end
+        };
+        return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatSelection);
+    }
+
+    function formatOutermostParent(position: number, expectedLastToken: SyntaxKind, sourceFile: SourceFile, options: FormatCodeOptions, rulesProvider: RulesProvider, requestKind: FormattingRequestKind): TextChange[] {
+        let parent = findOutermostParent(position, expectedLastToken, sourceFile);
+        if (!parent) {
+            return [];
+        }
+        let span = {
+            pos: getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile),
+            end: parent.end
+        };
+        return formatSpan(span, sourceFile, options, rulesProvider, requestKind);
+    }
+
+    function findOutermostParent(position: number, expectedTokenKind: SyntaxKind, sourceFile: SourceFile): Node {
+        let precedingToken = findPrecedingToken(position, sourceFile);
+        
+        // when it is claimed that trigger character was typed at given position 
+        // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed).
+        // If this condition is not hold - then trigger character was typed in some other context, 
+        // i.e.in comment and thus should not trigger autoformatting
+        if (!precedingToken ||
+            precedingToken.kind !== expectedTokenKind ||
+            position !== precedingToken.getEnd()) {
+            return undefined;
+        }
+
+        // walk up and search for the parent node that ends at the same position with precedingToken.
+        // for cases like this
+        // 
+        // let x = 1;
+        // while (true) {
+        // } 
+        // after typing close curly in while statement we want to reformat just the while statement.
+        // However if we just walk upwards searching for the parent that has the same end value - 
+        // we'll end up with the whole source file. isListElement allows to stop on the list element level
+        let current = precedingToken;
+        while (current &&
+            current.parent &&
+            current.parent.end === precedingToken.end &&
+            !isListElement(current.parent, current)) {
+            current = current.parent;
+        }
+
+        return current;
+    }
+    
+    // Returns true if node is a element in some list in parent
+    // i.e. parent is class declaration with the list of members and node is one of members.
+    function isListElement(parent: Node, node: Node): boolean {
+        switch (parent.kind) {
+            case SyntaxKind.ClassDeclaration:
+            case SyntaxKind.InterfaceDeclaration:
+                return rangeContainsRange((<InterfaceDeclaration>parent).members, node);
+            case SyntaxKind.ModuleDeclaration:
+                let body = (<ModuleDeclaration>parent).body;
+                return body && body.kind === SyntaxKind.Block && rangeContainsRange((<Block>body).statements, node);
+            case SyntaxKind.SourceFile:
+            case SyntaxKind.Block:
+            case SyntaxKind.ModuleBlock:
+                return rangeContainsRange((<Block>parent).statements, node);
+            case SyntaxKind.CatchClause:
+                return rangeContainsRange((<CatchClause>parent).block.statements, node);
+        }
+
+        return false;
+    }
+
+    /** find node that fully contains given text range */
+    function findEnclosingNode(range: TextRange, sourceFile: SourceFile): Node {
+        return find(sourceFile);
+
+        function find(n: Node): Node {
+            let candidate = forEachChild(n, c => startEndContainsRange(c.getStart(sourceFile), c.end, range) && c);
+            if (candidate) {
+                let result = find(candidate);
+                if (result) {
+                    return result;
+                }
+            }
+
+            return n;
+        }
+    }
+
+    /** formatting is not applied to ranges that contain parse errors.
+      * This function will return a predicate that for a given text range will tell
+      * if there are any parse errors that overlap with the range.
+      */
+    function prepareRangeContainsErrorFunction(errors: Diagnostic[], originalRange: TextRange): (r: TextRange) => boolean {
+        if (!errors.length) {
+            return rangeHasNoErrors;
+        }
+        
+        // pick only errors that fall in range
+        let sorted = errors
+            .filter(d => rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length))
+            .sort((e1, e2) => e1.start - e2.start);
+
+        if (!sorted.length) {
+            return rangeHasNoErrors;
+        }
+
+        let index = 0;
+
+        return r => {
+            // in current implementation sequence of arguments [r1, r2...] is monotonically increasing.
+            // 'index' tracks the index of the most recent error that was checked.
+            while (true) {
+                if (index >= sorted.length) {
+                    // all errors in the range were already checked -> no error in specified range 
+                    return false;
+                }
+
+                let error = sorted[index];
+                if (r.end <= error.start) {
+                    // specified range ends before the error refered by 'index' - no error in range
+                    return false;
+                }
+
+                if (startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) {
+                    // specified range overlaps with error range
+                    return true;
+                }
+
+                index++;
+            }
+        };
+
+        function rangeHasNoErrors(r: TextRange): boolean {
+            return false;
+        }
+    }
+
+    /**
+      * Start of the original range might fall inside the comment - scanner will not yield appropriate results
+      * This function will look for token that is located before the start of target range 
+      * and return its end as start position for the scanner.
+      */
+    function getScanStartPosition(enclosingNode: Node, originalRange: TextRange, sourceFile: SourceFile): number {
+        let start = enclosingNode.getStart(sourceFile);
+        if (start === originalRange.pos && enclosingNode.end === originalRange.end) {
+            return start;
+        }
+
+        let precedingToken = findPrecedingToken(originalRange.pos, sourceFile);
+        if (!precedingToken) {
+            // no preceding token found - start from the beginning of enclosing node
+            return enclosingNode.pos;
+        }
+
+        // preceding token ends after the start of original range (i.e when originaRange.pos falls in the middle of literal)
+        // start from the beginning of enclosingNode to handle the entire 'originalRange'
+        if (precedingToken.end >= originalRange.pos) {
+            return enclosingNode.pos;
+        }
+
+        return precedingToken.end;
+    }
+
+    /*
+     * For cases like 
+     * if (a ||
+     *     b ||$
+     *     c) {...}
+     * If we hit Enter at $ we want line '    b ||' to be indented.
+     * Formatting will be applied to the last two lines.
+     * Node that fully encloses these lines is binary expression 'a ||...'.
+     * Initial indentation for this node will be 0.
+     * Binary expressions don't introduce new indentation scopes, however it is possible
+     * that some parent node on the same line does - like if statement in this case.
+     * Note that we are considering parents only from the same line with initial node - 
+     * if parent is on the different line - its delta was already contributed 
+     * to the initial indentation.
+     */
+    function getOwnOrInheritedDelta(n: Node, options: FormatCodeOptions, sourceFile: SourceFile): number {
+        let previousLine = Constants.Unknown;
+        let childKind = SyntaxKind.Unknown;
+        while (n) {
+            let line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
+            if (previousLine !== Constants.Unknown && line !== previousLine) {
+                break;
+            }
+
+            if (SmartIndenter.shouldIndentChildNode(n.kind, childKind)) {
+                return options.IndentSize;
+            }
+
+            previousLine = line;
+            childKind = n.kind;
+            n = n.parent;
+        }
+        return 0;
+    }
+
+    function formatSpan(originalRange: TextRange,
+        sourceFile: SourceFile,
+        options: FormatCodeOptions,
+        rulesProvider: RulesProvider,
+        requestKind: FormattingRequestKind): TextChange[] {
+
+        let rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
+
+        // formatting context is used by rules provider
+        let formattingContext = new FormattingContext(sourceFile, requestKind);
+
+        // find the smallest node that fully wraps the range and compute the initial indentation for the node
+        let enclosingNode = findEnclosingNode(originalRange, sourceFile);
+
+        let formattingScanner = getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
+
+        let initialIndentation = SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
+
+        let previousRangeHasError: boolean;
+        let previousRange: TextRangeWithKind;
+        let previousParent: Node;
+        let previousRangeStartLine: number;
+
+        let edits: TextChange[] = [];
+
+        formattingScanner.advance();
+
+        if (formattingScanner.isOnToken()) {
+            let startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
+            let undecoratedStartLine = startLine;
+            if (enclosingNode.decorators) {
+                undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
+            }
+
+            let delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
+            processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
+        }
+
+        formattingScanner.close();
+
+        return edits;
+
+        // local functions
+
+        /** Tries to compute the indentation for a list element.
+          * If list element is not in range then 
+          * function will pick its actual indentation 
+          * so it can be pushed downstream as inherited indentation.
+          * If list element is in the range - its indentation will be equal 
+          * to inherited indentation from its predecessors.
+          */
+        function tryComputeIndentationForListItem(startPos: number, 
+            endPos: number, 
+            parentStartLine: number, 
+            range: TextRange, 
+            inheritedIndentation: number): number {
+            
+            if (rangeOverlapsWithStartEnd(range, startPos, endPos)) {
+                if (inheritedIndentation !== Constants.Unknown) {
+                    return inheritedIndentation;
+                }
+            }
+            else {
+                let startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
+                let startLinePosition = getLineStartPositionForPosition(startPos, sourceFile);
+                let column = SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
+                if (startLine !== parentStartLine || startPos === column) {
+                    return column
+                }
+            }
+
+            return Constants.Unknown;
+        }
+        
+        function computeIndentation(
+            node: TextRangeWithKind,
+            startLine: number,
+            inheritedIndentation: number,
+            parent: Node,
+            parentDynamicIndentation: DynamicIndentation,
+            effectiveParentStartLine: number): Indentation {
+
+            let indentation = inheritedIndentation;
+            if (indentation === Constants.Unknown) {
+                if (isSomeBlock(node.kind)) {
+                    // blocks should be indented in 
+                    // - other blocks
+                    // - source file 
+                    // - switch\default clauses
+                    if (isSomeBlock(parent.kind) ||
+                        parent.kind === SyntaxKind.SourceFile ||
+                        parent.kind === SyntaxKind.CaseClause ||
+                        parent.kind === SyntaxKind.DefaultClause) {
+
+                        indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
+                    }
+                    else {
+                        indentation = parentDynamicIndentation.getIndentation();
+                    }
+                }
+                else {
+                    if (SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
+                        indentation = parentDynamicIndentation.getIndentation();
+                    }
+                    else {
+                        indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta();
+                    }
+                }
+            }
+
+            var delta = SmartIndenter.shouldIndentChildNode(node.kind, SyntaxKind.Unknown) ? options.IndentSize : 0;
+
+            if (effectiveParentStartLine === startLine) {
+                // if node is located on the same line with the parent
+                // - inherit indentation from the parent
+                // - push children if either parent of node itself has non-zero delta
+                indentation = parentDynamicIndentation.getIndentation();
+                delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
+            }
+            return {
+                indentation,
+                delta
+            }
+        }
+
+        function getFirstNonDecoratorTokenOfNode(node: Node) {
+            if (node.modifiers && node.modifiers.length) {
+                return node.modifiers[0].kind;
+            }
+            switch (node.kind) {
+                case SyntaxKind.ClassDeclaration: return SyntaxKind.ClassKeyword;
+                case SyntaxKind.InterfaceDeclaration: return SyntaxKind.InterfaceKeyword;
+                case SyntaxKind.FunctionDeclaration: return SyntaxKind.FunctionKeyword;
+                case SyntaxKind.EnumDeclaration: return SyntaxKind.EnumDeclaration;
+                case SyntaxKind.GetAccessor: return SyntaxKind.GetKeyword;
+                case SyntaxKind.SetAccessor: return SyntaxKind.SetKeyword;
+                case SyntaxKind.MethodDeclaration:
+                    if ((<MethodDeclaration>node).asteriskToken) {
+                        return SyntaxKind.AsteriskToken;
+                    }
+                    // fall-through
+
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.Parameter:
+                    return (<Declaration>node).name.kind;
+            }
+        }
+
+        function getDynamicIndentation(node: Node, nodeStartLine: number, indentation: number, delta: number): DynamicIndentation {
+            return {
+                getIndentationForComment: kind => {
+                    switch (kind) {
+                        // preceding comment to the token that closes the indentation scope inherits the indentation from the scope
+                        // ..  {
+                        //     // comment
+                        // }
+                        case SyntaxKind.CloseBraceToken:
+                        case SyntaxKind.CloseBracketToken:
+                            return indentation + delta;
+                    }
+                    return indentation;
+                },
+                getIndentationForToken: (line, kind) => {
+                    if (nodeStartLine !== line && node.decorators) {
+                        if (kind === getFirstNonDecoratorTokenOfNode(node)) {
+                            // if this token is the first token following the list of decorators, we do not need to indent
+                            return indentation;
+                        }
+                    }
+                    switch (kind) {
+                        // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent
+                        case SyntaxKind.OpenBraceToken:
+                        case SyntaxKind.CloseBraceToken:
+                        case SyntaxKind.OpenBracketToken:
+                        case SyntaxKind.CloseBracketToken:
+                        case SyntaxKind.ElseKeyword:
+                        case SyntaxKind.WhileKeyword:
+                        case SyntaxKind.AtToken:
+                            return indentation;
+                        default:
+                            // if token line equals to the line of containing node (this is a first token in the node) - use node indentation
+                            return nodeStartLine !== line ? indentation + delta : indentation;
+                    }
+                },
+                getIndentation: () => indentation,
+                getDelta: () => delta,
+                recomputeIndentation: lineAdded => {
+                    if (node.parent && SmartIndenter.shouldIndentChildNode(node.parent.kind, node.kind)) {
+                        if (lineAdded) {
+                            indentation += options.IndentSize;
+                        }
+                        else {
+                            indentation -= options.IndentSize;
+                        }
+
+                        if (SmartIndenter.shouldIndentChildNode(node.kind, SyntaxKind.Unknown)) {
+                            delta = options.IndentSize;
+                        }
+                        else {
+                            delta = 0;
+                        }
+                    }
+                },
+            }
+        }
+
+        function processNode(node: Node, contextNode: Node, nodeStartLine: number, undecoratedNodeStartLine: number, indentation: number, delta: number) {
+            if (!rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) {
+                return;
+            }
+
+            let nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
+
+            // a useful observations when tracking context node
+            //        /
+            //      [a]
+            //   /   |   \ 
+            //  [b] [c] [d]
+            // node 'a' is a context node for nodes 'b', 'c', 'd' 
+            // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a'
+            // this rule can be applied recursively to child nodes of 'a'.
+            // 
+            // context node is set to parent node value after processing every child node
+            // context node is set to parent of the token after processing every token
+
+            let childContextNode = contextNode;
+
+            // if there are any tokens that logically belong to node and interleave child nodes
+            // such tokens will be consumed in processChildNode for for the child that follows them
+            forEachChild(
+                node,
+                child => {
+                    processChildNode(child, /*inheritedIndentation*/ Constants.Unknown, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListElement*/ false)
+                },
+                (nodes: NodeArray<Node>) => {
+                    processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation);
+                });
+
+            // proceed any tokens in the node that are located after child nodes
+            while (formattingScanner.isOnToken()) {
+                let tokenInfo = formattingScanner.readTokenInfo(node);
+                if (tokenInfo.token.end > node.end) {
+                    break;
+                }
+                consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation);
+            }
+
+            function processChildNode(
+                child: Node,
+                inheritedIndentation: number,
+                parent: Node,
+                parentDynamicIndentation: DynamicIndentation,
+                parentStartLine: number,
+                undecoratedParentStartLine: number,
+                isListItem: boolean): number {
+
+                let childStartPos = child.getStart(sourceFile);
+
+                let childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line;
+
+                let undecoratedChildStartLine = childStartLine;
+                if (child.decorators) {
+                    undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(child, sourceFile)).line;
+                }
+
+                // if child is a list item - try to get its indentation
+                let childIndentationAmount = Constants.Unknown;
+                if (isListItem) {
+                    childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
+                    if (childIndentationAmount !== Constants.Unknown) {
+                        inheritedIndentation = childIndentationAmount;
+                    }
+                }
+
+                // child node is outside the target range - do not dive inside
+                if (!rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
+                    return inheritedIndentation;
+                }
+                
+                if (child.getFullWidth() === 0) {
+                    return inheritedIndentation;
+                }
+
+                while (formattingScanner.isOnToken()) {
+                    // proceed any parent tokens that are located prior to child.getStart()
+                    let tokenInfo = formattingScanner.readTokenInfo(node);
+                    if (tokenInfo.token.end > childStartPos) {
+                        // stop when formatting scanner advances past the beginning of the child
+                        break;
+                    }
+
+                    consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
+                }
+
+                if (!formattingScanner.isOnToken()) {
+                    return inheritedIndentation;
+                }
+
+                if (isToken(child)) {
+                    // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
+                    let tokenInfo = formattingScanner.readTokenInfo(child);
+                    Debug.assert(tokenInfo.token.end === child.end);
+                    consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation);
+                    return inheritedIndentation;
+                }
+
+                let effectiveParentStartLine = child.kind === SyntaxKind.Decorator ? childStartLine : undecoratedParentStartLine;
+                let childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine);
+
+                processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta);
+
+                childContextNode = node;
+
+                return inheritedIndentation;
+            }
+
+            function processChildNodes(nodes: NodeArray<Node>, 
+                parent: Node, 
+                parentStartLine: number,
+                parentDynamicIndentation: DynamicIndentation): void {
+
+                let listStartToken = getOpenTokenForList(parent, nodes);
+                let listEndToken = getCloseTokenForOpenToken(listStartToken);
+
+                let listDynamicIndentation = parentDynamicIndentation;
+                let startLine = parentStartLine;
+
+                if (listStartToken !== SyntaxKind.Unknown) {
+                    // introduce a new indentation scope for lists (including list start and end tokens)
+                    while (formattingScanner.isOnToken()) {
+                        let tokenInfo = formattingScanner.readTokenInfo(parent);
+                        if (tokenInfo.token.end > nodes.pos) {
+                            // stop when formatting scanner moves past the beginning of node list
+                            break;
+                        }
+                        else if (tokenInfo.token.kind === listStartToken) {
+                            // consume list start token
+                            startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
+                            let indentation =
+                                computeIndentation(tokenInfo.token, startLine, Constants.Unknown, parent, parentDynamicIndentation, startLine);
+
+                            listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation.indentation, indentation.delta);
+                            consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
+                        }
+                        else {
+                            // consume any tokens that precede the list as child elements of 'node' using its indentation scope
+                            consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation);
+                        }
+                    }
+                }
+
+                let inheritedIndentation = Constants.Unknown;
+                for (let child of nodes) {
+                    inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListElement*/ true)
+                }
+
+                if (listEndToken !== SyntaxKind.Unknown) {
+                    if (formattingScanner.isOnToken()) {
+                        let tokenInfo = formattingScanner.readTokenInfo(parent);
+                        // consume the list end token only if it is still belong to the parent
+                        // there might be the case when current token matches end token but does not considered as one
+                        // function (x: function) <-- 
+                        // without this check close paren will be interpreted as list end token for function expression which is wrong
+                        if (tokenInfo.token.kind === listEndToken && rangeContainsRange(parent, tokenInfo.token)) {
+                            // consume list end token
+                            consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation);
+                        }
+                    }
+                }
+            }
+
+            function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation): void {
+                Debug.assert(rangeContainsRange(parent, currentTokenInfo.token));
+
+                let lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
+                let indentToken = false;
+
+                if (currentTokenInfo.leadingTrivia) {
+                    processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation);
+                }
+
+                let lineAdded: boolean;
+                let isTokenInRange = rangeContainsRange(originalRange, currentTokenInfo.token);
+
+                let tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
+                if (isTokenInRange) {
+                    let rangeHasError = rangeContainsError(currentTokenInfo.token);
+                    // save prevStartLine since processRange will overwrite this value with current ones
+                    let prevStartLine = previousRangeStartLine;
+                    lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
+                    if (rangeHasError) {
+                        // do not indent comments\token if token range overlaps with some error
+                        indentToken = false;
+                    }
+                    else {
+                        if (lineAdded !== undefined) {
+                            indentToken = lineAdded;
+                        }
+                        else {
+                            indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine;
+                        }
+                    }
+                }
+
+                if (currentTokenInfo.trailingTrivia) {
+                    processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation);
+                }
+
+                if (indentToken) {
+                    let indentNextTokenOrTrivia = true;
+                    if (currentTokenInfo.leadingTrivia) {
+                        for (let triviaItem of currentTokenInfo.leadingTrivia) {
+                            if (!rangeContainsRange(originalRange, triviaItem)) {
+                                continue;
+                            }
+
+                            let triviaStartLine = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos).line;
+                            switch (triviaItem.kind) {
+                                case SyntaxKind.MultiLineCommentTrivia:
+                                    let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
+                                    indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia);
+                                    indentNextTokenOrTrivia = false;
+                                    break;
+                                case SyntaxKind.SingleLineCommentTrivia:
+                                    if (indentNextTokenOrTrivia) {
+                                        let commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind);
+                                        insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false);
+                                        indentNextTokenOrTrivia = false;
+                                    }
+                                    break;
+                                case SyntaxKind.NewLineTrivia:
+                                    indentNextTokenOrTrivia = true;
+                                    break;
+                            }
+                        }
+                    }
+
+                    // indent token only if is it is in target range and does not overlap with any error ranges
+                    if (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) {
+                        let tokenIndentation = dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind);
+                        insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded);
+                    }
+                }
+
+                formattingScanner.advance();
+
+                childContextNode = parent;
+            }
+        }
+
+        function processTrivia(trivia: TextRangeWithKind[], parent: Node, contextNode: Node, dynamicIndentation: DynamicIndentation): void {
+            for (let triviaItem of trivia) {
+                if (isComment(triviaItem.kind) && rangeContainsRange(originalRange, triviaItem)) {
+                    let triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
+                    processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation);
+                }
+            }
+        }
+
+        function processRange(range: TextRangeWithKind, 
+            rangeStart: LineAndCharacter, 
+            parent: Node, 
+            contextNode: Node, 
+            dynamicIndentation: DynamicIndentation): boolean {
+            
+            let rangeHasError = rangeContainsError(range);
+            let lineAdded: boolean;
+            if (!rangeHasError && !previousRangeHasError) {
+                if (!previousRange) {
+                    // trim whitespaces starting from the beginning of the span up to the current line
+                    let originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
+                    trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
+                }
+                else {
+                    lineAdded = 
+                        processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation)
+                }
+            }
+
+            previousRange = range;
+            previousParent = parent;
+            previousRangeStartLine = rangeStart.line;
+            previousRangeHasError = rangeHasError;
+
+            return lineAdded;
+        }
+
+        function processPair(currentItem: TextRangeWithKind,
+            currentStartLine: number,
+            currentParent: Node,
+            previousItem: TextRangeWithKind,
+            previousStartLine: number,
+            previousParent: Node,
+            contextNode: Node,
+            dynamicIndentation: DynamicIndentation): boolean {
+
+            formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
+
+            let rule = rulesProvider.getRulesMap().GetRule(formattingContext);
+
+            let trimTrailingWhitespaces: boolean;
+            let lineAdded: boolean;
+            if (rule) {
+                applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
+
+                if (rule.Operation.Action & (RuleAction.Space | RuleAction.Delete) && currentStartLine !== previousStartLine) {
+                    lineAdded = false;
+                    // Handle the case where the next line is moved to be the end of this line. 
+                    // In this case we don't indent the next line in the next pass.
+                    if (currentParent.getStart(sourceFile) === currentItem.pos) {
+                        dynamicIndentation.recomputeIndentation(/*lineAdded*/ false);
+                    }
+                }
+                else if (rule.Operation.Action & RuleAction.NewLine && currentStartLine === previousStartLine) {
+                    lineAdded = true;
+                    // Handle the case where token2 is moved to the new line. 
+                    // In this case we indent token2 in the next pass but we set
+                    // sameLineIndent flag to notify the indenter that the indentation is within the line.
+                    if (currentParent.getStart(sourceFile) === currentItem.pos) {
+                        dynamicIndentation.recomputeIndentation(/*lineAdded*/ true);
+                    }
+                }
+
+                // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
+                trimTrailingWhitespaces =
+                (rule.Operation.Action & (RuleAction.NewLine | RuleAction.Space)) &&
+                rule.Flag !== RuleFlags.CanDeleteNewLines;
+            }
+            else {
+                trimTrailingWhitespaces = true;
+            }
+
+            if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) {
+                // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
+                trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem);
+            }
+
+            return lineAdded;
+        }
+
+        function insertIndentation(pos: number, indentation: number, lineAdded: boolean): void {
+            let indentationString = getIndentationString(indentation, options);
+            if (lineAdded) {
+                // new line is added before the token by the formatting rules
+                // insert indentation string at the very beginning of the token
+                recordReplace(pos, 0, indentationString);
+            }
+            else {
+                let tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
+                if (indentation !== tokenStart.character) {
+                    let startLinePosition = getStartPositionOfLine(tokenStart.line, sourceFile);
+                    recordReplace(startLinePosition, tokenStart.character, indentationString);
+                }
+            }
+        }
+
+        function indentMultilineComment(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean) {
+            // split comment in lines
+            let startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
+            let endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
+            let parts: TextRange[];
+            if (startLine === endLine) {
+                if (!firstLineIsIndented) {
+                    // treat as single line comment
+                    insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false);
+                }
+                return;
+            }
+            else {
+                parts = [];
+                let startPos = commentRange.pos;
+                for (let line = startLine; line < endLine; ++line) {
+                    let endOfLine = getEndLinePosition(line, sourceFile);
+                    parts.push({ pos: startPos, end: endOfLine });
+                    startPos = getStartPositionOfLine(line + 1, sourceFile);
+                }
+
+                parts.push({ pos: startPos, end: commentRange.end });
+            }
+
+            let startLinePos = getStartPositionOfLine(startLine, sourceFile);
+
+            let nonWhitespaceColumnInFirstPart =
+                SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
+
+            if (indentation === nonWhitespaceColumnInFirstPart.column) {
+                return;
+            }
+
+            let startIndex = 0;
+            if (firstLineIsIndented) {
+                startIndex = 1;
+                startLine++;
+            }
+
+            // shift all parts on the delta size
+            let delta = indentation - nonWhitespaceColumnInFirstPart.column;
+            for (let i = startIndex, len = parts.length; i < len; ++i, ++startLine) {
+                let startLinePos = getStartPositionOfLine(startLine, sourceFile);
+                let nonWhitespaceCharacterAndColumn =
+                    i === 0
+                        ? nonWhitespaceColumnInFirstPart
+                        : SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
+
+                let newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
+                if (newIndentation > 0) {
+                    let indentationString = getIndentationString(newIndentation, options);
+                    recordReplace(startLinePos, nonWhitespaceCharacterAndColumn.character, indentationString);
+                }
+                else {
+                    recordDelete(startLinePos, nonWhitespaceCharacterAndColumn.character);
+                }
+            }
+        }
+
+        function trimTrailingWhitespacesForLines(line1: number, line2: number, range?: TextRangeWithKind) {
+            for (let line = line1; line < line2; ++line) {
+                let lineStartPosition = getStartPositionOfLine(line, sourceFile);
+                let lineEndPosition = getEndLinePosition(line, sourceFile);
+
+                // do not trim whitespaces in comments
+                if (range && isComment(range.kind) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
+                    continue;
+                }
+
+                let pos = lineEndPosition;
+                while (pos >= lineStartPosition && isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
+                    pos--;
+                }
+                if (pos !== lineEndPosition) {
+                    Debug.assert(pos === lineStartPosition || !isWhiteSpace(sourceFile.text.charCodeAt(pos)));
+                    recordDelete(pos + 1, lineEndPosition - pos);
+                }
+            }
+        }
+
+        function newTextChange(start: number, len: number, newText: string): TextChange {
+            return { span: createTextSpan(start, len), newText }
+        }
+
+        function recordDelete(start: number, len: number) {
+            if (len) {
+                edits.push(newTextChange(start, len, ""));
+            }
+        }
+
+        function recordReplace(start: number, len: number, newText: string) {
+            if (len || newText) {
+                edits.push(newTextChange(start, len, newText));
+            }
+        }
+
+        function applyRuleEdits(rule: Rule,
+            previousRange: TextRangeWithKind,
+            previousStartLine: number,
+            currentRange: TextRangeWithKind,
+            currentStartLine: number): void {
+
+            let between: TextRange;
+            switch (rule.Operation.Action) {
+                case RuleAction.Ignore:
+                    // no action required
+                    return;
+                case RuleAction.Delete:
+                    if (previousRange.end !== currentRange.pos) {
+                        // delete characters starting from t1.end up to t2.pos exclusive
+                        recordDelete(previousRange.end, currentRange.pos - previousRange.end);
+                    }
+                    break;
+                case RuleAction.NewLine:
+                    // exit early if we on different lines and rule cannot change number of newlines
+                    // if line1 and line2 are on subsequent lines then no edits are required - ok to exit
+                    // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines
+                    if (rule.Flag !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) {
+                        return;
+                    }
+
+                    // edit should not be applied only if we have one line feed between elements
+                    let lineDelta = currentStartLine - previousStartLine;
+                    if (lineDelta !== 1) {
+                        recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter);
+                    }
+                    break;
+                case RuleAction.Space:
+                    // exit early if we on different lines and rule cannot change number of newlines
+                    if (rule.Flag !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) {
+                        return;
+                    }
+
+                    let posDelta = currentRange.pos - previousRange.end;
+                    if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== CharacterCodes.space) {
+                        recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
+                    }
+                    break;
+            }
+        }
+    }
+
+    function isSomeBlock(kind: SyntaxKind): boolean {
+        switch (kind) {
+            case SyntaxKind.Block:
+            case SyntaxKind.ModuleBlock:
+                return true;
+        }
+        return false;
+    }
+
+    function getOpenTokenForList(node: Node, list: Node[]) {
+        switch (node.kind) {
+            case SyntaxKind.Constructor:
+            case SyntaxKind.FunctionDeclaration:
+            case SyntaxKind.FunctionExpression:
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.MethodSignature:
+            case SyntaxKind.ArrowFunction:
+                if ((<FunctionDeclaration>node).typeParameters === list) {
+                    return SyntaxKind.LessThanToken;
+                }
+                else if ((<FunctionDeclaration>node).parameters === list) {
+                    return SyntaxKind.OpenParenToken;
+                }
+                break;
+            case SyntaxKind.CallExpression:
+            case SyntaxKind.NewExpression:
+                if ((<CallExpression>node).typeArguments === list) {
+                    return SyntaxKind.LessThanToken;
+                }
+                else if ((<CallExpression>node).arguments === list) {
+                    return SyntaxKind.OpenParenToken;
+                }
+                break;
+            case SyntaxKind.TypeReference:
+                if ((<TypeReferenceNode>node).typeArguments === list) {
+                    return SyntaxKind.LessThanToken;
+                }
+        }
+
+        return SyntaxKind.Unknown;
+    }
+
+    function getCloseTokenForOpenToken(kind: SyntaxKind) {
+        switch (kind) {
+            case SyntaxKind.OpenParenToken:
+                return SyntaxKind.CloseParenToken;
+            case SyntaxKind.LessThanToken:
+                return SyntaxKind.GreaterThanToken;
+        }
+
+        return SyntaxKind.Unknown;
+    }
+
+    var internedSizes: { tabSize: number; indentSize: number };
+    var internedTabsIndentation: string[];
+    var internedSpacesIndentation: string[];
+
+    export function getIndentationString(indentation: number, options: FormatCodeOptions): string {
+        // reset interned strings if FormatCodeOptions were changed
+        let resetInternedStrings =
+            !internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize);
+
+        if (resetInternedStrings) {
+            internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize };
+            internedTabsIndentation = internedSpacesIndentation = undefined;
+        }
+
+        if (!options.ConvertTabsToSpaces) {
+            let tabs = Math.floor(indentation / options.TabSize);
+            let spaces = indentation - tabs * options.TabSize;
+
+            let tabString: string;
+            if (!internedTabsIndentation) {
+                internedTabsIndentation = [];
+            }
+
+            if (internedTabsIndentation[tabs] === undefined) {
+                internedTabsIndentation[tabs] = tabString = repeat('\t', tabs);
+            }
+            else {
+                tabString = internedTabsIndentation[tabs];
+            }
+
+            return spaces ? tabString + repeat(" ", spaces) : tabString;
+        }
+        else {
+            let spacesString: string;
+            let quotient = Math.floor(indentation / options.IndentSize);
+            let remainder = indentation % options.IndentSize;
+            if (!internedSpacesIndentation) {
+                internedSpacesIndentation = [];
+            }
+
+            if (internedSpacesIndentation[quotient] === undefined) {
+                spacesString = repeat(" ", options.IndentSize * quotient);
+                internedSpacesIndentation[quotient] = spacesString;
+            }
+            else {
+                spacesString = internedSpacesIndentation[quotient];
+            }
+
+            return remainder ? spacesString + repeat(" ", remainder) : spacesString;
+        }
+
+        function repeat(value: string, count: number): string {
+            let s = "";
+            for (let i = 0; i < count; ++i) {
+                s += value;
+            }
+
+            return s;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/formattingContext.ts b/lib/typescript/services/formatting/formattingContext.ts
new file mode 100644
index 000000000..b34dad8ac
--- /dev/null
+++ b/lib/typescript/services/formatting/formattingContext.ts
@@ -0,0 +1,101 @@
+/// <reference path="references.ts"/>
+
+/* @internal */
+module ts.formatting {
+    export class FormattingContext {
+        public currentTokenSpan: TextRangeWithKind;
+        public nextTokenSpan: TextRangeWithKind;
+        public contextNode: Node;
+        public currentTokenParent: Node;
+        public nextTokenParent: Node;
+
+        private contextNodeAllOnSameLine: boolean;
+        private nextNodeAllOnSameLine: boolean;
+        private tokensAreOnSameLine: boolean;
+        private contextNodeBlockIsOnOneLine: boolean;
+        private nextNodeBlockIsOnOneLine: boolean;
+
+        constructor(public sourceFile: SourceFile, public formattingRequestKind: FormattingRequestKind) {
+        }
+
+        public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) {
+            Debug.assert(currentRange !== undefined, "currentTokenSpan is null");
+            Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null");
+            Debug.assert(nextRange !== undefined, "nextTokenSpan is null");
+            Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null");
+            Debug.assert(commonParent !== undefined, "commonParent is null");
+
+            this.currentTokenSpan = currentRange;
+            this.currentTokenParent = currentTokenParent;
+            this.nextTokenSpan = nextRange;
+            this.nextTokenParent = nextTokenParent;
+            this.contextNode = commonParent;
+
+            // drop cached results
+            this.contextNodeAllOnSameLine = undefined;
+            this.nextNodeAllOnSameLine = undefined;
+            this.tokensAreOnSameLine = undefined;
+            this.contextNodeBlockIsOnOneLine = undefined;
+            this.nextNodeBlockIsOnOneLine = undefined;
+        }
+
+        public ContextNodeAllOnSameLine(): boolean {
+            if (this.contextNodeAllOnSameLine === undefined) {
+                this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
+            }
+
+            return this.contextNodeAllOnSameLine;
+        }
+
+        public NextNodeAllOnSameLine(): boolean {
+            if (this.nextNodeAllOnSameLine === undefined) {
+                this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
+            }
+
+            return this.nextNodeAllOnSameLine;
+        }
+
+        public TokensAreOnSameLine(): boolean {
+            if (this.tokensAreOnSameLine === undefined) {
+                let startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
+                let endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
+                this.tokensAreOnSameLine = (startLine == endLine);
+            }
+
+            return this.tokensAreOnSameLine;
+        }
+
+        public ContextNodeBlockIsOnOneLine() {
+            if (this.contextNodeBlockIsOnOneLine === undefined) {
+                this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
+            }
+
+            return this.contextNodeBlockIsOnOneLine;
+        }
+
+        public NextNodeBlockIsOnOneLine() {
+            if (this.nextNodeBlockIsOnOneLine === undefined) {
+                this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
+            }
+
+            return this.nextNodeBlockIsOnOneLine;
+        }
+
+        private NodeIsOnOneLine(node: Node): boolean {
+            let startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
+            let endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
+            return startLine == endLine;
+        }
+
+        private BlockIsOnOneLine(node: Node): boolean {
+            let openBrace = findChildOfKind(node, SyntaxKind.OpenBraceToken, this.sourceFile);
+            let closeBrace = findChildOfKind(node, SyntaxKind.CloseBraceToken, this.sourceFile);
+            if (openBrace && closeBrace) {
+                let startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
+                let endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
+                return startLine === endLine;
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/formattingRequestKind.ts b/lib/typescript/services/formatting/formattingRequestKind.ts
new file mode 100644
index 000000000..3bf60cd2a
--- /dev/null
+++ b/lib/typescript/services/formatting/formattingRequestKind.ts
@@ -0,0 +1,12 @@
+/// <reference path="references.ts"/>
+
+/* @internal */
+module ts.formatting {
+    export const enum FormattingRequestKind {
+        FormatDocument,
+        FormatSelection,
+        FormatOnEnter,
+        FormatOnSemicolon,
+        FormatOnClosingCurlyBrace
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/formattingScanner.ts b/lib/typescript/services/formatting/formattingScanner.ts
new file mode 100644
index 000000000..680602ece
--- /dev/null
+++ b/lib/typescript/services/formatting/formattingScanner.ts
@@ -0,0 +1,243 @@
+/// <reference path="formatting.ts"/>
+/// <reference path="..\..\compiler\scanner.ts"/>
+
+/* @internal */
+module ts.formatting {
+    let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
+
+    export interface FormattingScanner {
+        advance(): void;
+        isOnToken(): boolean;
+        readTokenInfo(n: Node): TokenInfo;
+        lastTrailingTriviaWasNewLine(): boolean;
+        close(): void;
+    }
+
+    const enum ScanAction{
+        Scan,
+        RescanGreaterThanToken,
+        RescanSlashToken,
+        RescanTemplateToken
+    }
+
+    export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
+
+        scanner.setText(sourceFile.text);
+        scanner.setTextPos(startPos);
+
+        let wasNewLine: boolean = true;
+        let leadingTrivia: TextRangeWithKind[];
+        let trailingTrivia: TextRangeWithKind[];
+        
+        let savedPos: number;
+        let lastScanAction: ScanAction;
+        let lastTokenInfo: TokenInfo;
+
+        return {
+            advance: advance,
+            readTokenInfo: readTokenInfo,
+            isOnToken: isOnToken,
+            lastTrailingTriviaWasNewLine: () => wasNewLine,
+            close: () => {
+                lastTokenInfo = undefined;
+                scanner.setText(undefined);
+            }
+        }
+
+        function advance(): void {
+            lastTokenInfo = undefined;
+            let isStarted = scanner.getStartPos() !== startPos;
+
+            if (isStarted) {
+                if (trailingTrivia) {
+                    Debug.assert(trailingTrivia.length !== 0);
+                    wasNewLine = trailingTrivia[trailingTrivia.length - 1].kind === SyntaxKind.NewLineTrivia;
+                }
+                else {
+                    wasNewLine = false;
+                }
+            }
+
+            leadingTrivia = undefined;
+            trailingTrivia = undefined;
+
+            if (!isStarted) {
+                scanner.scan();
+            }
+
+            let t: SyntaxKind;
+            let pos = scanner.getStartPos();
+            
+            // Read leading trivia and token
+            while (pos < endPos) {
+                let t = scanner.getToken();
+                if (!isTrivia(t)) {
+                    break;
+                }
+
+                // consume leading trivia
+                scanner.scan();
+                let item = {
+                    pos: pos,
+                    end: scanner.getStartPos(),
+                    kind: t
+                }
+
+                pos = scanner.getStartPos();
+
+                if (!leadingTrivia) {
+                    leadingTrivia = [];
+                }
+                leadingTrivia.push(item);
+            }
+
+            savedPos = scanner.getStartPos();
+        }
+
+        function shouldRescanGreaterThanToken(node: Node): boolean {
+            if (node) {
+                switch (node.kind) {
+                    case SyntaxKind.GreaterThanEqualsToken:
+                    case SyntaxKind.GreaterThanGreaterThanEqualsToken:
+                    case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
+                    case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
+                    case SyntaxKind.GreaterThanGreaterThanToken:
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        function shouldRescanSlashToken(container: Node): boolean {
+            return container.kind === SyntaxKind.RegularExpressionLiteral;
+        }
+
+        function shouldRescanTemplateToken(container: Node): boolean {
+            return container.kind === SyntaxKind.TemplateMiddle || 
+                container.kind === SyntaxKind.TemplateTail;
+        }
+
+        function startsWithSlashToken(t: SyntaxKind): boolean {
+            return t === SyntaxKind.SlashToken || t === SyntaxKind.SlashEqualsToken;
+        }
+
+        function readTokenInfo(n: Node): TokenInfo {
+            if (!isOnToken()) {
+                // scanner is not on the token (either advance was not called yet or scanner is already past the end position)
+                return {
+                    leadingTrivia: leadingTrivia,
+                    trailingTrivia: undefined,
+                    token: undefined
+                };
+            }
+
+            // normally scanner returns the smallest available token
+            // check the kind of context node to determine if scanner should have more greedy behavior and consume more text.
+            let expectedScanAction = 
+                shouldRescanGreaterThanToken(n)
+                ? ScanAction.RescanGreaterThanToken
+                : shouldRescanSlashToken(n) 
+                    ? ScanAction.RescanSlashToken 
+                    : shouldRescanTemplateToken(n)
+                        ? ScanAction.RescanTemplateToken
+                        : ScanAction.Scan
+
+            if (lastTokenInfo && expectedScanAction === lastScanAction) {
+                // readTokenInfo was called before with the same expected scan action.
+                // No need to re-scan text, return existing 'lastTokenInfo'
+                // it is ok to call fixTokenKind here since it does not affect
+                // what portion of text is consumed. In opposize rescanning can change it,
+                // i.e. for '>=' when originally scanner eats just one character
+                // and rescanning forces it to consume more.
+                return fixTokenKind(lastTokenInfo, n);
+            }
+
+            if (scanner.getStartPos() !== savedPos) {
+                Debug.assert(lastTokenInfo !== undefined);
+                // readTokenInfo was called before but scan action differs - rescan text
+                scanner.setTextPos(savedPos);
+                scanner.scan();
+            }
+
+            let currentToken = scanner.getToken();
+
+            if (expectedScanAction === ScanAction.RescanGreaterThanToken && currentToken === SyntaxKind.GreaterThanToken) {
+                currentToken = scanner.reScanGreaterToken();
+                Debug.assert(n.kind === currentToken);
+                lastScanAction = ScanAction.RescanGreaterThanToken;
+            }
+            else if (expectedScanAction === ScanAction.RescanSlashToken && startsWithSlashToken(currentToken)) {
+                currentToken = scanner.reScanSlashToken();
+                Debug.assert(n.kind === currentToken);
+                lastScanAction = ScanAction.RescanSlashToken;
+            }
+            else if (expectedScanAction === ScanAction.RescanTemplateToken && currentToken === SyntaxKind.CloseBraceToken) {
+                currentToken = scanner.reScanTemplateToken();
+                lastScanAction = ScanAction.RescanTemplateToken;
+            }
+            else {
+                lastScanAction = ScanAction.Scan;
+            }
+
+            let token: TextRangeWithKind = {
+                pos: scanner.getStartPos(),
+                end: scanner.getTextPos(),
+                kind: currentToken
+            }
+
+            // consume trailing trivia
+            if (trailingTrivia) {
+                trailingTrivia = undefined;
+            }
+            while(scanner.getStartPos() < endPos) {
+                currentToken = scanner.scan();
+                if (!isTrivia(currentToken)) {
+                    break;
+                }
+                let trivia = {
+                    pos: scanner.getStartPos(),
+                    end: scanner.getTextPos(),
+                    kind: currentToken
+                };
+
+                if (!trailingTrivia) {
+                    trailingTrivia = [];
+                }
+
+                trailingTrivia.push(trivia);
+
+                if (currentToken === SyntaxKind.NewLineTrivia) {
+                    // move past new line
+                    scanner.scan();
+                    break;
+                }
+            }
+
+            lastTokenInfo = {
+                leadingTrivia: leadingTrivia,
+                trailingTrivia: trailingTrivia,
+                token: token
+            }
+
+            return fixTokenKind(lastTokenInfo, n);
+        }
+
+        function isOnToken(): boolean {
+            let current = (lastTokenInfo && lastTokenInfo.token.kind) ||  scanner.getToken();
+            let startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
+            return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
+        }
+
+        // when containing node in the tree is token 
+        // but its kind differs from the kind that was returned by the scanner,
+        // then kind needs to be fixed. This might happen in cases 
+        // when parser interprets token differently, i.e keyword treated as identifier
+        function fixTokenKind(tokenInfo: TokenInfo, container: Node): TokenInfo {
+            if (isToken(container) && tokenInfo.token.kind !== container.kind) {
+                tokenInfo.token.kind = container.kind;
+            }
+            return tokenInfo;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/references.ts b/lib/typescript/services/formatting/references.ts
new file mode 100644
index 000000000..e23ead5c5
--- /dev/null
+++ b/lib/typescript/services/formatting/references.ts
@@ -0,0 +1,12 @@
+///<reference path='..\services.ts' />
+///<reference path='formattingContext.ts' />
+///<reference path='formattingRequestKind.ts' />
+///<reference path='rule.ts' />
+///<reference path='ruleAction.ts' />
+///<reference path='ruleDescriptor.ts' />
+///<reference path='ruleFlag.ts' />
+///<reference path='ruleOperation.ts' />
+///<reference path='ruleOperationContext.ts' />
+///<reference path='rules.ts' />
+///<reference path='rulesMap.ts' />
+///<reference path='tokenRange.ts' />
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/rule.ts b/lib/typescript/services/formatting/rule.ts
new file mode 100644
index 000000000..807e0f056
--- /dev/null
+++ b/lib/typescript/services/formatting/rule.ts
@@ -0,0 +1,18 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+    export class Rule {
+        constructor(
+            public Descriptor: RuleDescriptor,
+            public Operation: RuleOperation,
+            public Flag: RuleFlags = RuleFlags.None) {
+        }
+
+        public toString() {
+            return "[desc=" + this.Descriptor + "," +
+                "operation=" + this.Operation + "," +
+                "flag=" + this.Flag + "]";
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/ruleAction.ts b/lib/typescript/services/formatting/ruleAction.ts
new file mode 100644
index 000000000..18d591199
--- /dev/null
+++ b/lib/typescript/services/formatting/ruleAction.ts
@@ -0,0 +1,11 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+    export const enum RuleAction {
+        Ignore      = 0x00000001,
+        Space       = 0x00000002,
+        NewLine     = 0x00000004,
+        Delete      = 0x00000008
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/ruleDescriptor.ts b/lib/typescript/services/formatting/ruleDescriptor.ts
new file mode 100644
index 000000000..f4ef9da34
--- /dev/null
+++ b/lib/typescript/services/formatting/ruleDescriptor.ts
@@ -0,0 +1,30 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+    export class RuleDescriptor {
+        constructor(public LeftTokenRange: Shared.TokenRange, public RightTokenRange: Shared.TokenRange) {
+        }
+
+        public toString(): string {
+            return "[leftRange=" + this.LeftTokenRange + "," +
+                "rightRange=" + this.RightTokenRange + "]";
+        }
+
+        static create1(left: SyntaxKind, right: SyntaxKind): RuleDescriptor {
+            return RuleDescriptor.create4(Shared.TokenRange.FromToken(left), Shared.TokenRange.FromToken(right));
+        }
+
+        static create2(left: Shared.TokenRange, right: SyntaxKind): RuleDescriptor {
+            return RuleDescriptor.create4(left, Shared.TokenRange.FromToken(right));
+        }
+
+        static create3(left: SyntaxKind, right: Shared.TokenRange): RuleDescriptor {
+            return RuleDescriptor.create4(Shared.TokenRange.FromToken(left), right);
+        }
+
+        static create4(left: Shared.TokenRange, right: Shared.TokenRange): RuleDescriptor {
+            return new RuleDescriptor(left, right);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/ruleFlag.ts b/lib/typescript/services/formatting/ruleFlag.ts
new file mode 100644
index 000000000..697aa5312
--- /dev/null
+++ b/lib/typescript/services/formatting/ruleFlag.ts
@@ -0,0 +1,10 @@
+///<reference path='references.ts' />
+
+
+/* @internal */
+module ts.formatting {
+    export const enum RuleFlags {
+        None,
+        CanDeleteNewLines
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/ruleOperation.ts b/lib/typescript/services/formatting/ruleOperation.ts
new file mode 100644
index 000000000..387b79537
--- /dev/null
+++ b/lib/typescript/services/formatting/ruleOperation.ts
@@ -0,0 +1,30 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+    export class RuleOperation {
+        public Context: RuleOperationContext;
+        public Action: RuleAction;
+
+        constructor() {
+            this.Context = null;
+            this.Action = null;
+        }
+
+        public toString(): string {
+            return "[context=" + this.Context + "," +
+                "action=" + this.Action + "]";
+        }
+
+        static create1(action: RuleAction) {
+            return RuleOperation.create2(RuleOperationContext.Any, action)
+        }
+
+        static create2(context: RuleOperationContext, action: RuleAction) {
+            let result = new RuleOperation();
+            result.Context = context;
+            result.Action = action;
+            return result;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/ruleOperationContext.ts b/lib/typescript/services/formatting/ruleOperationContext.ts
new file mode 100644
index 000000000..d4e103cef
--- /dev/null
+++ b/lib/typescript/services/formatting/ruleOperationContext.ts
@@ -0,0 +1,33 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+
+    export class RuleOperationContext {
+        private customContextChecks: { (context: FormattingContext): boolean; }[];
+        
+        constructor(...funcs: { (context: FormattingContext): boolean; }[]) {
+            this.customContextChecks = funcs;
+        }
+
+        static Any: RuleOperationContext = new RuleOperationContext();
+
+
+        public IsAny(): boolean {
+            return this == RuleOperationContext.Any;
+        }
+
+        public  InContext(context: FormattingContext): boolean {
+            if (this.IsAny()) {
+                return true;
+            }
+
+            for (let check of this.customContextChecks) {
+                if (!check(context)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/rules.ts b/lib/typescript/services/formatting/rules.ts
new file mode 100644
index 000000000..e4b54d1ba
--- /dev/null
+++ b/lib/typescript/services/formatting/rules.ts
@@ -0,0 +1,717 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+    export class Rules {
+        public getRuleName(rule: Rule) {
+            let o: ts.Map<any> = <any>this;
+            for (let name in o) {
+                if (o[name] === rule) {
+                    return name;
+                }
+            }
+            throw new Error("Unknown rule");
+        }
+
+        [name: string]: any;
+
+        public IgnoreBeforeComment: Rule;
+        public IgnoreAfterLineComment: Rule;
+
+        // Space after keyword but not before ; or : or ?
+        public NoSpaceBeforeSemicolon: Rule;
+        public NoSpaceBeforeColon: Rule;
+        public NoSpaceBeforeQuestionMark: Rule;
+        public SpaceAfterColon: Rule;
+        // insert space after '?' only when it is used in conditional operator
+        public SpaceAfterQuestionMarkInConditionalOperator: Rule;
+        // in other cases there should be no space between '?' and next token
+        public NoSpaceAfterQuestionMark: Rule;
+
+        public SpaceAfterSemicolon: Rule;
+
+        // Space/new line after }.
+        public SpaceAfterCloseBrace: Rule;
+
+        // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied
+        // Also should not apply to })
+        public SpaceBetweenCloseBraceAndElse: Rule;
+        public SpaceBetweenCloseBraceAndWhile: Rule;
+        public NoSpaceAfterCloseBrace: Rule;
+
+        // No space for indexer and dot
+        public NoSpaceBeforeDot: Rule;
+        public NoSpaceAfterDot: Rule;
+        public NoSpaceBeforeOpenBracket: Rule;
+        public NoSpaceAfterOpenBracket: Rule;
+        public NoSpaceBeforeCloseBracket: Rule;
+        public NoSpaceAfterCloseBracket: Rule;
+
+        // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
+        public SpaceAfterOpenBrace: Rule;
+        public SpaceBeforeCloseBrace: Rule;
+        public NoSpaceBetweenEmptyBraceBrackets: Rule;
+
+        // Insert new line after { and before } in multi-line contexts.
+        public NewLineAfterOpenBraceInBlockContext: Rule;
+
+        // For functions and control block place } on a new line    [multi-line rule]
+        public NewLineBeforeCloseBraceInBlockContext: Rule;
+
+        // Special handling of unary operators.
+        // Prefix operators generally shouldn't have a space between
+        // them and their target unary expression.
+        public NoSpaceAfterUnaryPrefixOperator: Rule;
+        public NoSpaceAfterUnaryPreincrementOperator: Rule;
+        public NoSpaceAfterUnaryPredecrementOperator: Rule;
+        public NoSpaceBeforeUnaryPostincrementOperator: Rule;
+        public NoSpaceBeforeUnaryPostdecrementOperator: Rule;
+
+        // More unary operator special-casing.
+        // DevDiv 181814:  Be careful when removing leading whitespace
+        // around unary operators.  Examples:
+        //      1 - -2  --X-->  1--2
+        //      a + ++b --X-->  a+++b
+        public SpaceAfterPostincrementWhenFollowedByAdd: Rule;
+        public SpaceAfterAddWhenFollowedByUnaryPlus: Rule;
+        public SpaceAfterAddWhenFollowedByPreincrement: Rule;
+        public SpaceAfterPostdecrementWhenFollowedBySubtract: Rule;
+        public SpaceAfterSubtractWhenFollowedByUnaryMinus: Rule;
+        public SpaceAfterSubtractWhenFollowedByPredecrement: Rule;
+
+        public NoSpaceBeforeComma: Rule;
+
+        public SpaceAfterCertainKeywords: Rule;
+        public SpaceAfterLetConstInVariableDeclaration: Rule;
+        public NoSpaceBeforeOpenParenInFuncCall: Rule;
+        public SpaceAfterFunctionInFuncDecl: Rule;
+        public NoSpaceBeforeOpenParenInFuncDecl: Rule;
+        public SpaceAfterVoidOperator: Rule;
+
+        public NoSpaceBetweenReturnAndSemicolon: Rule;
+
+        // Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
+        // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
+        public SpaceBetweenStatements: Rule;
+
+        // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
+        public SpaceAfterTryFinally: Rule;
+
+        // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token.
+        // Though, we do extra check on the context to make sure we are dealing with get/set node. Example:
+        //      get x() {}
+        //      set x(val) {}
+        public SpaceAfterGetSetInMember: Rule;
+
+        // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options.
+        public SpaceBeforeBinaryKeywordOperator: Rule;
+        public SpaceAfterBinaryKeywordOperator: Rule;
+
+        // TypeScript-specific rules
+
+        // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses
+        public NoSpaceAfterConstructor: Rule;
+
+        // Use of module as a function call. e.g.: import m2 = module("m2");
+        public NoSpaceAfterModuleImport: Rule;
+
+        // Add a space around certain TypeScript keywords
+        public SpaceAfterCertainTypeScriptKeywords: Rule;
+        public SpaceBeforeCertainTypeScriptKeywords: Rule;
+
+        // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
+        public SpaceAfterModuleName: Rule;
+
+        // Lambda expressions
+        public SpaceAfterArrow: Rule;
+
+        // Optional parameters and let args
+        public NoSpaceAfterEllipsis: Rule;
+        public NoSpaceAfterOptionalParameters: Rule;
+
+        // generics
+        public NoSpaceBeforeOpenAngularBracket: Rule;
+        public NoSpaceBetweenCloseParenAndAngularBracket: Rule;
+        public NoSpaceAfterOpenAngularBracket: Rule;
+        public NoSpaceBeforeCloseAngularBracket: Rule;
+        public NoSpaceAfterCloseAngularBracket: Rule;
+
+        // Remove spaces in empty interface literals. e.g.: x: {}
+        public NoSpaceBetweenEmptyInterfaceBraceBrackets: Rule;
+
+        // These rules are higher in priority than user-configurable rules.
+        public HighPriorityCommonRules: Rule[];
+
+        // These rules are lower in priority than user-configurable rules.
+        public LowPriorityCommonRules: Rule[];
+
+        ///
+        /// Rules controlled by user options
+        ///
+
+        // Insert space after comma delimiter
+        public SpaceAfterComma: Rule;
+        public NoSpaceAfterComma: Rule;
+
+        // Insert space before and after binary operators
+        public SpaceBeforeBinaryOperator: Rule;
+        public SpaceAfterBinaryOperator: Rule;
+        public NoSpaceBeforeBinaryOperator: Rule;
+        public NoSpaceAfterBinaryOperator: Rule;
+
+        // Insert space after keywords in control flow statements
+        public SpaceAfterKeywordInControl: Rule;
+        public NoSpaceAfterKeywordInControl: Rule;
+
+        // Open Brace braces after function
+        //TypeScript: Function can have return types, which can be made of tons of different token kinds
+        public FunctionOpenBraceLeftTokenRange: Shared.TokenRange;
+        public SpaceBeforeOpenBraceInFunction: Rule;
+        public NewLineBeforeOpenBraceInFunction: Rule;
+
+        // Open Brace braces after TypeScript module/class/interface
+        public TypeScriptOpenBraceLeftTokenRange: Shared.TokenRange;
+        public SpaceBeforeOpenBraceInTypeScriptDeclWithBlock: Rule;
+        public NewLineBeforeOpenBraceInTypeScriptDeclWithBlock: Rule;
+
+        // Open Brace braces after control block
+        public ControlOpenBraceLeftTokenRange: Shared.TokenRange;
+        public SpaceBeforeOpenBraceInControl: Rule;
+        public NewLineBeforeOpenBraceInControl: Rule;
+
+        // Insert space after semicolon in for statement
+        public SpaceAfterSemicolonInFor: Rule;
+        public NoSpaceAfterSemicolonInFor: Rule;
+
+        // Insert space after opening and before closing nonempty parenthesis
+        public SpaceAfterOpenParen: Rule;
+        public SpaceBeforeCloseParen: Rule;
+        public NoSpaceBetweenParens: Rule;
+        public NoSpaceAfterOpenParen: Rule;
+        public NoSpaceBeforeCloseParen: Rule;
+
+        // Insert space after function keyword for anonymous functions
+        public SpaceAfterAnonymousFunctionKeyword: Rule;
+        public NoSpaceAfterAnonymousFunctionKeyword: Rule;
+
+        // Insert space after @ in decorator
+        public SpaceBeforeAt: Rule;
+        public NoSpaceAfterAt: Rule;
+        public SpaceAfterDecorator: Rule;
+
+        constructor() {
+            ///
+            /// Common Rules
+            ///
+
+            // Leave comments alone
+            this.IgnoreBeforeComment = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.Comments), RuleOperation.create1(RuleAction.Ignore));
+            this.IgnoreAfterLineComment = new Rule(RuleDescriptor.create3(SyntaxKind.SingleLineCommentTrivia, Shared.TokenRange.Any), RuleOperation.create1(RuleAction.Ignore));
+
+            // Space after keyword but not before ; or : or ?
+            this.NoSpaceBeforeSemicolon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.SemicolonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceBeforeColon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.ColonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete));
+            this.NoSpaceBeforeQuestionMark = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.QuestionToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete));
+            this.SpaceAfterColon = new Rule(RuleDescriptor.create3(SyntaxKind.ColonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterQuestionMarkInConditionalOperator = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsConditionalOperatorContext), RuleAction.Space));
+            this.NoSpaceAfterQuestionMark = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.SpaceAfterSemicolon = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+
+            // Space after }.
+            this.SpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsAfterCodeBlockContext), RuleAction.Space));
+
+            // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied
+            this.SpaceBetweenCloseBraceAndElse = new Rule(RuleDescriptor.create1(SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.SpaceBetweenCloseBraceAndWhile = new Rule(RuleDescriptor.create1(SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.NoSpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken, SyntaxKind.SemicolonToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            // No space for indexer and dot
+            this.NoSpaceBeforeDot = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.DotToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceAfterDot = new Rule(RuleDescriptor.create3(SyntaxKind.DotToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceBeforeOpenBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            // Place a space before open brace in a function declaration
+            this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments;
+            this.SpaceBeforeOpenBraceInFunction = new Rule(RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines);
+
+            // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc)
+            this.TypeScriptOpenBraceLeftTokenRange = Shared.TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.MultiLineCommentTrivia]);
+            this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new Rule(RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines);
+
+            // Place a space before open brace in a control flow construct
+            this.ControlOpenBraceLeftTokenRange = Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.DoKeyword, SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword, SyntaxKind.ElseKeyword]);
+            this.SpaceBeforeOpenBraceInControl = new Rule(RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines);
+
+            // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
+            this.SpaceAfterOpenBrace = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSingleLineBlockContext), RuleAction.Space));
+            this.SpaceBeforeCloseBrace = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSingleLineBlockContext), RuleAction.Space));
+            this.NoSpaceBetweenEmptyBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectContext), RuleAction.Delete));
+
+            // Insert new line after { and before } in multi-line contexts.
+            this.NewLineAfterOpenBraceInBlockContext = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsMultilineBlockContext), RuleAction.NewLine));
+
+            // For functions and control block place } on a new line    [multi-line rule]
+            this.NewLineBeforeCloseBraceInBlockContext = new Rule(RuleDescriptor.create2(Shared.TokenRange.AnyIncludingMultilineComments, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsMultilineBlockContext), RuleAction.NewLine));
+
+            // Special handling of unary operators.
+            // Prefix operators generally shouldn't have a space between
+            // them and their target unary expression.
+            this.NoSpaceAfterUnaryPrefixOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.UnaryPrefixOperators, Shared.TokenRange.UnaryPrefixExpressions), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete));
+            this.NoSpaceAfterUnaryPreincrementOperator = new Rule(RuleDescriptor.create3(SyntaxKind.PlusPlusToken, Shared.TokenRange.UnaryPreincrementExpressions), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceAfterUnaryPredecrementOperator = new Rule(RuleDescriptor.create3(SyntaxKind.MinusMinusToken, Shared.TokenRange.UnaryPredecrementExpressions), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceBeforeUnaryPostincrementOperator = new Rule(RuleDescriptor.create2(Shared.TokenRange.UnaryPostincrementExpressions, SyntaxKind.PlusPlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceBeforeUnaryPostdecrementOperator = new Rule(RuleDescriptor.create2(Shared.TokenRange.UnaryPostdecrementExpressions, SyntaxKind.MinusMinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            // More unary operator special-casing.
+            // DevDiv 181814:  Be careful when removing leading whitespace
+            // around unary operators.  Examples:
+            //      1 - -2  --X-->  1--2
+            //      a + ++b --X-->  a+++b
+            this.SpaceAfterPostincrementWhenFollowedByAdd = new Rule(RuleDescriptor.create1(SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterAddWhenFollowedByUnaryPlus = new Rule(RuleDescriptor.create1(SyntaxKind.PlusToken, SyntaxKind.PlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterAddWhenFollowedByPreincrement = new Rule(RuleDescriptor.create1(SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterPostdecrementWhenFollowedBySubtract = new Rule(RuleDescriptor.create1(SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new Rule(RuleDescriptor.create1(SyntaxKind.MinusToken, SyntaxKind.MinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterSubtractWhenFollowedByPredecrement = new Rule(RuleDescriptor.create1(SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+
+            this.NoSpaceBeforeComma = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CommaToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            this.SpaceAfterCertainKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.SpaceAfterLetConstInVariableDeclaration = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), RuleAction.Space));
+            this.NoSpaceBeforeOpenParenInFuncCall = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), RuleAction.Delete));
+            this.SpaceAfterFunctionInFuncDecl = new Rule(RuleDescriptor.create3(SyntaxKind.FunctionKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space));
+            this.NoSpaceBeforeOpenParenInFuncDecl = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsFunctionDeclContext), RuleAction.Delete));
+            this.SpaceAfterVoidOperator = new Rule(RuleDescriptor.create3(SyntaxKind.VoidKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsVoidOpContext), RuleAction.Space));
+
+            this.NoSpaceBetweenReturnAndSemicolon = new Rule(RuleDescriptor.create1(SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            
+            // Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
+            // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
+            this.SpaceBetweenStatements = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotForContext), RuleAction.Space));
+
+            // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
+            this.SpaceAfterTryFinally = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword]), SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+
+            //      get x() {}
+            //      set x(val) {}
+            this.SpaceAfterGetSetInMember = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.GetKeyword, SyntaxKind.SetKeyword]), SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space));
+
+            // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options.
+            this.SpaceBeforeBinaryKeywordOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryKeywordOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterBinaryKeywordOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.BinaryKeywordOperators, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+
+            // TypeScript-specific higher priority rules
+
+            // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses
+            this.NoSpaceAfterConstructor = new Rule(RuleDescriptor.create1(SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            // Use of module as a function call. e.g.: import m2 = module("m2");
+            this.NoSpaceAfterModuleImport = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword]), SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            // Add a space around certain TypeScript keywords
+            this.SpaceAfterCertainTypeScriptKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.ClassKeyword, SyntaxKind.DeclareKeyword, SyntaxKind.EnumKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ExtendsKeyword, SyntaxKind.GetKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.ImportKeyword, SyntaxKind.InterfaceKeyword, SyntaxKind.ModuleKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.PublicKeyword, SyntaxKind.SetKeyword, SyntaxKind.StaticKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.SpaceBeforeCertainTypeScriptKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.ExtendsKeyword, SyntaxKind.ImplementsKeyword])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+
+            // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
+            this.SpaceAfterModuleName = new Rule(RuleDescriptor.create1(SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsModuleDeclContext), RuleAction.Space));
+
+            // Lambda expressions
+            this.SpaceAfterArrow = new Rule(RuleDescriptor.create3(SyntaxKind.EqualsGreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+
+            // Optional parameters and let args
+            this.NoSpaceAfterEllipsis = new Rule(RuleDescriptor.create1(SyntaxKind.DotDotDotToken, SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceAfterOptionalParameters = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete));
+
+            // generics
+            this.NoSpaceBeforeOpenAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.TypeNames, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete));
+            this.NoSpaceBetweenCloseParenAndAngularBracket = new Rule(RuleDescriptor.create1(SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete));
+            this.NoSpaceAfterOpenAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.LessThanToken, Shared.TokenRange.TypeNames), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete));
+            this.NoSpaceBeforeCloseAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete));
+            this.NoSpaceAfterCloseAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.FromTokens([SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete));
+
+            // Remove spaces in empty interface literals. e.g.: x: {}
+            this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectTypeContext), RuleAction.Delete));
+
+            // decorators
+            this.SpaceBeforeAt = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.AtToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.NoSpaceAfterAt = new Rule(RuleDescriptor.create3(SyntaxKind.AtToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.SpaceAfterDecorator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.ExportKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.ClassKeyword, SyntaxKind.StaticKeyword, SyntaxKind.PublicKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword, SyntaxKind.OpenBracketToken, SyntaxKind.AsteriskToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), RuleAction.Space));
+
+            // These rules are higher in priority than user-configurable rules.
+            this.HighPriorityCommonRules =
+            [
+                this.IgnoreBeforeComment, this.IgnoreAfterLineComment,
+                this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator,
+                this.NoSpaceAfterQuestionMark,
+                this.NoSpaceBeforeDot, this.NoSpaceAfterDot,
+                this.NoSpaceAfterUnaryPrefixOperator,
+                this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator,
+                this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator,
+                this.SpaceAfterPostincrementWhenFollowedByAdd,
+                this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement,
+                this.SpaceAfterPostdecrementWhenFollowedBySubtract,
+                this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement,
+                this.NoSpaceAfterCloseBrace,
+                this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NewLineBeforeCloseBraceInBlockContext,
+                this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets,
+                this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember,
+                this.NoSpaceBetweenReturnAndSemicolon,
+                this.SpaceAfterCertainKeywords,
+                this.SpaceAfterLetConstInVariableDeclaration,
+                this.NoSpaceBeforeOpenParenInFuncCall,
+                this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator,
+                this.SpaceAfterVoidOperator,
+
+                // TypeScript-specific rules
+                this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport,
+                this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords,
+                this.SpaceAfterModuleName,
+                this.SpaceAfterArrow,
+                this.NoSpaceAfterEllipsis,
+                this.NoSpaceAfterOptionalParameters,
+                this.NoSpaceBetweenEmptyInterfaceBraceBrackets,
+                this.NoSpaceBeforeOpenAngularBracket,
+                this.NoSpaceBetweenCloseParenAndAngularBracket,
+                this.NoSpaceAfterOpenAngularBracket,
+                this.NoSpaceBeforeCloseAngularBracket,
+                this.NoSpaceAfterCloseAngularBracket,
+                this.SpaceBeforeAt,
+                this.NoSpaceAfterAt,
+                this.SpaceAfterDecorator,
+            ];
+
+            // These rules are lower in priority than user-configurable rules.
+            this.LowPriorityCommonRules =
+            [
+                this.NoSpaceBeforeSemicolon,
+                this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock,
+                this.NoSpaceBeforeComma,
+                this.NoSpaceBeforeOpenBracket, this.NoSpaceAfterOpenBracket,
+                this.NoSpaceBeforeCloseBracket, this.NoSpaceAfterCloseBracket,
+                this.SpaceAfterSemicolon,
+                this.NoSpaceBeforeOpenParenInFuncDecl,
+                this.SpaceBetweenStatements, this.SpaceAfterTryFinally
+            ];
+
+            ///
+            /// Rules controlled by user options
+            ///
+
+            // Insert space after comma delimiter
+            this.SpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.NoSpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            // Insert space before and after binary operators
+            this.SpaceBeforeBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.SpaceAfterBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.BinaryOperators, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space));
+            this.NoSpaceBeforeBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Delete));
+            this.NoSpaceAfterBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.BinaryOperators, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Delete));
+
+            // Insert space after keywords in control flow statements
+            this.SpaceAfterKeywordInControl = new Rule(RuleDescriptor.create2(Shared.TokenRange.Keywords, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsControlDeclContext), RuleAction.Space));
+            this.NoSpaceAfterKeywordInControl = new Rule(RuleDescriptor.create2(Shared.TokenRange.Keywords, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsControlDeclContext), RuleAction.Delete));
+
+            // Open Brace braces after function
+            //TypeScript: Function can have return types, which can be made of tons of different token kinds
+            this.NewLineBeforeOpenBraceInFunction = new Rule(RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), RuleAction.NewLine), RuleFlags.CanDeleteNewLines);
+
+            // Open Brace braces after TypeScript module/class/interface
+            this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new Rule(RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), RuleAction.NewLine), RuleFlags.CanDeleteNewLines);
+
+            // Open Brace braces after control block
+            this.NewLineBeforeOpenBraceInControl = new Rule(RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), RuleAction.NewLine), RuleFlags.CanDeleteNewLines);
+
+            // Insert space after semicolon in for statement
+            this.SpaceAfterSemicolonInFor = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), RuleAction.Space));
+            this.NoSpaceAfterSemicolonInFor = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsForContext), RuleAction.Delete));
+
+            // Insert space after opening and before closing nonempty parenthesis
+            this.SpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.SpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
+            this.NoSpaceBetweenParens = new Rule(RuleDescriptor.create1(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+            this.NoSpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete));
+
+            // Insert space after function keyword for anonymous functions
+            this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space));
+            this.NoSpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Delete));
+        }
+
+        ///
+        /// Contexts
+        ///
+
+        static IsForContext(context: FormattingContext): boolean {
+            return context.contextNode.kind === SyntaxKind.ForStatement;
+        }
+
+        static IsNotForContext(context: FormattingContext): boolean {
+            return !Rules.IsForContext(context);
+        }
+
+        static IsBinaryOpContext(context: FormattingContext): boolean {
+
+            switch (context.contextNode.kind) {
+                case SyntaxKind.BinaryExpression:
+                case SyntaxKind.ConditionalExpression:
+                    return true;
+                
+                // equals in binding elements: function foo([[x, y] = [1, 2]])
+                case SyntaxKind.BindingElement:
+                // equals in type X = ...
+                case SyntaxKind.TypeAliasDeclaration:
+                // equal in import a = module('a');
+                case SyntaxKind.ImportEqualsDeclaration:
+                // equal in let a = 0;
+                case SyntaxKind.VariableDeclaration:
+                // equal in p = 0;
+                case SyntaxKind.Parameter:
+                case SyntaxKind.EnumMember:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    return context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken;
+                // "in" keyword in for (let x in []) { }
+                case SyntaxKind.ForInStatement:
+                    return context.currentTokenSpan.kind === SyntaxKind.InKeyword || context.nextTokenSpan.kind === SyntaxKind.InKeyword;
+                // Technically, "of" is not a binary operator, but format it the same way as "in"
+                case SyntaxKind.ForOfStatement:
+                    return context.currentTokenSpan.kind === SyntaxKind.OfKeyword || context.nextTokenSpan.kind === SyntaxKind.OfKeyword;
+            }
+            return false;
+        }
+
+        static IsNotBinaryOpContext(context: FormattingContext): boolean {
+            return !Rules.IsBinaryOpContext(context);
+        }
+
+        static IsConditionalOperatorContext(context: FormattingContext): boolean {
+            return context.contextNode.kind === SyntaxKind.ConditionalExpression;
+        }
+
+        static IsSameLineTokenOrBeforeMultilineBlockContext(context: FormattingContext): boolean {
+            //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction.
+            ////
+            //// Ex: 
+            //// if (1)     { ....
+            ////      * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context
+            ////
+            //// Ex: 
+            //// if (1)
+            //// { ... }
+            ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we don't format.
+            ////
+            //// Ex:
+            //// if (1) 
+            //// { ...
+            //// }
+            ////      * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we format.
+
+            return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context);
+        }
+
+        // This check is done before an open brace in a control construct, a function, or a typescript block declaration
+        static IsBeforeMultilineBlockContext(context: FormattingContext): boolean {
+            return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine());
+        }
+
+        static IsMultilineBlockContext(context: FormattingContext): boolean {
+            return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
+        }
+
+        static IsSingleLineBlockContext(context: FormattingContext): boolean {
+            return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
+        }
+
+        static IsBlockContext(context: FormattingContext): boolean {
+            return Rules.NodeIsBlockContext(context.contextNode);
+        }
+
+        static IsBeforeBlockContext(context: FormattingContext): boolean {
+            return Rules.NodeIsBlockContext(context.nextTokenParent);
+        }
+
+        // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children
+        static NodeIsBlockContext(node: Node): boolean {
+            if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) {
+                // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc).
+                return true;
+            }
+
+            switch (node.kind) {
+                case SyntaxKind.Block:
+                case SyntaxKind.CaseBlock:
+                case SyntaxKind.ObjectLiteralExpression:
+                case SyntaxKind.ModuleBlock:
+                    return true;
+            }
+
+            return false;
+        }
+
+        static IsFunctionDeclContext(context: FormattingContext): boolean {
+            switch (context.contextNode.kind) {
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                //case SyntaxKind.MemberFunctionDeclaration:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                ///case SyntaxKind.MethodSignature:
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.Constructor:
+                case SyntaxKind.ArrowFunction:
+                //case SyntaxKind.ConstructorDeclaration:
+                //case SyntaxKind.SimpleArrowFunctionExpression:
+                //case SyntaxKind.ParenthesizedArrowFunctionExpression:
+                case SyntaxKind.InterfaceDeclaration: // This one is not truly a function, but for formatting purposes, it acts just like one
+                    return true;
+            }
+
+            return false;
+        }
+
+        static IsTypeScriptDeclWithBlockContext(context: FormattingContext): boolean {
+            return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode);
+        }
+
+        static NodeIsTypeScriptDeclWithBlockContext(node: Node): boolean {
+            switch (node.kind) {
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                case SyntaxKind.TypeLiteral:
+                case SyntaxKind.ModuleDeclaration:
+                    return true;
+            }
+
+            return false;
+        }
+
+        static IsAfterCodeBlockContext(context: FormattingContext): boolean {
+            switch (context.currentTokenParent.kind) {
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.ModuleDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                case SyntaxKind.Block:
+                case SyntaxKind.CatchClause:
+                case SyntaxKind.ModuleBlock:
+                case SyntaxKind.SwitchStatement:
+                    return true;
+            }
+            return false;
+        }
+
+        static IsControlDeclContext(context: FormattingContext): boolean {
+            switch (context.contextNode.kind) {
+                case SyntaxKind.IfStatement:
+                case SyntaxKind.SwitchStatement:
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                case SyntaxKind.WhileStatement:
+                case SyntaxKind.TryStatement:
+                case SyntaxKind.DoStatement:
+                case SyntaxKind.WithStatement:
+                // TODO
+                // case SyntaxKind.ElseClause:
+                case SyntaxKind.CatchClause:
+                    return true;
+
+                default:
+                    return false;
+            }
+        }
+
+        static IsObjectContext(context: FormattingContext): boolean {
+            return context.contextNode.kind === SyntaxKind.ObjectLiteralExpression;
+        }
+
+        static IsFunctionCallContext(context: FormattingContext): boolean {
+            return context.contextNode.kind === SyntaxKind.CallExpression;
+        }
+
+        static IsNewContext(context: FormattingContext): boolean {
+            return context.contextNode.kind === SyntaxKind.NewExpression;
+        }
+
+        static IsFunctionCallOrNewContext(context: FormattingContext): boolean {
+            return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context);
+        }
+
+        static IsPreviousTokenNotComma(context: FormattingContext): boolean {
+            return context.currentTokenSpan.kind !== SyntaxKind.CommaToken;
+        }
+
+        static IsSameLineTokenContext(context: FormattingContext): boolean {
+            return context.TokensAreOnSameLine();
+        }
+
+        static IsEndOfDecoratorContextOnSameLine(context: FormattingContext): boolean {
+            return context.TokensAreOnSameLine() &&
+                context.contextNode.decorators &&
+                Rules.NodeIsInDecoratorContext(context.currentTokenParent) &&
+                !Rules.NodeIsInDecoratorContext(context.nextTokenParent);
+        }
+
+        static NodeIsInDecoratorContext(node: Node): boolean {
+            while (isExpression(node)) {
+                node = node.parent;
+            }
+            return node.kind === SyntaxKind.Decorator;
+        }
+
+        static IsStartOfVariableDeclarationList(context: FormattingContext): boolean {
+            return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList && 
+                context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
+        }
+
+        static IsNotFormatOnEnter(context: FormattingContext): boolean {
+            return context.formattingRequestKind != FormattingRequestKind.FormatOnEnter;
+        }
+
+        static IsModuleDeclContext(context: FormattingContext): boolean {
+            return context.contextNode.kind === SyntaxKind.ModuleDeclaration;
+        }
+
+        static IsObjectTypeContext(context: FormattingContext): boolean {
+            return context.contextNode.kind === SyntaxKind.TypeLiteral;// && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration;
+        }
+
+        static IsTypeArgumentOrParameter(token: TextRangeWithKind, parent: Node): boolean {
+            if (token.kind !== SyntaxKind.LessThanToken && token.kind !== SyntaxKind.GreaterThanToken) {
+                return false;
+            }
+            switch (parent.kind) {
+                case SyntaxKind.TypeReference:
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.ConstructSignature:
+                case SyntaxKind.CallExpression:
+                case SyntaxKind.NewExpression:
+                    return true;
+                default:
+                    return false;
+
+            }
+        }
+
+        static IsTypeArgumentOrParameterContext(context: FormattingContext): boolean {
+            return Rules.IsTypeArgumentOrParameter(context.currentTokenSpan, context.currentTokenParent) ||
+                Rules.IsTypeArgumentOrParameter(context.nextTokenSpan, context.nextTokenParent);
+        }
+
+        static IsVoidOpContext(context: FormattingContext): boolean {
+            return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword && context.currentTokenParent.kind === SyntaxKind.VoidExpression;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/rulesMap.ts b/lib/typescript/services/formatting/rulesMap.ts
new file mode 100644
index 000000000..397a2331e
--- /dev/null
+++ b/lib/typescript/services/formatting/rulesMap.ts
@@ -0,0 +1,175 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+    export class RulesMap {
+        public map: RulesBucket[];
+        public mapRowLength: number;
+
+        constructor() {
+            this.map = [];
+            this.mapRowLength = 0;
+        }
+
+        static create(rules: Rule[]): RulesMap {
+            let result = new RulesMap();
+            result.Initialize(rules);
+            return result;
+        }
+
+        public Initialize(rules: Rule[]) {
+            this.mapRowLength = SyntaxKind.LastToken + 1;
+            this.map = <any> new Array(this.mapRowLength * this.mapRowLength);//new Array<RulesBucket>(this.mapRowLength * this.mapRowLength);
+
+            // This array is used only during construction of the rulesbucket in the map
+            let rulesBucketConstructionStateList: RulesBucketConstructionState[] = <any> new Array(this.map.length);//new Array<RulesBucketConstructionState>(this.map.length);
+
+            this.FillRules(rules, rulesBucketConstructionStateList);
+            return this.map;
+        }
+
+        public FillRules(rules: Rule[], rulesBucketConstructionStateList: RulesBucketConstructionState[]): void {
+            rules.forEach((rule) => {
+                this.FillRule(rule, rulesBucketConstructionStateList);
+            });
+        }
+
+        private GetRuleBucketIndex(row: number, column: number): number {
+            let rulesBucketIndex = (row * this.mapRowLength) + column;
+            //Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array.");
+            return rulesBucketIndex;
+        }
+
+        private FillRule(rule: Rule, rulesBucketConstructionStateList: RulesBucketConstructionState[]): void {
+            let specificRule = rule.Descriptor.LeftTokenRange != Shared.TokenRange.Any &&
+                               rule.Descriptor.RightTokenRange != Shared.TokenRange.Any;
+
+            rule.Descriptor.LeftTokenRange.GetTokens().forEach((left) => {
+                rule.Descriptor.RightTokenRange.GetTokens().forEach((right) => {
+                    let rulesBucketIndex = this.GetRuleBucketIndex(left, right);
+
+                    let rulesBucket = this.map[rulesBucketIndex];
+                    if (rulesBucket == undefined) {
+                        rulesBucket = this.map[rulesBucketIndex] = new RulesBucket();
+                    }
+
+                    rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex);
+                })
+            })
+        }
+
+        public GetRule(context: FormattingContext): Rule {
+            let bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind);
+            let bucket = this.map[bucketIndex];
+            if (bucket != null) {
+                for (let rule of bucket.Rules()) {
+                    if (rule.Operation.Context.InContext(context)) {
+                        return rule;
+                    }
+                }
+            }
+            return null;
+        }
+    }
+
+    let MaskBitSize = 5;
+    let Mask = 0x1f;
+
+    export enum RulesPosition {
+        IgnoreRulesSpecific = 0,
+        IgnoreRulesAny = MaskBitSize * 1,
+        ContextRulesSpecific = MaskBitSize * 2,
+        ContextRulesAny = MaskBitSize * 3,
+        NoContextRulesSpecific = MaskBitSize * 4,
+        NoContextRulesAny = MaskBitSize * 5
+    }
+
+    export class RulesBucketConstructionState {
+        private rulesInsertionIndexBitmap: number;
+
+        constructor() {
+            //// The Rules list contains all the inserted rules into a rulebucket in the following order:
+            ////    1- Ignore rules with specific token combination
+            ////    2- Ignore rules with any token combination
+            ////    3- Context rules with specific token combination
+            ////    4- Context rules with any token combination
+            ////    5- Non-context rules with specific token combination
+            ////    6- Non-context rules with any token combination
+            //// 
+            //// The member rulesInsertionIndexBitmap is used to describe the number of rules
+            //// in each sub-bucket (above) hence can be used to know the index of where to insert 
+            //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
+            ////
+            //// Example:
+            //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding
+            //// the values in the bitmap segments 3rd, 2nd, and 1st.
+            this.rulesInsertionIndexBitmap = 0;
+        }
+
+        public GetInsertionIndex(maskPosition: RulesPosition): number {
+            let index = 0;
+
+            let pos = 0;
+            let indexBitmap = this.rulesInsertionIndexBitmap;
+
+            while (pos <= maskPosition) {
+                index += (indexBitmap & Mask);
+                indexBitmap >>= MaskBitSize;
+                pos += MaskBitSize;
+            }
+
+            return index;
+        }
+
+        public IncreaseInsertionIndex(maskPosition: RulesPosition): void {
+            let value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
+            value++;
+            Debug.assert((value & Mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
+
+            let temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
+            temp |= value << maskPosition;
+
+            this.rulesInsertionIndexBitmap = temp;
+        }
+    }
+
+    export class RulesBucket {
+        private rules: Rule[];
+
+        constructor() {
+            this.rules = [];
+        }
+
+        public Rules(): Rule[] {
+            return this.rules;
+        }
+
+        public AddRule(rule: Rule, specificTokens: boolean, constructionState: RulesBucketConstructionState[], rulesBucketIndex: number): void {
+            let position: RulesPosition;
+
+            if (rule.Operation.Action == RuleAction.Ignore) {
+                position = specificTokens ?
+                    RulesPosition.IgnoreRulesSpecific :
+                    RulesPosition.IgnoreRulesAny;
+            }
+            else if (!rule.Operation.Context.IsAny()) {
+                position = specificTokens ?
+                    RulesPosition.ContextRulesSpecific :
+                    RulesPosition.ContextRulesAny;
+            }
+            else {
+                position = specificTokens ?
+                    RulesPosition.NoContextRulesSpecific :
+                    RulesPosition.NoContextRulesAny;
+            }
+
+            let state = constructionState[rulesBucketIndex];
+            if (state === undefined) {
+                state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState();
+            }
+            let index = state.GetInsertionIndex(position);
+            this.rules.splice(index, 0, rule);
+            state.IncreaseInsertionIndex(position);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/rulesProvider.ts b/lib/typescript/services/formatting/rulesProvider.ts
new file mode 100644
index 000000000..c3e8cb56c
--- /dev/null
+++ b/lib/typescript/services/formatting/rulesProvider.ts
@@ -0,0 +1,103 @@
+/// <reference path="references.ts"/>
+
+/* @internal */
+module ts.formatting {
+    export class RulesProvider {
+        private globalRules: Rules;
+        private options: ts.FormatCodeOptions;
+        private activeRules: Rule[];
+        private rulesMap: RulesMap;
+
+        constructor() {
+            this.globalRules = new Rules();
+        }
+
+        public getRuleName(rule: Rule): string {
+            return this.globalRules.getRuleName(rule);
+        }
+
+        public getRuleByName(name: string): Rule {
+            return this.globalRules[name];
+        }
+
+        public getRulesMap() {
+            return this.rulesMap;
+        }
+
+        public ensureUpToDate(options: ts.FormatCodeOptions) {
+            if (this.options == null || !ts.compareDataObjects(this.options, options)) {
+                let activeRules = this.createActiveRules(options);
+                let rulesMap = RulesMap.create(activeRules);
+
+                this.activeRules = activeRules;
+                this.rulesMap = rulesMap;
+                this.options = ts.clone(options);
+            }
+        }
+
+        private createActiveRules(options: ts.FormatCodeOptions): Rule[] {
+            let rules = this.globalRules.HighPriorityCommonRules.slice(0);
+
+            if (options.InsertSpaceAfterCommaDelimiter) {
+                rules.push(this.globalRules.SpaceAfterComma);
+            }
+            else {
+                rules.push(this.globalRules.NoSpaceAfterComma);
+            }
+
+            if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) {
+                rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword);
+            }
+            else {
+                rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword);
+            }
+
+            if (options.InsertSpaceAfterKeywordsInControlFlowStatements) {
+                rules.push(this.globalRules.SpaceAfterKeywordInControl);
+            }
+            else {
+                rules.push(this.globalRules.NoSpaceAfterKeywordInControl);
+            }
+
+            if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) {
+                rules.push(this.globalRules.SpaceAfterOpenParen);
+                rules.push(this.globalRules.SpaceBeforeCloseParen);
+                rules.push(this.globalRules.NoSpaceBetweenParens);
+            }
+            else {
+                rules.push(this.globalRules.NoSpaceAfterOpenParen);
+                rules.push(this.globalRules.NoSpaceBeforeCloseParen);
+                rules.push(this.globalRules.NoSpaceBetweenParens);
+            }
+
+            if (options.InsertSpaceAfterSemicolonInForStatements) {
+                rules.push(this.globalRules.SpaceAfterSemicolonInFor);
+            }
+            else {
+                rules.push(this.globalRules.NoSpaceAfterSemicolonInFor);
+            }
+
+            if (options.InsertSpaceBeforeAndAfterBinaryOperators) {
+                rules.push(this.globalRules.SpaceBeforeBinaryOperator);
+                rules.push(this.globalRules.SpaceAfterBinaryOperator);
+            }
+            else {
+                rules.push(this.globalRules.NoSpaceBeforeBinaryOperator);
+                rules.push(this.globalRules.NoSpaceAfterBinaryOperator);
+            }
+
+            if (options.PlaceOpenBraceOnNewLineForControlBlocks) {
+                rules.push(this.globalRules.NewLineBeforeOpenBraceInControl);
+            }
+
+            if (options.PlaceOpenBraceOnNewLineForFunctions) {
+                rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction);
+                rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock);
+            }
+
+            rules = rules.concat(this.globalRules.LowPriorityCommonRules);
+
+            return rules;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/smartIndenter.ts b/lib/typescript/services/formatting/smartIndenter.ts
new file mode 100644
index 000000000..91d9f18a9
--- /dev/null
+++ b/lib/typescript/services/formatting/smartIndenter.ts
@@ -0,0 +1,404 @@
+///<reference path='..\services.ts' />
+
+/* @internal */
+module ts.formatting {
+    export module SmartIndenter {
+
+        const enum Value {
+            Unknown = -1
+        }
+
+        export function getIndentation(position: number, sourceFile: SourceFile, options: EditorOptions): number {
+            if (position > sourceFile.text.length) {
+                return 0; // past EOF
+            }
+
+            let precedingToken = findPrecedingToken(position, sourceFile);
+            if (!precedingToken) {
+                return 0;
+            }
+
+            // no indentation in string \regex\template literals
+            let precedingTokenIsLiteral =
+                precedingToken.kind === SyntaxKind.StringLiteral ||
+                precedingToken.kind === SyntaxKind.RegularExpressionLiteral ||
+                precedingToken.kind === SyntaxKind.NoSubstitutionTemplateLiteral ||
+                precedingToken.kind === SyntaxKind.TemplateHead ||
+                precedingToken.kind === SyntaxKind.TemplateMiddle ||
+                precedingToken.kind === SyntaxKind.TemplateTail;
+            if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position &&  precedingToken.end > position) {
+                return 0;
+            }
+
+            let lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
+
+            if (precedingToken.kind === SyntaxKind.CommaToken && precedingToken.parent.kind !== SyntaxKind.BinaryExpression) {
+                // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
+                let actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
+                if (actualIndentation !== Value.Unknown) {
+                    return actualIndentation;
+                }
+            }
+
+            // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken'
+            // if such node is found - compute initial indentation for 'position' inside this node
+            let previous: Node;
+            let current = precedingToken;
+            let currentStart: LineAndCharacter;
+            let indentationDelta: number;
+
+            while (current) {
+                if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current.kind, previous ? previous.kind : SyntaxKind.Unknown)) {
+                    currentStart = getStartLineAndCharacterForNode(current, sourceFile);
+
+                    if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
+                        indentationDelta = 0;
+                    }
+                    else {
+                        indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0;
+                    }
+
+                    break;
+                }
+
+                // check if current node is a list item - if yes, take indentation from it
+                let actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
+                if (actualIndentation !== Value.Unknown) {
+                    return actualIndentation;
+                }
+
+                previous = current;
+                current = current.parent;
+            }
+
+            if (!current) {
+                // no parent was found - return 0 to be indented on the level of SourceFile
+                return 0;
+            }
+
+            return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, options);
+        }
+
+        export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: FormatCodeOptions): number {
+            let start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
+            return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options);
+        }
+
+        function getIndentationForNodeWorker(
+            current: Node,
+            currentStart: LineAndCharacter,
+            ignoreActualIndentationRange: TextRange,
+            indentationDelta: number,
+            sourceFile: SourceFile,
+            options: EditorOptions): number {
+
+            let parent: Node = current.parent;
+            let parentStart: LineAndCharacter;
+
+            // walk upwards and collect indentations for pairs of parent-child nodes
+            // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause'
+            while (parent) {
+                let useActualIndentation = true;
+                if (ignoreActualIndentationRange) {
+                    let start = current.getStart(sourceFile);
+                    useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end;
+                }
+
+                if (useActualIndentation) {
+                    // check if current node is a list item - if yes, take indentation from it
+                    let actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
+                    if (actualIndentation !== Value.Unknown) {
+                        return actualIndentation + indentationDelta;
+                    }
+                }
+                parentStart = getParentStart(parent, current, sourceFile);
+                let parentAndChildShareLine =
+                    parentStart.line === currentStart.line ||
+                    childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
+
+                if (useActualIndentation) {
+                    // try to fetch actual indentation for current node from source text
+                    let actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
+                    if (actualIndentation !== Value.Unknown) {
+                        return actualIndentation + indentationDelta;
+                    }
+                }
+
+                // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
+                if (shouldIndentChildNode(parent.kind, current.kind) && !parentAndChildShareLine) {
+                    indentationDelta += options.IndentSize;
+                }
+
+                current = parent;
+                currentStart = parentStart;
+                parent = current.parent;
+            }
+
+            return indentationDelta;
+        }
+
+
+        function getParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter {
+            let containingList = getContainingList(child, sourceFile);
+            if (containingList) {
+                return sourceFile.getLineAndCharacterOfPosition(containingList.pos);
+            }
+
+            return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile));
+        }
+
+        /*
+         * Function returns Value.Unknown if indentation cannot be determined
+         */
+        function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorOptions): number {
+            // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
+            let commaItemInfo = findListItemInfo(commaToken);
+            if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
+                return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
+            }
+            else {
+                // handle broken code gracefully
+                return Value.Unknown;
+            }
+        }
+
+        /*
+         * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression)
+         */
+        function getActualIndentationForNode(current: Node,
+            parent: Node,
+            currentLineAndChar: LineAndCharacter,
+            parentAndChildShareLine: boolean,
+            sourceFile: SourceFile,
+            options: EditorOptions): number {
+
+            // actual indentation is used for statements\declarations if one of cases below is true:
+            // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
+            // - parent and child are not on the same line
+            let useActualIndentation =
+                (isDeclaration(current) || isStatement(current)) &&
+                (parent.kind === SyntaxKind.SourceFile || !parentAndChildShareLine);
+
+            if (!useActualIndentation) {
+                return Value.Unknown;
+            }
+
+            return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
+        }
+
+        function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): boolean {
+            let nextToken = findNextToken(precedingToken, current);
+            if (!nextToken) {
+                return false;
+            }
+
+            if (nextToken.kind === SyntaxKind.OpenBraceToken) {
+                // open braces are always indented at the parent level
+                return true;
+            }
+            else if (nextToken.kind === SyntaxKind.CloseBraceToken) {
+                // close braces are indented at the parent level if they are located on the same line with cursor
+                // this means that if new line will be added at $ position, this case will be indented
+                // class A {
+                //    $
+                // }
+                /// and this one - not
+                // class A {
+                // $}
+
+                let nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
+                return lineAtPosition === nextTokenStartLine;
+            }
+
+            return false;
+        }
+
+        function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
+            return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
+        }
+        
+        export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
+            if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
+                let elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
+                Debug.assert(elseKeyword !== undefined);
+
+                let elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
+                return elseKeywordStartLine === childStartLine;
+            }
+
+            return false;
+        }
+
+        function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
+            if (node.parent) {
+                switch (node.parent.kind) {
+                    case SyntaxKind.TypeReference:
+                        if ((<TypeReferenceNode>node.parent).typeArguments &&
+                            rangeContainsStartEnd((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd())) {
+                            return (<TypeReferenceNode>node.parent).typeArguments;
+                        }
+                        break;
+                    case SyntaxKind.ObjectLiteralExpression:
+                        return (<ObjectLiteralExpression>node.parent).properties;
+                    case SyntaxKind.ArrayLiteralExpression:
+                        return (<ArrayLiteralExpression>node.parent).elements;
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.ArrowFunction:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.CallSignature:
+                    case SyntaxKind.ConstructSignature: {
+                        let start = node.getStart(sourceFile);
+                        if ((<SignatureDeclaration>node.parent).typeParameters &&
+                            rangeContainsStartEnd((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd())) {
+                            return (<SignatureDeclaration>node.parent).typeParameters;
+                        }
+                        if (rangeContainsStartEnd((<SignatureDeclaration>node.parent).parameters, start, node.getEnd())) {
+                            return (<SignatureDeclaration>node.parent).parameters;
+                        }
+                        break;
+                    }
+                    case SyntaxKind.NewExpression:
+                    case SyntaxKind.CallExpression: {
+                        let start = node.getStart(sourceFile);
+                        if ((<CallExpression>node.parent).typeArguments &&
+                            rangeContainsStartEnd((<CallExpression>node.parent).typeArguments, start, node.getEnd())) {
+                            return (<CallExpression>node.parent).typeArguments;
+                        }
+                        if ((<CallExpression>node.parent).arguments &&
+                            rangeContainsStartEnd((<CallExpression>node.parent).arguments, start, node.getEnd())) {
+                            return (<CallExpression>node.parent).arguments;
+                        }
+                        break;
+                    }
+                }
+            }
+            return undefined;
+        }
+
+        function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorOptions): number {
+            let containingList = getContainingList(node, sourceFile);
+            return containingList ? getActualIndentationFromList(containingList) : Value.Unknown;
+
+            function getActualIndentationFromList(list: Node[]): number {
+                let index = indexOf(list, node);
+                return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : Value.Unknown;
+            }
+        }
+
+        function deriveActualIndentationFromList(list: Node[], index: number, sourceFile: SourceFile, options: EditorOptions): number {
+            Debug.assert(index >= 0 && index < list.length);
+            let node = list[index];
+
+            // walk toward the start of the list starting from current node and check if the line is the same for all items.
+            // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i]
+            let lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
+            for (let i = index - 1; i >= 0; --i) {
+                if (list[i].kind === SyntaxKind.CommaToken) {
+                    continue;
+                }
+                // skip list items that ends on the same line with the current list element
+                let prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line;
+                if (prevEndLine !== lineAndCharacter.line) {
+                    return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
+                }
+
+                lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile);
+            }
+            return Value.Unknown;
+        }
+
+        function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorOptions): number {
+            let lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
+            return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
+        }
+
+        /*
+            Character is the actual index of the character since the beginning of the line.
+            Column - position of the character after expanding tabs to spaces
+            "0\t2$"
+            value of 'character' for '$' is 3
+            value of 'column' for '$' is 6 (assuming that tab size is 4)
+        */
+        export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions) {
+            let character = 0;
+            let column = 0;
+            for (let pos = startPos; pos < endPos; ++pos) {
+                let ch = sourceFile.text.charCodeAt(pos);
+                if (!isWhiteSpace(ch)) {
+                    break;
+                }
+
+                if (ch === CharacterCodes.tab) {
+                    column += options.TabSize + (column % options.TabSize);
+                }
+                else {
+                    column++;
+                }
+
+                character++;
+            }
+            return { column, character };
+        }
+
+        export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): number {
+            return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
+        }
+
+        function nodeContentIsAlwaysIndented(kind: SyntaxKind): boolean {
+            switch (kind) {
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                case SyntaxKind.ArrayLiteralExpression:
+                case SyntaxKind.Block:
+                case SyntaxKind.ModuleBlock:
+                case SyntaxKind.ObjectLiteralExpression:
+                case SyntaxKind.TypeLiteral:
+                case SyntaxKind.TupleType:
+                case SyntaxKind.CaseBlock:
+                case SyntaxKind.DefaultClause:
+                case SyntaxKind.CaseClause:
+                case SyntaxKind.ParenthesizedExpression:
+                case SyntaxKind.CallExpression:
+                case SyntaxKind.NewExpression:
+                case SyntaxKind.VariableStatement:
+                case SyntaxKind.VariableDeclaration:
+                case SyntaxKind.ExportAssignment:
+                case SyntaxKind.ReturnStatement:
+                case SyntaxKind.ConditionalExpression:
+                case SyntaxKind.ArrayBindingPattern:
+                case SyntaxKind.ObjectBindingPattern:
+                    return true;
+            }
+            return false;
+        }
+
+        export function shouldIndentChildNode(parent: SyntaxKind, child: SyntaxKind): boolean {
+            if (nodeContentIsAlwaysIndented(parent)) {
+                return true;
+            }
+            switch (parent) {
+                case SyntaxKind.DoStatement:
+                case SyntaxKind.WhileStatement:
+                case SyntaxKind.ForInStatement:
+                case SyntaxKind.ForOfStatement:
+                case SyntaxKind.ForStatement:
+                case SyntaxKind.IfStatement:
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.CallSignature:
+                case SyntaxKind.ArrowFunction:
+                case SyntaxKind.Constructor:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                    return child !== SyntaxKind.Block;
+                default:
+                    return false;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/formatting/tokenRange.ts b/lib/typescript/services/formatting/tokenRange.ts
new file mode 100644
index 000000000..bb3b720bf
--- /dev/null
+++ b/lib/typescript/services/formatting/tokenRange.ts
@@ -0,0 +1,126 @@
+///<reference path='references.ts' />
+
+/* @internal */
+module ts.formatting {
+    export module Shared {
+        export interface ITokenAccess {
+            GetTokens(): SyntaxKind[];
+            Contains(token: SyntaxKind): boolean;
+        }
+
+        export class TokenRangeAccess implements ITokenAccess {
+            private tokens: SyntaxKind[];
+
+            constructor(from: SyntaxKind, to: SyntaxKind, except: SyntaxKind[]) {
+                this.tokens = [];
+                for (let token = from; token <= to; token++) {
+                    if (except.indexOf(token) < 0) {
+                        this.tokens.push(token);
+                    }
+                }
+            }
+
+            public GetTokens(): SyntaxKind[] {
+                return this.tokens;
+            }
+
+            public Contains(token: SyntaxKind): boolean {
+                return this.tokens.indexOf(token) >= 0;
+            }
+        }
+
+        export class TokenValuesAccess implements ITokenAccess {
+            private tokens: SyntaxKind[];
+
+            constructor(tks: SyntaxKind[]) {
+                this.tokens = tks && tks.length ? tks : <SyntaxKind[]>[];
+            }
+
+            public GetTokens(): SyntaxKind[] {
+                return this.tokens;
+            }
+
+            public Contains(token: SyntaxKind): boolean {
+                return this.tokens.indexOf(token) >= 0;
+            }
+        }
+
+        export class TokenSingleValueAccess implements ITokenAccess {
+            constructor(public token: SyntaxKind) {
+            }
+
+            public GetTokens(): SyntaxKind[] {
+                return [this.token];
+            }
+
+            public Contains(tokenValue: SyntaxKind): boolean {
+                return tokenValue == this.token;
+            }
+        }
+
+        export class TokenAllAccess implements ITokenAccess {
+            public GetTokens(): SyntaxKind[] {
+                let result: SyntaxKind[] = [];
+                for (let token = SyntaxKind.FirstToken; token <= SyntaxKind.LastToken; token++) {
+                    result.push(token);
+                }
+                return result;
+            }
+
+            public Contains(tokenValue: SyntaxKind): boolean {
+                return true;
+            }
+
+            public toString(): string {
+                return "[allTokens]";
+            }
+        }
+
+        export class TokenRange {
+            constructor(public tokenAccess: ITokenAccess) {
+            }
+
+            static FromToken(token: SyntaxKind): TokenRange {
+                return new TokenRange(new TokenSingleValueAccess(token));
+            }
+
+            static FromTokens(tokens: SyntaxKind[]): TokenRange {
+                return new TokenRange(new TokenValuesAccess(tokens));
+            }
+
+            static FromRange(f: SyntaxKind, to: SyntaxKind, except: SyntaxKind[] = []): TokenRange {
+                return new TokenRange(new TokenRangeAccess(f, to, except));
+            }
+
+            static AllTokens(): TokenRange {
+                return new TokenRange(new TokenAllAccess());
+            }
+
+            public GetTokens(): SyntaxKind[] {
+                return this.tokenAccess.GetTokens();
+            }
+
+            public Contains(token: SyntaxKind): boolean {
+                return this.tokenAccess.Contains(token);
+            }
+
+            public toString(): string {
+                return this.tokenAccess.toString();
+            }
+
+            static Any: TokenRange = TokenRange.AllTokens();
+            static AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([SyntaxKind.MultiLineCommentTrivia]));
+            static Keywords = TokenRange.FromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword);
+            static BinaryOperators = TokenRange.FromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator);
+            static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword]);
+            static UnaryPrefixOperators = TokenRange.FromTokens([SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]);
+            static UnaryPrefixExpressions = TokenRange.FromTokens([SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
+            static UnaryPreincrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
+            static UnaryPostincrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]);
+            static UnaryPredecrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
+            static UnaryPostdecrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]);
+            static Comments = TokenRange.FromTokens([SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia]);
+            static TypeNames = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.NumberKeyword, SyntaxKind.StringKeyword, SyntaxKind.BooleanKeyword, SyntaxKind.SymbolKeyword, SyntaxKind.VoidKeyword, SyntaxKind.AnyKeyword]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/navigateTo.ts b/lib/typescript/services/navigateTo.ts
new file mode 100644
index 000000000..6d399c5b0
--- /dev/null
+++ b/lib/typescript/services/navigateTo.ts
@@ -0,0 +1,194 @@
+/* @internal */
+module ts.NavigateTo {
+    type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration };
+
+    export function getNavigateToItems(program: Program, cancellationToken: CancellationTokenObject, searchValue: string, maxResultCount: number): NavigateToItem[] {
+        let patternMatcher = createPatternMatcher(searchValue);
+        let rawItems: RawNavigateToItem[] = [];
+
+        // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] 
+        forEach(program.getSourceFiles(), sourceFile => {
+            cancellationToken.throwIfCancellationRequested();
+
+            let nameToDeclarations = sourceFile.getNamedDeclarations();
+            for (let name in nameToDeclarations) {
+                let declarations = getProperty(nameToDeclarations, name);
+                if (declarations) {
+                    // First do a quick check to see if the name of the declaration matches the 
+                    // last portion of the (possibly) dotted name they're searching for.
+                    let matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
+
+                    if (!matches) {
+                        continue;
+                    }
+
+                    for (let declaration of declarations) {
+                        // It was a match!  If the pattern has dots in it, then also see if the 
+                        // declaration container matches as well.
+                        if (patternMatcher.patternContainsDots) {
+                            let containers = getContainers(declaration);
+                            if (!containers) {
+                                return undefined;
+                            }
+
+                            matches = patternMatcher.getMatches(containers, name);
+
+                            if (!matches) {
+                                continue;
+                            }
+                        }
+
+                        let fileName = sourceFile.fileName;
+                        let matchKind = bestMatchKind(matches);
+                        rawItems.push({ name, fileName, matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration });
+                    }
+                }
+            }
+        });
+
+        rawItems.sort(compareNavigateToItems);
+        if (maxResultCount !== undefined) {
+            rawItems = rawItems.slice(0, maxResultCount);
+        }
+
+        let items = map(rawItems, createNavigateToItem);
+
+        return items;
+
+        function allMatchesAreCaseSensitive(matches: PatternMatch[]): boolean {
+            Debug.assert(matches.length > 0);
+
+            // This is a case sensitive match, only if all the submatches were case sensitive.
+            for (let match of matches) {
+                if (!match.isCaseSensitive) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        function getTextOfIdentifierOrLiteral(node: Node) {
+            if (node) {
+                if (node.kind === SyntaxKind.Identifier ||
+                    node.kind === SyntaxKind.StringLiteral ||
+                    node.kind === SyntaxKind.NumericLiteral) {
+
+                    return (<Identifier | LiteralExpression>node).text;
+                }
+            }
+
+            return undefined;
+        }
+
+        function tryAddSingleDeclarationName(declaration: Declaration, containers: string[]) {
+            if (declaration && declaration.name) {
+                let text = getTextOfIdentifierOrLiteral(declaration.name);
+                if (text !== undefined) {
+                    containers.unshift(text);
+                }
+                else if (declaration.name.kind === SyntaxKind.ComputedPropertyName) {
+                    return tryAddComputedPropertyName((<ComputedPropertyName>declaration.name).expression, containers, /*includeLastPortion:*/ true);
+                }
+                else {
+                    // Don't know how to add this.
+                    return false
+                }
+            }
+
+            return true;
+        }
+
+        // Only added the names of computed properties if they're simple dotted expressions, like:
+        //
+        //      [X.Y.Z]() { }
+        function tryAddComputedPropertyName(expression: Expression, containers: string[], includeLastPortion: boolean): boolean {
+            let text = getTextOfIdentifierOrLiteral(expression);
+            if (text !== undefined) {
+                if (includeLastPortion) {
+                    containers.unshift(text);
+                }
+                return true;
+            }
+
+            if (expression.kind === SyntaxKind.PropertyAccessExpression) {
+                let propertyAccess = <PropertyAccessExpression>expression;
+                if (includeLastPortion) {
+                    containers.unshift(propertyAccess.name.text);
+                }
+
+                return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion:*/ true);
+            }
+
+            return false;
+        }
+
+        function getContainers(declaration: Declaration) {
+            let containers: string[] = [];
+
+            // First, if we started with a computed property name, then add all but the last
+            // portion into the container array.
+            if (declaration.name.kind === SyntaxKind.ComputedPropertyName) {
+                if (!tryAddComputedPropertyName((<ComputedPropertyName>declaration.name).expression, containers, /*includeLastPortion:*/ false)) {
+                    return undefined;
+                }
+            }
+
+            // Now, walk up our containers, adding all their names to the container array.
+            declaration = getContainerNode(declaration);
+
+            while (declaration) {
+                if (!tryAddSingleDeclarationName(declaration, containers)) {
+                    return undefined;
+                }
+
+                declaration = getContainerNode(declaration);
+            }
+
+            return containers;
+        }
+
+        function bestMatchKind(matches: PatternMatch[]) {
+            Debug.assert(matches.length > 0);
+            let bestMatchKind = PatternMatchKind.camelCase;
+
+            for (let match of matches) {
+                let kind = match.kind;
+                if (kind < bestMatchKind) {
+                    bestMatchKind = kind;
+                }
+            }
+
+            return bestMatchKind;
+        }
+
+        // This means "compare in a case insensitive manner."
+        let baseSensitivity: Intl.CollatorOptions = { sensitivity: "base" };
+        function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem) {
+            // TODO(cyrusn): get the gamut of comparisons that VS already uses here.
+            // Right now we just sort by kind first, and then by name of the item.
+            // We first sort case insensitively.  So "Aaa" will come before "bar".
+            // Then we sort case sensitively, so "aaa" will come before "Aaa".
+            return i1.matchKind - i2.matchKind ||
+                i1.name.localeCompare(i2.name, undefined, baseSensitivity) || 
+                i1.name.localeCompare(i2.name);
+        }
+
+        function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem {
+            let declaration = rawItem.declaration;
+            let container = <Declaration>getContainerNode(declaration);
+            return {
+                name: rawItem.name,
+                kind: getNodeKind(declaration),
+                kindModifiers: getNodeModifiers(declaration),
+                matchKind: PatternMatchKind[rawItem.matchKind],
+                isCaseSensitive: rawItem.isCaseSensitive,
+                fileName: rawItem.fileName,
+                textSpan: createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()),
+                // TODO(jfreeman): What should be the containerName when the container has a computed name?
+                containerName: container && container.name ? (<Identifier>container.name).text : "",
+                containerKind: container && container.name ? getNodeKind(container) : ""
+            };
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/navigationBar.ts b/lib/typescript/services/navigationBar.ts
new file mode 100644
index 000000000..5e5f40802
--- /dev/null
+++ b/lib/typescript/services/navigationBar.ts
@@ -0,0 +1,537 @@
+/// <reference path='services.ts' />
+
+/* @internal */
+module ts.NavigationBar {
+    export function getNavigationBarItems(sourceFile: SourceFile): ts.NavigationBarItem[]  {
+        // If the source file has any child items, then it included in the tree
+        // and takes lexical ownership of all other top-level items.
+        let hasGlobalNode = false;
+
+        return getItemsWorker(getTopLevelNodes(sourceFile), createTopLevelItem);
+
+        function getIndent(node: Node): number {
+            // If we have a global node in the tree,
+            // then it adds an extra layer of depth to all subnodes.
+            let indent = hasGlobalNode ? 1 : 0;
+
+            let current = node.parent;
+            while (current) {
+                switch (current.kind) {
+                    case SyntaxKind.ModuleDeclaration:
+                        // If we have a module declared as A.B.C, it is more "intuitive"
+                        // to say it only has a single layer of depth
+                        do {
+                            current = current.parent;
+                        }
+                        while (current.kind === SyntaxKind.ModuleDeclaration);
+
+                        // fall through
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.FunctionDeclaration:
+                        indent++;
+                }
+
+                current = current.parent;
+            }
+
+            return indent;
+        }
+
+        function getChildNodes(nodes: Node[]): Node[] {
+            let childNodes: Node[] = [];
+
+            function visit(node: Node) {
+                switch (node.kind) {
+                    case SyntaxKind.VariableStatement:
+                        forEach((<VariableStatement>node).declarationList.declarations, visit);
+                        break;
+                    case SyntaxKind.ObjectBindingPattern:
+                    case SyntaxKind.ArrayBindingPattern:
+                        forEach((<BindingPattern>node).elements, visit);
+                        break;
+
+                    case SyntaxKind.ExportDeclaration:
+                        // Handle named exports case e.g.:
+                        //    export {a, b as B} from "mod";
+                        if ((<ExportDeclaration>node).exportClause) {
+                            forEach((<ExportDeclaration>node).exportClause.elements, visit);
+                        }
+                        break;
+
+                    case SyntaxKind.ImportDeclaration:
+                        let importClause = (<ImportDeclaration>node).importClause;
+                        if (importClause) {
+                            // Handle default import case e.g.:
+                            //    import d from "mod";
+                            if (importClause.name) {
+                                childNodes.push(importClause);
+                            }
+
+                            // Handle named bindings in imports e.g.:
+                            //    import * as NS from "mod";
+                            //    import {a, b as B} from "mod";
+                            if (importClause.namedBindings) {
+                                if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
+                                    childNodes.push(importClause.namedBindings);
+                                }
+                                else {
+                                    forEach((<NamedImports>importClause.namedBindings).elements, visit);
+                                }
+                            }
+                        }
+                        break;
+
+                    case SyntaxKind.BindingElement:
+                    case SyntaxKind.VariableDeclaration:
+                        if (isBindingPattern((<VariableDeclaration>node).name)) {
+                            visit((<VariableDeclaration>node).name);
+                            break;
+                        }
+                        // Fall through
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.ModuleDeclaration:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.ImportEqualsDeclaration:
+                    case SyntaxKind.ImportSpecifier:
+                    case SyntaxKind.ExportSpecifier:
+                        childNodes.push(node);
+                        break;
+                }
+            }
+
+            //for (let i = 0, n = nodes.length; i < n; i++) {
+            //    let node = nodes[i];
+
+            //    if (node.kind === SyntaxKind.ClassDeclaration ||
+            //        node.kind === SyntaxKind.EnumDeclaration ||
+            //        node.kind === SyntaxKind.InterfaceDeclaration ||
+            //        node.kind === SyntaxKind.ModuleDeclaration ||
+            //        node.kind === SyntaxKind.FunctionDeclaration) {
+
+            //        childNodes.push(node);
+            //    }
+            //    else if (node.kind === SyntaxKind.VariableStatement) {
+            //        childNodes.push.apply(childNodes, (<VariableStatement>node).declarations);
+            //    }
+            //}
+            forEach(nodes, visit);
+            return sortNodes(childNodes);
+        }
+
+        function getTopLevelNodes(node: SourceFile): Node[] {
+            let topLevelNodes: Node[] = [];
+            topLevelNodes.push(node);
+
+            addTopLevelNodes(node.statements, topLevelNodes);
+
+            return topLevelNodes;
+        }
+         
+        function sortNodes(nodes: Node[]): Node[] {
+            return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => {
+                if (n1.name && n2.name) {
+                    return getPropertyNameForPropertyNameNode(n1.name).localeCompare(getPropertyNameForPropertyNameNode(n2.name));
+                }
+                else if (n1.name) {
+                    return 1;
+                }
+                else if (n2.name) {
+                    return -1;
+                }
+                else {
+                    return n1.kind - n2.kind;
+                }
+            });
+        }
+        
+        function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void {
+            nodes = sortNodes(nodes);
+
+            for (let node of nodes) {
+                switch (node.kind) {
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                        topLevelNodes.push(node);
+                        break;
+
+                    case SyntaxKind.ModuleDeclaration:
+                        let moduleDeclaration = <ModuleDeclaration>node;
+                        topLevelNodes.push(node);
+                        addTopLevelNodes((<Block>getInnermostModule(moduleDeclaration).body).statements, topLevelNodes);
+                        break;
+
+                    case SyntaxKind.FunctionDeclaration:
+                        let functionDeclaration = <FunctionLikeDeclaration>node;
+                        if (isTopLevelFunctionDeclaration(functionDeclaration)) {
+                            topLevelNodes.push(node);
+                            addTopLevelNodes((<Block>functionDeclaration.body).statements, topLevelNodes);
+                        }
+                        break;
+                }
+            }
+        }
+
+        function isTopLevelFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration) {
+            if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) {
+                // A function declaration is 'top level' if it contains any function declarations 
+                // within it. 
+                if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.Block) {
+                    // Proper function declarations can only have identifier names
+                    if (forEach((<Block>functionDeclaration.body).statements,
+                        s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((<FunctionDeclaration>s).name.text))) {
+
+                        return true;
+                    }
+
+                    // Or if it is not parented by another function.  i.e all functions
+                    // at module scope are 'top level'.
+                    if (!isFunctionBlock(functionDeclaration.parent)) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+        
+        function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] {
+            let items: ts.NavigationBarItem[] = [];
+
+            let keyToItem: Map<NavigationBarItem> = {};
+
+            for (let child of nodes) {
+                let item = createItem(child);
+                if (item !== undefined) {
+                    if (item.text.length > 0) {
+                        let key = item.text + "-" + item.kind + "-" + item.indent;
+
+                        let itemWithSameName = keyToItem[key];
+                        if (itemWithSameName) {
+                            // We had an item with the same name.  Merge these items together.
+                            merge(itemWithSameName, item);
+                        }
+                        else {
+                            keyToItem[key] = item;
+                            items.push(item);
+                        }
+                    }
+                }
+            }
+
+            return items;
+        }
+
+        function merge(target: ts.NavigationBarItem, source: ts.NavigationBarItem) {
+            // First, add any spans in the source to the target.
+            target.spans.push.apply(target.spans, source.spans);
+
+            if (source.childItems) {
+                if (!target.childItems) {
+                    target.childItems = [];
+                }
+
+                // Next, recursively merge or add any children in the source as appropriate.
+                outer:
+                for (let sourceChild of source.childItems) {
+                    for (let targetChild of target.childItems) {
+                        if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
+                            // Found a match.  merge them.
+                            merge(targetChild, sourceChild);
+                            continue outer;
+                        }
+                    }
+
+                    // Didn't find a match, just add this child to the list.
+                    target.childItems.push(sourceChild);
+                }
+            }
+        }
+
+        function createChildItem(node: Node): ts.NavigationBarItem {
+            switch (node.kind) {
+                case SyntaxKind.Parameter:
+                    if (isBindingPattern((<ParameterDeclaration>node).name)) {
+                        break;
+                    }
+                    if ((node.flags & NodeFlags.Modifier) === 0) {
+                        return undefined;
+                    }
+                    return createItem(node, getTextOfNode((<ParameterDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
+
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                    return createItem(node, getTextOfNode((<MethodDeclaration>node).name), ts.ScriptElementKind.memberFunctionElement);
+
+                case SyntaxKind.GetAccessor:
+                    return createItem(node, getTextOfNode((<AccessorDeclaration>node).name), ts.ScriptElementKind.memberGetAccessorElement);
+
+                case SyntaxKind.SetAccessor:
+                    return createItem(node, getTextOfNode((<AccessorDeclaration>node).name), ts.ScriptElementKind.memberSetAccessorElement);
+
+                case SyntaxKind.IndexSignature:
+                    return createItem(node, "[]", ts.ScriptElementKind.indexSignatureElement);
+
+                case SyntaxKind.EnumMember:
+                    return createItem(node, getTextOfNode((<EnumMember>node).name), ts.ScriptElementKind.memberVariableElement);
+
+                case SyntaxKind.CallSignature:
+                    return createItem(node, "()", ts.ScriptElementKind.callSignatureElement);
+
+                case SyntaxKind.ConstructSignature:
+                    return createItem(node, "new()", ts.ScriptElementKind.constructSignatureElement);
+
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                    return createItem(node, getTextOfNode((<PropertyDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
+
+                case SyntaxKind.FunctionDeclaration:
+                    return createItem(node, getTextOfNode((<FunctionLikeDeclaration>node).name), ts.ScriptElementKind.functionElement);
+
+                case SyntaxKind.VariableDeclaration:
+                case SyntaxKind.BindingElement:
+                    let variableDeclarationNode: Node;
+                    let name: Node;
+
+                    if (node.kind === SyntaxKind.BindingElement) {
+                        name = (<BindingElement>node).name;
+                        variableDeclarationNode = node;
+                        // binding elements are added only for variable declarations
+                        // bubble up to the containing variable declaration
+                        while (variableDeclarationNode && variableDeclarationNode.kind !== SyntaxKind.VariableDeclaration) {
+                            variableDeclarationNode = variableDeclarationNode.parent;
+                        }
+                        Debug.assert(variableDeclarationNode !== undefined);
+                    }
+                    else {
+                        Debug.assert(!isBindingPattern((<VariableDeclaration>node).name));
+                        variableDeclarationNode = node;
+                        name = (<VariableDeclaration>node).name;
+                    }
+
+                    if (isConst(variableDeclarationNode)) {
+                        return createItem(node, getTextOfNode(name), ts.ScriptElementKind.constElement);
+                    }
+                    else if (isLet(variableDeclarationNode)) {
+                        return createItem(node, getTextOfNode(name), ts.ScriptElementKind.letElement);
+                    }
+                    else {
+                        return createItem(node, getTextOfNode(name), ts.ScriptElementKind.variableElement);
+                    }
+
+                case SyntaxKind.Constructor:
+                    return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement);
+
+                case SyntaxKind.ExportSpecifier:
+                case SyntaxKind.ImportSpecifier:
+                case SyntaxKind.ImportEqualsDeclaration:
+                case SyntaxKind.ImportClause:
+                case SyntaxKind.NamespaceImport:
+                    return createItem(node, getTextOfNode((<Declaration>node).name), ts.ScriptElementKind.alias);
+            }
+
+            return undefined;
+
+            function createItem(node: Node, name: string, scriptElementKind: string): NavigationBarItem {
+                return getNavigationBarItem(name, scriptElementKind, getNodeModifiers(node), [getNodeSpan(node)]);
+            }
+        }
+
+        function isEmpty(text: string) {
+            return !text || text.trim() === "";
+        }
+
+        function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TextSpan[], childItems: NavigationBarItem[] = [], indent: number = 0): NavigationBarItem {
+            if (isEmpty(text)) {
+                return undefined;
+            }
+
+            return {
+                text,
+                kind,
+                kindModifiers,
+                spans,
+                childItems,
+                indent,
+                bolded: false,
+                grayed: false
+            };
+        }
+
+        function createTopLevelItem(node: Node): ts.NavigationBarItem {
+            switch (node.kind) {
+                case SyntaxKind.SourceFile:
+                    return createSourceFileItem(<SourceFile>node);
+
+                case SyntaxKind.ClassDeclaration:
+                    return createClassItem(<ClassDeclaration>node);
+
+                case SyntaxKind.EnumDeclaration:
+                    return createEnumItem(<EnumDeclaration>node);
+
+                case SyntaxKind.InterfaceDeclaration:
+                    return createIterfaceItem(<InterfaceDeclaration>node);
+
+                case SyntaxKind.ModuleDeclaration:
+                    return createModuleItem(<ModuleDeclaration>node);
+
+                case SyntaxKind.FunctionDeclaration:
+                    return createFunctionItem(<FunctionDeclaration>node);
+            }
+
+            return undefined;
+
+            function getModuleName(moduleDeclaration: ModuleDeclaration): string {
+                // We want to maintain quotation marks.
+                if (moduleDeclaration.name.kind === SyntaxKind.StringLiteral) {
+                    return getTextOfNode(moduleDeclaration.name);
+                }
+
+                // Otherwise, we need to aggregate each identifier to build up the qualified name.
+                let result: string[] = [];
+
+                result.push(moduleDeclaration.name.text);
+                
+                while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
+                    moduleDeclaration = <ModuleDeclaration>moduleDeclaration.body;
+
+                    result.push(moduleDeclaration.name.text);
+                } 
+
+                return result.join(".");
+            }
+
+            function createModuleItem(node: ModuleDeclaration): NavigationBarItem {
+                let moduleName = getModuleName(node);
+                
+                let childItems = getItemsWorker(getChildNodes((<Block>getInnermostModule(node).body).statements), createChildItem);
+
+                return getNavigationBarItem(moduleName,
+                    ts.ScriptElementKind.moduleElement,
+                    getNodeModifiers(node),
+                    [getNodeSpan(node)],
+                    childItems,
+                    getIndent(node));
+            }
+
+            function createFunctionItem(node: FunctionDeclaration) {
+                if (node.body && node.body.kind === SyntaxKind.Block) {
+                    let childItems = getItemsWorker(sortNodes((<Block>node.body).statements), createChildItem);
+
+                    return getNavigationBarItem(!node.name ? "default": node.name.text ,
+                        ts.ScriptElementKind.functionElement,
+                        getNodeModifiers(node),
+                        [getNodeSpan(node)],
+                        childItems,
+                        getIndent(node));
+                }
+
+                return undefined;
+            }
+
+            function createSourceFileItem(node: SourceFile): ts.NavigationBarItem {
+                let childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
+
+                if (childItems === undefined || childItems.length === 0) {
+                    return undefined;
+                }
+
+                hasGlobalNode = true;
+                let rootName = isExternalModule(node)
+                    ? "\"" + escapeString(getBaseFileName(removeFileExtension(normalizePath(node.fileName)))) + "\""
+                    : "<global>"
+
+                return getNavigationBarItem(rootName,
+                    ts.ScriptElementKind.moduleElement,
+                    ts.ScriptElementKindModifier.none,
+                    [getNodeSpan(node)],
+                    childItems);
+            }
+
+            function createClassItem(node: ClassDeclaration): ts.NavigationBarItem {
+                let childItems: NavigationBarItem[];
+
+                if (node.members) {
+                    let constructor = <ConstructorDeclaration>forEach(node.members, member => {
+                        return member.kind === SyntaxKind.Constructor && member;
+                    });
+
+                    // Add the constructor parameters in as children of the class (for property parameters).
+                    // Note that *all non-binding pattern named* parameters will be added to the nodes array, but parameters that
+                    // are not properties will be filtered out later by createChildItem.
+                    let nodes: Node[] = removeDynamicallyNamedProperties(node);
+                    if (constructor) {
+                        nodes.push.apply(nodes, filter(constructor.parameters, p => !isBindingPattern(p.name)));
+                    }
+
+                    childItems = getItemsWorker(sortNodes(nodes), createChildItem);
+                }
+
+                var nodeName = !node.name ? "default" : node.name.text;
+
+                return getNavigationBarItem(
+                    nodeName,
+                    ts.ScriptElementKind.classElement,
+                    getNodeModifiers(node),
+                    [getNodeSpan(node)],
+                    childItems,
+                    getIndent(node));
+            }
+
+            function createEnumItem(node: EnumDeclaration): ts.NavigationBarItem {
+                let childItems = getItemsWorker(sortNodes(removeComputedProperties(node)), createChildItem);
+                return getNavigationBarItem(
+                    node.name.text,
+                    ts.ScriptElementKind.enumElement,
+                    getNodeModifiers(node),
+                    [getNodeSpan(node)],
+                    childItems,
+                    getIndent(node));
+            }
+
+            function createIterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem {
+                let childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem);
+                return getNavigationBarItem(
+                    node.name.text,
+                    ts.ScriptElementKind.interfaceElement,
+                    getNodeModifiers(node),
+                    [getNodeSpan(node)],
+                    childItems,
+                    getIndent(node));
+            }
+        }
+
+        function removeComputedProperties(node: EnumDeclaration): Declaration[] {
+            return filter<Declaration>(node.members, member => member.name === undefined || member.name.kind !== SyntaxKind.ComputedPropertyName);
+        }
+
+        /**
+         * Like removeComputedProperties, but retains the properties with well known symbol names
+         */
+        function removeDynamicallyNamedProperties(node: ClassDeclaration | InterfaceDeclaration): Declaration[]{
+            return filter<Declaration>(node.members, member => !hasDynamicName(member));
+        }
+
+        function getInnermostModule(node: ModuleDeclaration): ModuleDeclaration {
+            while (node.body.kind === SyntaxKind.ModuleDeclaration) {
+                node = <ModuleDeclaration>node.body;
+            }
+
+            return node;
+        }
+
+        function getNodeSpan(node: Node) {
+            return node.kind === SyntaxKind.SourceFile
+                ? createTextSpanFromBounds(node.getFullStart(), node.getEnd())
+                : createTextSpanFromBounds(node.getStart(), node.getEnd());
+        }
+
+        function getTextOfNode(node: Node): string {
+            return getTextOfNodeFromSourceText(sourceFile.text, node);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/outliningElementsCollector.ts b/lib/typescript/services/outliningElementsCollector.ts
new file mode 100644
index 000000000..7c5ea3aa9
--- /dev/null
+++ b/lib/typescript/services/outliningElementsCollector.ts
@@ -0,0 +1,180 @@
+/* @internal */
+module ts {
+    export module OutliningElementsCollector {
+        export function collectElements(sourceFile: SourceFile): OutliningSpan[] {
+            let elements: OutliningSpan[] = [];
+            let collapseText = "...";
+
+            function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) {
+                if (hintSpanNode && startElement && endElement) {
+                    let span: OutliningSpan = {
+                        textSpan: createTextSpanFromBounds(startElement.pos, endElement.end),
+                        hintSpan: createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end),
+                        bannerText: collapseText,
+                        autoCollapse: autoCollapse
+                    };
+                    elements.push(span);
+                }
+            }
+
+            function addOutliningSpanComments(commentSpan: CommentRange, autoCollapse: boolean) {
+                if (commentSpan) {
+                    let span: OutliningSpan = {
+                        textSpan: createTextSpanFromBounds(commentSpan.pos, commentSpan.end),
+                        hintSpan: createTextSpanFromBounds(commentSpan.pos, commentSpan.end),
+                        bannerText: collapseText,
+                        autoCollapse: autoCollapse
+                    };
+                    elements.push(span);
+                }
+            }
+
+            function addOutliningForLeadingCommentsForNode(n: Node) {
+                let comments = ts.getLeadingCommentRangesOfNode(n, sourceFile);
+
+                if (comments) {
+                    let firstSingleLineCommentStart = -1;
+                    let lastSingleLineCommentEnd = -1;
+                    let isFirstSingleLineComment = true;
+                    let singleLineCommentCount = 0;
+
+                    for (let currentComment of comments) {
+
+                        // For single line comments, combine consecutive ones (2 or more) into
+                        // a single span from the start of the first till the end of the last
+                        if (currentComment.kind === SyntaxKind.SingleLineCommentTrivia) {
+                            if (isFirstSingleLineComment) {
+                                firstSingleLineCommentStart = currentComment.pos;
+                            }
+                            isFirstSingleLineComment = false;
+                            lastSingleLineCommentEnd = currentComment.end;
+                            singleLineCommentCount++;
+                        }
+                        else if (currentComment.kind === SyntaxKind.MultiLineCommentTrivia) {
+                            combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd);
+                            addOutliningSpanComments(currentComment, /*autoCollapse*/ false);
+
+                            singleLineCommentCount = 0;
+                            lastSingleLineCommentEnd = -1;
+                            isFirstSingleLineComment = true;
+                        }
+                    }
+
+                    combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd);
+                }
+            }
+
+            function combineAndAddMultipleSingleLineComments(count: number, start: number, end: number) {                
+                // Only outline spans of two or more consecutive single line comments
+                if (count > 1) {
+                    let multipleSingleLineComments = {
+                        pos: start,
+                        end: end,
+                        kind: SyntaxKind.SingleLineCommentTrivia
+                    }
+
+                    addOutliningSpanComments(multipleSingleLineComments, /*autoCollapse*/ false);
+                }
+            }
+
+            function autoCollapse(node: Node) {
+                return isFunctionBlock(node) && node.parent.kind !== SyntaxKind.ArrowFunction;
+            }
+
+            let depth = 0;
+            let maxDepth = 20;
+            function walk(n: Node): void {
+                if (depth > maxDepth) {
+                    return;
+                }
+
+                if (isDeclaration(n)) {
+                    addOutliningForLeadingCommentsForNode(n);
+                }
+
+                switch (n.kind) {
+                    case SyntaxKind.Block:
+                        if (!isFunctionBlock(n)) {
+                            let parent = n.parent;
+                            let openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
+                            let closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
+
+                            // Check if the block is standalone, or 'attached' to some parent statement.
+                            // If the latter, we want to collaps the block, but consider its hint span
+                            // to be the entire span of the parent.
+                            if (parent.kind === SyntaxKind.DoStatement ||
+                                parent.kind === SyntaxKind.ForInStatement ||
+                                parent.kind === SyntaxKind.ForOfStatement ||
+                                parent.kind === SyntaxKind.ForStatement ||
+                                parent.kind === SyntaxKind.IfStatement ||
+                                parent.kind === SyntaxKind.WhileStatement ||
+                                parent.kind === SyntaxKind.WithStatement ||
+                                parent.kind === SyntaxKind.CatchClause) {
+
+                                addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
+                                break;
+                            }
+
+                            if (parent.kind === SyntaxKind.TryStatement) {
+                                // Could be the try-block, or the finally-block.
+                                let tryStatement = <TryStatement>parent;
+                                if (tryStatement.tryBlock === n) {
+                                    addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
+                                    break;
+                                }
+                                else if (tryStatement.finallyBlock === n) {
+                                    let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
+                                    if (finallyKeyword) {
+                                        addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n));
+                                        break;
+                                    }
+                                }
+
+                                // fall through.
+                            }
+
+                            // Block was a standalone block.  In this case we want to only collapse
+                            // the span of the block, independent of any parent span.
+                            let span = createTextSpanFromBounds(n.getStart(), n.end);
+                            elements.push({
+                                textSpan: span,
+                                hintSpan: span,
+                                bannerText: collapseText,
+                                autoCollapse: autoCollapse(n)
+                            });
+                            break;
+                        }
+                    // Fallthrough.
+
+                    case SyntaxKind.ModuleBlock: {
+                        let openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
+                        let closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
+                        addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n));
+                        break;
+                    }
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.ObjectLiteralExpression:
+                    case SyntaxKind.CaseBlock: {
+                        let openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
+                        let closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
+                        addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n));
+                        break;
+                    }
+                    case SyntaxKind.ArrayLiteralExpression:
+                        let openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile);
+                        let closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
+                        addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n));
+                        break;
+                }
+                depth++;
+                forEachChild(n, walk);
+                depth--;
+            }
+
+            walk(sourceFile);
+            return elements;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/patternMatcher.ts b/lib/typescript/services/patternMatcher.ts
new file mode 100644
index 000000000..e701a2e83
--- /dev/null
+++ b/lib/typescript/services/patternMatcher.ts
@@ -0,0 +1,810 @@
+/* @internal */
+module ts {
+    // Note(cyrusn): this enum is ordered from strongest match type to weakest match type.
+    export enum PatternMatchKind {
+        exact,
+        prefix,
+        substring,
+        camelCase
+    }
+
+    // Information about a match made by the pattern matcher between a candidate and the 
+    // search pattern.
+    export interface PatternMatch {
+        // What kind of match this was.  Exact matches are better than prefix matches which are 
+        // better than substring matches which are better than CamelCase matches.
+        kind: PatternMatchKind;
+
+        // If this was a camel case match, how strong the match is.  Higher number means
+        // it was a better match.
+        camelCaseWeight?: number;
+
+        // If this was a match where all constituent parts of the candidate and search pattern 
+        // matched case sensitively or case insensitively.  Case sensitive matches of the kind
+        // are better matches than insensitive matches.
+        isCaseSensitive: boolean;
+
+        // Whether or not this match occurred with the punctuation from the search pattern stripped
+        // out or not.  Matches without the punctuation stripped are better than ones with punctuation
+        // stripped.
+        punctuationStripped: boolean;
+    }
+
+    // The pattern matcher maintains an internal cache of information as it is used.  Therefore,
+    // you should not keep it around forever and should get and release the matcher appropriately
+    // once you no longer need it.
+    export interface PatternMatcher {
+        // Used to match a candidate against the last segment of a possibly dotted pattern.  This
+        // is useful as a quick check to prevent having to compute a container before calling 
+        // "getMatches".
+        //
+        // For example, if the search pattern is "ts.c.SK" and the candidate is "SyntaxKind", then
+        // this will return a successful match, having only tested "SK" against "SyntaxKind".  At
+        // that point a call can be made to 'getMatches("SyntaxKind", "ts.compiler")', with the
+        // work to create 'ts.compiler' only being done once the first match succeeded.
+        getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[];
+
+        // Fully checks a candidate, with an dotted container, against the search pattern.
+        // The candidate must match the last part of the search pattern, and the dotted container
+        // must match the preceding segments of the pattern.
+        getMatches(candidateContainers: string[], candidate: string): PatternMatch[];
+
+        // Whether or not the pattern contained dots or not.  Clients can use this to determine
+        // If they should call getMatches, or if getMatchesForLastSegmentOfPattern is sufficient.
+        patternContainsDots: boolean;
+    }
+
+    // First we break up the pattern given by dots.  Each portion of the pattern between the
+    // dots is a 'Segment'.  The 'Segment' contains information about the entire section of 
+    // text between the dots, as well as information about any individual 'Words' that we 
+    // can break the segment into.  A 'Word' is simply a contiguous sequence of characters
+    // that can appear in a typescript identifier.  So "GetKeyword" would be one word, while
+    // "Get Keyword" would be two words.  Once we have the individual 'words', we break those
+    // into constituent 'character spans' of interest.  For example, while 'UIElement' is one
+    // word, it make character spans corresponding to "U", "I" and "Element".  These spans
+    // are then used when doing camel cased matches against candidate patterns.
+    interface Segment {
+        // Information about the entire piece of text between the dots.  For example, if the 
+        // text between the dots is 'GetKeyword', then TotalTextChunk.Text will be 'GetKeyword' and 
+        // TotalTextChunk.CharacterSpans will correspond to 'Get', 'Keyword'.
+        totalTextChunk: TextChunk;
+
+        // Information about the subwords compromising the total word.  For example, if the 
+        // text between the dots is 'GetFoo KeywordBar', then the subwords will be 'GetFoo' 
+        // and 'KeywordBar'.  Those individual words will have CharacterSpans of ('Get' and 
+        // 'Foo') and('Keyword' and 'Bar') respectively. 
+        subWordTextChunks: TextChunk[];
+    }
+
+    // Information about a chunk of text from the pattern.  The chunk is a piece of text, with 
+    // cached information about the character spans within in.  Character spans are used for 
+    // camel case matching.
+    interface TextChunk {
+        // The text of the chunk.  This should be a contiguous sequence of character that could
+        // occur in a symbol name.
+        text: string;
+
+        // The text of a chunk in lower case.  Cached because it is needed often to check for
+        // case insensitive matches.
+        textLowerCase: string;
+
+        // Whether or not this chunk is entirely lowercase. We have different rules when searching
+        // for something entirely lowercase or not.
+        isLowerCase: boolean;
+
+        // The spans in this text chunk that we think are of interest and should be matched 
+        // independently.  For example, if the chunk is for "UIElement" the the spans of interest
+        // correspond to "U", "I" and "Element".  If "UIElement" isn't found as an exaxt, prefix.
+        // or substring match, then the character spans will be used to attempt a camel case match.
+        characterSpans: TextSpan[];
+    }
+
+    function createPatternMatch(kind: PatternMatchKind, punctuationStripped: boolean, isCaseSensitive: boolean, camelCaseWeight?: number): PatternMatch {
+        return {
+            kind,
+            punctuationStripped,
+            isCaseSensitive,
+            camelCaseWeight
+        };
+    }
+
+    export function createPatternMatcher(pattern: string): PatternMatcher {
+        // We'll often see the same candidate string many times when searching (For example, when
+        // we see the name of a module that is used everywhere, or the name of an overload).  As 
+        // such, we cache the information we compute about the candidate for the life of this 
+        // pattern matcher so we don't have to compute it multiple times.
+        let stringToWordSpans: Map<TextSpan[]> = {};
+
+        pattern = pattern.trim();
+
+        let fullPatternSegment = createSegment(pattern);
+        let dotSeparatedSegments = pattern.split(".").map(p => createSegment(p.trim()));
+        let invalidPattern = dotSeparatedSegments.length === 0 || forEach(dotSeparatedSegments, segmentIsInvalid);
+
+        return {
+            getMatches,
+            getMatchesForLastSegmentOfPattern, 
+            patternContainsDots: dotSeparatedSegments.length > 1
+        };
+
+        // Quick checks so we can bail out when asked to match a candidate.
+        function skipMatch(candidate: string) {
+            return invalidPattern || !candidate;
+        }
+        
+        function getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[] {
+            if (skipMatch(candidate)) {
+                return undefined;
+            }
+
+            return matchSegment(candidate, lastOrUndefined(dotSeparatedSegments));
+        }
+
+        function getMatches(candidateContainers: string[], candidate: string): PatternMatch[] {
+            if (skipMatch(candidate)) {
+                return undefined;
+            }
+
+            // First, check that the last part of the dot separated pattern matches the name of the
+            // candidate.  If not, then there's no point in proceeding and doing the more
+            // expensive work.
+            let candidateMatch = matchSegment(candidate, lastOrUndefined(dotSeparatedSegments));
+            if (!candidateMatch) {
+                return undefined;
+            }
+
+            candidateContainers = candidateContainers || [];
+
+            // -1 because the last part was checked against the name, and only the rest
+            // of the parts are checked against the container.
+            if (dotSeparatedSegments.length - 1 > candidateContainers.length) {
+                // There weren't enough container parts to match against the pattern parts.
+                // So this definitely doesn't match.
+                return undefined;
+            }
+
+            // So far so good.  Now break up the container for the candidate and check if all
+            // the dotted parts match up correctly.
+            let totalMatch = candidateMatch;
+
+            for (let i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1;
+                 i >= 0;
+                 i--, j--) {
+
+                let segment = dotSeparatedSegments[i];
+                let containerName = candidateContainers[j];
+
+                let containerMatch = matchSegment(containerName, segment);
+                if (!containerMatch) {
+                    // This container didn't match the pattern piece.  So there's no match at all.
+                    return undefined;
+                }
+
+                addRange(totalMatch, containerMatch);
+            }
+
+            // Success, this symbol's full name matched against the dotted name the user was asking
+            // about.
+            return totalMatch;
+        }
+
+        function getWordSpans(word: string): TextSpan[] {
+            if (!hasProperty(stringToWordSpans, word)) {
+                stringToWordSpans[word] = breakIntoWordSpans(word);
+            }
+
+            return stringToWordSpans[word];
+        }
+
+        function matchTextChunk(candidate: string, chunk: TextChunk, punctuationStripped: boolean): PatternMatch {
+            let index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
+            if (index === 0) {
+                if (chunk.text.length === candidate.length) {
+                    // a) Check if the part matches the candidate entirely, in an case insensitive or
+                    //    sensitive manner.  If it does, return that there was an exact match.
+                    return createPatternMatch(PatternMatchKind.exact, punctuationStripped, /*isCaseSensitive:*/ candidate === chunk.text);
+                }
+                else {
+                    // b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive
+                    //    manner.  If it does, return that there was a prefix match.
+                    return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, /*isCaseSensitive:*/ startsWith(candidate, chunk.text));
+                }
+            }
+
+            let isLowercase = chunk.isLowerCase;
+            if (isLowercase) {
+                if (index > 0) {
+                    // c) If the part is entirely lowercase, then check if it is contained anywhere in the
+                    //    candidate in a case insensitive manner.  If so, return that there was a substring
+                    //    match. 
+                    //
+                    //    Note: We only have a substring match if the lowercase part is prefix match of some
+                    //    word part. That way we don't match something like 'Class' when the user types 'a'.
+                    //    But we would match 'FooAttribute' (since 'Attribute' starts with 'a').
+                    let wordSpans = getWordSpans(candidate);
+                    for (let span of wordSpans) {
+                        if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) {
+                            return createPatternMatch(PatternMatchKind.substring, punctuationStripped,
+                                /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false));
+                        }
+                    }
+                }
+            }
+            else {
+                // d) If the part was not entirely lowercase, then check if it is contained in the
+                //    candidate in a case *sensitive* manner. If so, return that there was a substring
+                //    match.
+                if (candidate.indexOf(chunk.text) > 0) {
+                    return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ true);
+                }
+            }
+
+            if (!isLowercase) {
+                // e) If the part was not entirely lowercase, then attempt a camel cased match as well.
+                if (chunk.characterSpans.length > 0) {
+                    let candidateParts = getWordSpans(candidate);
+                    let camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false);
+                    if (camelCaseWeight !== undefined) {
+                        return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight);
+                    }
+
+                    camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true);
+                    if (camelCaseWeight !== undefined) {
+                        return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ false, /*camelCaseWeight:*/ camelCaseWeight);
+                    }
+                }
+            }
+
+            if (isLowercase) {
+                // f) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries?
+
+                // We could check every character boundary start of the candidate for the pattern. However, that's
+                // an m * n operation in the wost case. Instead, find the first instance of the pattern 
+                // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to 
+                // filter the list based on a substring that starts on a capital letter and also with a lowercase one.
+                // (Pattern: fogbar, Candidate: quuxfogbarFogBar).
+                if (chunk.text.length < candidate.length) {
+                    if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) {
+                        return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ false);
+                    }
+                }
+            }
+
+            return undefined;
+        }
+
+        function containsSpaceOrAsterisk(text: string): boolean {
+            for (let i = 0; i < text.length; i++) {
+                let ch = text.charCodeAt(i);
+                if (ch === CharacterCodes.space || ch === CharacterCodes.asterisk) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        function matchSegment(candidate: string, segment: Segment): PatternMatch[] {
+            // First check if the segment matches as is.  This is also useful if the segment contains
+            // characters we would normally strip when splitting into parts that we also may want to
+            // match in the candidate.  For example if the segment is "@int" and the candidate is
+            // "@int", then that will show up as an exact match here.
+            //
+            // Note: if the segment contains a space or an asterisk then we must assume that it's a
+            // multi-word segment.
+            if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) {
+                let match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false);
+                if (match) {
+                    return [match];
+                }
+            }
+
+            // The logic for pattern matching is now as follows:
+            //
+            // 1) Break the segment passed in into words.  Breaking is rather simple and a
+            //    good way to think about it that if gives you all the individual alphanumeric words
+            //    of the pattern.
+            //
+            // 2) For each word try to match the word against the candidate value.
+            //
+            // 3) Matching is as follows:
+            //
+            //   a) Check if the word matches the candidate entirely, in an case insensitive or
+            //    sensitive manner.  If it does, return that there was an exact match.
+            //
+            //   b) Check if the word is a prefix of the candidate, in a case insensitive or
+            //      sensitive manner.  If it does, return that there was a prefix match.
+            //
+            //   c) If the word is entirely lowercase, then check if it is contained anywhere in the
+            //      candidate in a case insensitive manner.  If so, return that there was a substring
+            //      match. 
+            //
+            //      Note: We only have a substring match if the lowercase part is prefix match of
+            //      some word part. That way we don't match something like 'Class' when the user
+            //      types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with
+            //      'a').
+            //
+            //   d) If the word was not entirely lowercase, then check if it is contained in the
+            //      candidate in a case *sensitive* manner. If so, return that there was a substring
+            //      match.
+            //
+            //   e) If the word was not entirely lowercase, then attempt a camel cased match as
+            //      well.
+            //
+            //   f) The word is all lower case. Is it a case insensitive substring of the candidate starting 
+            //      on a part boundary of the candidate?
+            //
+            // Only if all words have some sort of match is the pattern considered matched.
+
+            let subWordTextChunks = segment.subWordTextChunks;
+            let matches: PatternMatch[] = undefined;
+
+            for (let subWordTextChunk of subWordTextChunks) {
+                // Try to match the candidate with this word
+                let result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true);
+                if (!result) {
+                    return undefined;
+                }
+
+                matches = matches || [];
+                matches.push(result);
+            }
+
+            return matches;
+        }
+
+        function partStartsWith(candidate: string, candidateSpan: TextSpan, pattern: string, ignoreCase: boolean, patternSpan?: TextSpan): boolean {
+            let patternPartStart = patternSpan ? patternSpan.start : 0;
+            let patternPartLength = patternSpan ? patternSpan.length : pattern.length;
+
+            if (patternPartLength > candidateSpan.length) {
+                // Pattern part is longer than the candidate part. There can never be a match.
+                return false;
+            }
+            
+            if (ignoreCase) {
+                for (let i = 0; i < patternPartLength; i++) {
+                    let ch1 = pattern.charCodeAt(patternPartStart + i);
+                    let ch2 = candidate.charCodeAt(candidateSpan.start + i);
+                    if (toLowerCase(ch1) !== toLowerCase(ch2)) {
+                        return false;
+                    }
+                }
+            }
+            else {
+                for (let i = 0; i < patternPartLength; i++) {
+                    let ch1 = pattern.charCodeAt(patternPartStart + i);
+                    let ch2 = candidate.charCodeAt(candidateSpan.start + i);
+                    if (ch1 !== ch2) {
+                        return false;
+                    }
+                }
+            }
+
+            return true;
+        }
+
+        function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): number {
+            let chunkCharacterSpans = chunk.characterSpans;
+
+            // Note: we may have more pattern parts than candidate parts.  This is because multiple
+            // pattern parts may match a candidate part.  For example "SiUI" against "SimpleUI".
+            // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI.  However, U
+            // and I will both match in UI. 
+
+            let currentCandidate = 0;
+            let currentChunkSpan = 0;
+            let firstMatch: number = undefined;
+            let contiguous: boolean = undefined;
+
+            while (true) {
+                // Let's consider our termination cases
+                if (currentChunkSpan === chunkCharacterSpans.length) {
+                    // We did match! We shall assign a weight to this
+                    let weight = 0;
+
+                    // Was this contiguous?
+                    if (contiguous) {
+                        weight += 1;
+                    }
+
+                    // Did we start at the beginning of the candidate?
+                    if (firstMatch === 0) {
+                        weight += 2;
+                    }
+
+                    return weight;
+                }
+                else if (currentCandidate === candidateParts.length) {
+                    // No match, since we still have more of the pattern to hit
+                    return undefined;
+                }
+
+                let candidatePart = candidateParts[currentCandidate];
+                let gotOneMatchThisCandidate = false;
+
+                // Consider the case of matching SiUI against SimpleUIElement. The candidate parts
+                // will be Simple/UI/Element, and the pattern parts will be Si/U/I.  We'll match 'Si'
+                // against 'Simple' first.  Then we'll match 'U' against 'UI'. However, we want to
+                // still keep matching pattern parts against that candidate part. 
+                for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) {
+                    let chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
+
+                    if (gotOneMatchThisCandidate) {
+                        // We've already gotten one pattern part match in this candidate.  We will
+                        // only continue trying to consumer pattern parts if the last part and this
+                        // part are both upper case.  
+                        if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) ||
+                            !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) {
+                            break;
+                        }
+                    }
+
+                    if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) {
+                        break;
+                    }
+
+                    gotOneMatchThisCandidate = true;
+
+                    firstMatch = firstMatch === undefined ? currentCandidate : firstMatch;
+
+                    // If we were contiguous, then keep that value.  If we weren't, then keep that
+                    // value.  If we don't know, then set the value to 'true' as an initial match is
+                    // obviously contiguous.
+                    contiguous = contiguous === undefined ? true : contiguous;
+
+                    candidatePart = createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length);
+                }
+
+                // Check if we matched anything at all.  If we didn't, then we need to unset the
+                // contiguous bit if we currently had it set.
+                // If we haven't set the bit yet, then that means we haven't matched anything so
+                // far, and we don't want to change that.
+                if (!gotOneMatchThisCandidate && contiguous !== undefined) {
+                    contiguous = false;
+                }
+
+                // Move onto the next candidate.
+                currentCandidate++;
+            }
+        }
+    }
+
+    // Helper function to compare two matches to determine which is better.  Matches are first
+    // ordered by kind (so all prefix matches always beat all substring matches).  Then, if the
+    // match is a camel case match, the relative weights of the match are used to determine 
+    // which is better (with a greater weight being better).  Then if the match is of the same 
+    // type, then a case sensitive match is considered better than an insensitive one. 
+    function patternMatchCompareTo(match1: PatternMatch, match2: PatternMatch): number {
+        return compareType(match1, match2) ||
+            compareCamelCase(match1, match2) ||
+            compareCase(match1, match2) ||
+            comparePunctuation(match1, match2);
+    }
+
+    function comparePunctuation(result1: PatternMatch, result2: PatternMatch) {
+        // Consider a match to be better if it was successful without stripping punctuation
+        // versus a match that had to strip punctuation to succeed.
+        if (result1.punctuationStripped !== result2.punctuationStripped) {
+            return result1.punctuationStripped ? 1 : -1;
+        }
+
+        return 0;
+    }
+
+    function compareCase(result1: PatternMatch, result2: PatternMatch) {
+        if (result1.isCaseSensitive !== result2.isCaseSensitive) {
+            return result1.isCaseSensitive ? -1 : 1;
+        }
+
+        return 0;
+    }
+
+    function compareType(result1: PatternMatch, result2: PatternMatch) {
+        return result1.kind - result2.kind;
+    }
+
+    function compareCamelCase(result1: PatternMatch, result2: PatternMatch) {
+        if (result1.kind === PatternMatchKind.camelCase && result2.kind === PatternMatchKind.camelCase) {
+            // Swap the values here.  If result1 has a higher weight, then we want it to come
+            // first.
+            return result2.camelCaseWeight - result1.camelCaseWeight;
+        }
+
+        return 0;
+    }
+
+    function createSegment(text: string): Segment {
+        return {
+            totalTextChunk: createTextChunk(text),
+            subWordTextChunks: breakPatternIntoTextChunks(text)
+        }
+    }
+
+    // A segment is considered invalid if we couldn't find any words in it.
+    function segmentIsInvalid(segment: Segment) {
+        return segment.subWordTextChunks.length === 0;
+    }
+
+    function isUpperCaseLetter(ch: number) {
+        // Fast check for the ascii range.
+        if (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) {
+            return true;
+        }
+
+        if (ch < CharacterCodes.maxAsciiCharacter || !isUnicodeIdentifierStart(ch, ScriptTarget.Latest)) {
+            return false;
+        }
+
+        // TODO: find a way to determine this for any unicode characters in a 
+        // non-allocating manner.
+        let str = String.fromCharCode(ch);
+        return str === str.toUpperCase();
+    }
+
+    function isLowerCaseLetter(ch: number) {
+        // Fast check for the ascii range.
+        if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) {
+            return true;
+        }
+
+        if (ch < CharacterCodes.maxAsciiCharacter || !isUnicodeIdentifierStart(ch, ScriptTarget.Latest)) {
+            return false;
+        }
+
+
+        // TODO: find a way to determine this for any unicode characters in a 
+        // non-allocating manner.
+        let str = String.fromCharCode(ch);
+        return str === str.toLowerCase();
+    }
+
+    function containsUpperCaseLetter(string: string): boolean {
+        for (let i = 0, n = string.length; i < n; i++) {
+            if (isUpperCaseLetter(string.charCodeAt(i))) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    function startsWith(string: string, search: string) {
+        for (let i = 0, n = search.length; i < n; i++) {
+            if (string.charCodeAt(i) !== search.charCodeAt(i)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    // Assumes 'value' is already lowercase.
+    function indexOfIgnoringCase(string: string, value: string): number {
+        for (let i = 0, n = string.length - value.length; i <= n; i++) {
+            if (startsWithIgnoringCase(string, value, i)) {
+                return i;
+            }
+        }
+
+        return -1;
+    }
+
+    // Assumes 'value' is already lowercase.
+    function startsWithIgnoringCase(string: string, value: string, start: number): boolean {
+        for (let i = 0, n = value.length; i < n; i++) {
+            let ch1 = toLowerCase(string.charCodeAt(i + start));
+            let ch2 = value.charCodeAt(i);
+
+            if (ch1 !== ch2) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    function toLowerCase(ch: number): number {
+        // Fast convert for the ascii range.
+        if (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) {
+            return CharacterCodes.a + (ch - CharacterCodes.A);
+        }
+
+        if (ch < CharacterCodes.maxAsciiCharacter) {
+            return ch;
+        }
+
+        // TODO: find a way to compute this for any unicode characters in a 
+        // non-allocating manner.
+        return String.fromCharCode(ch).toLowerCase().charCodeAt(0);
+    }
+
+    function isDigit(ch: number) {
+        // TODO(cyrusn): Find a way to support this for unicode digits.
+        return ch >= CharacterCodes._0 && ch <= CharacterCodes._9;
+    }
+
+    function isWordChar(ch: number) {
+        return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === CharacterCodes._ || ch === CharacterCodes.$;
+    }
+
+    function breakPatternIntoTextChunks(pattern: string): TextChunk[] {
+        let result: TextChunk[] = [];
+        let wordStart = 0;
+        let wordLength = 0;
+
+        for (let i = 0; i < pattern.length; i++) {
+            let ch = pattern.charCodeAt(i);
+            if (isWordChar(ch)) {
+                if (wordLength++ === 0) {
+                    wordStart = i;
+                }
+            }
+            else {
+                if (wordLength > 0) {
+                    result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
+                    wordLength = 0;
+                }
+            }
+        }
+
+        if (wordLength > 0) {
+            result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
+        }
+
+        return result;
+    }
+
+    function createTextChunk(text: string): TextChunk {
+        let textLowerCase = text.toLowerCase();
+        return {
+            text,
+            textLowerCase,
+            isLowerCase: text === textLowerCase,
+            characterSpans: breakIntoCharacterSpans(text)
+        }
+    }
+
+    /* @internal */ export function breakIntoCharacterSpans(identifier: string): TextSpan[] {
+        return breakIntoSpans(identifier, /*word:*/ false);
+    }
+
+    /* @internal */ export function breakIntoWordSpans(identifier: string): TextSpan[] {
+        return breakIntoSpans(identifier, /*word:*/ true);
+    }
+
+    function breakIntoSpans(identifier: string, word: boolean): TextSpan[] {
+        let result: TextSpan[] = [];
+
+        let wordStart = 0;
+        for (let i = 1, n = identifier.length; i < n; i++) {
+            let lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
+            let currentIsDigit = isDigit(identifier.charCodeAt(i));
+
+            let hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
+            let hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart);
+
+            if (charIsPunctuation(identifier.charCodeAt(i - 1)) ||
+                charIsPunctuation(identifier.charCodeAt(i)) ||
+                lastIsDigit != currentIsDigit ||
+                hasTransitionFromLowerToUpper ||
+                hasTransitionFromUpperToLower) {
+
+                if (!isAllPunctuation(identifier, wordStart, i)) {
+                    result.push(createTextSpan(wordStart, i - wordStart));
+                }
+
+                wordStart = i;
+            }
+        }
+
+        if (!isAllPunctuation(identifier, wordStart, identifier.length)) {
+            result.push(createTextSpan(wordStart, identifier.length - wordStart));
+        }
+
+        return result;
+    }
+
+    function charIsPunctuation(ch: number) {
+        switch (ch) {
+            case CharacterCodes.exclamation:
+            case CharacterCodes.doubleQuote:
+            case CharacterCodes.hash:
+            case CharacterCodes.percent:
+            case CharacterCodes.ampersand:
+            case CharacterCodes.singleQuote:
+            case CharacterCodes.openParen:
+            case CharacterCodes.closeParen:
+            case CharacterCodes.asterisk:
+            case CharacterCodes.comma:
+            case CharacterCodes.minus:
+            case CharacterCodes.dot:
+            case CharacterCodes.slash:
+            case CharacterCodes.colon:
+            case CharacterCodes.semicolon:
+            case CharacterCodes.question:
+            case CharacterCodes.at:
+            case CharacterCodes.openBracket:
+            case CharacterCodes.backslash:
+            case CharacterCodes.closeBracket:
+            case CharacterCodes._:
+            case CharacterCodes.openBrace:
+            case CharacterCodes.closeBrace:
+                return true;
+        }
+
+        return false;
+    }
+
+    function isAllPunctuation(identifier: string, start: number, end: number): boolean {
+        for (let i = start; i < end; i++) {
+            let ch = identifier.charCodeAt(i);
+
+            // We don't consider _ or $ as punctuation as there may be things with that name.
+            if (!charIsPunctuation(ch) || ch === CharacterCodes._ || ch === CharacterCodes.$) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    function transitionFromUpperToLower(identifier: string, word: boolean, index: number, wordStart: number): boolean {
+        if (word) {
+            // Cases this supports:
+            // 1) IDisposable -> I, Disposable
+            // 2) UIElement -> UI, Element
+            // 3) HTMLDocument -> HTML, Document
+            //
+            // etc.
+            if (index != wordStart &&
+                index + 1 < identifier.length) {
+                let currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
+                let nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
+
+                if (currentIsUpper && nextIsLower) {
+                    // We have a transition from an upper to a lower letter here.  But we only
+                    // want to break if all the letters that preceded are uppercase.  i.e. if we
+                    // have "Foo" we don't want to break that into "F, oo".  But if we have
+                    // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI,
+                    // Foo".  i.e. the last uppercase letter belongs to the lowercase letters
+                    // that follows.  Note: this will make the following not split properly:
+                    // "HELLOthere".  However, these sorts of names do not show up in .Net
+                    // programs.
+                    for (let i = wordStart; i < index; i++) {
+                        if (!isUpperCaseLetter(identifier.charCodeAt(i))) {
+                            return false;
+                        }
+                    }
+
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    function transitionFromLowerToUpper(identifier: string, word: boolean, index: number): boolean {
+        let lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
+        let currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
+
+        // See if the casing indicates we're starting a new word. Note: if we're breaking on
+        // words, then just seeing an upper case character isn't enough.  Instead, it has to
+        // be uppercase and the previous character can't be uppercase. 
+        //
+        // For example, breaking "AddMetadata" on words would make: Add Metadata
+        //
+        // on characters would be: A dd M etadata
+        //
+        // Break "AM" on words would be: AM
+        //
+        // on characters would be: A M
+        //
+        // We break the search string on characters.  But we break the symbol name on words.
+        let transition = word
+            ? (currentIsUpper && !lastIsUpper)
+            : currentIsUpper;
+        return transition;
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/services.ts b/lib/typescript/services/services.ts
new file mode 100644
index 000000000..9742b07b5
--- /dev/null
+++ b/lib/typescript/services/services.ts
@@ -0,0 +1,6904 @@
+/// <reference path="..\compiler\program.ts"/>
+
+/// <reference path='breakpoints.ts' />
+/// <reference path='outliningElementsCollector.ts' />
+/// <reference path='navigateTo.ts' />
+/// <reference path='navigationBar.ts' />
+/// <reference path='patternMatcher.ts' />
+/// <reference path='signatureHelp.ts' />
+/// <reference path='utilities.ts' />
+/// <reference path='formatting\formatting.ts' />
+/// <reference path='formatting\smartIndenter.ts' />
+
+module ts {
+    /** The version of the language service API */
+    export let servicesVersion = "0.4"
+
+    export interface Node {
+        getSourceFile(): SourceFile;
+        getChildCount(sourceFile?: SourceFile): number;
+        getChildAt(index: number, sourceFile?: SourceFile): Node;
+        getChildren(sourceFile?: SourceFile): Node[];
+        getStart(sourceFile?: SourceFile): number;
+        getFullStart(): number;
+        getEnd(): number;
+        getWidth(sourceFile?: SourceFile): number;
+        getFullWidth(): number;
+        getLeadingTriviaWidth(sourceFile?: SourceFile): number;
+        getFullText(sourceFile?: SourceFile): string;
+        getText(sourceFile?: SourceFile): string;
+        getFirstToken(sourceFile?: SourceFile): Node;
+        getLastToken(sourceFile?: SourceFile): Node;
+    }
+
+    export interface Symbol {
+        getFlags(): SymbolFlags;
+        getName(): string;
+        getDeclarations(): Declaration[];
+        getDocumentationComment(): SymbolDisplayPart[];
+    }
+
+    export interface Type {
+        getFlags(): TypeFlags;
+        getSymbol(): Symbol;
+        getProperties(): Symbol[];
+        getProperty(propertyName: string): Symbol;
+        getApparentProperties(): Symbol[];
+        getCallSignatures(): Signature[];
+        getConstructSignatures(): Signature[];
+        getStringIndexType(): Type;
+        getNumberIndexType(): Type;
+    }
+
+    export interface Signature {
+        getDeclaration(): SignatureDeclaration;
+        getTypeParameters(): Type[];
+        getParameters(): Symbol[];
+        getReturnType(): Type;
+        getDocumentationComment(): SymbolDisplayPart[];
+    }
+
+    export interface SourceFile {
+        /* @internal */ version: string;
+        /* @internal */ scriptSnapshot: IScriptSnapshot;
+        /* @internal */ nameTable: Map<string>;
+
+        /* @internal */ getNamedDeclarations(): Map<Declaration[]>;
+
+        getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
+        getLineStarts(): number[];
+        getPositionOfLineAndCharacter(line: number, character: number): number;
+        update(newText: string, textChangeRange: TextChangeRange): SourceFile;
+    }
+
+    /**
+     * Represents an immutable snapshot of a script at a specified time.Once acquired, the 
+     * snapshot is observably immutable. i.e. the same calls with the same parameters will return
+     * the same values.
+     */
+    export interface IScriptSnapshot {
+        /** Gets a portion of the script snapshot specified by [start, end). */
+        getText(start: number, end: number): string;
+
+        /** Gets the length of this script snapshot. */
+        getLength(): number;
+
+        /**
+         * Gets the TextChangeRange that describe how the text changed between this text and 
+         * an older version.  This information is used by the incremental parser to determine
+         * what sections of the script need to be re-parsed.  'undefined' can be returned if the 
+         * change range cannot be determined.  However, in that case, incremental parsing will
+         * not happen and the entire document will be re - parsed.
+         */
+        getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange;
+    }
+
+    export module ScriptSnapshot {
+        class StringScriptSnapshot implements IScriptSnapshot {
+            private _lineStartPositions: number[] = undefined;
+
+            constructor(private text: string) {
+            }
+
+            public getText(start: number, end: number): string {
+                return this.text.substring(start, end);
+            }
+
+            public getLength(): number {
+                return this.text.length;
+            }
+
+            public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
+                // Text-based snapshots do not support incremental parsing. Return undefined
+                // to signal that to the caller.
+                return undefined;
+            }
+        }
+
+        export function fromString(text: string): IScriptSnapshot {
+            return new StringScriptSnapshot(text);
+        }
+    }
+    export interface PreProcessedFileInfo {
+        referencedFiles: FileReference[];
+        importedFiles: FileReference[];
+        isLibFile: boolean
+    }
+
+    let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
+
+    let emptyArray: any[] = [];
+
+    function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject {
+        let node = <NodeObject> new (getNodeConstructor(kind))();
+        node.pos = pos;
+        node.end = end;
+        node.flags = flags;
+        node.parent = parent;
+        return node;
+    }
+
+    class NodeObject implements Node {
+        public kind: SyntaxKind;
+        public pos: number;
+        public end: number;
+        public flags: NodeFlags;
+        public parent: Node;
+        private _children: Node[];
+
+        public getSourceFile(): SourceFile {
+            return getSourceFileOfNode(this);
+        }
+
+        public getStart(sourceFile?: SourceFile): number {
+            return getTokenPosOfNode(this, sourceFile);
+        }
+
+        public getFullStart(): number {
+            return this.pos;
+        }
+
+        public getEnd(): number {
+            return this.end;
+        }
+
+        public getWidth(sourceFile?: SourceFile): number {
+            return this.getEnd() - this.getStart(sourceFile);
+        }
+
+        public getFullWidth(): number {
+            return this.end - this.getFullStart();
+        }
+
+        public getLeadingTriviaWidth(sourceFile?: SourceFile): number {
+            return this.getStart(sourceFile) - this.pos;
+        }
+
+        public getFullText(sourceFile?: SourceFile): string {
+            return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
+        }
+
+        public getText(sourceFile?: SourceFile): string {
+            return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
+        }
+
+        private addSyntheticNodes(nodes: Node[], pos: number, end: number): number {
+            scanner.setTextPos(pos);
+            while (pos < end) {
+                let token = scanner.scan();
+                let textPos = scanner.getTextPos();
+                nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this));
+                pos = textPos;
+            }
+            return pos;
+        }
+
+        private createSyntaxList(nodes: NodeArray<Node>): Node {
+            let list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this);
+            list._children = [];
+            let pos = nodes.pos;
+            for (let node of nodes) {
+                if (pos < node.pos) {
+                    pos = this.addSyntheticNodes(list._children, pos, node.pos);
+                }
+                list._children.push(node);
+                pos = node.end;
+            }
+            if (pos < nodes.end) {
+                this.addSyntheticNodes(list._children, pos, nodes.end);
+            }
+            return list;
+        }
+
+        private createChildren(sourceFile?: SourceFile) {
+            let children: Node[];
+            if (this.kind >= SyntaxKind.FirstNode) {
+                scanner.setText((sourceFile || this.getSourceFile()).text);
+                children = [];
+                let pos = this.pos;
+                let processNode = (node: Node) => {
+                    if (pos < node.pos) {
+                        pos = this.addSyntheticNodes(children, pos, node.pos);
+                    }
+                    children.push(node);
+                    pos = node.end;
+                };
+                let processNodes = (nodes: NodeArray<Node>) => {
+                    if (pos < nodes.pos) {
+                        pos = this.addSyntheticNodes(children, pos, nodes.pos);
+                    }
+                    children.push(this.createSyntaxList(<NodeArray<Node>>nodes));
+                    pos = nodes.end;
+                };
+                forEachChild(this, processNode, processNodes);
+                if (pos < this.end) {
+                    this.addSyntheticNodes(children, pos, this.end);
+                }
+                scanner.setText(undefined);
+            }
+            this._children = children || emptyArray;
+        }
+
+        public getChildCount(sourceFile?: SourceFile): number {
+            if (!this._children) this.createChildren(sourceFile);
+            return this._children.length;
+        }
+
+        public getChildAt(index: number, sourceFile?: SourceFile): Node {
+            if (!this._children) this.createChildren(sourceFile);
+            return this._children[index];
+        }
+
+        public getChildren(sourceFile?: SourceFile): Node[] {
+            if (!this._children) this.createChildren(sourceFile);
+            return this._children;
+        }
+
+        public getFirstToken(sourceFile?: SourceFile): Node {
+            let children = this.getChildren();
+            for (let child of children) {
+                if (child.kind < SyntaxKind.FirstNode) {
+                    return child;
+                }
+
+                return child.getFirstToken(sourceFile);
+            }
+        }
+
+        public getLastToken(sourceFile?: SourceFile): Node {
+            let children = this.getChildren(sourceFile);
+            for (let i = children.length - 1; i >= 0; i--) {
+                let child = children[i];
+                if (child.kind < SyntaxKind.FirstNode) {
+                    return child;
+                }
+
+                return child.getLastToken(sourceFile);
+            }
+        }
+    }
+
+    class SymbolObject implements Symbol {
+        flags: SymbolFlags;
+        name: string;
+        declarations: Declaration[];
+
+        // Undefined is used to indicate the value has not been computed. If, after computing, the
+        // symbol has no doc comment, then the empty string will be returned.
+        documentationComment: SymbolDisplayPart[];
+
+        constructor(flags: SymbolFlags, name: string) {
+            this.flags = flags;
+            this.name = name;
+        }
+
+        getFlags(): SymbolFlags {
+            return this.flags;
+        }
+
+        getName(): string {
+            return this.name;
+        }
+
+        getDeclarations(): Declaration[] {
+            return this.declarations;
+        }
+
+        getDocumentationComment(): SymbolDisplayPart[] {
+            if (this.documentationComment === undefined) {
+                this.documentationComment = getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & SymbolFlags.Property));
+            }
+
+            return this.documentationComment;
+        }
+    }
+
+    function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean) {
+        let documentationComment = <SymbolDisplayPart[]>[];
+        let docComments = getJsDocCommentsSeparatedByNewLines();
+        ts.forEach(docComments, docComment => {
+            if (documentationComment.length) {
+                documentationComment.push(lineBreakPart());
+            }
+            documentationComment.push(docComment);
+        });
+
+        return documentationComment;
+
+        function getJsDocCommentsSeparatedByNewLines() {
+            let paramTag = "@param";
+            let jsDocCommentParts: SymbolDisplayPart[] = [];
+
+            ts.forEach(declarations, (declaration, indexOfDeclaration) => {
+                // Make sure we are collecting doc comment from declaration once,
+                // In case of union property there might be same declaration multiple times 
+                // which only varies in type parameter
+                // Eg. let a: Array<string> | Array<number>; a.length
+                // The property length will have two declarations of property length coming 
+                // from Array<T> - Array<string> and Array<number>
+                if (indexOf(declarations, declaration) === indexOfDeclaration) {
+                    let sourceFileOfDeclaration = getSourceFileOfNode(declaration);
+                    // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments
+                    if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) {
+                        ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => {
+                            let cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
+                            if (cleanedParamJsDocComment) {
+                                jsDocCommentParts.push.apply(jsDocCommentParts, cleanedParamJsDocComment);
+                            }
+                        });
+                    }
+
+                    // If this is left side of dotted module declaration, there is no doc comments associated with this node
+                    if (declaration.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>declaration).body.kind === SyntaxKind.ModuleDeclaration) {
+                        return;
+                    }
+
+                    // If this is dotted module name, get the doc comments from the parent
+                    while (declaration.kind === SyntaxKind.ModuleDeclaration && declaration.parent.kind === SyntaxKind.ModuleDeclaration) {
+                        declaration = <ModuleDeclaration>declaration.parent;
+                    } 
+
+                    // Get the cleaned js doc comment text from the declaration
+                    ts.forEach(getJsDocCommentTextRange(
+                        declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => {
+                            let cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
+                            if (cleanedJsDocComment) {
+                                jsDocCommentParts.push.apply(jsDocCommentParts, cleanedJsDocComment);
+                            }
+                        });
+                }
+            });
+
+            return jsDocCommentParts;
+
+            function getJsDocCommentTextRange(node: Node, sourceFile: SourceFile): TextRange[] {
+                return ts.map(getJsDocComments(node, sourceFile),
+                    jsDocComment => {
+                        return {
+                            pos: jsDocComment.pos + "/*".length, // Consume /* from the comment
+                            end: jsDocComment.end - "*/".length // Trim off comment end indicator 
+                        };
+                    });
+            }
+
+            function consumeWhiteSpacesOnTheLine(pos: number, end: number, sourceFile: SourceFile, maxSpacesToRemove?: number) {
+                if (maxSpacesToRemove !== undefined) {
+                    end = Math.min(end, pos + maxSpacesToRemove);
+                }
+
+                for (; pos < end; pos++) {
+                    let ch = sourceFile.text.charCodeAt(pos);
+                    if (!isWhiteSpace(ch) || isLineBreak(ch)) {
+                        // Either found lineBreak or non whiteSpace
+                        return pos;
+                    }
+                }
+
+                return end;
+            }
+
+            function consumeLineBreaks(pos: number, end: number, sourceFile: SourceFile) {
+                while (pos < end && isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                    pos++;
+                }
+
+                return pos;
+            }
+
+            function isName(pos: number, end: number, sourceFile: SourceFile, name: string) {
+                return pos + name.length < end &&
+                    sourceFile.text.substr(pos, name.length) === name &&
+                    (isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)) ||
+                        isLineBreak(sourceFile.text.charCodeAt(pos + name.length)));
+            }
+
+            function isParamTag(pos: number, end: number, sourceFile: SourceFile) {
+                // If it is @param tag
+                return isName(pos, end, sourceFile, paramTag);
+            }
+
+            function pushDocCommentLineText(docComments: SymbolDisplayPart[], text: string, blankLineCount: number) {
+                // Add the empty lines in between texts
+                while (blankLineCount--) {
+                    docComments.push(textPart(""));
+                }
+
+                docComments.push(textPart(text));
+            }
+
+            function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) {
+                let spacesToRemoveAfterAsterisk: number;
+                let docComments: SymbolDisplayPart[] = [];
+                let blankLineCount = 0;
+                let isInParamTag = false;
+
+                while (pos < end) {
+                    let docCommentTextOfLine = "";
+                    // First consume leading white space
+                    pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile);
+
+                    // If the comment starts with '*' consume the spaces on this line
+                    if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) {
+                        let lineStartPos = pos + 1;
+                        pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk);
+
+                        // Set the spaces to remove after asterisk as margin if not already set
+                        if (spacesToRemoveAfterAsterisk === undefined && pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                            spacesToRemoveAfterAsterisk = pos - lineStartPos;
+                        }
+                    }
+                    else if (spacesToRemoveAfterAsterisk === undefined) {
+                        spacesToRemoveAfterAsterisk = 0;
+                    }
+
+                    // Analyse text on this line
+                    while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                        let ch = sourceFile.text.charAt(pos);
+                        if (ch === "@") {
+                            // If it is @param tag
+                            if (isParamTag(pos, end, sourceFile)) {
+                                isInParamTag = true;
+                                pos += paramTag.length;
+                                continue;
+                            }
+                            else {
+                                isInParamTag = false;
+                            }
+                        }
+
+                        // Add the ch to doc text if we arent in param tag
+                        if (!isInParamTag) {
+                            docCommentTextOfLine += ch;
+                        }
+
+                        // Scan next character
+                        pos++;
+                    }
+
+                    // Continue with next line
+                    pos = consumeLineBreaks(pos, end, sourceFile);
+                    if (docCommentTextOfLine) {
+                        pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount);
+                        blankLineCount = 0;
+                    }
+                    else if (!isInParamTag && docComments.length) { 
+                        // This is blank line when there is text already parsed
+                        blankLineCount++;
+                    }
+                }
+
+                return docComments;
+            }
+
+            function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) {
+                let paramHelpStringMargin: number;
+                let paramDocComments: SymbolDisplayPart[] = [];
+                while (pos < end) {
+                    if (isParamTag(pos, end, sourceFile)) {
+                        let blankLineCount = 0;
+                        let recordedParamTag = false;
+                        // Consume leading spaces 
+                        pos = consumeWhiteSpaces(pos + paramTag.length);
+                        if (pos >= end) {
+                            break;
+                        }
+
+                        // Ignore type expression
+                        if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) {
+                            pos++;
+                            for (let curlies = 1; pos < end; pos++) {
+                                let charCode = sourceFile.text.charCodeAt(pos);
+
+                                // { character means we need to find another } to match the found one
+                                if (charCode === CharacterCodes.openBrace) {
+                                    curlies++;
+                                    continue;
+                                }
+
+                                // } char
+                                if (charCode === CharacterCodes.closeBrace) {
+                                    curlies--;
+                                    if (curlies === 0) {
+                                        // We do not have any more } to match the type expression is ignored completely
+                                        pos++;
+                                        break;
+                                    }
+                                    else {
+                                        // there are more { to be matched with }
+                                        continue;
+                                    }
+                                }
+
+                                // Found start of another tag
+                                if (charCode === CharacterCodes.at) {
+                                    break;
+                                }
+                            }
+
+                            // Consume white spaces
+                            pos = consumeWhiteSpaces(pos);
+                            if (pos >= end) {
+                                break;
+                            }
+                        }
+
+                        // Parameter name
+                        if (isName(pos, end, sourceFile, name)) {
+                            // Found the parameter we are looking for consume white spaces
+                            pos = consumeWhiteSpaces(pos + name.length);
+                            if (pos >= end) {
+                                break;
+                            }
+
+                            let paramHelpString = "";
+                            let firstLineParamHelpStringPos = pos;
+                            while (pos < end) {
+                                let ch = sourceFile.text.charCodeAt(pos);
+
+                                // at line break, set this comment line text and go to next line 
+                                if (isLineBreak(ch)) {
+                                    if (paramHelpString) {
+                                        pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
+                                        paramHelpString = "";
+                                        blankLineCount = 0;
+                                        recordedParamTag = true;
+                                    }
+                                    else if (recordedParamTag) {
+                                        blankLineCount++;
+                                    }
+
+                                    // Get the pos after cleaning start of the line
+                                    setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos);
+                                    continue;
+                                }
+
+                                // Done scanning param help string - next tag found
+                                if (ch === CharacterCodes.at) {
+                                    break;
+                                }
+
+                                paramHelpString += sourceFile.text.charAt(pos);
+
+                                // Go to next character
+                                pos++;
+                            }
+
+                            // If there is param help text, add it top the doc comments
+                            if (paramHelpString) {
+                                pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
+                            }
+                            paramHelpStringMargin = undefined;
+                        }
+
+                        // If this is the start of another tag, continue with the loop in seach of param tag with symbol name
+                        if (sourceFile.text.charCodeAt(pos) === CharacterCodes.at) {
+                            continue;
+                        }
+                    }
+
+                    // Next character
+                    pos++;
+                }
+
+                return paramDocComments;
+
+                function consumeWhiteSpaces(pos: number) {
+                    while (pos < end && isWhiteSpace(sourceFile.text.charCodeAt(pos))) {
+                        pos++;
+                    }
+
+                    return pos;
+                }
+
+                function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos: number) {
+                    // Get the pos after consuming line breaks
+                    pos = consumeLineBreaks(pos, end, sourceFile);
+                    if (pos >= end) {
+                        return;
+                    }
+
+                    if (paramHelpStringMargin === undefined) {
+                        paramHelpStringMargin = sourceFile.getLineAndCharacterOfPosition(firstLineParamHelpStringPos).character;
+                    }
+
+                    // Now consume white spaces max 
+                    let startOfLinePos = pos;
+                    pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin);
+                    if (pos >= end) {
+                        return;
+                    }
+
+                    let consumedSpaces = pos - startOfLinePos;
+                    if (consumedSpaces < paramHelpStringMargin) {
+                        let ch = sourceFile.text.charCodeAt(pos);
+                        if (ch === CharacterCodes.asterisk) {
+                            // Consume more spaces after asterisk
+                            pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    class TypeObject implements Type {
+        checker: TypeChecker;
+        flags: TypeFlags;
+        id: number;
+        symbol: Symbol;
+        constructor(checker: TypeChecker, flags: TypeFlags) {
+            this.checker = checker;
+            this.flags = flags;
+        }
+        getFlags(): TypeFlags {
+            return this.flags;
+        }
+        getSymbol(): Symbol {
+            return this.symbol;
+        }
+        getProperties(): Symbol[] {
+            return this.checker.getPropertiesOfType(this);
+        }
+        getProperty(propertyName: string): Symbol {
+            return this.checker.getPropertyOfType(this, propertyName);
+        }
+        getApparentProperties(): Symbol[] {
+            return this.checker.getAugmentedPropertiesOfType(this);
+        }
+        getCallSignatures(): Signature[] {
+            return this.checker.getSignaturesOfType(this, SignatureKind.Call);
+        }
+        getConstructSignatures(): Signature[] {
+            return this.checker.getSignaturesOfType(this, SignatureKind.Construct);
+        }
+        getStringIndexType(): Type {
+            return this.checker.getIndexTypeOfType(this, IndexKind.String);
+        }
+        getNumberIndexType(): Type {
+            return this.checker.getIndexTypeOfType(this, IndexKind.Number);
+        }
+    }
+
+    class SignatureObject implements Signature {
+        checker: TypeChecker;
+        declaration: SignatureDeclaration;
+        typeParameters: TypeParameter[];
+        parameters: Symbol[];
+        resolvedReturnType: Type;
+        minArgumentCount: number;
+        hasRestParameter: boolean;
+        hasStringLiterals: boolean;
+
+        // Undefined is used to indicate the value has not been computed. If, after computing, the
+        // symbol has no doc comment, then the empty string will be returned.
+        documentationComment: SymbolDisplayPart[];
+
+        constructor(checker: TypeChecker) {
+            this.checker = checker;
+        }
+        getDeclaration(): SignatureDeclaration {
+            return this.declaration;
+        }
+        getTypeParameters(): Type[] {
+            return this.typeParameters;
+        }
+        getParameters(): Symbol[] {
+            return this.parameters;
+        }
+        getReturnType(): Type {
+            return this.checker.getReturnTypeOfSignature(this);
+        }
+
+        getDocumentationComment(): SymbolDisplayPart[] {
+            if (this.documentationComment === undefined) {
+                this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations(
+                    [this.declaration],
+                    /*name*/ undefined,
+                    /*canUseParsedParamTagComments*/ false) : [];
+            }
+
+            return this.documentationComment;
+        }
+    }
+
+    class SourceFileObject extends NodeObject implements SourceFile {
+        public _declarationBrand: any;
+        public fileName: string;
+        public text: string;
+        public scriptSnapshot: IScriptSnapshot;
+        public lineMap: number[];
+
+        public statements: NodeArray<Statement>;
+        public endOfFileToken: Node;
+
+        public amdDependencies: { name: string; path: string }[];
+        public amdModuleName: string;
+        public referencedFiles: FileReference[];
+
+        public syntacticDiagnostics: Diagnostic[];
+        public referenceDiagnostics: Diagnostic[];
+        public parseDiagnostics: Diagnostic[];
+        public bindDiagnostics: Diagnostic[];
+
+        public hasNoDefaultLib: boolean;
+        public externalModuleIndicator: Node; // The first node that causes this file to be an external module
+        public nodeCount: number;
+        public identifierCount: number;
+        public symbolCount: number;
+        public version: string;
+        public languageVersion: ScriptTarget;
+        public identifiers: Map<string>;
+        public nameTable: Map<string>;
+
+        private namedDeclarations: Map<Declaration[]>;
+
+        public update(newText: string, textChangeRange: TextChangeRange): SourceFile {
+            return updateSourceFile(<any>this, newText, textChangeRange);
+        }
+
+        public getLineAndCharacterOfPosition(position: number): LineAndCharacter {
+            return ts.getLineAndCharacterOfPosition(this, position);
+        }
+
+        public getLineStarts(): number[] {
+            return getLineStarts(this);
+        }
+
+        public getPositionOfLineAndCharacter(line: number, character: number): number {
+            return ts.getPositionOfLineAndCharacter(this, line, character);
+        }
+
+        public getNamedDeclarations(): Map<Declaration[]> {
+            if (!this.namedDeclarations) {
+                this.namedDeclarations = this.computeNamedDeclarations();
+            }
+
+            return this.namedDeclarations;
+        }
+
+        private computeNamedDeclarations(): Map<Declaration[]> {
+            let result: Map<Declaration[]> = {};
+
+            forEachChild(this, visit);
+
+            return result;
+
+            function addDeclaration(declaration: Declaration) {
+                let name = getDeclarationName(declaration);
+                if (name) {
+                    let declarations = getDeclarations(name);
+                    declarations.push(declaration);
+                }
+            }
+
+            function getDeclarations(name: string) {
+                return getProperty(result, name) || (result[name] = []);
+            }
+
+            function getDeclarationName(declaration: Declaration) {
+                if (declaration.name) {
+                    let result = getTextOfIdentifierOrLiteral(declaration.name);
+                    if (result !== undefined) {
+                        return result;
+                    }
+
+                    if (declaration.name.kind === SyntaxKind.ComputedPropertyName) {
+                        let expr = (<ComputedPropertyName>declaration.name).expression;
+                        if (expr.kind === SyntaxKind.PropertyAccessExpression) {
+                            return (<PropertyAccessExpression>expr).name.text;
+                        }
+
+                        return getTextOfIdentifierOrLiteral(expr);
+                    }
+                }
+
+                return undefined;
+            }
+
+            function getTextOfIdentifierOrLiteral(node: Node) {
+                if (node) {
+                    if (node.kind === SyntaxKind.Identifier ||
+                        node.kind === SyntaxKind.StringLiteral ||
+                        node.kind === SyntaxKind.NumericLiteral) {
+
+                        return (<Identifier | LiteralExpression>node).text;
+                    }
+                }
+
+                return undefined;
+            }
+
+            function visit(node: Node): void {
+                switch (node.kind) {
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                        let functionDeclaration = <FunctionLikeDeclaration>node;
+                        let declarationName = getDeclarationName(functionDeclaration);
+
+                        if (declarationName) {
+                            let declarations = getDeclarations(declarationName);
+                            let lastDeclaration = lastOrUndefined(declarations);
+
+                            // Check whether this declaration belongs to an "overload group".
+                            if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) {
+                                // Overwrite the last declaration if it was an overload
+                                // and this one is an implementation.
+                                if (functionDeclaration.body && !(<FunctionLikeDeclaration>lastDeclaration).body) {
+                                    declarations[declarations.length - 1] = functionDeclaration;
+                                }
+                            }
+                            else {
+                                declarations.push(functionDeclaration);
+                            }
+
+                            forEachChild(node, visit);
+                        }
+                        break;
+
+                    case SyntaxKind.ClassDeclaration:
+                    case SyntaxKind.InterfaceDeclaration:
+                    case SyntaxKind.TypeAliasDeclaration:
+                    case SyntaxKind.EnumDeclaration:
+                    case SyntaxKind.ModuleDeclaration:
+                    case SyntaxKind.ImportEqualsDeclaration:
+                    case SyntaxKind.ExportSpecifier:
+                    case SyntaxKind.ImportSpecifier:
+                    case SyntaxKind.ImportEqualsDeclaration:
+                    case SyntaxKind.ImportClause:
+                    case SyntaxKind.NamespaceImport:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.TypeLiteral:
+                        addDeclaration(<Declaration>node);
+                        // fall through
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.VariableStatement:
+                    case SyntaxKind.VariableDeclarationList:
+                    case SyntaxKind.ObjectBindingPattern:
+                    case SyntaxKind.ArrayBindingPattern:
+                    case SyntaxKind.ModuleBlock:
+                        forEachChild(node, visit);
+                        break;
+
+                    case SyntaxKind.Block:
+                        if (isFunctionBlock(node)) {
+                            forEachChild(node, visit);
+                        }
+                        break;
+
+                    case SyntaxKind.Parameter:
+                        // Only consider properties defined as constructor parameters
+                        if (!(node.flags & NodeFlags.AccessibilityModifier)) {
+                            break;
+                        }
+                    // fall through
+                    case SyntaxKind.VariableDeclaration:
+                    case SyntaxKind.BindingElement:
+                        if (isBindingPattern((<VariableDeclaration>node).name)) {
+                            forEachChild((<VariableDeclaration>node).name, visit);
+                            break;
+                        }
+                    case SyntaxKind.EnumMember:
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                        addDeclaration(<Declaration>node);
+                        break;
+
+                    case SyntaxKind.ExportDeclaration:
+                        // Handle named exports case e.g.:
+                        //    export {a, b as B} from "mod";
+                        if ((<ExportDeclaration>node).exportClause) {
+                            forEach((<ExportDeclaration>node).exportClause.elements, visit);
+                        }
+                        break;
+
+                    case SyntaxKind.ImportDeclaration:
+                        let importClause = (<ImportDeclaration>node).importClause;
+                        if (importClause) {
+                            // Handle default import case e.g.:
+                            //    import d from "mod";
+                            if (importClause.name) {
+                                addDeclaration(importClause);
+                            }
+
+                            // Handle named bindings in imports e.g.:
+                            //    import * as NS from "mod";
+                            //    import {a, b as B} from "mod";
+                            if (importClause.namedBindings) {
+                                if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
+                                    addDeclaration(<NamespaceImport>importClause.namedBindings);
+                                }
+                                else {
+                                    forEach((<NamedImports>importClause.namedBindings).elements, visit);
+                                }
+                            }
+                        }
+                        break;
+                }
+            }
+        }
+    }
+
+    //
+    // Public interface of the host of a language service instance.
+    //
+    export interface LanguageServiceHost {
+        getCompilationSettings(): CompilerOptions;
+        getNewLine?(): string;
+        getScriptFileNames(): string[];
+        getScriptVersion(fileName: string): string;
+        getScriptSnapshot(fileName: string): IScriptSnapshot;
+        getLocalizedDiagnosticMessages?(): any;
+        getCancellationToken?(): CancellationToken;
+        getCurrentDirectory(): string;
+        getDefaultLibFileName(options: CompilerOptions): string;
+        log? (s: string): void;
+        trace? (s: string): void;
+        error? (s: string): void;
+    }
+
+    //
+    // Public services of a language service instance associated
+    // with a language service host instance
+    //
+    export interface LanguageService {
+        cleanupSemanticCache(): void;
+
+        getSyntacticDiagnostics(fileName: string): Diagnostic[];
+        getSemanticDiagnostics(fileName: string): Diagnostic[];
+        getCompilerOptionsDiagnostics(): Diagnostic[];
+
+        getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
+        getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[];
+
+        getCompletionsAtPosition(fileName: string, position: number): CompletionInfo;
+        getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails;
+
+        getQuickInfoAtPosition(fileName: string, position: number): QuickInfo;
+
+        getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan;
+
+        getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan;
+
+        getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems;
+
+        getRenameInfo(fileName: string, position: number): RenameInfo;
+        findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[];
+
+        getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
+        getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
+        findReferences(fileName: string, position: number): ReferencedSymbol[];
+        getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[];
+
+        /** @deprecated */
+        getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
+
+        getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[];
+        getNavigationBarItems(fileName: string): NavigationBarItem[];
+
+        getOutliningSpans(fileName: string): OutliningSpan[];
+        getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
+        getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[];
+        getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
+
+        getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[];
+        getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[];
+        getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[];
+
+        getEmitOutput(fileName: string): EmitOutput;
+
+        getProgram(): Program;
+
+        getSourceFile(fileName: string): SourceFile;
+
+        dispose(): void;
+    }
+
+    export interface ClassifiedSpan {
+        textSpan: TextSpan;
+        classificationType: string; // ClassificationTypeNames
+    }
+
+    export interface NavigationBarItem {
+        text: string;
+        kind: string;
+        kindModifiers: string;
+        spans: TextSpan[];
+        childItems: NavigationBarItem[];
+        indent: number;
+        bolded: boolean;
+        grayed: boolean;
+    }
+
+    export interface TodoCommentDescriptor {
+        text: string;
+        priority: number;
+    }
+
+    export interface TodoComment {
+        descriptor: TodoCommentDescriptor;
+        message: string;
+        position: number;
+    }
+
+    export class TextChange {
+        span: TextSpan;
+        newText: string;
+    }
+
+    export interface RenameLocation {
+        textSpan: TextSpan;
+        fileName: string;
+    }
+
+    export interface ReferenceEntry {
+        textSpan: TextSpan;
+        fileName: string;
+        isWriteAccess: boolean;
+    }
+
+    export interface DocumentHighlights {
+        fileName: string;
+        highlightSpans: HighlightSpan[];
+    }
+
+    export module HighlightSpanKind {
+        export const none = "none";
+        export const definition = "definition";
+        export const reference = "reference";
+        export const writtenReference = "writtenReference";
+    } 
+
+    export interface HighlightSpan {
+        textSpan: TextSpan;
+        kind: string;
+    }
+
+    export interface NavigateToItem {
+        name: string;
+        kind: string;
+        kindModifiers: string;
+        matchKind: string;
+        isCaseSensitive: boolean;
+        fileName: string;
+        textSpan: TextSpan;
+        containerName: string;
+        containerKind: string;
+    }
+
+    export interface EditorOptions {
+        IndentSize: number;
+        TabSize: number;
+        NewLineCharacter: string;
+        ConvertTabsToSpaces: boolean;
+    }
+
+    export interface FormatCodeOptions extends EditorOptions {
+        InsertSpaceAfterCommaDelimiter: boolean;
+        InsertSpaceAfterSemicolonInForStatements: boolean;
+        InsertSpaceBeforeAndAfterBinaryOperators: boolean;
+        InsertSpaceAfterKeywordsInControlFlowStatements: boolean;
+        InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean;
+        InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean;
+        PlaceOpenBraceOnNewLineForFunctions: boolean;
+        PlaceOpenBraceOnNewLineForControlBlocks: boolean;
+        [s: string]: boolean | number| string;
+    }
+
+    export interface DefinitionInfo {
+        fileName: string;
+        textSpan: TextSpan;
+        kind: string;
+        name: string;
+        containerKind: string;
+        containerName: string;
+    }
+
+    export interface ReferencedSymbol {
+        definition: DefinitionInfo;
+        references: ReferenceEntry[];
+    }
+
+    export enum SymbolDisplayPartKind {
+        aliasName,
+        className,
+        enumName,
+        fieldName,
+        interfaceName,
+        keyword,
+        lineBreak,
+        numericLiteral,
+        stringLiteral,
+        localName,
+        methodName,
+        moduleName,
+        operator,
+        parameterName,
+        propertyName,
+        punctuation,
+        space,
+        text,
+        typeParameterName,
+        enumMemberName,
+        functionName,
+        regularExpressionLiteral,
+    }
+
+    export interface SymbolDisplayPart {
+        text: string;
+        kind: string;
+    }
+
+    export interface QuickInfo {
+        kind: string;
+        kindModifiers: string;
+        textSpan: TextSpan;
+        displayParts: SymbolDisplayPart[];
+        documentation: SymbolDisplayPart[];
+    }
+
+    export interface RenameInfo {
+        canRename: boolean;
+        localizedErrorMessage: string;
+        displayName: string;
+        fullDisplayName: string;
+        kind: string;
+        kindModifiers: string;
+        triggerSpan: TextSpan;
+    }
+
+    export interface SignatureHelpParameter {
+        name: string;
+        documentation: SymbolDisplayPart[];
+        displayParts: SymbolDisplayPart[];
+        isOptional: boolean;
+    }
+
+    /**
+     * Represents a single signature to show in signature help.
+     * The id is used for subsequent calls into the language service to ask questions about the
+     * signature help item in the context of any documents that have been updated.  i.e. after
+     * an edit has happened, while signature help is still active, the host can ask important 
+     * questions like 'what parameter is the user currently contained within?'.
+     */
+    export interface SignatureHelpItem {
+        isVariadic: boolean;
+        prefixDisplayParts: SymbolDisplayPart[];
+        suffixDisplayParts: SymbolDisplayPart[];
+        separatorDisplayParts: SymbolDisplayPart[];
+        parameters: SignatureHelpParameter[];
+        documentation: SymbolDisplayPart[];
+    }
+
+    /**
+     * Represents a set of signature help items, and the preferred item that should be selected.
+     */
+    export interface SignatureHelpItems {
+        items: SignatureHelpItem[];
+        applicableSpan: TextSpan;
+        selectedItemIndex: number;
+        argumentIndex: number;
+        argumentCount: number;
+    }
+
+    export interface CompletionInfo {
+        isMemberCompletion: boolean;
+        isNewIdentifierLocation: boolean;  // true when the current location also allows for a new identifier
+        entries: CompletionEntry[];
+    }
+
+    export interface CompletionEntry {
+        name: string;
+        kind: string;            // see ScriptElementKind
+        kindModifiers: string;   // see ScriptElementKindModifier, comma separated
+        sortText: string;
+    }
+
+    export interface CompletionEntryDetails {
+        name: string;
+        kind: string;            // see ScriptElementKind
+        kindModifiers: string;   // see ScriptElementKindModifier, comma separated
+        displayParts: SymbolDisplayPart[];
+        documentation: SymbolDisplayPart[];
+    }
+
+    export interface OutliningSpan {
+        /** The span of the document to actually collapse. */
+        textSpan: TextSpan;
+
+        /** The span of the document to display when the user hovers over the collapsed span. */
+        hintSpan: TextSpan;
+
+        /** The text to display in the editor for the collapsed region. */
+        bannerText: string;
+
+        /** 
+          * Whether or not this region should be automatically collapsed when 
+          * the 'Collapse to Definitions' command is invoked.
+          */
+        autoCollapse: boolean;
+    }
+
+    export interface EmitOutput {
+        outputFiles: OutputFile[];
+        emitSkipped: boolean;
+    }
+
+    export const enum OutputFileType {
+        JavaScript,
+        SourceMap,
+        Declaration
+    }
+
+    export interface OutputFile {
+        name: string;
+        writeByteOrderMark: boolean;
+        text: string;
+    }
+
+    export const enum EndOfLineState {
+        Start,
+        InMultiLineCommentTrivia,
+        InSingleQuoteStringLiteral,
+        InDoubleQuoteStringLiteral,
+        InTemplateHeadOrNoSubstitutionTemplate,
+        InTemplateMiddleOrTail,
+        InTemplateSubstitutionPosition,
+    }
+
+    export enum TokenClass {
+        Punctuation,
+        Keyword,
+        Operator,
+        Comment,
+        Whitespace,
+        Identifier,
+        NumberLiteral,
+        StringLiteral,
+        RegExpLiteral,
+    }
+
+    export interface ClassificationResult {
+        finalLexState: EndOfLineState;
+        entries: ClassificationInfo[];
+    }
+
+    export interface ClassificationInfo {
+        length: number;
+        classification: TokenClass;
+    }
+
+    export interface Classifier {
+        /**
+         * Gives lexical classifications of tokens on a line without any syntactic context.
+         * For instance, a token consisting of the text 'string' can be either an identifier
+         * named 'string' or the keyword 'string', however, because this classifier is not aware,
+         * it relies on certain heuristics to give acceptable results. For classifications where
+         * speed trumps accuracy, this function is preferable; however, for true accuracy, the
+         * syntactic classifier is ideal. In fact, in certain editing scenarios, combining the
+         * lexical, syntactic, and semantic classifiers may issue the best user experience.
+         *
+         * @param text                      The text of a line to classify.
+         * @param lexState                  The state of the lexical classifier at the end of the previous line.
+         * @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier.
+         *                                  If there is no syntactic classifier (syntacticClassifierAbsent=true),
+         *                                  certain heuristics may be used in its place; however, if there is a
+         *                                  syntactic classifier (syntacticClassifierAbsent=false), certain
+         *                                  classifications which may be incorrectly categorized will be given
+         *                                  back as Identifiers in order to allow the syntactic classifier to
+         *                                  subsume the classification.
+         */
+        getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult;
+    }
+
+    /**
+      * The document registry represents a store of SourceFile objects that can be shared between 
+      * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)
+      * of files in the context. 
+      * SourceFile objects account for most of the memory usage by the language service. Sharing 
+      * the same DocumentRegistry instance between different instances of LanguageService allow 
+      * for more efficient memory utilization since all projects will share at least the library 
+      * file (lib.d.ts).
+      *
+      * A more advanced use of the document registry is to serialize sourceFile objects to disk 
+      * and re-hydrate them when needed.
+      *
+      * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it 
+      * to all subsequent createLanguageService calls.
+      */
+    export interface DocumentRegistry {
+        /**
+          * Request a stored SourceFile with a given fileName and compilationSettings.
+          * The first call to acquire will call createLanguageServiceSourceFile to generate
+          * the SourceFile if was not found in the registry.
+          *
+          * @param fileName The name of the file requested
+          * @param compilationSettings Some compilation settings like target affects the 
+          * shape of a the resulting SourceFile. This allows the DocumentRegistry to store
+          * multiple copies of the same file for different compilation settings.
+          * @parm scriptSnapshot Text of the file. Only used if the file was not found
+          * in the registry and a new one was created.
+          * @parm version Current version of the file. Only used if the file was not found
+          * in the registry and a new one was created.
+          */
+        acquireDocument(
+            fileName: string,
+            compilationSettings: CompilerOptions,
+            scriptSnapshot: IScriptSnapshot,
+            version: string): SourceFile;
+
+        /**
+          * Request an updated version of an already existing SourceFile with a given fileName
+          * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile
+          * to get an updated SourceFile.
+          *
+          * @param fileName The name of the file requested
+          * @param compilationSettings Some compilation settings like target affects the 
+          * shape of a the resulting SourceFile. This allows the DocumentRegistry to store
+          * multiple copies of the same file for different compilation settings.
+          * @param scriptSnapshot Text of the file. 
+          * @param version Current version of the file.
+          */
+        updateDocument(
+            fileName: string,
+            compilationSettings: CompilerOptions,
+            scriptSnapshot: IScriptSnapshot,
+            version: string): SourceFile;
+
+        /**
+          * Informs the DocumentRegistry that a file is not needed any longer.
+          *
+          * Note: It is not allowed to call release on a SourceFile that was not acquired from
+          * this registry originally.
+          *
+          * @param fileName The name of the file to be released
+          * @param compilationSettings The compilation settings used to acquire the file
+          */
+        releaseDocument(fileName: string, compilationSettings: CompilerOptions): void
+    }
+
+    // TODO: move these to enums
+    export module ScriptElementKind {
+        export const unknown = "";
+        export const warning = "warning";
+
+        // predefined type (void) or keyword (class)
+        export const keyword = "keyword";
+
+        // top level script node
+        export const scriptElement = "script";
+
+        // module foo {}
+        export const moduleElement = "module";
+
+        // class X {}
+        export const classElement = "class";
+
+        // interface Y {}
+        export const interfaceElement = "interface";
+
+        // type T = ...
+        export const typeElement = "type";
+
+        // enum E
+        export const enumElement = "enum";
+
+        // Inside module and script only
+        // let v = ..
+        export const variableElement = "var";
+
+        // Inside function
+        export const localVariableElement = "local var";
+
+        // Inside module and script only
+        // function f() { }
+        export const functionElement = "function";
+
+        // Inside function
+        export const localFunctionElement = "local function";
+
+        // class X { [public|private]* foo() {} }
+        export const memberFunctionElement = "method";
+
+        // class X { [public|private]* [get|set] foo:number; }
+        export const memberGetAccessorElement = "getter";
+        export const memberSetAccessorElement = "setter";
+
+        // class X { [public|private]* foo:number; }
+        // interface Y { foo:number; }
+        export const memberVariableElement = "property";
+
+        // class X { constructor() { } }
+        export const constructorImplementationElement = "constructor";
+
+        // interface Y { ():number; }
+        export const callSignatureElement = "call";
+
+        // interface Y { []:number; }
+        export const indexSignatureElement = "index";
+
+        // interface Y { new():Y; }
+        export const constructSignatureElement = "construct";
+
+        // function foo(*Y*: string)
+        export const parameterElement = "parameter";
+
+        export const typeParameterElement = "type parameter";
+
+        export const primitiveType = "primitive type";
+
+        export const label = "label";
+
+        export const alias = "alias";
+
+        export const constElement = "const";
+
+        export const letElement = "let";
+    }
+
+    export module ScriptElementKindModifier {
+        export const none = "";
+        export const publicMemberModifier = "public";
+        export const privateMemberModifier = "private";
+        export const protectedMemberModifier = "protected";
+        export const exportedModifier = "export";
+        export const ambientModifier = "declare";
+        export const staticModifier = "static";
+    }
+
+    export class ClassificationTypeNames {
+        public static comment = "comment";
+        public static identifier = "identifier";
+        public static keyword = "keyword";
+        public static numericLiteral = "number";
+        public static operator = "operator";
+        public static stringLiteral = "string";
+        public static whiteSpace = "whitespace";
+        public static text = "text";
+
+        public static punctuation = "punctuation";
+
+        public static className = "class name";
+        public static enumName = "enum name";
+        public static interfaceName = "interface name";
+        public static moduleName = "module name";
+        public static typeParameterName = "type parameter name";
+        public static typeAlias = "type alias name";
+    }
+
+    /// Language Service
+
+    interface FormattingOptions {
+        useTabs: boolean;
+        spacesPerTab: number;
+        indentSpaces: number;
+        newLineCharacter: string;
+    }
+
+    // Information about a specific host file.
+    interface HostFileInformation {
+        hostFileName: string;
+        version: string;
+        scriptSnapshot: IScriptSnapshot;
+    }
+
+    interface DocumentRegistryEntry {
+        sourceFile: SourceFile;
+
+        // The number of language services that this source file is referenced in.   When no more
+        // language services are referencing the file, then the file can be removed from the 
+        // registry.
+        languageServiceRefCount: number;
+        owners: string[];
+    }
+
+    export interface DisplayPartsSymbolWriter extends SymbolWriter {
+        displayParts(): SymbolDisplayPart[];
+    }
+
+    export function displayPartsToString(displayParts: SymbolDisplayPart[]) {
+        if (displayParts) {
+            return map(displayParts, displayPart => displayPart.text).join("");
+        }
+
+        return "";
+    }
+
+    function isLocalVariableOrFunction(symbol: Symbol) {
+        if (symbol.parent) {
+            return false; // This is exported symbol
+        }
+
+        return ts.forEach(symbol.declarations, declaration => {
+            // Function expressions are local
+            if (declaration.kind === SyntaxKind.FunctionExpression) {
+                return true;
+            }
+
+            if (declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.FunctionDeclaration) {
+                return false;
+            }
+
+            // If the parent is not sourceFile or module block it is local variable
+            for (let parent = declaration.parent; !isFunctionBlock(parent); parent = parent.parent) {
+                // Reached source file or module block
+                if (parent.kind === SyntaxKind.SourceFile || parent.kind === SyntaxKind.ModuleBlock) {
+                    return false;
+                }
+            }
+
+            // parent is in function block
+            return true;
+        });
+    }
+
+    export function getDefaultCompilerOptions(): CompilerOptions {
+        // Always default to "ScriptTarget.ES5" for the language service
+        return {
+            target: ScriptTarget.ES5,
+            module: ModuleKind.None,
+        };
+    }
+
+    export class OperationCanceledException { }
+
+    export class CancellationTokenObject {
+
+        public static None: CancellationTokenObject = new CancellationTokenObject(null)
+
+        constructor(private cancellationToken: CancellationToken) {
+        }
+
+        public isCancellationRequested() {
+            return this.cancellationToken && this.cancellationToken.isCancellationRequested();
+        }
+
+        public throwIfCancellationRequested(): void {
+            if (this.isCancellationRequested()) {
+                throw new OperationCanceledException();
+            }
+        }
+    }
+
+    // Cache host information about scrip Should be refreshed 
+    // at each language service public entry point, since we don't know when 
+    // set of scripts handled by the host changes.
+    class HostCache {
+        private fileNameToEntry: Map<HostFileInformation>;
+        private _compilationSettings: CompilerOptions;
+
+        constructor(private host: LanguageServiceHost) {
+            // script id => script index
+            this.fileNameToEntry = {};
+
+            // Initialize the list with the root file names
+            let rootFileNames = host.getScriptFileNames();
+            for (let fileName of rootFileNames) {
+                this.createEntry(fileName);
+            }
+
+            // store the compilation settings
+            this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
+        }
+
+        public compilationSettings() {
+            return this._compilationSettings;
+        }
+
+        private createEntry(fileName: string) {
+            let entry: HostFileInformation;
+            let scriptSnapshot = this.host.getScriptSnapshot(fileName);
+            if (scriptSnapshot) {
+                entry = {
+                    hostFileName: fileName,
+                    version: this.host.getScriptVersion(fileName),
+                    scriptSnapshot: scriptSnapshot
+                };
+            }
+
+            return this.fileNameToEntry[normalizeSlashes(fileName)] = entry;
+        }
+
+        public getEntry(fileName: string): HostFileInformation {
+            return lookUp(this.fileNameToEntry, normalizeSlashes(fileName));
+        }
+
+        public contains(fileName: string): boolean {
+            return hasProperty(this.fileNameToEntry, normalizeSlashes(fileName));
+        }
+
+        public getOrCreateEntry(fileName: string): HostFileInformation {
+            if (this.contains(fileName)) {
+                return this.getEntry(fileName);
+            }
+
+            return this.createEntry(fileName);
+        }
+
+        public getRootFileNames(): string[] {
+            let fileNames: string[] = [];
+
+            forEachKey(this.fileNameToEntry, key => {
+                if (hasProperty(this.fileNameToEntry, key) && this.fileNameToEntry[key])
+                    fileNames.push(key);
+            });
+
+            return fileNames;
+        }
+
+        public getVersion(fileName: string): string {
+            let file = this.getEntry(fileName);
+            return file && file.version;
+        }
+
+        public getScriptSnapshot(fileName: string): IScriptSnapshot {
+            let file = this.getEntry(fileName);
+            return file && file.scriptSnapshot;
+        }
+    }
+
+    class SyntaxTreeCache {
+        // For our syntactic only features, we also keep a cache of the syntax tree for the 
+        // currently edited file.  
+        private currentFileName: string;
+        private currentFileVersion: string;
+        private currentFileScriptSnapshot: IScriptSnapshot;
+        private currentSourceFile: SourceFile;
+
+        constructor(private host: LanguageServiceHost) {
+        }
+
+        public getCurrentSourceFile(fileName: string): SourceFile {
+            let scriptSnapshot = this.host.getScriptSnapshot(fileName);
+            if (!scriptSnapshot) {
+                // The host does not know about this file.
+                throw new Error("Could not find file: '" + fileName + "'.");
+            }
+
+            let version = this.host.getScriptVersion(fileName);
+            let sourceFile: SourceFile;
+
+            if (this.currentFileName !== fileName) {
+                // This is a new file, just parse it
+                sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true);
+            }
+            else if (this.currentFileVersion !== version) {
+                // This is the same file, just a newer version. Incrementally parse the file.
+                let editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
+                sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
+            }
+
+            if (sourceFile) {
+                // All done, ensure state is up to date
+                this.currentFileVersion = version;
+                this.currentFileName = fileName;
+                this.currentFileScriptSnapshot = scriptSnapshot;
+                this.currentSourceFile = sourceFile;
+            }
+
+            return this.currentSourceFile;
+        }
+    }
+
+    function setSourceFileFields(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string) {
+        sourceFile.version = version;
+        sourceFile.scriptSnapshot = scriptSnapshot;
+    }
+
+    /*
+     * This function will compile source text from 'input' argument using specified compiler options.
+     * If not options are provided - it will use a set of default compiler options.
+     * Extra compiler options that will unconditionally be used bu this function are:
+     * - separateCompilation = true
+     * - allowNonTsExtensions = true
+     */
+    export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[]): string {
+        let options = compilerOptions ? clone(compilerOptions) : getDefaultCompilerOptions();
+
+        options.separateCompilation = true;
+
+        // Filename can be non-ts file.
+        options.allowNonTsExtensions = true;
+
+        // Parse
+        var inputFileName = fileName || "module.ts";
+        var sourceFile = createSourceFile(inputFileName, input, options.target);
+
+        // Store syntactic diagnostics
+        if (diagnostics && sourceFile.parseDiagnostics) {
+            diagnostics.push(...sourceFile.parseDiagnostics);
+        }
+
+        // Output
+        let outputText: string;
+
+        // Create a compilerHost object to allow the compiler to read and write files
+        var compilerHost: CompilerHost = {
+            getSourceFile: (fileName, target) => fileName === inputFileName ? sourceFile : undefined,
+            writeFile: (name, text, writeByteOrderMark) => {
+                Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: " + name);
+                outputText = text;
+            },
+            getDefaultLibFileName: () => "lib.d.ts",
+            useCaseSensitiveFileNames: () => false,
+            getCanonicalFileName: fileName => fileName,
+            getCurrentDirectory: () => "",
+            getNewLine: () => (sys && sys.newLine) || "\r\n"
+        };
+
+        var program = createProgram([inputFileName], options, compilerHost);
+
+        if (diagnostics) {
+            diagnostics.push(...program.getGlobalDiagnostics());
+        }
+
+        // Emit
+        program.emit();
+
+        Debug.assert(outputText !== undefined, "Output generation failed");
+
+        return outputText;
+    }
+
+    export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile {
+        let sourceFile = createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), scriptTarget, setNodeParents);
+        setSourceFileFields(sourceFile, scriptSnapshot, version);
+        // after full parsing we can use table with interned strings as name table
+        sourceFile.nameTable = sourceFile.identifiers;
+        return sourceFile;
+    }
+
+    export let disableIncrementalParsing = false;
+
+    export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
+        // If we were given a text change range, and our version or open-ness changed, then 
+        // incrementally parse this file.
+        if (textChangeRange) {
+            if (version !== sourceFile.version) {
+                // Once incremental parsing is ready, then just call into this function.
+                if (!disableIncrementalParsing) {
+                    let newSourceFile = updateSourceFile(sourceFile, scriptSnapshot.getText(0, scriptSnapshot.getLength()), textChangeRange, aggressiveChecks);
+                    setSourceFileFields(newSourceFile, scriptSnapshot, version);
+                    // after incremental parsing nameTable might not be up-to-date
+                    // drop it so it can be lazily recreated later
+                    newSourceFile.nameTable = undefined;
+                    return newSourceFile;
+                }
+            }
+        }
+
+        // Otherwise, just create a new source file.
+        return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true);
+    }
+
+    export function createDocumentRegistry(): DocumentRegistry {
+        // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
+        // for those settings.
+        let buckets: Map<Map<DocumentRegistryEntry>> = {};
+
+        function getKeyFromCompilationSettings(settings: CompilerOptions): string {
+            return "_" + settings.target; //  + "|" + settings.propagateEnumConstantoString()
+        }
+
+        function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): Map<DocumentRegistryEntry> {
+            let key = getKeyFromCompilationSettings(settings);
+            let bucket = lookUp(buckets, key);
+            if (!bucket && createIfMissing) {
+                buckets[key] = bucket = {};
+            }
+            return bucket;
+        }
+
+        function reportStats() {
+            let bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => {
+                let entries = lookUp(buckets, name);
+                let sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
+                for (let i in entries) {
+                    let entry = entries[i];
+                    sourceFiles.push({
+                        name: i,
+                        refCount: entry.languageServiceRefCount,
+                        references: entry.owners.slice(0)
+                    });
+                }
+                sourceFiles.sort((x, y) => y.refCount - x.refCount);
+                return {
+                    bucket: name,
+                    sourceFiles
+                };
+            });
+            return JSON.stringify(bucketInfoArray, null, 2);
+        }
+
+        function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile {
+            return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ true);
+        }
+
+        function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile {
+            return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ false);
+        }
+
+        function acquireOrUpdateDocument(
+            fileName: string,
+            compilationSettings: CompilerOptions,
+            scriptSnapshot: IScriptSnapshot,
+            version: string,
+            acquiring: boolean): SourceFile {
+
+            let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
+            let entry = lookUp(bucket, fileName);
+            if (!entry) {
+                Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
+
+                // Have never seen this file with these settings.  Create a new source file for it.
+                let sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false);
+
+                bucket[fileName] = entry = {
+                    sourceFile: sourceFile,
+                    languageServiceRefCount: 0,
+                    owners: []
+                };
+            }
+            else {
+                // We have an entry for this file.  However, it may be for a different version of 
+                // the script snapshot.  If so, update it appropriately.  Otherwise, we can just
+                // return it as is.
+                if (entry.sourceFile.version !== version) {
+                    entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
+                        scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
+                }
+            }
+
+            // If we're acquiring, then this is the first time this LS is asking for this document.
+            // Increase our ref count so we know there's another LS using the document.  If we're
+            // not acquiring, then that means the LS is 'updating' the file instead, and that means
+            // it has already acquired the document previously.  As such, we do not need to increase
+            // the ref count.
+            if (acquiring) {
+                entry.languageServiceRefCount++;
+            }
+
+            return entry.sourceFile;
+        }
+
+        function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void {
+            let bucket = getBucketForCompilationSettings(compilationSettings, false);
+            Debug.assert(bucket !== undefined);
+
+            let entry = lookUp(bucket, fileName);
+            entry.languageServiceRefCount--;
+
+            Debug.assert(entry.languageServiceRefCount >= 0);
+            if (entry.languageServiceRefCount === 0) {
+                delete bucket[fileName];
+            }
+        }
+
+        return {
+            acquireDocument,
+            updateDocument,
+            releaseDocument,
+            reportStats
+        };
+    }
+
+    export function preProcessFile(sourceText: string, readImportFiles = true): PreProcessedFileInfo {
+        let referencedFiles: FileReference[] = [];
+        let importedFiles: FileReference[] = [];
+        let isNoDefaultLib = false;
+
+        function processTripleSlashDirectives(): void {
+            let commentRanges = getLeadingCommentRanges(sourceText, 0);
+            forEach(commentRanges, commentRange => {
+                let comment = sourceText.substring(commentRange.pos, commentRange.end);
+                let referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange);
+                if (referencePathMatchResult) {
+                    isNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
+                    let fileReference = referencePathMatchResult.fileReference;
+                    if (fileReference) {
+                        referencedFiles.push(fileReference);
+                    }
+                }
+            });
+        }
+
+        function recordModuleName() {
+            let importPath = scanner.getTokenValue();
+            let pos = scanner.getTokenPos();
+            importedFiles.push({
+                fileName: importPath,
+                pos: pos,
+                end: pos + importPath.length
+            });
+        }
+
+        function processImport(): void {
+            scanner.setText(sourceText);
+            let token = scanner.scan();
+            // Look for:
+            //    import "mod";
+            //    import d from "mod"
+            //    import {a as A } from "mod";
+            //    import * as NS  from "mod"
+            //    import d, {a, b as B} from "mod"
+            //    import i = require("mod");
+            //
+            //    export * from "mod"
+            //    export {a as b} from "mod"
+
+            while (token !== SyntaxKind.EndOfFileToken) {
+                if (token === SyntaxKind.ImportKeyword) {
+                    token = scanner.scan();
+                    if (token === SyntaxKind.StringLiteral) {
+                        // import "mod";
+                        recordModuleName();
+                        continue;
+                    }
+                    else {
+                        if (token === SyntaxKind.Identifier) {
+                            token = scanner.scan();
+                            if (token === SyntaxKind.FromKeyword) {
+                                token = scanner.scan();
+                                if (token === SyntaxKind.StringLiteral) {
+                                    // import d from "mod";
+                                    recordModuleName();
+                                    continue
+                                }
+                            }
+                            else if (token === SyntaxKind.EqualsToken) {
+                                token = scanner.scan();
+                                if (token === SyntaxKind.RequireKeyword) {
+                                    token = scanner.scan();
+                                    if (token === SyntaxKind.OpenParenToken) {
+                                        token = scanner.scan();
+                                        if (token === SyntaxKind.StringLiteral) {
+                                            //  import i = require("mod");
+                                            recordModuleName();
+                                            continue;
+                                        }
+                                    }
+                                }
+                            }
+                            else if (token === SyntaxKind.CommaToken) {
+                                // consume comma and keep going
+                                token = scanner.scan();
+                            }
+                            else {
+                                // unknown syntax
+                                continue;
+                            }
+                        }
+
+                        if (token === SyntaxKind.OpenBraceToken) {
+                            token = scanner.scan();
+                            // consume "{ a as B, c, d as D}" clauses
+                            while (token !== SyntaxKind.CloseBraceToken) {
+                                token = scanner.scan();
+                            }
+
+                            if (token === SyntaxKind.CloseBraceToken) {
+                                token = scanner.scan();
+                                if (token === SyntaxKind.FromKeyword) {
+                                    token = scanner.scan();
+                                    if (token === SyntaxKind.StringLiteral) {
+                                        // import {a as A} from "mod";
+                                        // import d, {a, b as B} from "mod"
+                                        recordModuleName();
+                                    }
+                                }
+                            }
+                        }
+                        else if (token === SyntaxKind.AsteriskToken) {
+                            token = scanner.scan();
+                            if (token === SyntaxKind.AsKeyword) {
+                                token = scanner.scan();
+                                if (token === SyntaxKind.Identifier) {
+                                    token = scanner.scan();
+                                    if (token === SyntaxKind.FromKeyword) {
+                                        token = scanner.scan();
+                                        if (token === SyntaxKind.StringLiteral) {
+                                            // import * as NS from "mod"
+                                            // import d, * as NS from "mod"
+                                            recordModuleName();
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                else if (token === SyntaxKind.ExportKeyword) {
+                    token = scanner.scan();
+                    if (token === SyntaxKind.OpenBraceToken) {
+                        token = scanner.scan();
+                        // consume "{ a as B, c, d as D}" clauses
+                        while (token !== SyntaxKind.CloseBraceToken) {
+                            token = scanner.scan();
+                        }
+
+                        if (token === SyntaxKind.CloseBraceToken) {
+                            token = scanner.scan();
+                            if (token === SyntaxKind.FromKeyword) {
+                                token = scanner.scan();
+                                if (token === SyntaxKind.StringLiteral) {
+                                    // export {a as A} from "mod";
+                                    // export {a, b as B} from "mod"
+                                    recordModuleName();
+                                }
+                            }
+                        }
+                    }
+                    else if (token === SyntaxKind.AsteriskToken) {
+                        token = scanner.scan();
+                        if (token === SyntaxKind.FromKeyword) {
+                            token = scanner.scan();
+                            if (token === SyntaxKind.StringLiteral) {
+                                // export * from "mod"
+                                recordModuleName();
+                            }
+                        }
+                    }
+                }
+                token = scanner.scan();
+            }
+            scanner.setText(undefined);
+        }
+
+        if (readImportFiles) {
+            processImport();
+        }
+        processTripleSlashDirectives();
+        return { referencedFiles, importedFiles, isLibFile: isNoDefaultLib };
+    }
+
+    /// Helpers
+    function getTargetLabel(referenceNode: Node, labelName: string): Identifier {
+        while (referenceNode) {
+            if (referenceNode.kind === SyntaxKind.LabeledStatement && (<LabeledStatement>referenceNode).label.text === labelName) {
+                return (<LabeledStatement>referenceNode).label;
+            }
+            referenceNode = referenceNode.parent;
+        }
+        return undefined;
+    }
+
+    function isJumpStatementTarget(node: Node): boolean {
+        return node.kind === SyntaxKind.Identifier &&
+            (node.parent.kind === SyntaxKind.BreakStatement || node.parent.kind === SyntaxKind.ContinueStatement) &&
+            (<BreakOrContinueStatement>node.parent).label === node;
+    }
+
+    function isLabelOfLabeledStatement(node: Node): boolean {
+        return node.kind === SyntaxKind.Identifier &&
+            node.parent.kind === SyntaxKind.LabeledStatement &&
+            (<LabeledStatement>node.parent).label === node;
+    }
+
+    /**
+     * Whether or not a 'node' is preceded by a label of the given string.
+     * Note: 'node' cannot be a SourceFile.
+     */
+    function isLabeledBy(node: Node, labelName: string) {
+        for (let owner = node.parent; owner.kind === SyntaxKind.LabeledStatement; owner = owner.parent) {
+            if ((<LabeledStatement>owner).label.text === labelName) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    function isLabelName(node: Node): boolean {
+        return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node);
+    }
+
+    function isRightSideOfQualifiedName(node: Node) {
+        return node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node;
+    }
+
+    function isRightSideOfPropertyAccess(node: Node) {
+        return node && node.parent && node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node;
+    }
+
+    function isCallExpressionTarget(node: Node): boolean {
+        if (isRightSideOfPropertyAccess(node)) {
+            node = node.parent;
+        }
+        return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).expression === node;
+    }
+
+    function isNewExpressionTarget(node: Node): boolean {
+        if (isRightSideOfPropertyAccess(node)) {
+            node = node.parent;
+        }
+        return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (<CallExpression>node.parent).expression === node;
+    }
+
+    function isNameOfModuleDeclaration(node: Node) {
+        return node.parent.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node.parent).name === node;
+    }
+
+    function isNameOfFunctionDeclaration(node: Node): boolean {
+        return node.kind === SyntaxKind.Identifier &&
+            isFunctionLike(node.parent) && (<FunctionLikeDeclaration>node.parent).name === node;
+    }
+
+    /** Returns true if node is a name of an object literal property, e.g. "a" in x = { "a": 1 } */
+    function isNameOfPropertyAssignment(node: Node): boolean {
+        return (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) &&
+            (node.parent.kind === SyntaxKind.PropertyAssignment || node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) && (<PropertyDeclaration>node.parent).name === node;
+    }
+
+    function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: Node): boolean {
+        if (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) {
+            switch (node.parent.kind) {
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.PropertyAssignment:
+                case SyntaxKind.EnumMember:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.ModuleDeclaration:
+                    return (<Declaration>node.parent).name === node;
+                case SyntaxKind.ElementAccessExpression:
+                    return (<ElementAccessExpression>node.parent).argumentExpression === node;
+            }
+        }
+
+        return false;
+    }
+
+    function isNameOfExternalModuleImportOrDeclaration(node: Node): boolean {
+        if (node.kind === SyntaxKind.StringLiteral) {
+            return isNameOfModuleDeclaration(node) ||
+                (isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node);
+        }
+
+        return false;
+    }
+
+    /** Returns true if the position is within a comment */
+    function isInsideComment(sourceFile: SourceFile, token: Node, position: number): boolean {
+        // The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment
+        return position <= token.getStart(sourceFile) &&
+            (isInsideCommentRange(getTrailingCommentRanges(sourceFile.text, token.getFullStart())) ||
+                isInsideCommentRange(getLeadingCommentRanges(sourceFile.text, token.getFullStart())));
+
+        function isInsideCommentRange(comments: CommentRange[]): boolean {
+            return forEach(comments, comment => {
+                // either we are 1. completely inside the comment, or 2. at the end of the comment
+                if (comment.pos < position && position < comment.end) {
+                    return true;
+                }
+                else if (position === comment.end) {
+                    let text = sourceFile.text;
+                    let width = comment.end - comment.pos;
+                    // is single line comment or just /*
+                    if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) {
+                        return true;
+                    }
+                    else {
+                        // is unterminated multi-line comment
+                        return !(text.charCodeAt(comment.end - 1) === CharacterCodes.slash &&
+                            text.charCodeAt(comment.end - 2) === CharacterCodes.asterisk);
+                    }
+                }
+                return false;
+            });
+        }
+    }
+
+    const enum SemanticMeaning {
+        None = 0x0,
+        Value = 0x1,
+        Type = 0x2,
+        Namespace = 0x4,
+        All = Value | Type | Namespace
+    }
+
+    const enum BreakContinueSearchType {
+        None = 0x0,
+        Unlabeled = 0x1,
+        Labeled = 0x2,
+        All = Unlabeled | Labeled
+    }
+
+    // A cache of completion entries for keywords, these do not change between sessions
+    let keywordCompletions: CompletionEntry[] = [];
+    for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
+        keywordCompletions.push({
+            name: tokenToString(i),
+            kind: ScriptElementKind.keyword,
+            kindModifiers: ScriptElementKindModifier.none,
+            sortText: "0"
+        });
+    }
+
+    /* @internal */ export function getContainerNode(node: Node): Declaration {
+        while (true) {
+            node = node.parent;
+            if (!node) {
+                return undefined;
+            }
+            switch (node.kind) {
+                case SyntaxKind.SourceFile:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                case SyntaxKind.ModuleDeclaration:
+                    return <Declaration>node;
+            }
+        }
+    }
+
+    /* @internal */ export function getNodeKind(node: Node): string {
+        switch (node.kind) {
+            case SyntaxKind.ModuleDeclaration: return ScriptElementKind.moduleElement;
+            case SyntaxKind.ClassDeclaration: return ScriptElementKind.classElement;
+            case SyntaxKind.InterfaceDeclaration: return ScriptElementKind.interfaceElement;
+            case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement;
+            case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement;
+            case SyntaxKind.VariableDeclaration:
+                return isConst(node)
+                    ? ScriptElementKind.constElement
+                    : isLet(node)
+                        ? ScriptElementKind.letElement
+                        : ScriptElementKind.variableElement;
+            case SyntaxKind.FunctionDeclaration: return ScriptElementKind.functionElement;
+            case SyntaxKind.GetAccessor: return ScriptElementKind.memberGetAccessorElement;
+            case SyntaxKind.SetAccessor: return ScriptElementKind.memberSetAccessorElement;
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.MethodSignature:
+                return ScriptElementKind.memberFunctionElement;
+            case SyntaxKind.PropertyDeclaration:
+            case SyntaxKind.PropertySignature:
+                return ScriptElementKind.memberVariableElement;
+            case SyntaxKind.IndexSignature: return ScriptElementKind.indexSignatureElement;
+            case SyntaxKind.ConstructSignature: return ScriptElementKind.constructSignatureElement;
+            case SyntaxKind.CallSignature: return ScriptElementKind.callSignatureElement;
+            case SyntaxKind.Constructor: return ScriptElementKind.constructorImplementationElement;
+            case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement;
+            case SyntaxKind.EnumMember: return ScriptElementKind.variableElement;
+            case SyntaxKind.Parameter: return (node.flags & NodeFlags.AccessibilityModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
+            case SyntaxKind.ImportEqualsDeclaration:
+            case SyntaxKind.ImportSpecifier:
+            case SyntaxKind.ImportClause:
+            case SyntaxKind.ExportSpecifier:
+            case SyntaxKind.NamespaceImport:
+                return ScriptElementKind.alias;
+        }
+        return ScriptElementKind.unknown;
+    }
+
+    export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry()): LanguageService {
+        let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host);
+        let ruleProvider: formatting.RulesProvider;
+        let program: Program;
+
+        let useCaseSensitivefileNames = false;
+        let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
+
+        // Check if the localized messages json is set, otherwise query the host for it
+        if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
+            localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
+        }
+
+        function log(message: string) {
+            if (host.log) {
+                host.log(message);
+            }
+        }
+
+        function getCanonicalFileName(fileName: string) {
+            return useCaseSensitivefileNames ? fileName : fileName.toLowerCase();
+        }
+
+        function getValidSourceFile(fileName: string): SourceFile {
+            fileName = normalizeSlashes(fileName);
+            let sourceFile = program.getSourceFile(getCanonicalFileName(fileName));
+            if (!sourceFile) {
+                throw new Error("Could not find file: '" + fileName + "'.");
+            }
+            return sourceFile;
+        }
+
+        function getRuleProvider(options: FormatCodeOptions) {
+            // Ensure rules are initialized and up to date wrt to formatting options
+            if (!ruleProvider) {
+                ruleProvider = new formatting.RulesProvider();
+            }
+
+            ruleProvider.ensureUpToDate(options);
+            return ruleProvider;
+        }
+
+        function synchronizeHostData(): void {
+            // Get a fresh cache of the host information
+            let hostCache = new HostCache(host);
+
+            // If the program is already up-to-date, we can reuse it
+            if (programUpToDate()) {
+                return;
+            }
+
+            // IMPORTANT - It is critical from this moment onward that we do not check 
+            // cancellation tokens.  We are about to mutate source files from a previous program
+            // instance.  If we cancel midway through, we may end up in an inconsistent state where
+            // the program points to old source files that have been invalidated because of 
+            // incremental parsing.
+
+            let oldSettings = program && program.getCompilerOptions();
+            let newSettings = hostCache.compilationSettings();
+            let changesInCompilationSettingsAffectSyntax = oldSettings && oldSettings.target !== newSettings.target;
+
+            // Now create a new compiler
+            let newProgram = createProgram(hostCache.getRootFileNames(), newSettings, {
+                getSourceFile: getOrCreateSourceFile,
+                getCancellationToken: () => cancellationToken,
+                getCanonicalFileName: (fileName) => useCaseSensitivefileNames ? fileName : fileName.toLowerCase(),
+                useCaseSensitiveFileNames: () => useCaseSensitivefileNames,
+                getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n",
+                getDefaultLibFileName: (options) => host.getDefaultLibFileName(options),
+                writeFile: (fileName, data, writeByteOrderMark) => { },
+                getCurrentDirectory: () => host.getCurrentDirectory()
+            });
+
+            // Release any files we have acquired in the old program but are 
+            // not part of the new program.
+            if (program) {
+                let oldSourceFiles = program.getSourceFiles();
+                for (let oldSourceFile of oldSourceFiles) {
+                    let fileName = oldSourceFile.fileName;
+                    if (!newProgram.getSourceFile(fileName) || changesInCompilationSettingsAffectSyntax) {
+                        documentRegistry.releaseDocument(fileName, oldSettings);
+                    }
+                }
+            }
+
+            program = newProgram;
+
+            // Make sure all the nodes in the program are both bound, and have their parent 
+            // pointers set property.
+            program.getTypeChecker();
+            return;
+
+            function getOrCreateSourceFile(fileName: string): SourceFile {
+                // The program is asking for this file, check first if the host can locate it.
+                // If the host can not locate the file, then it does not exist. return undefined
+                // to the program to allow reporting of errors for missing files.
+                let hostFileInformation = hostCache.getOrCreateEntry(fileName);
+                if (!hostFileInformation) {
+                    return undefined;
+                }
+
+                // Check if the language version has changed since we last created a program; if they are the same,
+                // it is safe to reuse the souceFiles; if not, then the shape of the AST can change, and the oldSourceFile
+                // can not be reused. we have to dump all syntax trees and create new ones.
+                if (!changesInCompilationSettingsAffectSyntax) {
+                    // Check if the old program had this file already
+                    let oldSourceFile = program && program.getSourceFile(fileName);
+                    if (oldSourceFile) {
+                        // We already had a source file for this file name.  Go to the registry to 
+                        // ensure that we get the right up to date version of it.  We need this to
+                        // address the following 'race'.  Specifically, say we have the following:
+                        //
+                        //      LS1
+                        //          \
+                        //           DocumentRegistry
+                        //          /
+                        //      LS2
+                        //
+                        // Each LS has a reference to file 'foo.ts' at version 1.  LS2 then updates
+                        // it's version of 'foo.ts' to version 2.  This will cause LS2 and the 
+                        // DocumentRegistry to have version 2 of the document.  HOwever, LS1 will 
+                        // have version 1.  And *importantly* this source file will be *corrupt*.
+                        // The act of creating version 2 of the file irrevocably damages the version
+                        // 1 file.
+                        //
+                        // So, later when we call into LS1, we need to make sure that it doesn't use
+                        // it's source file any more, and instead defers to DocumentRegistry to get
+                        // either version 1, version 2 (or some other version) depending on what the 
+                        // host says should be used.
+                        return documentRegistry.updateDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
+                    }
+
+                    // We didn't already have the file.  Fall through and acquire it from the registry.
+                }
+
+                // Could not find this file in the old program, create a new SourceFile for it.
+                return documentRegistry.acquireDocument(fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version);
+            }
+
+            function sourceFileUpToDate(sourceFile: SourceFile): boolean {
+                return sourceFile && sourceFile.version === hostCache.getVersion(sourceFile.fileName);
+            }
+
+            function programUpToDate(): boolean {
+                // If we haven't create a program yet, then it is not up-to-date
+                if (!program) {
+                    return false;
+                }
+
+                // If number of files in the program do not match, it is not up-to-date
+                let rootFileNames = hostCache.getRootFileNames();
+                if (program.getSourceFiles().length !== rootFileNames.length) {
+                    return false;
+                }
+
+                // If any file is not up-to-date, then the whole program is not up-to-date
+                for (let fileName of rootFileNames) {
+                    if (!sourceFileUpToDate(program.getSourceFile(fileName))) {
+                        return false;
+                    }
+                }
+
+                // If the compilation settings do no match, then the program is not up-to-date
+                return compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings());
+            }
+        }
+
+        function getProgram(): Program {
+            synchronizeHostData();
+
+            return program;
+        }
+
+        function cleanupSemanticCache(): void {
+            // TODO: Should we jettison the program (or it's type checker) here?
+        }
+
+        function dispose(): void {
+            if (program) {
+                forEach(program.getSourceFiles(), f =>
+                    documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()));
+            }
+        }
+
+        /// Diagnostics
+        function getSyntacticDiagnostics(fileName: string) {
+            synchronizeHostData();
+
+            return program.getSyntacticDiagnostics(getValidSourceFile(fileName));
+        }
+
+        /**
+         * getSemanticDiagnostiscs return array of Diagnostics. If '-d' is not enabled, only report semantic errors
+         * If '-d' enabled, report both semantic and emitter errors  
+         */
+        function getSemanticDiagnostics(fileName: string): Diagnostic[] {
+            synchronizeHostData();
+
+            let targetSourceFile = getValidSourceFile(fileName);
+
+            // For JavaScript files, we don't want to report the normal typescript semantic errors.
+            // Instead, we just report errors for using TypeScript-only constructs from within a 
+            // JavaScript file.
+            if (isJavaScript(fileName)) {
+                return getJavaScriptSemanticDiagnostics(targetSourceFile);
+            }
+
+            // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
+            // Therefore only get diagnostics for given file.
+
+            let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile);
+            if (!program.getCompilerOptions().declaration) {
+                return semanticDiagnostics;
+            }
+
+            // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface
+            let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile);
+            return concatenate(semanticDiagnostics, declarationDiagnostics);
+        }
+
+        function getJavaScriptSemanticDiagnostics(sourceFile: SourceFile): Diagnostic[] {
+            let diagnostics: Diagnostic[] = [];
+            walk(sourceFile);
+
+            return diagnostics;
+
+            function walk(node: Node): boolean {
+                if (!node) {
+                    return false;
+                }
+
+                switch (node.kind) {
+                    case SyntaxKind.ImportEqualsDeclaration:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.import_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.ExportAssignment:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.export_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.ClassDeclaration:
+                        let classDeclaration = <ClassDeclaration>node;
+                        if (checkModifiers(classDeclaration.modifiers) ||
+                            checkTypeParameters(classDeclaration.typeParameters)) {
+                            return true;
+                        }
+                        break;
+                    case SyntaxKind.HeritageClause:
+                        let heritageClause = <HeritageClause>node;
+                        if (heritageClause.token === SyntaxKind.ImplementsKeyword) {
+                            diagnostics.push(createDiagnosticForNode(node, Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        break;
+                    case SyntaxKind.InterfaceDeclaration:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.ModuleDeclaration:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.module_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.TypeAliasDeclaration:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.type_aliases_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.ArrowFunction:
+                    case SyntaxKind.FunctionDeclaration:
+                        let functionDeclaration = <FunctionLikeDeclaration>node;
+                        if (checkModifiers(functionDeclaration.modifiers) ||
+                            checkTypeParameters(functionDeclaration.typeParameters) ||
+                            checkTypeAnnotation(functionDeclaration.type)) {
+                            return true;
+                        }
+                        break;
+                    case SyntaxKind.VariableStatement:
+                        let variableStatement = <VariableStatement>node;
+                        if (checkModifiers(variableStatement.modifiers)) {
+                            return true;
+                        }
+                        break;
+                    case SyntaxKind.VariableDeclaration:
+                        let variableDeclaration = <VariableDeclaration>node;
+                        if (checkTypeAnnotation(variableDeclaration.type)) {
+                            return true;
+                        }
+                        break;
+                    case SyntaxKind.CallExpression:
+                    case SyntaxKind.NewExpression:
+                        let expression = <CallExpression>node;
+                        if (expression.typeArguments && expression.typeArguments.length > 0) {
+                            let start = expression.typeArguments.pos;
+                            diagnostics.push(createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start,
+                                Diagnostics.type_arguments_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        break;
+                    case SyntaxKind.Parameter:
+                        let parameter = <ParameterDeclaration>node;
+                        if (parameter.modifiers) {
+                            let start = parameter.modifiers.pos;
+                            diagnostics.push(createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start,
+                                Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        if (parameter.questionToken) {
+                            diagnostics.push(createDiagnosticForNode(parameter.questionToken, Diagnostics.can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        if (parameter.type) {
+                            diagnostics.push(createDiagnosticForNode(parameter.type, Diagnostics.types_can_only_be_used_in_a_ts_file));
+                            return true;
+                        }
+                        break;
+                    case SyntaxKind.PropertyDeclaration:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.property_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.EnumDeclaration:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.TypeAssertionExpression:
+                        let typeAssertionExpression = <TypeAssertion>node;
+                        diagnostics.push(createDiagnosticForNode(typeAssertionExpression.type, Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
+                        return true;
+                    case SyntaxKind.Decorator:
+                        diagnostics.push(createDiagnosticForNode(node, Diagnostics.decorators_can_only_be_used_in_a_ts_file));
+                        return true;
+                }
+
+                return forEachChild(node, walk);
+            }
+
+            function checkTypeParameters(typeParameters: NodeArray<TypeParameterDeclaration>): boolean {
+                if (typeParameters) {
+                    let start = typeParameters.pos;
+                    diagnostics.push(createFileDiagnostic(sourceFile, start, typeParameters.end - start, Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file));
+                    return true;
+                }
+                return false;
+            }
+
+            function checkTypeAnnotation(type: TypeNode): boolean {
+                if (type) {
+                    diagnostics.push(createDiagnosticForNode(type, Diagnostics.types_can_only_be_used_in_a_ts_file));
+                    return true;
+                }
+
+                return false;
+            }
+
+            function checkModifiers(modifiers: ModifiersArray): boolean {
+                if (modifiers) {
+                    for (let modifier of modifiers) {
+                        switch (modifier.kind) {
+                            case SyntaxKind.PublicKeyword:
+                            case SyntaxKind.PrivateKeyword:
+                            case SyntaxKind.ProtectedKeyword:
+                            case SyntaxKind.DeclareKeyword:
+                                diagnostics.push(createDiagnosticForNode(modifier, Diagnostics._0_can_only_be_used_in_a_ts_file, tokenToString(modifier.kind)));
+                                return true;
+
+                            // These are all legal modifiers.
+                            case SyntaxKind.StaticKeyword:
+                            case SyntaxKind.ExportKeyword:
+                            case SyntaxKind.ConstKeyword:
+                            case SyntaxKind.DefaultKeyword:
+                        }
+                    }
+                }
+
+                return false;
+            }
+        }
+
+        function getCompilerOptionsDiagnostics() {
+            synchronizeHostData();
+            return program.getGlobalDiagnostics();
+        }
+
+        /// Completion
+        function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean): string {
+            let displayName = symbol.getName();
+            if (displayName) {
+                // If this is the default export, get the name of the declaration if it exists
+                if (displayName === "default") {
+                    let localSymbol = getLocalSymbolForExportDefault(symbol);
+                    if (localSymbol && localSymbol.name) {
+                        displayName = symbol.valueDeclaration.localSymbol.name;
+                    }
+                }
+
+                let firstCharCode = displayName.charCodeAt(0);
+                // First check of the displayName is not external module; if it is an external module, it is not valid entry
+                if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
+                    // If the symbol is external module, don't show it in the completion list
+                    // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there)
+                    return undefined;
+                }
+            }
+
+            return getCompletionEntryDisplayName(displayName, target, performCharacterChecks);
+        }
+
+        function getCompletionEntryDisplayName(displayName: string, target: ScriptTarget, performCharacterChecks: boolean): string {
+            if (!displayName) {
+                return undefined;
+            }
+
+            let firstCharCode = displayName.charCodeAt(0);
+            if (displayName.length >= 2 &&
+                firstCharCode === displayName.charCodeAt(displayName.length - 1) &&
+                (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
+                // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
+                // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
+                displayName = displayName.substring(1, displayName.length - 1);
+            }
+
+            if (!displayName) {
+                return undefined;
+            }
+
+            if (performCharacterChecks) {
+                if (!isIdentifierStart(displayName.charCodeAt(0), target)) {
+                    return undefined;
+                }
+
+                for (let i = 1, n = displayName.length; i < n; i++) {
+                    if (!isIdentifierPart(displayName.charCodeAt(i), target)) {
+                        return undefined;
+                    }
+                }
+            }
+
+            return unescapeIdentifier(displayName);
+        }
+
+        function getCompletionData(fileName: string, position: number) {
+            let typeChecker = program.getTypeChecker();
+            let syntacticStart = new Date().getTime();
+            let sourceFile = getValidSourceFile(fileName);
+
+            let start = new Date().getTime();
+            let currentToken = getTokenAtPosition(sourceFile, position);
+            log("getCompletionData: Get current token: " + (new Date().getTime() - start));
+
+            start = new Date().getTime();
+            // Completion not allowed inside comments, bail out if this is the case
+            let insideComment = isInsideComment(sourceFile, currentToken, position);
+            log("getCompletionData: Is inside comment: " + (new Date().getTime() - start));
+
+            if (insideComment) {
+                log("Returning an empty list because completion was inside a comment.");
+                return undefined;
+            }
+
+            start = new Date().getTime();
+            let previousToken = findPrecedingToken(position, sourceFile);
+            log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start));
+
+            // The decision to provide completion depends on the contextToken, which is determined through the previousToken.
+            // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
+            let contextToken = previousToken;
+
+            // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
+            // Skip this partial identifier and adjust the contextToken to the token that precedes it.
+            if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) {
+                let start = new Date().getTime();
+                contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile);
+                log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start));
+            }
+
+            // Check if this is a valid completion location
+            if (contextToken && isCompletionListBlocker(contextToken)) {
+                log("Returning an empty list because completion was requested in an invalid position.");
+                return undefined;
+            }
+
+            // Find the node where completion is requested on, in the case of a completion after 
+            // a dot, it is the member access expression other wise, it is a request for all 
+            // visible symbols in the scope, and the node is the current location.
+            let node = currentToken;
+            let isRightOfDot = false;
+            if (contextToken && contextToken.kind === SyntaxKind.DotToken && contextToken.parent.kind === SyntaxKind.PropertyAccessExpression) {
+                node = (<PropertyAccessExpression>contextToken.parent).expression;
+                isRightOfDot = true;
+            }
+            else if (contextToken && contextToken.kind === SyntaxKind.DotToken && contextToken.parent.kind === SyntaxKind.QualifiedName) {
+                node = (<QualifiedName>contextToken.parent).left;
+                isRightOfDot = true;
+            }
+
+            let location = getTouchingPropertyName(sourceFile, position);
+            var target = program.getCompilerOptions().target;
+
+            let semanticStart = new Date().getTime();
+            let isMemberCompletion: boolean;
+            let isNewIdentifierLocation: boolean;
+            let symbols: Symbol[] = [];
+
+            if (isRightOfDot) {
+                getTypeScriptMemberSymbols();
+            }
+            else {
+                // For JavaScript or TypeScript, if we're not after a dot, then just try to get the
+                // global symbols in scope.  These results should be valid for either language as
+                // the set of symbols that can be referenced from this location.
+                if (!tryGetGlobalSymbols()) {
+                    return undefined;
+                }
+            }
+
+            log("getCompletionData: Semantic work: " + (new Date().getTime() - semanticStart));
+
+            return { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot };
+
+            function getTypeScriptMemberSymbols(): void {
+                // Right of dot member completion list
+                isMemberCompletion = true;
+                isNewIdentifierLocation = false;
+
+                if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression) {
+                    let symbol = typeChecker.getSymbolAtLocation(node);
+
+                    // This is an alias, follow what it aliases
+                    if (symbol && symbol.flags & SymbolFlags.Alias) {
+                        symbol = typeChecker.getAliasedSymbol(symbol);
+                    }
+
+                    if (symbol && symbol.flags & SymbolFlags.HasExports) {
+                        // Extract module or enum members
+                        let exportedSymbols = typeChecker.getExportsOfModule(symbol);
+                        forEach(exportedSymbols, symbol => {
+                            if (typeChecker.isValidPropertyAccess(<PropertyAccessExpression>(node.parent), symbol.name)) {
+                                symbols.push(symbol);
+                            }
+                        });
+                    }
+                }
+
+                let type = typeChecker.getTypeAtLocation(node);
+                if (type) {
+                    // Filter private properties
+                    forEach(type.getApparentProperties(), symbol => {
+                        if (typeChecker.isValidPropertyAccess(<PropertyAccessExpression>(node.parent), symbol.name)) {
+                            symbols.push(symbol);
+                        }
+                    });
+                }
+            }
+
+            function tryGetGlobalSymbols(): boolean {
+                let containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(contextToken);
+                if (containingObjectLiteral) {
+                    // Object literal expression, look up possible property names from contextual type
+                    isMemberCompletion = true;
+                    isNewIdentifierLocation = true;
+
+                    let contextualType = typeChecker.getContextualType(containingObjectLiteral);
+                    if (!contextualType) {
+                        return false;
+                    }
+
+                    let contextualTypeMembers = typeChecker.getPropertiesOfType(contextualType);
+                    if (contextualTypeMembers && contextualTypeMembers.length > 0) {
+                        // Add filtered items to the completion list
+                        symbols = filterContextualMembersList(contextualTypeMembers, containingObjectLiteral.properties);
+                    }
+                }
+                else if (getAncestor(contextToken, SyntaxKind.ImportClause)) {
+                    // cursor is in import clause
+                    // try to show exported member for imported module
+                    isMemberCompletion = true;
+                    isNewIdentifierLocation = true;
+                    if (showCompletionsInImportsClause(contextToken)) {
+                        let importDeclaration = <ImportDeclaration>getAncestor(contextToken, SyntaxKind.ImportDeclaration);
+                        Debug.assert(importDeclaration !== undefined);
+
+                        let exports: Symbol[];
+                        if (importDeclaration.moduleSpecifier) {
+                            let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier);
+                            if (moduleSpecifierSymbol) {
+                                exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol);
+                            }
+                        }
+
+                        //let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration);
+                        symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray;
+                    }
+                }
+                else {
+                    // Get all entities in the current scope.
+                    isMemberCompletion = false;
+                    isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
+
+                    if (previousToken !== contextToken) {
+                        Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'.");
+                    }
+                    // We need to find the node that will give us an appropriate scope to begin
+                    // aggregating completion candidates. This is achieved in 'getScopeNode'
+                    // by finding the first node that encompasses a position, accounting for whether a node
+                    // is "complete" to decide whether a position belongs to the node.
+                    // 
+                    // However, at the end of an identifier, we are interested in the scope of the identifier
+                    // itself, but fall outside of the identifier. For instance:
+                    // 
+                    //      xyz => x$
+                    //
+                    // the cursor is outside of both the 'x' and the arrow function 'xyz => x',
+                    // so 'xyz' is not returned in our results.
+                    //
+                    // We define 'adjustedPosition' so that we may appropriately account for
+                    // being at the end of an identifier. The intention is that if requesting completion
+                    // at the end of an identifier, it should be effectively equivalent to requesting completion
+                    // anywhere inside/at the beginning of the identifier. So in the previous case, the
+                    // 'adjustedPosition' will work as if requesting completion in the following:
+                    //
+                    //      xyz => $x
+                    //
+                    // If previousToken !== contextToken, then
+                    //   - 'contextToken' was adjusted to the token prior to 'previousToken'
+                    //      because we were at the end of an identifier.
+                    //   - 'previousToken' is defined.
+                    let adjustedPosition = previousToken !== contextToken ?
+                        previousToken.getStart() :
+                        position;
+
+                    let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
+
+                    /// TODO filter meaning based on the current context
+                    let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
+                    symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
+                }
+
+                return true;
+            }
+
+            /**
+             * Finds the first node that "embraces" the position, so that one may
+             * accurately aggregate locals from the closest containing scope.
+             */
+            function getScopeNode(initialToken: Node, position: number, sourceFile: SourceFile) {
+                var scope = initialToken;
+                while (scope && !positionBelongsToNode(scope, position, sourceFile)) {
+                    scope = scope.parent;
+                }
+                return scope;
+            }
+
+            function isCompletionListBlocker(previousToken: Node): boolean {
+                let start = new Date().getTime();
+                let result = isInStringOrRegularExpressionOrTemplateLiteral(previousToken) ||
+                    isIdentifierDefinitionLocation(previousToken) ||
+                    isRightOfIllegalDot(previousToken);
+                log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
+                return result;
+            }
+
+            function showCompletionsInImportsClause(node: Node): boolean {
+                if (node) {
+                    // import {| 
+                    // import {a,|
+                    if (node.kind === SyntaxKind.OpenBraceToken || node.kind === SyntaxKind.CommaToken) {
+                        return node.parent.kind === SyntaxKind.NamedImports;
+                    }
+                }
+
+                return false;
+            }
+
+            function isNewIdentifierDefinitionLocation(previousToken: Node): boolean {
+                if (previousToken) {
+                    let containingNodeKind = previousToken.parent.kind;
+                    switch (previousToken.kind) {
+                        case SyntaxKind.CommaToken:
+                            return containingNodeKind === SyntaxKind.CallExpression                         // func( a, |
+                                || containingNodeKind === SyntaxKind.Constructor                            // constructor( a, |   public, protected, private keywords are allowed here, so show completion
+                                || containingNodeKind === SyntaxKind.NewExpression                          // new C(a, |
+                                || containingNodeKind === SyntaxKind.ArrayLiteralExpression                 // [a, |
+                                || containingNodeKind === SyntaxKind.BinaryExpression;                      // let x = (a, |
+
+              
+                        case SyntaxKind.OpenParenToken:
+                            return containingNodeKind === SyntaxKind.CallExpression               // func( |
+                                || containingNodeKind === SyntaxKind.Constructor                  // constructor( |
+                                || containingNodeKind === SyntaxKind.NewExpression                // new C(a|
+                                || containingNodeKind === SyntaxKind.ParenthesizedExpression;     // let x = (a|
+
+                        case SyntaxKind.OpenBracketToken:
+                            return containingNodeKind === SyntaxKind.ArrayLiteralExpression;                 // [ |
+
+                        case SyntaxKind.ModuleKeyword:                               // module | 
+                            return true;
+
+                        case SyntaxKind.DotToken:
+                            return containingNodeKind === SyntaxKind.ModuleDeclaration; // module A.|
+
+                        case SyntaxKind.OpenBraceToken:
+                            return containingNodeKind === SyntaxKind.ClassDeclaration;  // class A{ |
+
+                        case SyntaxKind.EqualsToken:
+                            return containingNodeKind === SyntaxKind.VariableDeclaration // let x = a|
+                                || containingNodeKind === SyntaxKind.BinaryExpression;   // x = a|
+
+                        case SyntaxKind.TemplateHead:
+                            return containingNodeKind === SyntaxKind.TemplateExpression; // `aa ${|
+
+                        case SyntaxKind.TemplateMiddle:
+                            return containingNodeKind === SyntaxKind.TemplateSpan; // `aa ${10} dd ${|
+
+                        case SyntaxKind.PublicKeyword:
+                        case SyntaxKind.PrivateKeyword:
+                        case SyntaxKind.ProtectedKeyword:
+                            return containingNodeKind === SyntaxKind.PropertyDeclaration; // class A{ public |
+                    }
+
+                    // Previous token may have been a keyword that was converted to an identifier.
+                    switch (previousToken.getText()) {
+                        case "public":
+                        case "protected":
+                        case "private":
+                            return true;
+                    }
+                }
+
+                return false;
+            }
+
+            function isInStringOrRegularExpressionOrTemplateLiteral(previousToken: Node): boolean {
+                if (previousToken.kind === SyntaxKind.StringLiteral
+                    || previousToken.kind === SyntaxKind.RegularExpressionLiteral
+                    || isTemplateLiteralKind(previousToken.kind)) {
+                    // The position has to be either: 1. entirely within the token text, or 
+                    // 2. at the end position of an unterminated token.
+                    let start = previousToken.getStart();
+                    let end = previousToken.getEnd();
+
+                    if (start < position && position < end) {
+                        return true;
+                    }
+                    else if (position === end) {
+                        return !!(<LiteralExpression>previousToken).isUnterminated;
+                    }
+                }
+
+                return false;
+            }
+
+            function getContainingObjectLiteralApplicableForCompletion(previousToken: Node): ObjectLiteralExpression {
+                // The locations in an object literal expression that are applicable for completion are property name definition locations.
+
+                if (previousToken) {
+                    let parent = previousToken.parent;
+
+                    switch (previousToken.kind) {
+                        case SyntaxKind.OpenBraceToken:  // let x = { |
+                        case SyntaxKind.CommaToken:      // let x = { a: 0, |
+                            if (parent && parent.kind === SyntaxKind.ObjectLiteralExpression) {
+                                return <ObjectLiteralExpression>parent;
+                            }
+                            break;
+                    }
+                }
+
+                return undefined;
+            }
+
+            function isFunction(kind: SyntaxKind): boolean {
+                switch (kind) {
+                    case SyntaxKind.FunctionExpression:
+                    case SyntaxKind.ArrowFunction:
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                    case SyntaxKind.CallSignature:
+                    case SyntaxKind.ConstructSignature:
+                    case SyntaxKind.IndexSignature:
+                        return true;
+                }
+                return false;
+            }
+
+            function isIdentifierDefinitionLocation(previousToken: Node): boolean {
+                if (previousToken) {
+                    let containingNodeKind = previousToken.parent.kind;
+                    switch (previousToken.kind) {
+                        case SyntaxKind.CommaToken:
+                            return containingNodeKind === SyntaxKind.VariableDeclaration ||
+                                containingNodeKind === SyntaxKind.VariableDeclarationList ||
+                                containingNodeKind === SyntaxKind.VariableStatement ||
+                                containingNodeKind === SyntaxKind.EnumDeclaration ||           // enum a { foo, |
+                                isFunction(containingNodeKind) ||
+                                containingNodeKind === SyntaxKind.ClassDeclaration ||          // class A<T, |
+                                containingNodeKind === SyntaxKind.FunctionDeclaration ||       // function A<T, |
+                                containingNodeKind === SyntaxKind.InterfaceDeclaration ||      // interface A<T, |
+                                containingNodeKind === SyntaxKind.ArrayBindingPattern ||       //  var [x, y|
+                                containingNodeKind === SyntaxKind.ObjectBindingPattern;        // function func({ x, y|
+
+                        case SyntaxKind.DotToken:
+                            return containingNodeKind === SyntaxKind.ArrayBindingPattern;       // var [.|
+
+                        case SyntaxKind.OpenBracketToken:
+                            return containingNodeKind === SyntaxKind.ArrayBindingPattern;         //  var [x|
+
+                        case SyntaxKind.OpenParenToken:
+                            return containingNodeKind === SyntaxKind.CatchClause ||
+                                isFunction(containingNodeKind);
+
+                        case SyntaxKind.OpenBraceToken:
+                            return containingNodeKind === SyntaxKind.EnumDeclaration ||        // enum a { |
+                                containingNodeKind === SyntaxKind.InterfaceDeclaration ||      // interface a { |
+                                containingNodeKind === SyntaxKind.TypeLiteral ||               // let x : { |
+                                containingNodeKind === SyntaxKind.ObjectBindingPattern;        // function func({ x|
+
+                        case SyntaxKind.SemicolonToken:
+                            return containingNodeKind === SyntaxKind.PropertySignature &&
+                                previousToken.parent && previousToken.parent.parent &&
+                                (previousToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration ||    // interface a { f; |
+                                    previousToken.parent.parent.kind === SyntaxKind.TypeLiteral);           //  let x : { a; |
+
+                        case SyntaxKind.LessThanToken:
+                            return containingNodeKind === SyntaxKind.ClassDeclaration ||        // class A< |
+                                containingNodeKind === SyntaxKind.FunctionDeclaration ||        // function A< |
+                                containingNodeKind === SyntaxKind.InterfaceDeclaration ||       // interface A< |
+                                isFunction(containingNodeKind);
+
+                        case SyntaxKind.StaticKeyword:
+                            return containingNodeKind === SyntaxKind.PropertyDeclaration;
+
+                        case SyntaxKind.DotDotDotToken:
+                            return containingNodeKind === SyntaxKind.Parameter ||
+                                containingNodeKind === SyntaxKind.Constructor ||
+                                (previousToken.parent && previousToken.parent.parent &&
+                                    previousToken.parent.parent.kind === SyntaxKind.ArrayBindingPattern);  // var [ ...z|
+
+                        case SyntaxKind.PublicKeyword:
+                        case SyntaxKind.PrivateKeyword:
+                        case SyntaxKind.ProtectedKeyword:
+                            return containingNodeKind === SyntaxKind.Parameter;
+
+                        case SyntaxKind.ClassKeyword:
+                        case SyntaxKind.EnumKeyword:
+                        case SyntaxKind.InterfaceKeyword:
+                        case SyntaxKind.FunctionKeyword:
+                        case SyntaxKind.VarKeyword:
+                        case SyntaxKind.GetKeyword:
+                        case SyntaxKind.SetKeyword:
+                        case SyntaxKind.ImportKeyword:
+                        case SyntaxKind.LetKeyword:
+                        case SyntaxKind.ConstKeyword:
+                        case SyntaxKind.YieldKeyword:
+                            return true;
+                    }
+
+                    // Previous token may have been a keyword that was converted to an identifier.
+                    switch (previousToken.getText()) {
+                        case "class":
+                        case "interface":
+                        case "enum":
+                        case "function":
+                        case "var":
+                        case "static":
+                        case "let":
+                        case "const":
+                        case "yield":
+                            return true;
+                    }
+                }
+
+                return false;
+            }
+
+            function isRightOfIllegalDot(previousToken: Node): boolean {
+                if (previousToken && previousToken.kind === SyntaxKind.NumericLiteral) {
+                    let text = previousToken.getFullText();
+                    return text.charAt(text.length - 1) === ".";
+                }
+
+                return false;
+            }
+
+            function filterModuleExports(exports: Symbol[], importDeclaration: ImportDeclaration): Symbol[] {
+                let exisingImports: Map<boolean> = {};
+
+                if (!importDeclaration.importClause) {
+                    return exports;
+                }
+
+                if (importDeclaration.importClause.namedBindings &&
+                    importDeclaration.importClause.namedBindings.kind === SyntaxKind.NamedImports) {
+
+                    forEach((<NamedImports>importDeclaration.importClause.namedBindings).elements, el => {
+                        let name = el.propertyName || el.name;
+                        exisingImports[name.text] = true;
+                    });
+                }
+
+                if (isEmpty(exisingImports)) {
+                    return exports;
+                }
+                return filter(exports, e => !lookUp(exisingImports, e.name));
+            }
+
+            function filterContextualMembersList(contextualMemberSymbols: Symbol[], existingMembers: Declaration[]): Symbol[] {
+                if (!existingMembers || existingMembers.length === 0) {
+                    return contextualMemberSymbols;
+                }
+
+                let existingMemberNames: Map<boolean> = {};
+                forEach(existingMembers, m => {
+                    if (m.kind !== SyntaxKind.PropertyAssignment && m.kind !== SyntaxKind.ShorthandPropertyAssignment) {
+                        // Ignore omitted expressions for missing members in the object literal
+                        return;
+                    }
+
+                    if (m.getStart() <= position && position <= m.getEnd()) {
+                        // If this is the current item we are editing right now, do not filter it out
+                        return;
+                    }
+
+                    // TODO(jfreeman): Account for computed property name
+                    existingMemberNames[(<Identifier>m.name).text] = true;
+                });
+
+                let filteredMembers: Symbol[] = [];
+                forEach(contextualMemberSymbols, s => {
+                    if (!existingMemberNames[s.name]) {
+                        filteredMembers.push(s);
+                    }
+                });
+
+                return filteredMembers;
+            }
+        }
+
+        function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
+            synchronizeHostData();
+
+            let completionData = getCompletionData(fileName, position);
+            if (!completionData) {
+                return undefined;
+            }
+
+            let { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot } = completionData;
+
+            let entries: CompletionEntry[];
+            if (isRightOfDot && isJavaScript(fileName)) {
+                entries = getCompletionEntriesFromSymbols(symbols);
+                addRange(entries, getJavaScriptCompletionEntries());
+            }
+            else {
+                if (!symbols || symbols.length === 0) {
+                    return undefined;
+                }
+
+                entries = getCompletionEntriesFromSymbols(symbols);
+            }
+
+            // Add keywords if this is not a member completion list
+            if (!isMemberCompletion) {
+                addRange(entries, keywordCompletions);
+            }
+
+            return { isMemberCompletion, isNewIdentifierLocation, entries };
+
+            function getJavaScriptCompletionEntries(): CompletionEntry[] {
+                let entries: CompletionEntry[] = [];
+                let allNames: Map<string> = {};
+                let target = program.getCompilerOptions().target;
+
+                for (let sourceFile of program.getSourceFiles()) {
+                    let nameTable = getNameTable(sourceFile);
+                    for (let name in nameTable) {
+                        if (!allNames[name]) {
+                            allNames[name] = name;
+                            let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true);
+                            if (displayName) {
+                                let entry = {
+                                    name: displayName,
+                                    kind: ScriptElementKind.warning,
+                                    kindModifiers: "",
+                                    sortText: "1"
+                                };
+                                entries.push(entry);
+                            }
+                        }
+                    }
+                }
+
+                return entries;
+            }
+
+            function createCompletionEntry(symbol: Symbol, location: Node): CompletionEntry {
+                // Try to get a valid display name for this symbol, if we could not find one, then ignore it. 
+                // We would like to only show things that can be added after a dot, so for instance numeric properties can
+                // not be accessed with a dot (a.1 <- invalid)
+                let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true);
+                if (!displayName) {
+                    return undefined;
+                }
+
+                // TODO(drosen): Right now we just permit *all* semantic meanings when calling 
+                // 'getSymbolKind' which is permissible given that it is backwards compatible; but 
+                // really we should consider passing the meaning for the node so that we don't report
+                // that a suggestion for a value is an interface.  We COULD also just do what 
+                // 'getSymbolModifiers' does, which is to use the first declaration.
+
+                // Use a 'sortText' of 0' so that all symbol completion entries come before any other
+                // entries (like JavaScript identifier entries).
+                return {
+                    name: displayName,
+                    kind: getSymbolKind(symbol, location),
+                    kindModifiers: getSymbolModifiers(symbol),
+                    sortText: "0",
+                };
+            }
+
+            function getCompletionEntriesFromSymbols(symbols: Symbol[]): CompletionEntry[] {
+                let start = new Date().getTime();
+                var entries: CompletionEntry[] = [];
+
+                if (symbols) {
+                    var nameToSymbol: Map<Symbol> = {};
+                    for (let symbol of symbols) {
+                        let entry = createCompletionEntry(symbol, location);
+                        if (entry) {
+                            let id = escapeIdentifier(entry.name);
+                            if (!lookUp(nameToSymbol, id)) {
+                                entries.push(entry);
+                                nameToSymbol[id] = symbol;
+                            }
+                        }
+                    }
+                }
+
+                log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
+                return entries;
+            }
+        }
+
+        function getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {
+            synchronizeHostData();
+
+            // Compute all the completion symbols again.
+            let completionData = getCompletionData(fileName, position);
+            if (completionData) {
+                let { symbols, location } = completionData;
+
+                // Find the symbol with the matching entry name.
+                let target = program.getCompilerOptions().target;
+                // We don't need to perform character checks here because we're only comparing the 
+                // name against 'entryName' (which is known to be good), not building a new 
+                // completion entry.
+                let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false) === entryName ? s : undefined);
+
+                if (symbol) {
+                    let displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All);
+                    return {
+                        name: entryName,
+                        kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
+                        kindModifiers: getSymbolModifiers(symbol),
+                        displayParts: displayPartsDocumentationsAndSymbolKind.displayParts,
+                        documentation: displayPartsDocumentationsAndSymbolKind.documentation
+                    };
+                }
+            }
+            
+            // Didn't find a symbol with this name.  See if we can find a keyword instead.
+            let keywordCompletion = forEach(keywordCompletions, c => c.name === entryName);
+            if (keywordCompletion) {
+                return {
+                    name: entryName,
+                    kind: ScriptElementKind.keyword,
+                    kindModifiers: ScriptElementKindModifier.none,
+                    displayParts: [displayPart(entryName, SymbolDisplayPartKind.keyword)],
+                    documentation: undefined
+                };
+            }
+
+            return undefined;
+        }
+
+        // TODO(drosen): use contextual SemanticMeaning.
+        function getSymbolKind(symbol: Symbol, location: Node): string {
+            let flags = symbol.getFlags();
+
+            if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
+            if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
+            if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement;
+            if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
+            if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
+
+            let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location);
+            if (result === ScriptElementKind.unknown) {
+                if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
+                if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
+                if (flags & SymbolFlags.Alias) return ScriptElementKind.alias;
+                if (flags & SymbolFlags.Module) return ScriptElementKind.moduleElement;
+            }
+
+            return result;
+        }
+
+        function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, location: Node) {
+            let typeChecker = program.getTypeChecker();
+
+            if (typeChecker.isUndefinedSymbol(symbol)) {
+                return ScriptElementKind.variableElement;
+            }
+            if (typeChecker.isArgumentsSymbol(symbol)) {
+                return ScriptElementKind.localVariableElement;
+            }
+            if (flags & SymbolFlags.Variable) {
+                if (isFirstDeclarationOfSymbolParameter(symbol)) {
+                    return ScriptElementKind.parameterElement;
+                }
+                else if (symbol.valueDeclaration && isConst(symbol.valueDeclaration)) {
+                    return ScriptElementKind.constElement;
+                }
+                else if (forEach(symbol.declarations, isLet)) {
+                    return ScriptElementKind.letElement;
+                }
+                return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement;
+            }
+            if (flags & SymbolFlags.Function) return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement;
+            if (flags & SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement;
+            if (flags & SymbolFlags.SetAccessor) return ScriptElementKind.memberSetAccessorElement;
+            if (flags & SymbolFlags.Method) return ScriptElementKind.memberFunctionElement;
+            if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
+
+            if (flags & SymbolFlags.Property) {
+                if (flags & SymbolFlags.UnionProperty) {
+                    // If union property is result of union of non method (property/accessors/variables), it is labeled as property
+                    let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => {
+                        let rootSymbolFlags = rootSymbol.getFlags();
+                        if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) {
+                            return ScriptElementKind.memberVariableElement;
+                        }
+                        Debug.assert(!!(rootSymbolFlags & SymbolFlags.Method));
+                    });
+                    if (!unionPropertyKind) {
+                        // If this was union of all methods, 
+                        //make sure it has call signatures before we can label it as method
+                        let typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
+                        if (typeOfUnionProperty.getCallSignatures().length) {
+                            return ScriptElementKind.memberFunctionElement;
+                        }
+                        return ScriptElementKind.memberVariableElement;
+                    }
+                    return unionPropertyKind;
+                }
+                return ScriptElementKind.memberVariableElement;
+            }
+
+            return ScriptElementKind.unknown;
+        }
+
+        function getTypeKind(type: Type): string {
+            let flags = type.getFlags();
+
+            if (flags & TypeFlags.Enum) return ScriptElementKind.enumElement;
+            if (flags & TypeFlags.Class) return ScriptElementKind.classElement;
+            if (flags & TypeFlags.Interface) return ScriptElementKind.interfaceElement;
+            if (flags & TypeFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
+            if (flags & TypeFlags.Intrinsic) return ScriptElementKind.primitiveType;
+            if (flags & TypeFlags.StringLiteral) return ScriptElementKind.primitiveType;
+
+            return ScriptElementKind.unknown;
+        }
+
+        function getSymbolModifiers(symbol: Symbol): string {
+            return symbol && symbol.declarations && symbol.declarations.length > 0
+                ? getNodeModifiers(symbol.declarations[0])
+                : ScriptElementKindModifier.none;
+        }
+
+        // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
+        function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node,
+            location: Node, semanticMeaning = getMeaningFromLocation(location)) {
+
+            let typeChecker = program.getTypeChecker();
+
+            let displayParts: SymbolDisplayPart[] = [];
+            let documentation: SymbolDisplayPart[];
+            let symbolFlags = symbol.flags;
+            let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location);
+            let hasAddedSymbolInfo: boolean;
+            let type: Type;
+
+            // Class at constructor site need to be shown as constructor apart from property,method, vars
+            if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias) {
+                // If it is accessor they are allowed only if location is at name of the accessor
+                if (symbolKind === ScriptElementKind.memberGetAccessorElement || symbolKind === ScriptElementKind.memberSetAccessorElement) {
+                    symbolKind = ScriptElementKind.memberVariableElement;
+                }
+
+                let signature: Signature;
+                type = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
+                if (type) {
+                    if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) {
+                        let right = (<PropertyAccessExpression>location.parent).name;
+                        // Either the location is on the right of a property access, or on the left and the right is missing
+                        if (right === location || (right && right.getFullWidth() === 0)) {
+                            location = location.parent;
+                        }
+                    }
+
+                    // try get the call/construct signature from the type if it matches
+                    let callExpression: CallExpression;
+                    if (location.kind === SyntaxKind.CallExpression || location.kind === SyntaxKind.NewExpression) {
+                        callExpression = <CallExpression> location;
+                    }
+                    else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
+                        callExpression = <CallExpression>location.parent;
+                    }
+
+                    if (callExpression) {
+                        let candidateSignatures: Signature[] = [];
+                        signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures);
+                        if (!signature && candidateSignatures.length) {
+                            // Use the first candidate:
+                            signature = candidateSignatures[0];
+                        }
+
+                        let useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword;
+                        let allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();
+
+                        if (!contains(allSignatures, signature.target || signature)) {
+                            // Get the first signature if there 
+                            signature = allSignatures.length ? allSignatures[0] : undefined;
+                        }
+
+                        if (signature) {
+                            if (useConstructSignatures && (symbolFlags & SymbolFlags.Class)) {
+                                // Constructor
+                                symbolKind = ScriptElementKind.constructorImplementationElement;
+                                addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
+                            }
+                            else if (symbolFlags & SymbolFlags.Alias) {
+                                symbolKind = ScriptElementKind.alias;
+                                pushTypePart(symbolKind);
+                                displayParts.push(spacePart());
+                                if (useConstructSignatures) {
+                                    displayParts.push(keywordPart(SyntaxKind.NewKeyword));
+                                    displayParts.push(spacePart());
+                                }
+                                addFullSymbolName(symbol);
+                            }
+                            else {
+                                addPrefixForAnyFunctionOrVar(symbol, symbolKind);
+                            }
+
+                            switch (symbolKind) {
+                                case ScriptElementKind.memberVariableElement:
+                                case ScriptElementKind.variableElement:
+                                case ScriptElementKind.constElement:
+                                case ScriptElementKind.letElement:
+                                case ScriptElementKind.parameterElement:
+                                case ScriptElementKind.localVariableElement:
+                                    // If it is call or construct signature of lambda's write type name
+                                    displayParts.push(punctuationPart(SyntaxKind.ColonToken));
+                                    displayParts.push(spacePart());
+                                    if (useConstructSignatures) {
+                                        displayParts.push(keywordPart(SyntaxKind.NewKeyword));
+                                        displayParts.push(spacePart());
+                                    }
+                                    if (!(type.flags & TypeFlags.Anonymous)) {
+                                        displayParts.push.apply(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments));
+                                    }
+                                    addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature);
+                                    break;
+
+                                default:
+                                    // Just signature
+                                    addSignatureDisplayParts(signature, allSignatures);
+                            }
+                            hasAddedSymbolInfo = true;
+                        }
+                    }
+                    else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration
+                        (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration
+                        // get the signature from the declaration and write it
+                        let functionDeclaration = <FunctionLikeDeclaration>location.parent;
+                        let allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures();
+                        if (!typeChecker.isImplementationOfOverload(functionDeclaration)) {
+                            signature = typeChecker.getSignatureFromDeclaration(functionDeclaration);
+                        }
+                        else {
+                            signature = allSignatures[0];
+                        }
+
+                        if (functionDeclaration.kind === SyntaxKind.Constructor) {
+                            // show (constructor) Type(...) signature
+                            symbolKind = ScriptElementKind.constructorImplementationElement;
+                            addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
+                        }
+                        else {
+                            // (function/method) symbol(..signature)
+                            addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature &&
+                                !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind);
+                        }
+
+                        addSignatureDisplayParts(signature, allSignatures);
+                        hasAddedSymbolInfo = true;
+                    }
+                }
+            }
+            if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo) {
+                displayParts.push(keywordPart(SyntaxKind.ClassKeyword));
+                displayParts.push(spacePart());
+                addFullSymbolName(symbol);
+                writeTypeParametersOfSymbol(symbol, sourceFile);
+            }
+            if ((symbolFlags & SymbolFlags.Interface) && (semanticMeaning & SemanticMeaning.Type)) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
+                displayParts.push(spacePart());
+                addFullSymbolName(symbol);
+                writeTypeParametersOfSymbol(symbol, sourceFile);
+            }
+            if (symbolFlags & SymbolFlags.TypeAlias) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
+                displayParts.push(spacePart());
+                addFullSymbolName(symbol);
+                displayParts.push(spacePart());
+                displayParts.push(operatorPart(SyntaxKind.EqualsToken));
+                displayParts.push(spacePart());
+                displayParts.push.apply(displayParts, typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration));
+            }
+            if (symbolFlags & SymbolFlags.Enum) {
+                addNewLineIfDisplayPartsExist();
+                if (forEach(symbol.declarations, isConstEnumDeclaration)) {
+                    displayParts.push(keywordPart(SyntaxKind.ConstKeyword));
+                    displayParts.push(spacePart());
+                }
+                displayParts.push(keywordPart(SyntaxKind.EnumKeyword));
+                displayParts.push(spacePart());
+                addFullSymbolName(symbol);
+            }
+            if (symbolFlags & SymbolFlags.Module) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(keywordPart(SyntaxKind.ModuleKeyword));
+                displayParts.push(spacePart());
+                addFullSymbolName(symbol);
+            }
+            if ((symbolFlags & SymbolFlags.TypeParameter) && (semanticMeaning & SemanticMeaning.Type)) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
+                displayParts.push(textPart("type parameter"));
+                displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
+                displayParts.push(spacePart());
+                addFullSymbolName(symbol);
+                displayParts.push(spacePart());
+                displayParts.push(keywordPart(SyntaxKind.InKeyword));
+                displayParts.push(spacePart());
+                if (symbol.parent) {
+                    // Class/Interface type parameter
+                    addFullSymbolName(symbol.parent, enclosingDeclaration);
+                    writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration);
+                }
+                else {
+                    // Method/function type parameter
+                    let signatureDeclaration = <SignatureDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent;
+                    let signature = typeChecker.getSignatureFromDeclaration(signatureDeclaration);
+                    if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) {
+                        displayParts.push(keywordPart(SyntaxKind.NewKeyword));
+                        displayParts.push(spacePart());
+                    }
+                    else if (signatureDeclaration.kind !== SyntaxKind.CallSignature && signatureDeclaration.name) {
+                        addFullSymbolName(signatureDeclaration.symbol);
+                    }
+                    displayParts.push.apply(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature));
+                }
+            }
+            if (symbolFlags & SymbolFlags.EnumMember) {
+                addPrefixForAnyFunctionOrVar(symbol, "enum member");
+                let declaration = symbol.declarations[0];
+                if (declaration.kind === SyntaxKind.EnumMember) {
+                    let constantValue = typeChecker.getConstantValue(<EnumMember>declaration);
+                    if (constantValue !== undefined) {
+                        displayParts.push(spacePart());
+                        displayParts.push(operatorPart(SyntaxKind.EqualsToken));
+                        displayParts.push(spacePart());
+                        displayParts.push(displayPart(constantValue.toString(), SymbolDisplayPartKind.numericLiteral));
+                    }
+                }
+            }
+            if (symbolFlags & SymbolFlags.Alias) {
+                addNewLineIfDisplayPartsExist();
+                displayParts.push(keywordPart(SyntaxKind.ImportKeyword));
+                displayParts.push(spacePart());
+                addFullSymbolName(symbol);
+                ts.forEach(symbol.declarations, declaration => {
+                    if (declaration.kind === SyntaxKind.ImportEqualsDeclaration) {
+                        let importEqualsDeclaration = <ImportEqualsDeclaration>declaration;
+                        if (isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) {
+                            displayParts.push(spacePart());
+                            displayParts.push(operatorPart(SyntaxKind.EqualsToken));
+                            displayParts.push(spacePart());
+                            displayParts.push(keywordPart(SyntaxKind.RequireKeyword));
+                            displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
+                            displayParts.push(displayPart(getTextOfNode(getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), SymbolDisplayPartKind.stringLiteral));
+                            displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
+                        }
+                        else {
+                            let internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference);
+                            if (internalAliasSymbol) {
+                                displayParts.push(spacePart());
+                                displayParts.push(operatorPart(SyntaxKind.EqualsToken));
+                                displayParts.push(spacePart());
+                                addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
+                            }
+                        }
+                        return true;
+                    }
+                });
+            }
+            if (!hasAddedSymbolInfo) {
+                if (symbolKind !== ScriptElementKind.unknown) {
+                    if (type) {
+                        addPrefixForAnyFunctionOrVar(symbol, symbolKind);
+                        // For properties, variables and local vars: show the type
+                        if (symbolKind === ScriptElementKind.memberVariableElement ||
+                            symbolFlags & SymbolFlags.Variable ||
+                            symbolKind === ScriptElementKind.localVariableElement) {
+                            displayParts.push(punctuationPart(SyntaxKind.ColonToken));
+                            displayParts.push(spacePart());
+                            // If the type is type parameter, format it specially
+                            if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) {
+                                let typeParameterParts = mapToDisplayParts(writer => {
+                                    typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(<TypeParameter>type, writer, enclosingDeclaration);
+                                });
+                                displayParts.push.apply(displayParts, typeParameterParts);
+                            }
+                            else {
+                                displayParts.push.apply(displayParts, typeToDisplayParts(typeChecker, type, enclosingDeclaration));
+                            }
+                        }
+                        else if (symbolFlags & SymbolFlags.Function ||
+                            symbolFlags & SymbolFlags.Method ||
+                            symbolFlags & SymbolFlags.Constructor ||
+                            symbolFlags & SymbolFlags.Signature ||
+                            symbolFlags & SymbolFlags.Accessor ||
+                            symbolKind === ScriptElementKind.memberFunctionElement) {
+                            let allSignatures = type.getCallSignatures();
+                            addSignatureDisplayParts(allSignatures[0], allSignatures);
+                        }
+                    }
+                }
+                else {
+                    symbolKind = getSymbolKind(symbol, location);
+                }
+            }
+
+            if (!documentation) {
+                documentation = symbol.getDocumentationComment();
+            }
+
+            return { displayParts, documentation, symbolKind };
+
+            function addNewLineIfDisplayPartsExist() {
+                if (displayParts.length) {
+                    displayParts.push(lineBreakPart());
+                }
+            }
+
+            function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) {
+                let fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined,
+                    SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing);
+                displayParts.push.apply(displayParts, fullSymbolDisplayParts);
+            }
+
+            function addPrefixForAnyFunctionOrVar(symbol: Symbol, symbolKind: string) {
+                addNewLineIfDisplayPartsExist();
+                if (symbolKind) {
+                    pushTypePart(symbolKind);
+                    displayParts.push(spacePart());
+                    addFullSymbolName(symbol);
+                }
+            }
+
+            function pushTypePart(symbolKind: string) {
+                switch (symbolKind) {
+                    case ScriptElementKind.variableElement:
+                    case ScriptElementKind.functionElement:
+                    case ScriptElementKind.letElement:
+                    case ScriptElementKind.constElement:
+                    case ScriptElementKind.constructorImplementationElement:
+                        displayParts.push(textOrKeywordPart(symbolKind));
+                        return;
+                    default:
+                        displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
+                        displayParts.push(textOrKeywordPart(symbolKind));
+                        displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
+                        return;
+                }
+            }
+
+            function addSignatureDisplayParts(signature: Signature, allSignatures: Signature[], flags?: TypeFormatFlags) {
+                displayParts.push.apply(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | TypeFormatFlags.WriteTypeArgumentsOfSignature));
+                if (allSignatures.length > 1) {
+                    displayParts.push(spacePart());
+                    displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
+                    displayParts.push(operatorPart(SyntaxKind.PlusToken));
+                    displayParts.push(displayPart((allSignatures.length - 1).toString(), SymbolDisplayPartKind.numericLiteral));
+                    displayParts.push(spacePart());
+                    displayParts.push(textPart(allSignatures.length === 2 ? "overload" : "overloads"));
+                    displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
+                }
+                documentation = signature.getDocumentationComment();
+            }
+
+            function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) {
+                let typeParameterParts = mapToDisplayParts(writer => {
+                    typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration);
+                });
+                displayParts.push.apply(displayParts, typeParameterParts);
+            }
+        }
+
+        function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+            let node = getTouchingPropertyName(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+
+            if (isLabelName(node)) {
+                return undefined;
+            }
+
+            let typeChecker = program.getTypeChecker();
+            let symbol = typeChecker.getSymbolAtLocation(node);
+
+            if (!symbol) {
+                // Try getting just type at this position and show
+                switch (node.kind) {
+                    case SyntaxKind.Identifier:
+                    case SyntaxKind.PropertyAccessExpression:
+                    case SyntaxKind.QualifiedName:
+                    case SyntaxKind.ThisKeyword:
+                    case SyntaxKind.SuperKeyword:
+                        // For the identifiers/this/super etc get the type at position
+                        let type = typeChecker.getTypeAtLocation(node);
+                        if (type) {
+                            return {
+                                kind: ScriptElementKind.unknown,
+                                kindModifiers: ScriptElementKindModifier.none,
+                                textSpan: createTextSpan(node.getStart(), node.getWidth()),
+                                displayParts: typeToDisplayParts(typeChecker, type, getContainerNode(node)),
+                                documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined
+                            };
+                        }
+                }
+
+                return undefined;
+            }
+
+            let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node);
+            return {
+                kind: displayPartsDocumentationsAndKind.symbolKind,
+                kindModifiers: getSymbolModifiers(symbol),
+                textSpan: createTextSpan(node.getStart(), node.getWidth()),
+                displayParts: displayPartsDocumentationsAndKind.displayParts,
+                documentation: displayPartsDocumentationsAndKind.documentation
+            };
+        }
+
+        function createDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo {
+            return {
+                fileName: node.getSourceFile().fileName,
+                textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()),
+                kind: symbolKind,
+                name: symbolName,
+                containerKind: undefined,
+                containerName
+            };
+        }
+
+        /// Goto definition
+        function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+
+            let node = getTouchingPropertyName(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+
+            // Labels
+            if (isJumpStatementTarget(node)) {
+                let labelName = (<Identifier>node).text;
+                let label = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
+                return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined;
+            }
+
+            /// Triple slash reference comments
+            let comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined);
+            if (comment) {
+                let referenceFile = tryResolveScriptReference(program, sourceFile, comment);
+                if (referenceFile) {
+                    return [{
+                        fileName: referenceFile.fileName,
+                        textSpan: createTextSpanFromBounds(0, 0),
+                        kind: ScriptElementKind.scriptElement,
+                        name: comment.fileName,
+                        containerName: undefined,
+                        containerKind: undefined
+                    }];
+                }
+                return undefined;
+            }
+
+            let typeChecker = program.getTypeChecker();
+            let symbol = typeChecker.getSymbolAtLocation(node);
+
+            // Could not find a symbol e.g. node is string or number keyword,
+            // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
+            if (!symbol) {
+                return undefined;
+            }
+
+            // If this is an alias, and the request came at the declaration location
+            // get the aliased symbol instead. This allows for goto def on an import e.g.
+            //   import {A, B} from "mod";
+            // to jump to the implementation directly.
+            if (symbol.flags & SymbolFlags.Alias) {
+                let declaration = symbol.declarations[0];
+                if (node.kind === SyntaxKind.Identifier && node.parent === declaration) {
+                    symbol = typeChecker.getAliasedSymbol(symbol);
+                }
+            }
+
+            // Because name in short-hand property assignment has two different meanings: property name and property value,
+            // using go-to-definition at such position should go to the variable declaration of the property value rather than
+            // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition 
+            // is performed at the location of property access, we would like to go to definition of the property in the short-hand
+            // assignment. This case and others are handled by the following code.
+            if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
+                let shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
+                if (!shorthandSymbol) {
+                    return [];
+                }
+
+                let shorthandDeclarations = shorthandSymbol.getDeclarations();
+                let shorthandSymbolKind = getSymbolKind(shorthandSymbol, node);
+                let shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol);
+                let shorthandContainerName = typeChecker.symbolToString(symbol.parent, node);
+                return map(shorthandDeclarations,
+                    declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName));
+            }
+
+            let result: DefinitionInfo[] = [];
+            let declarations = symbol.getDeclarations();
+            let symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
+            let symbolKind = getSymbolKind(symbol, node);
+            let containerSymbol = symbol.parent;
+            let containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : "";
+
+            if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
+                !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
+                // Just add all the declarations. 
+                forEach(declarations, declaration => {
+                    result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName));
+                });
+            }
+
+            return result;
+
+            function tryAddConstructSignature(symbol: Symbol, location: Node, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) {
+                // Applicable only if we are in a new expression, or we are on a constructor declaration
+                // and in either case the symbol has a construct signature definition, i.e. class
+                if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) {
+                    if (symbol.flags & SymbolFlags.Class) {
+                        let classDeclaration = <ClassDeclaration>symbol.getDeclarations()[0];
+                        Debug.assert(classDeclaration && classDeclaration.kind === SyntaxKind.ClassDeclaration);
+
+                        return tryAddSignature(classDeclaration.members, /*selectConstructors*/ true, symbolKind, symbolName, containerName, result);
+                    }
+                }
+                return false;
+            }
+
+            function tryAddCallSignature(symbol: Symbol, location: Node, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) {
+                if (isCallExpressionTarget(location) || isNewExpressionTarget(location) || isNameOfFunctionDeclaration(location)) {
+                    return tryAddSignature(symbol.declarations, /*selectConstructors*/ false, symbolKind, symbolName, containerName, result);
+                }
+                return false;
+            }
+
+            function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) {
+                let declarations: Declaration[] = [];
+                let definition: Declaration;
+
+                forEach(signatureDeclarations, d => {
+                    if ((selectConstructors && d.kind === SyntaxKind.Constructor) ||
+                        (!selectConstructors && (d.kind === SyntaxKind.FunctionDeclaration || d.kind === SyntaxKind.MethodDeclaration || d.kind === SyntaxKind.MethodSignature))) {
+                        declarations.push(d);
+                        if ((<FunctionLikeDeclaration>d).body) definition = d;
+                    }
+                });
+
+                if (definition) {
+                    result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName));
+                    return true;
+                }
+                else if (declarations.length) {
+                    result.push(createDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName));
+                    return true;
+                }
+
+                return false;
+            }
+        }
+
+        function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
+            let results = getOccurrencesAtPositionCore(fileName, position);
+            
+            if (results) {
+                let sourceFile = getCanonicalFileName(normalizeSlashes(fileName));
+
+                // Get occurrences only supports reporting occurrences for the file queried.  So 
+                // filter down to that list.
+                results = filter(results, r => getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile);
+            }
+
+            return results;
+        }
+
+        function getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] {
+            synchronizeHostData();
+
+            filesToSearch = map(filesToSearch, normalizeSlashes);
+            let sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName));
+            let sourceFile = getValidSourceFile(fileName);
+
+            let node = getTouchingWord(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+
+            return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node);
+
+            function getHighlightSpanForNode(node: Node): HighlightSpan {
+                let start = node.getStart();
+                let end = node.getEnd();
+
+                return {
+                    fileName: sourceFile.fileName,
+                    textSpan: createTextSpanFromBounds(start, end),
+                    kind: HighlightSpanKind.none
+                };
+            }
+
+            function getSemanticDocumentHighlights(node: Node): DocumentHighlights[] {
+                if (node.kind === SyntaxKind.Identifier ||
+                    node.kind === SyntaxKind.ThisKeyword ||
+                    node.kind === SyntaxKind.SuperKeyword ||
+                    isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
+                    isNameOfExternalModuleImportOrDeclaration(node)) {
+
+                    let referencedSymbols = getReferencedSymbolsForNodes(node, sourceFilesToSearch, /*findInStrings:*/ false, /*findInComments:*/ false);
+                    return convertReferencedSymbols(referencedSymbols);
+                }
+
+                return undefined;
+
+                function convertReferencedSymbols(referencedSymbols: ReferencedSymbol[]): DocumentHighlights[] {
+                    if (!referencedSymbols) {
+                        return undefined;
+                    }
+
+                    let fileNameToDocumentHighlights: Map<DocumentHighlights> = {};
+                    let result: DocumentHighlights[] = [];
+                    for (let referencedSymbol of referencedSymbols) {
+                        for (let referenceEntry of referencedSymbol.references) {
+                            let fileName = referenceEntry.fileName;
+                            let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName);
+                            if (!documentHighlights) {
+                                documentHighlights = { fileName, highlightSpans: [] };
+
+                                fileNameToDocumentHighlights[fileName] = documentHighlights;
+                                result.push(documentHighlights);
+                            }
+
+                            documentHighlights.highlightSpans.push({
+                                textSpan: referenceEntry.textSpan,
+                                kind: referenceEntry.isWriteAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference
+                            });
+                        }
+                    }
+
+                    return result;
+                }
+            }
+
+            function getSyntacticDocumentHighlights(node: Node): DocumentHighlights[] {
+                let fileName = sourceFile.fileName;
+
+                var highlightSpans = getHighlightSpans(node);
+                if (!highlightSpans || highlightSpans.length === 0) {
+                    return undefined;
+                }
+
+                return [{ fileName, highlightSpans }];
+
+                // returns true if 'node' is defined and has a matching 'kind'.
+                function hasKind(node: Node, kind: SyntaxKind) {
+                    return node !== undefined && node.kind === kind;
+                }
+
+                // Null-propagating 'parent' function.
+                function parent(node: Node): Node {
+                    return node && node.parent;
+                }
+
+                function getHighlightSpans(node: Node): HighlightSpan[] {
+                    if (node) {
+                        switch (node.kind) {
+                            case SyntaxKind.IfKeyword:
+                            case SyntaxKind.ElseKeyword:
+                                if (hasKind(node.parent, SyntaxKind.IfStatement)) {
+                                    return getIfElseOccurrences(<IfStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.ReturnKeyword:
+                                if (hasKind(node.parent, SyntaxKind.ReturnStatement)) {
+                                    return getReturnOccurrences(<ReturnStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.ThrowKeyword:
+                                if (hasKind(node.parent, SyntaxKind.ThrowStatement)) {
+                                    return getThrowOccurrences(<ThrowStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.CatchKeyword:
+                                if (hasKind(parent(parent(node)), SyntaxKind.TryStatement)) {
+                                    return getTryCatchFinallyOccurrences(<TryStatement>node.parent.parent);
+                                }
+                                break;
+                            case SyntaxKind.TryKeyword:
+                            case SyntaxKind.FinallyKeyword:
+                                if (hasKind(parent(node), SyntaxKind.TryStatement)) {
+                                    return getTryCatchFinallyOccurrences(<TryStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.SwitchKeyword:
+                                if (hasKind(node.parent, SyntaxKind.SwitchStatement)) {
+                                    return getSwitchCaseDefaultOccurrences(<SwitchStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.CaseKeyword:
+                            case SyntaxKind.DefaultKeyword:
+                                if (hasKind(parent(parent(parent(node))), SyntaxKind.SwitchStatement)) {
+                                    return getSwitchCaseDefaultOccurrences(<SwitchStatement>node.parent.parent.parent);
+                                }
+                                break;
+                            case SyntaxKind.BreakKeyword:
+                            case SyntaxKind.ContinueKeyword:
+                                if (hasKind(node.parent, SyntaxKind.BreakStatement) || hasKind(node.parent, SyntaxKind.ContinueStatement)) {
+                                    return getBreakOrContinueStatementOccurences(<BreakOrContinueStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.ForKeyword:
+                                if (hasKind(node.parent, SyntaxKind.ForStatement) ||
+                                    hasKind(node.parent, SyntaxKind.ForInStatement) ||
+                                    hasKind(node.parent, SyntaxKind.ForOfStatement)) {
+                                    return getLoopBreakContinueOccurrences(<IterationStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.WhileKeyword:
+                            case SyntaxKind.DoKeyword:
+                                if (hasKind(node.parent, SyntaxKind.WhileStatement) || hasKind(node.parent, SyntaxKind.DoStatement)) {
+                                    return getLoopBreakContinueOccurrences(<IterationStatement>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.ConstructorKeyword:
+                                if (hasKind(node.parent, SyntaxKind.Constructor)) {
+                                    return getConstructorOccurrences(<ConstructorDeclaration>node.parent);
+                                }
+                                break;
+                            case SyntaxKind.GetKeyword:
+                            case SyntaxKind.SetKeyword:
+                                if (hasKind(node.parent, SyntaxKind.GetAccessor) || hasKind(node.parent, SyntaxKind.SetAccessor)) {
+                                    return getGetAndSetOccurrences(<AccessorDeclaration>node.parent);
+                                }
+                            default:
+                                if (isModifier(node.kind) && node.parent &&
+                                    (isDeclaration(node.parent) || node.parent.kind === SyntaxKind.VariableStatement)) {
+                                    return getModifierOccurrences(node.kind, node.parent);
+                                }
+                        }
+                    }
+
+                    return undefined;
+                }
+
+                /**
+                 * Aggregates all throw-statements within this node *without* crossing
+                 * into function boundaries and try-blocks with catch-clauses.
+                 */
+                function aggregateOwnedThrowStatements(node: Node): ThrowStatement[] {
+                    let statementAccumulator: ThrowStatement[] = []
+                    aggregate(node);
+                    return statementAccumulator;
+
+                    function aggregate(node: Node): void {
+                        if (node.kind === SyntaxKind.ThrowStatement) {
+                            statementAccumulator.push(<ThrowStatement>node);
+                        }
+                        else if (node.kind === SyntaxKind.TryStatement) {
+                            let tryStatement = <TryStatement>node;
+
+                            if (tryStatement.catchClause) {
+                                aggregate(tryStatement.catchClause);
+                            }
+                            else {
+                                // Exceptions thrown within a try block lacking a catch clause
+                                // are "owned" in the current context.
+                                aggregate(tryStatement.tryBlock);
+                            }
+
+                            if (tryStatement.finallyBlock) {
+                                aggregate(tryStatement.finallyBlock);
+                            }
+                        }
+                        // Do not cross function boundaries.
+                        else if (!isFunctionLike(node)) {
+                            forEachChild(node, aggregate);
+                        }
+                    };
+                }
+
+                /**
+                 * For lack of a better name, this function takes a throw statement and returns the
+                 * nearest ancestor that is a try-block (whose try statement has a catch clause),
+                 * function-block, or source file.
+                 */
+                function getThrowStatementOwner(throwStatement: ThrowStatement): Node {
+                    let child: Node = throwStatement;
+
+                    while (child.parent) {
+                        let parent = child.parent;
+
+                        if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) {
+                            return parent;
+                        }
+                    
+                        // A throw-statement is only owned by a try-statement if the try-statement has
+                        // a catch clause, and if the throw-statement occurs within the try block.
+                        if (parent.kind === SyntaxKind.TryStatement) {
+                            let tryStatement = <TryStatement>parent;
+
+                            if (tryStatement.tryBlock === child && tryStatement.catchClause) {
+                                return child;
+                            }
+                        }
+
+                        child = parent;
+                    }
+
+                    return undefined;
+                }
+
+                function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] {
+                    let statementAccumulator: BreakOrContinueStatement[] = []
+                    aggregate(node);
+                    return statementAccumulator;
+
+                    function aggregate(node: Node): void {
+                        if (node.kind === SyntaxKind.BreakStatement || node.kind === SyntaxKind.ContinueStatement) {
+                            statementAccumulator.push(<BreakOrContinueStatement>node);
+                        }
+                        // Do not cross function boundaries.
+                        else if (!isFunctionLike(node)) {
+                            forEachChild(node, aggregate);
+                        }
+                    };
+                }
+
+                function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean {
+                    let actualOwner = getBreakOrContinueOwner(statement);
+
+                    return actualOwner && actualOwner === owner;
+                }
+
+                function getBreakOrContinueOwner(statement: BreakOrContinueStatement): Node {
+                    for (let node = statement.parent; node; node = node.parent) {
+                        switch (node.kind) {
+                            case SyntaxKind.SwitchStatement:
+                                if (statement.kind === SyntaxKind.ContinueStatement) {
+                                    continue;
+                                }
+                            // Fall through.
+                            case SyntaxKind.ForStatement:
+                            case SyntaxKind.ForInStatement:
+                            case SyntaxKind.ForOfStatement:
+                            case SyntaxKind.WhileStatement:
+                            case SyntaxKind.DoStatement:
+                                if (!statement.label || isLabeledBy(node, statement.label.text)) {
+                                    return node;
+                                }
+                                break;
+                            default:
+                                // Don't cross function boundaries.
+                                if (isFunctionLike(node)) {
+                                    return undefined;
+                                }
+                                break;
+                        }
+                    }
+
+                    return undefined;
+                }
+
+                function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): HighlightSpan[] {
+                    let container = declaration.parent;
+
+                    // Make sure we only highlight the keyword when it makes sense to do so.
+                    if (isAccessibilityModifier(modifier)) {
+                        if (!(container.kind === SyntaxKind.ClassDeclaration ||
+                            (declaration.kind === SyntaxKind.Parameter && hasKind(container, SyntaxKind.Constructor)))) {
+                            return undefined;
+                        }
+                    }
+                    else if (modifier === SyntaxKind.StaticKeyword) {
+                        if (container.kind !== SyntaxKind.ClassDeclaration) {
+                            return undefined;
+                        }
+                    }
+                    else if (modifier === SyntaxKind.ExportKeyword || modifier === SyntaxKind.DeclareKeyword) {
+                        if (!(container.kind === SyntaxKind.ModuleBlock || container.kind === SyntaxKind.SourceFile)) {
+                            return undefined;
+                        }
+                    }
+                    else { 
+                        // unsupported modifier
+                        return undefined;
+                    }
+
+                    let keywords: Node[] = [];
+                    let modifierFlag: NodeFlags = getFlagFromModifier(modifier);
+
+                    let nodes: Node[];
+                    switch (container.kind) {
+                        case SyntaxKind.ModuleBlock:
+                        case SyntaxKind.SourceFile:
+                            nodes = (<Block>container).statements;
+                            break;
+                        case SyntaxKind.Constructor:
+                            nodes = (<Node[]>(<ConstructorDeclaration>container).parameters).concat(
+                                (<ClassDeclaration>container.parent).members);
+                            break;
+                        case SyntaxKind.ClassDeclaration:
+                            nodes = (<ClassDeclaration>container).members;
+
+                            // If we're an accessibility modifier, we're in an instance member and should search
+                            // the constructor's parameter list for instance members as well.
+                            if (modifierFlag & NodeFlags.AccessibilityModifier) {
+                                let constructor = forEach((<ClassDeclaration>container).members, member => {
+                                    return member.kind === SyntaxKind.Constructor && <ConstructorDeclaration>member;
+                                });
+
+                                if (constructor) {
+                                    nodes = nodes.concat(constructor.parameters);
+                                }
+                            }
+                            break;
+                        default:
+                            Debug.fail("Invalid container kind.")
+                    }
+
+                    forEach(nodes, node => {
+                        if (node.modifiers && node.flags & modifierFlag) {
+                            forEach(node.modifiers, child => pushKeywordIf(keywords, child, modifier));
+                        }
+                    });
+
+                    return map(keywords, getHighlightSpanForNode);
+
+                    function getFlagFromModifier(modifier: SyntaxKind) {
+                        switch (modifier) {
+                            case SyntaxKind.PublicKeyword:
+                                return NodeFlags.Public;
+                            case SyntaxKind.PrivateKeyword:
+                                return NodeFlags.Private;
+                            case SyntaxKind.ProtectedKeyword:
+                                return NodeFlags.Protected;
+                            case SyntaxKind.StaticKeyword:
+                                return NodeFlags.Static;
+                            case SyntaxKind.ExportKeyword:
+                                return NodeFlags.Export;
+                            case SyntaxKind.DeclareKeyword:
+                                return NodeFlags.Ambient;
+                            default:
+                                Debug.fail();
+                        }
+                    }
+                }
+
+                function pushKeywordIf(keywordList: Node[], token: Node, ...expected: SyntaxKind[]): boolean {
+                    if (token && contains(expected, token.kind)) {
+                        keywordList.push(token);
+                        return true;
+                    }
+
+                    return false;
+                }
+
+                function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): HighlightSpan[] {
+                    let keywords: Node[] = [];
+
+                    tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor);
+                    tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor);
+
+                    return map(keywords, getHighlightSpanForNode);
+
+                    function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void {
+                        let accessor = getDeclarationOfKind(accessorSymbol, accessorKind);
+
+                        if (accessor) {
+                            forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword));
+                        }
+                    }
+                }
+
+                function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): HighlightSpan[] {
+                    let declarations = constructorDeclaration.symbol.getDeclarations()
+
+                    let keywords: Node[] = [];
+
+                    forEach(declarations, declaration => {
+                        forEach(declaration.getChildren(), token => {
+                            return pushKeywordIf(keywords, token, SyntaxKind.ConstructorKeyword);
+                        });
+                    });
+
+                    return map(keywords, getHighlightSpanForNode);
+                }
+
+                function getLoopBreakContinueOccurrences(loopNode: IterationStatement): HighlightSpan[] {
+                    let keywords: Node[] = [];
+
+                    if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) {
+                        // If we succeeded and got a do-while loop, then start looking for a 'while' keyword.
+                        if (loopNode.kind === SyntaxKind.DoStatement) {
+                            let loopTokens = loopNode.getChildren();
+
+                            for (let i = loopTokens.length - 1; i >= 0; i--) {
+                                if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) {
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement);
+
+                    forEach(breaksAndContinues, statement => {
+                        if (ownsBreakOrContinueStatement(loopNode, statement)) {
+                            pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword);
+                        }
+                    });
+
+                    return map(keywords, getHighlightSpanForNode);
+                }
+
+                function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] {
+                    let owner = getBreakOrContinueOwner(breakOrContinueStatement);
+
+                    if (owner) {
+                        switch (owner.kind) {
+                            case SyntaxKind.ForStatement:
+                            case SyntaxKind.ForInStatement:
+                            case SyntaxKind.ForOfStatement:
+                            case SyntaxKind.DoStatement:
+                            case SyntaxKind.WhileStatement:
+                                return getLoopBreakContinueOccurrences(<IterationStatement>owner)
+                            case SyntaxKind.SwitchStatement:
+                                return getSwitchCaseDefaultOccurrences(<SwitchStatement>owner);
+
+                        }
+                    }
+
+                    return undefined;
+                }
+
+                function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): HighlightSpan[] {
+                    let keywords: Node[] = [];
+
+                    pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword);
+
+                    // Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
+                    forEach(switchStatement.caseBlock.clauses, clause => {
+                        pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword);
+
+                        let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause);
+
+                        forEach(breaksAndContinues, statement => {
+                            if (ownsBreakOrContinueStatement(switchStatement, statement)) {
+                                pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword);
+                            }
+                        });
+                    });
+
+                    return map(keywords, getHighlightSpanForNode);
+                }
+
+                function getTryCatchFinallyOccurrences(tryStatement: TryStatement): HighlightSpan[] {
+                    let keywords: Node[] = [];
+
+                    pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword);
+
+                    if (tryStatement.catchClause) {
+                        pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword);
+                    }
+
+                    if (tryStatement.finallyBlock) {
+                        let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
+                        pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword);
+                    }
+
+                    return map(keywords, getHighlightSpanForNode);
+                }
+
+                function getThrowOccurrences(throwStatement: ThrowStatement): HighlightSpan[] {
+                    let owner = getThrowStatementOwner(throwStatement);
+
+                    if (!owner) {
+                        return undefined;
+                    }
+
+                    let keywords: Node[] = [];
+
+                    forEach(aggregateOwnedThrowStatements(owner), throwStatement => {
+                        pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword);
+                    });
+
+                    // If the "owner" is a function, then we equate 'return' and 'throw' statements in their
+                    // ability to "jump out" of the function, and include occurrences for both.
+                    if (isFunctionBlock(owner)) {
+                        forEachReturnStatement(<Block>owner, returnStatement => {
+                            pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
+                        });
+                    }
+
+                    return map(keywords, getHighlightSpanForNode);
+                }
+
+                function getReturnOccurrences(returnStatement: ReturnStatement): HighlightSpan[] {
+                    let func = <FunctionLikeDeclaration>getContainingFunction(returnStatement);
+
+                    // If we didn't find a containing function with a block body, bail out.
+                    if (!(func && hasKind(func.body, SyntaxKind.Block))) {
+                        return undefined;
+                    }
+
+                    let keywords: Node[] = []
+                    forEachReturnStatement(<Block>func.body, returnStatement => {
+                        pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
+                    });
+
+                    // Include 'throw' statements that do not occur within a try block.
+                    forEach(aggregateOwnedThrowStatements(func.body), throwStatement => {
+                        pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword);
+                    });
+
+                    return map(keywords, getHighlightSpanForNode);
+                }
+
+                function getIfElseOccurrences(ifStatement: IfStatement): HighlightSpan[] {
+                    let keywords: Node[] = [];
+
+                    // Traverse upwards through all parent if-statements linked by their else-branches.
+                    while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (<IfStatement>ifStatement.parent).elseStatement === ifStatement) {
+                        ifStatement = <IfStatement>ifStatement.parent;
+                    }
+
+                    // Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
+                    while (ifStatement) {
+                        let children = ifStatement.getChildren();
+                        pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword);
+
+                        // Generally the 'else' keyword is second-to-last, so we traverse backwards.
+                        for (let i = children.length - 1; i >= 0; i--) {
+                            if (pushKeywordIf(keywords, children[i], SyntaxKind.ElseKeyword)) {
+                                break;
+                            }
+                        }
+
+                        if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) {
+                            break
+                        }
+
+                        ifStatement = <IfStatement>ifStatement.elseStatement;
+                    }
+
+                    let result: HighlightSpan[] = [];
+
+                    // We'd like to highlight else/ifs together if they are only separated by whitespace
+                    // (i.e. the keywords are separated by no comments, no newlines).
+                    for (let i = 0; i < keywords.length; i++) {
+                        if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) {
+                            let elseKeyword = keywords[i];
+                            let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
+
+                            let shouldCombindElseAndIf = true;
+
+                            // Avoid recalculating getStart() by iterating backwards.
+                            for (let j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
+                                if (!isWhiteSpace(sourceFile.text.charCodeAt(j))) {
+                                    shouldCombindElseAndIf = false;
+                                    break;
+                                }
+                            }
+
+                            if (shouldCombindElseAndIf) {
+                                result.push({
+                                    fileName: fileName,
+                                    textSpan: createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
+                                    kind: HighlightSpanKind.reference
+                                });
+                                i++; // skip the next keyword
+                                continue;
+                            }
+                        }
+
+                        // Ordinary case: just highlight the keyword.
+                        result.push(getHighlightSpanForNode(keywords[i]));
+                    }
+
+                    return result;
+                }
+            }
+        }
+
+        /// References and Occurrences
+        function getOccurrencesAtPositionCore(fileName: string, position: number): ReferenceEntry[] {
+            synchronizeHostData();
+
+            return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName]));
+
+            function convertDocumentHighlights(documentHighlights: DocumentHighlights[]): ReferenceEntry[] {
+                if (!documentHighlights) {
+                    return undefined;
+                }
+
+                let result: ReferenceEntry[] = [];
+                for (let entry of documentHighlights) {
+                    for (let highlightSpan of entry.highlightSpans) {
+                        result.push({
+                            fileName: entry.fileName,
+                            textSpan: highlightSpan.textSpan,
+                            isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference
+                        });
+                    }
+                }
+
+                return result;
+            }
+        }
+
+        function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] {
+            if (!referenceSymbols) {
+                return undefined;
+            }
+
+            let referenceEntries: ReferenceEntry[] = [];
+
+            for (let referenceSymbol of referenceSymbols) {
+                addRange(referenceEntries, referenceSymbol.references);
+            }
+
+            return referenceEntries;
+        }
+
+        function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
+            var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments);
+            return convertReferences(referencedSymbols);
+        }
+
+        function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
+            var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false);
+            return convertReferences(referencedSymbols);
+        }
+
+        function findReferences(fileName: string, position: number): ReferencedSymbol[]{
+            var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false);
+
+            // Only include referenced symbols that have a valid definition.
+            return filter(referencedSymbols, rs => !!rs.definition);
+        }
+
+        function findReferencedSymbols(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] {
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+
+            let node = getTouchingPropertyName(sourceFile, position);
+            if (!node) {
+                return undefined;
+            }
+
+            if (node.kind !== SyntaxKind.Identifier &&
+                // TODO (drosen): This should be enabled in a later release - currently breaks rename.
+                //node.kind !== SyntaxKind.ThisKeyword &&
+                //node.kind !== SyntaxKind.SuperKeyword &&
+                !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) &&
+                !isNameOfExternalModuleImportOrDeclaration(node)) {
+                return undefined;
+            }
+
+            Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.NumericLiteral || node.kind === SyntaxKind.StringLiteral);
+            return getReferencedSymbolsForNodes(node, program.getSourceFiles(), findInStrings, findInComments);
+        }
+
+        function getReferencedSymbolsForNodes(node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] {
+            let typeChecker = program.getTypeChecker();
+
+            // Labels
+            if (isLabelName(node)) {
+                if (isJumpStatementTarget(node)) {
+                    let labelDefinition = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
+                    // if we have a label definition, look within its statement for references, if not, then
+                    // the label is undefined and we have no results..
+                    return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined;
+                }
+                else {
+                    // it is a label definition and not a target, search within the parent labeledStatement
+                    return getLabelReferencesInNode(node.parent, <Identifier>node);
+                }
+            }
+
+            if (node.kind === SyntaxKind.ThisKeyword) {
+                return getReferencesForThisKeyword(node, sourceFiles);
+            }
+
+            if (node.kind === SyntaxKind.SuperKeyword) {
+                return getReferencesForSuperKeyword(node);
+            }
+
+            let symbol = typeChecker.getSymbolAtLocation(node);
+
+            // Could not find a symbol e.g. unknown identifier
+            if (!symbol) {
+                // Can't have references to something that we have no symbol for.
+                return undefined;
+            }
+
+            let declarations = symbol.declarations;
+
+            // The symbol was an internal symbol and does not have a declaration e.g.undefined symbol
+            if (!declarations || !declarations.length) {
+                return undefined;
+            }
+
+            let result: ReferencedSymbol[];
+
+            // Compute the meaning from the location and the symbol it references
+            let searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
+
+            // Get the text to search for, we need to normalize it as external module names will have quote
+            let declaredName = getDeclaredName(symbol, node);
+
+            // Try to get the smallest valid scope that we can limit our search to;
+            // otherwise we'll need to search globally (i.e. include each file).
+            let scope = getSymbolScope(symbol);
+
+            // Maps from a symbol ID to the ReferencedSymbol entry in 'result'.
+            let symbolToIndex: number[] = [];
+
+            if (scope) {
+                result = [];
+                getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
+            }
+            else {
+                let internedName = getInternedName(symbol, node, declarations)
+                for (let sourceFile of sourceFiles) {
+                    cancellationToken.throwIfCancellationRequested();
+
+                    let nameTable = getNameTable(sourceFile);
+
+                    if (lookUp(nameTable, internedName)) {
+                        result = result || [];
+                        getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
+                    }
+                }
+            }
+
+            return result;
+
+            function getDefinition(symbol: Symbol): DefinitionInfo {
+                let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node);
+                let name = map(info.displayParts, p => p.text).join("");
+                let declarations = symbol.declarations;
+                if (!declarations || declarations.length === 0) {
+                    return undefined;
+                }
+
+                return {
+                    containerKind: "",
+                    containerName: "",
+                    name,
+                    kind: info.symbolKind,
+                    fileName: declarations[0].getSourceFile().fileName,
+                    textSpan: createTextSpan(declarations[0].getStart(), 0)
+                };
+            }
+
+            function isImportOrExportSpecifierName(location: Node): boolean {
+                return location.parent &&
+                    (location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) &&
+                    (<ImportOrExportSpecifier>location.parent).propertyName === location;
+            }
+
+            function isImportOrExportSpecifierImportSymbol(symbol: Symbol) {
+                return (symbol.flags & SymbolFlags.Alias) && forEach(symbol.declarations, declaration => {
+                    return declaration.kind === SyntaxKind.ImportSpecifier || declaration.kind === SyntaxKind.ExportSpecifier;
+                });
+            }
+
+            function getDeclaredName(symbol: Symbol, location: Node) {
+                // Special case for function expressions, whose names are solely local to their bodies.
+                let functionExpression = forEach(symbol.declarations, d => d.kind === SyntaxKind.FunctionExpression ? <FunctionExpression>d : undefined);
+
+                // When a name gets interned into a SourceFile's 'identifiers' Map,
+                // its name is escaped and stored in the same way its symbol name/identifier
+                // name should be stored. Function expressions, however, are a special case,
+                // because despite sometimes having a name, the binder unconditionally binds them
+                // to a symbol with the name "__function".
+                let name: string;
+                if (functionExpression && functionExpression.name) {
+                    name = functionExpression.name.text;
+                }
+
+                // If this is an export or import specifier it could have been renamed using the as syntax.
+                // if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name)
+                // so check for the propertyName.
+                if (isImportOrExportSpecifierName(location)) {
+                    return location.getText();
+                }
+
+                name = typeChecker.symbolToString(symbol);
+
+                return stripQuotes(name);
+            }
+
+            function getInternedName(symbol: Symbol, location: Node, declarations: Declaration[]): string {
+                // If this is an export or import specifier it could have been renamed using the as syntax.
+                // if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name)
+                // so check for the propertyName.
+                if (isImportOrExportSpecifierName(location)) {
+                    return location.getText();
+                }
+
+                // Special case for function expressions, whose names are solely local to their bodies.
+                let functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? <FunctionExpression>d : undefined);
+
+                // When a name gets interned into a SourceFile's 'identifiers' Map,
+                // its name is escaped and stored in the same way its symbol name/identifier
+                // name should be stored. Function expressions, however, are a special case,
+                // because despite sometimes having a name, the binder unconditionally binds them
+                // to a symbol with the name "__function".
+                let name = functionExpression && functionExpression.name
+                    ? functionExpression.name.text
+                    : symbol.name;
+
+                return stripQuotes(name);
+            }
+
+            function stripQuotes(name: string) {
+                let length = name.length;
+                if (length >= 2 && name.charCodeAt(0) === CharacterCodes.doubleQuote && name.charCodeAt(length - 1) === CharacterCodes.doubleQuote) {
+                    return name.substring(1, length - 1);
+                };
+                return name;
+            }
+
+            function getSymbolScope(symbol: Symbol): Node {
+                // If this is private property or method, the scope is the containing class
+                if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) {
+                    let privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined);
+                    if (privateDeclaration) {
+                        return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration);
+                    }
+                }
+
+                // If the symbol is an import we would like to find it if we are looking for what it imports.
+                // So consider it visibile outside its declaration scope.
+                if (symbol.flags & SymbolFlags.Alias) {
+                    return undefined;
+                }
+
+                // if this symbol is visible from its parent container, e.g. exported, then bail out
+                // if symbol correspond to the union property - bail out
+                if (symbol.parent || (symbol.flags & SymbolFlags.UnionProperty)) {
+                    return undefined;
+                }
+
+                let scope: Node = undefined;
+
+                let declarations = symbol.getDeclarations();
+                if (declarations) {
+                    for (let declaration of declarations) {
+                        let container = getContainerNode(declaration);
+
+                        if (!container) {
+                            return undefined;
+                        }
+
+                        if (scope && scope !== container) {
+                            // Different declarations have different containers, bail out
+                            return undefined;
+                        }
+
+                        if (container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container)) {
+                            // This is a global variable and not an external module, any declaration defined
+                            // within this scope is visible outside the file
+                            return undefined;
+                        }
+
+                        // The search scope is the container node
+                        scope = container;
+                    }
+                }
+
+                return scope;
+            }
+
+            function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, start: number, end: number): number[] {
+                let positions: number[] = [];
+
+                /// TODO: Cache symbol existence for files to save text search
+                // Also, need to make this work for unicode escapes.
+
+                // Be resilient in the face of a symbol with no name or zero length name
+                if (!symbolName || !symbolName.length) {
+                    return positions;
+                }
+
+                let text = sourceFile.text;
+                let sourceLength = text.length;
+                let symbolNameLength = symbolName.length;
+
+                let position = text.indexOf(symbolName, start);
+                while (position >= 0) {
+                    cancellationToken.throwIfCancellationRequested();
+
+                    // If we are past the end, stop looking
+                    if (position > end) break;
+
+                    // We found a match.  Make sure it's not part of a larger word (i.e. the char 
+                    // before and after it have to be a non-identifier char).
+                    let endPosition = position + symbolNameLength;
+
+                    if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) &&
+                        (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) {
+                        // Found a real match.  Keep searching.  
+                        positions.push(position);
+                    }
+                    position = text.indexOf(symbolName, position + symbolNameLength + 1);
+                }
+
+                return positions;
+            }
+
+            function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferencedSymbol[] {
+                let references: ReferenceEntry[] = [];
+                let sourceFile = container.getSourceFile();
+                let labelName = targetLabel.text;
+                let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd());
+                forEach(possiblePositions, position => {
+                    cancellationToken.throwIfCancellationRequested();
+
+                    let node = getTouchingWord(sourceFile, position);
+                    if (!node || node.getWidth() !== labelName.length) {
+                        return;
+                    }
+
+                    // Only pick labels that are either the target label, or have a target that is the target label
+                    if (node === targetLabel ||
+                        (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) {
+                        references.push(getReferenceEntryFromNode(node));
+                    }
+                });
+
+                var definition: DefinitionInfo = {
+                    containerKind: "",
+                    containerName: "",
+                    fileName: targetLabel.getSourceFile().fileName,
+                    kind: ScriptElementKind.label,
+                    name: labelName,
+                    textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd())
+                }
+
+                return [{ definition, references }];
+            }
+
+            function isValidReferencePosition(node: Node, searchSymbolName: string): boolean {
+                if (node) {
+                    // Compare the length so we filter out strict superstrings of the symbol we are looking for
+                    switch (node.kind) {
+                        case SyntaxKind.Identifier:
+                            return node.getWidth() === searchSymbolName.length;
+
+                        case SyntaxKind.StringLiteral:
+                            if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
+                                isNameOfExternalModuleImportOrDeclaration(node)) {
+                                // For string literals we have two additional chars for the quotes
+                                return node.getWidth() === searchSymbolName.length + 2;
+                            }
+                            break;
+
+                        case SyntaxKind.NumericLiteral:
+                            if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
+                                return node.getWidth() === searchSymbolName.length;
+                            }
+                            break;
+                    }
+                }
+
+                return false;
+            }
+
+            /** Search within node "container" for references for a search value, where the search value is defined as a 
+              * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
+              * searchLocation: a node where the search value 
+              */
+            function getReferencesInNode(container: Node,
+                searchSymbol: Symbol,
+                searchText: string,
+                searchLocation: Node,
+                searchMeaning: SemanticMeaning,
+                findInStrings: boolean,
+                findInComments: boolean,
+                result: ReferencedSymbol[],
+                symbolToIndex: number[]): void {
+
+                let sourceFile = container.getSourceFile();
+                let tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</
+
+                let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
+
+                if (possiblePositions.length) {
+                    // Build the set of symbols to search for, initially it has only the current symbol
+                    let searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation);
+
+                    forEach(possiblePositions, position => {
+                        cancellationToken.throwIfCancellationRequested();
+
+                        let referenceLocation = getTouchingPropertyName(sourceFile, position);
+                        if (!isValidReferencePosition(referenceLocation, searchText)) {
+                            // This wasn't the start of a token.  Check to see if it might be a 
+                            // match in a comment or string if that's what the caller is asking
+                            // for.
+                            if ((findInStrings && isInString(position)) ||
+                                (findInComments && isInComment(position))) {
+
+                                // In the case where we're looking inside comments/strings, we don't have
+                                // an actual definition.  So just use 'undefined' here.  Features like
+                                // 'Rename' won't care (as they ignore the definitions), and features like
+                                // 'FindReferences' will just filter out these results.
+                                result.push({
+                                    definition: undefined,
+                                    references: [{
+                                        fileName: sourceFile.fileName,
+                                        textSpan: createTextSpan(position, searchText.length),
+                                        isWriteAccess: false
+                                    }]
+                                });
+                            }
+                            return;
+                        }
+
+                        if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
+                            return;
+                        }
+
+                        let referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
+                        if (referenceSymbol) {
+                            let referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
+                            let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
+                            var relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation);
+
+                            if (relatedSymbol) {
+                                var referencedSymbol = getReferencedSymbol(relatedSymbol);
+                                referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation));
+                            }
+                            /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
+                             * has two meaning : property name and property value. Therefore when we do findAllReference at the position where
+                             * an identifier is declared, the language service should return the position of the variable declaration as well as
+                             * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
+                             * position of property accessing, the referenceEntry of such position will be handled in the first case.
+                             */
+                            else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
+                                var referencedSymbol = getReferencedSymbol(shorthandValueSymbol);
+                                referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name));
+                            }
+                        }
+                    });
+                }
+
+                return;
+
+                function getReferencedSymbol(symbol: Symbol): ReferencedSymbol {
+                    var symbolId = getSymbolId(symbol);
+                    var index = symbolToIndex[symbolId];
+                    if (index === undefined) {
+                        index = result.length;
+                        symbolToIndex[symbolId] = index;
+
+                        result.push({
+                            definition: getDefinition(symbol),
+                            references: []
+                        });
+                    }
+
+                    return result[index];
+                }
+
+                function isInString(position: number) {
+                    let token = getTokenAtPosition(sourceFile, position);
+                    return token && token.kind === SyntaxKind.StringLiteral && position > token.getStart();
+                }
+
+                function isInComment(position: number) {
+                    let token = getTokenAtPosition(sourceFile, position);
+                    if (token && position < token.getStart()) {
+                        // First, we have to see if this position actually landed in a comment.
+                        let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos);
+
+                        // Then we want to make sure that it wasn't in a "///<" directive comment
+                        // We don't want to unintentionally update a file name.
+                        return forEach(commentRanges, c => {
+                            if (c.pos < position && position < c.end) {
+                                let commentText = sourceFile.text.substring(c.pos, c.end);
+                                if (!tripleSlashDirectivePrefixRegex.test(commentText)) {
+                                    return true;
+                                }
+                            }
+                        });
+                    }
+
+                    return false;
+                }
+            }
+
+            function getReferencesForSuperKeyword(superKeyword: Node): ReferencedSymbol[] {
+                let searchSpaceNode = getSuperContainer(superKeyword, /*includeFunctions*/ false);
+                if (!searchSpaceNode) {
+                    return undefined;
+                }
+                // Whether 'super' occurs in a static context within a class.
+                let staticFlag = NodeFlags.Static;
+
+                switch (searchSpaceNode.kind) {
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                        staticFlag &= searchSpaceNode.flags;
+                        searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
+                        break;
+                    default:
+                        return undefined;
+                }
+
+                let references: ReferenceEntry[] = [];
+
+                let sourceFile = searchSpaceNode.getSourceFile();
+                let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
+                forEach(possiblePositions, position => {
+                    cancellationToken.throwIfCancellationRequested();
+
+                    let node = getTouchingWord(sourceFile, position);
+
+                    if (!node || node.kind !== SyntaxKind.SuperKeyword) {
+                        return;
+                    }
+
+                    let container = getSuperContainer(node, /*includeFunctions*/ false);
+
+                    // If we have a 'super' container, we must have an enclosing class.
+                    // Now make sure the owning class is the same as the search-space
+                    // and has the same static qualifier as the original 'super's owner.
+                    if (container && (NodeFlags.Static & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
+                        references.push(getReferenceEntryFromNode(node));
+                    }
+                });
+
+                var definition = getDefinition(searchSpaceNode.symbol);
+                return [{ definition, references }];
+            }
+
+            function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[]): ReferencedSymbol[] {
+                let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
+
+                // Whether 'this' occurs in a static context within a class.
+                let staticFlag = NodeFlags.Static;
+
+                switch (searchSpaceNode.kind) {
+                    case SyntaxKind.MethodDeclaration:
+                    case SyntaxKind.MethodSignature:
+                        if (isObjectLiteralMethod(searchSpaceNode)) {
+                            break;
+                        }
+                    // fall through
+                    case SyntaxKind.PropertyDeclaration:
+                    case SyntaxKind.PropertySignature:
+                    case SyntaxKind.Constructor:
+                    case SyntaxKind.GetAccessor:
+                    case SyntaxKind.SetAccessor:
+                        staticFlag &= searchSpaceNode.flags
+                        searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
+                        break;
+                    case SyntaxKind.SourceFile:
+                        if (isExternalModule(<SourceFile>searchSpaceNode)) {
+                            return undefined;
+                        }
+                    // Fall through
+                    case SyntaxKind.FunctionDeclaration:
+                    case SyntaxKind.FunctionExpression:
+                        break;
+                    // Computed properties in classes are not handled here because references to this are illegal,
+                    // so there is no point finding references to them.
+                    default:
+                        return undefined;
+                }
+
+                let references: ReferenceEntry[] = [];
+
+                let possiblePositions: number[];
+                if (searchSpaceNode.kind === SyntaxKind.SourceFile) {
+                    forEach(sourceFiles, sourceFile => {
+                        possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd());
+                        getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references);
+                    });
+                }
+                else {
+                    let sourceFile = searchSpaceNode.getSourceFile();
+                    possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
+                    getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references);
+                }
+
+                return [{
+                    definition: {
+                        containerKind: "",
+                        containerName: "",
+                        fileName: node.getSourceFile().fileName,
+                        kind: ScriptElementKind.variableElement,
+                        name: "this",
+                        textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd())
+                    },
+                    references: references
+                }];
+
+                function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: number[], result: ReferenceEntry[]): void {
+                    forEach(possiblePositions, position => {
+                        cancellationToken.throwIfCancellationRequested();
+
+                        let node = getTouchingWord(sourceFile, position);
+                        if (!node || node.kind !== SyntaxKind.ThisKeyword) {
+                            return;
+                        }
+
+                        let container = getThisContainer(node, /* includeArrowFunctions */ false);
+
+                        switch (searchSpaceNode.kind) {
+                            case SyntaxKind.FunctionExpression:
+                            case SyntaxKind.FunctionDeclaration:
+                                if (searchSpaceNode.symbol === container.symbol) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                            case SyntaxKind.MethodDeclaration:
+                            case SyntaxKind.MethodSignature:
+                                if (isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                            case SyntaxKind.ClassDeclaration:
+                                // Make sure the container belongs to the same class
+                                // and has the appropriate static modifier from the original container.
+                                if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & NodeFlags.Static) === staticFlag) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                            case SyntaxKind.SourceFile:
+                                if (container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container)) {
+                                    result.push(getReferenceEntryFromNode(node));
+                                }
+                                break;
+                        }
+                    });
+                }
+            }
+
+            function populateSearchSymbolSet(symbol: Symbol, location: Node): Symbol[] {
+                // The search set contains at least the current symbol
+                let result = [symbol];
+
+                // If the symbol is an alias, add what it alaises to the list
+                if (isImportOrExportSpecifierImportSymbol(symbol)) {
+                    result.push(typeChecker.getAliasedSymbol(symbol));
+                }
+
+                // If the location is in a context sensitive location (i.e. in an object literal) try
+                // to get a contextual type for it, and add the property symbol from the contextual
+                // type to the search set
+                if (isNameOfPropertyAssignment(location)) {
+                    forEach(getPropertySymbolsFromContextualType(location), contextualSymbol => {
+                        result.push.apply(result, typeChecker.getRootSymbols(contextualSymbol));
+                    });
+
+                    /* Because in short-hand property assignment, location has two meaning : property name and as value of the property
+                     * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
+                     * property name and variable declaration of the identifier.
+                     * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service
+                     * should show both 'name' in 'obj' and 'name' in variable declaration
+                     *      let name = "Foo";
+                     *      let obj = { name };
+                     * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment
+                     * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
+                     * will be included correctly.
+                     */
+                    let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent);
+                    if (shorthandValueSymbol) {
+                        result.push(shorthandValueSymbol);
+                    }
+                }
+
+                // If this is a union property, add all the symbols from all its source symbols in all unioned types.
+                // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
+                forEach(typeChecker.getRootSymbols(symbol), rootSymbol => {
+                    if (rootSymbol !== symbol) {
+                        result.push(rootSymbol);
+                    }
+
+                    // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
+                    if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
+                        getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
+                    }
+                });
+
+                return result;
+            }
+
+            function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Symbol[]): void {
+                if (symbol && symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
+                    forEach(symbol.getDeclarations(), declaration => {
+                        if (declaration.kind === SyntaxKind.ClassDeclaration) {
+                            getPropertySymbolFromTypeReference(getClassExtendsHeritageClauseElement(<ClassDeclaration>declaration));
+                            forEach(getClassImplementsHeritageClauseElements(<ClassDeclaration>declaration), getPropertySymbolFromTypeReference);
+                        }
+                        else if (declaration.kind === SyntaxKind.InterfaceDeclaration) {
+                            forEach(getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration), getPropertySymbolFromTypeReference);
+                        }
+                    });
+                }
+                return;
+
+                function getPropertySymbolFromTypeReference(typeReference: HeritageClauseElement) {
+                    if (typeReference) {
+                        let type = typeChecker.getTypeAtLocation(typeReference);
+                        if (type) {
+                            let propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
+                            if (propertySymbol) {
+                                result.push(propertySymbol);
+                            }
+
+                            // Visit the typeReference as well to see if it directly or indirectly use that property
+                            getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result);
+                        }
+                    }
+                }
+            }
+
+            function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): Symbol {
+                if (searchSymbols.indexOf(referenceSymbol) >= 0) {
+                    return referenceSymbol;
+                }
+
+                // If the reference symbol is an alias, check if what it is aliasing is one of the search
+                // symbols.
+                if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) {
+                    var aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol);
+                    if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
+                        return aliasedSymbol;
+                    }
+                }
+
+                // If the reference location is in an object literal, try to get the contextual type for the 
+                // object literal, lookup the property symbol in the contextual type, and use this symbol to
+                // compare to our searchSymbol
+                if (isNameOfPropertyAssignment(referenceLocation)) {
+                    return forEach(getPropertySymbolsFromContextualType(referenceLocation), contextualSymbol => {
+                        return forEach(typeChecker.getRootSymbols(contextualSymbol), s => searchSymbols.indexOf(s) >= 0 ? s : undefined);
+                    });
+                }
+
+                // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
+                // Or a union property, use its underlying unioned symbols
+                return forEach(typeChecker.getRootSymbols(referenceSymbol), rootSymbol => {
+                    // if it is in the list, then we are done
+                    if (searchSymbols.indexOf(rootSymbol) >= 0) {
+                        return rootSymbol;
+                    }
+
+                    // Finally, try all properties with the same name in any type the containing type extended or implemented, and 
+                    // see if any is in the list
+                    if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
+                        let result: Symbol[] = [];
+                        getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result);
+                        return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined);
+                    }
+
+                    return undefined;
+                });
+            }
+
+            function getPropertySymbolsFromContextualType(node: Node): Symbol[] {
+                if (isNameOfPropertyAssignment(node)) {
+                    let objectLiteral = <ObjectLiteralExpression>node.parent.parent;
+                    let contextualType = typeChecker.getContextualType(objectLiteral);
+                    let name = (<Identifier>node).text;
+                    if (contextualType) {
+                        if (contextualType.flags & TypeFlags.Union) {
+                            // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types)
+                            // if not, search the constituent types for the property
+                            let unionProperty = contextualType.getProperty(name)
+                            if (unionProperty) {
+                                return [unionProperty];
+                            }
+                            else {
+                                let result: Symbol[] = [];
+                                forEach((<UnionType>contextualType).types, t => {
+                                    let symbol = t.getProperty(name);
+                                    if (symbol) {
+                                        result.push(symbol);
+                                    }
+                                });
+                                return result;
+                            }
+                        }
+                        else {
+                            let symbol = contextualType.getProperty(name);
+                            if (symbol) {
+                                return [symbol];
+                            }
+                        }
+                    }
+                }
+                return undefined;
+            }
+
+            /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
+              * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
+              * then we need to widen the search to include type positions as well.
+              * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
+              * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
+              * do not intersect in any of the three spaces.
+              */
+            function getIntersectingMeaningFromDeclarations(meaning: SemanticMeaning, declarations: Declaration[]): SemanticMeaning {
+                if (declarations) {
+                    let lastIterationMeaning: SemanticMeaning;
+                    do {
+                        // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module]
+                        // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module
+                        // intersects with the class in the value space.
+                        // To achieve that we will keep iterating until the result stabilizes.
+
+                        // Remember the last meaning
+                        lastIterationMeaning = meaning;
+
+                        for (let declaration of declarations) {
+                            let declarationMeaning = getMeaningFromDeclaration(declaration);
+
+                            if (declarationMeaning & meaning) {
+                                meaning |= declarationMeaning;
+                            }
+                        }
+                    }
+                    while (meaning !== lastIterationMeaning);
+                }
+                return meaning;
+            }
+        }
+
+        function getReferenceEntryFromNode(node: Node): ReferenceEntry {
+            let start = node.getStart();
+            let end = node.getEnd();
+
+            if (node.kind === SyntaxKind.StringLiteral) {
+                start += 1;
+                end -= 1;
+            }
+
+            return {
+                fileName: node.getSourceFile().fileName,
+                textSpan: createTextSpanFromBounds(start, end),
+                isWriteAccess: isWriteAccess(node)
+            };
+        }
+
+        /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
+        function isWriteAccess(node: Node): boolean {
+            if (node.kind === SyntaxKind.Identifier && isDeclarationName(node)) {
+                return true;
+            }
+
+            let parent = node.parent;
+            if (parent) {
+                if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) {
+                    return true;
+                }
+                else if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).left === node) {
+                    let operator = (<BinaryExpression>parent).operatorToken.kind;
+                    return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment;
+                }
+            }
+
+            return false;
+        }
+
+        /// NavigateTo
+        function getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[] {
+            synchronizeHostData();
+
+            return ts.NavigateTo.getNavigateToItems(program, cancellationToken, searchValue, maxResultCount);
+        }
+
+        function containErrors(diagnostics: Diagnostic[]): boolean {
+            return forEach(diagnostics, diagnostic => diagnostic.category === DiagnosticCategory.Error);
+        }
+
+        function getEmitOutput(fileName: string): EmitOutput {
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+            let outputFiles: OutputFile[] = [];
+
+            function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) {
+                outputFiles.push({
+                    name: fileName,
+                    writeByteOrderMark: writeByteOrderMark,
+                    text: data
+                });
+            }
+
+            let emitOutput = program.emit(sourceFile, writeFile);
+
+            return {
+                outputFiles,
+                emitSkipped: emitOutput.emitSkipped
+            };
+        }
+
+        function getMeaningFromDeclaration(node: Node): SemanticMeaning {
+            switch (node.kind) {
+                case SyntaxKind.Parameter:
+                case SyntaxKind.VariableDeclaration:
+                case SyntaxKind.BindingElement:
+                case SyntaxKind.PropertyDeclaration:
+                case SyntaxKind.PropertySignature:
+                case SyntaxKind.PropertyAssignment:
+                case SyntaxKind.ShorthandPropertyAssignment:
+                case SyntaxKind.EnumMember:
+                case SyntaxKind.MethodDeclaration:
+                case SyntaxKind.MethodSignature:
+                case SyntaxKind.Constructor:
+                case SyntaxKind.GetAccessor:
+                case SyntaxKind.SetAccessor:
+                case SyntaxKind.FunctionDeclaration:
+                case SyntaxKind.FunctionExpression:
+                case SyntaxKind.ArrowFunction:
+                case SyntaxKind.CatchClause:
+                    return SemanticMeaning.Value;
+
+                case SyntaxKind.TypeParameter:
+                case SyntaxKind.InterfaceDeclaration:
+                case SyntaxKind.TypeAliasDeclaration:
+                case SyntaxKind.TypeLiteral:
+                    return SemanticMeaning.Type;
+
+                case SyntaxKind.ClassDeclaration:
+                case SyntaxKind.EnumDeclaration:
+                    return SemanticMeaning.Value | SemanticMeaning.Type;
+
+                case SyntaxKind.ModuleDeclaration:
+                    if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral) {
+                        return SemanticMeaning.Namespace | SemanticMeaning.Value;
+                    }
+                    else if (getModuleInstanceState(node) === ModuleInstanceState.Instantiated) {
+                        return SemanticMeaning.Namespace | SemanticMeaning.Value;
+                    }
+                    else {
+                        return SemanticMeaning.Namespace;
+                    }
+
+                case SyntaxKind.NamedImports:
+                case SyntaxKind.ImportSpecifier:
+                case SyntaxKind.ImportEqualsDeclaration:
+                case SyntaxKind.ImportDeclaration:
+                case SyntaxKind.ExportAssignment:
+                case SyntaxKind.ExportDeclaration:
+                    return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
+
+                // An external module can be a Value
+                case SyntaxKind.SourceFile:
+                    return SemanticMeaning.Namespace | SemanticMeaning.Value;
+            }
+
+            return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
+
+            Debug.fail("Unknown declaration type");
+        }
+
+        function isTypeReference(node: Node): boolean {
+            if (isRightSideOfQualifiedNameOrPropertyAccess(node) ) {
+                node = node.parent;
+            }
+
+            return node.parent.kind === SyntaxKind.TypeReference || node.parent.kind === SyntaxKind.HeritageClauseElement;
+        }
+
+        function isNamespaceReference(node: Node): boolean {
+            return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node);
+        }
+
+        function isPropertyAccessNamespaceReference(node: Node): boolean {
+            let root = node;
+            let isLastClause = true;
+            if (root.parent.kind === SyntaxKind.PropertyAccessExpression) {
+                while (root.parent && root.parent.kind === SyntaxKind.PropertyAccessExpression) {
+                    root = root.parent;
+                }
+
+                isLastClause = (<PropertyAccessExpression>root).name === node;
+            }
+
+            if (!isLastClause && root.parent.kind === SyntaxKind.HeritageClauseElement && root.parent.parent.kind === SyntaxKind.HeritageClause) {
+                let decl = root.parent.parent.parent;
+                return (decl.kind === SyntaxKind.ClassDeclaration && (<HeritageClause>root.parent.parent).token === SyntaxKind.ImplementsKeyword) ||
+                    (decl.kind === SyntaxKind.InterfaceDeclaration && (<HeritageClause>root.parent.parent).token === SyntaxKind.ExtendsKeyword);
+            }
+
+            return false;
+        }
+
+        function isQualifiedNameNamespaceReference(node: Node): boolean {
+            let root = node;
+            let isLastClause = true;
+            if (root.parent.kind === SyntaxKind.QualifiedName) {
+                while (root.parent && root.parent.kind === SyntaxKind.QualifiedName) {
+                    root = root.parent;
+                }
+
+                isLastClause = (<QualifiedName>root).right === node;
+            }
+
+            return root.parent.kind === SyntaxKind.TypeReference && !isLastClause;
+        }
+
+        function isInRightSideOfImport(node: Node) {
+            while (node.parent.kind === SyntaxKind.QualifiedName) {
+                node = node.parent;
+            }
+            return isInternalModuleImportEqualsDeclaration(node.parent) && (<ImportEqualsDeclaration>node.parent).moduleReference === node;
+        }
+
+        function getMeaningFromRightHandSideOfImportEquals(node: Node) {
+            Debug.assert(node.kind === SyntaxKind.Identifier);
+
+            //     import a = |b|; // Namespace
+            //     import a = |b.c|; // Value, type, namespace
+            //     import a = |b.c|.d; // Namespace
+
+            if (node.parent.kind === SyntaxKind.QualifiedName &&
+                (<QualifiedName>node.parent).right === node &&
+                node.parent.parent.kind === SyntaxKind.ImportEqualsDeclaration) {
+                return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
+            }
+            return SemanticMeaning.Namespace;
+        }
+
+        function getMeaningFromLocation(node: Node): SemanticMeaning {
+            if (node.parent.kind === SyntaxKind.ExportAssignment) {
+                return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
+            }
+            else if (isInRightSideOfImport(node)) {
+                return getMeaningFromRightHandSideOfImportEquals(node);
+            }
+            else if (isDeclarationName(node)) {
+                return getMeaningFromDeclaration(node.parent);
+            }
+            else if (isTypeReference(node)) {
+                return SemanticMeaning.Type;
+            }
+            else if (isNamespaceReference(node)) {
+                return SemanticMeaning.Namespace;
+            }
+            else {
+                return SemanticMeaning.Value;
+            }
+        }
+
+        // Signature help
+        /**
+         * This is a semantic operation.
+         */
+        function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+
+            return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken);
+        }
+
+        /// Syntactic features
+        function getSourceFile(fileName: string): SourceFile {
+            return syntaxTreeCache.getCurrentSourceFile(fileName);
+        }
+
+        function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan {
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+
+            // Get node at the location
+            let node = getTouchingPropertyName(sourceFile, startPos);
+
+            if (!node) {
+                return;
+            }
+
+            switch (node.kind) {
+                case SyntaxKind.PropertyAccessExpression:
+                case SyntaxKind.QualifiedName:
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.FalseKeyword:
+                case SyntaxKind.TrueKeyword:
+                case SyntaxKind.NullKeyword:
+                case SyntaxKind.SuperKeyword:
+                case SyntaxKind.ThisKeyword:
+                case SyntaxKind.Identifier:
+                    break;
+
+                // Cant create the text span
+                default:
+                    return;
+            }
+
+            let nodeForStartPos = node;
+            while (true) {
+                if (isRightSideOfPropertyAccess(nodeForStartPos) || isRightSideOfQualifiedName(nodeForStartPos)) {
+                    // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node
+                    nodeForStartPos = nodeForStartPos.parent;
+                }
+                else if (isNameOfModuleDeclaration(nodeForStartPos)) {
+                    // If this is name of a module declarations, check if this is right side of dotted module name
+                    // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of 
+                    // Then this name is name from dotted module
+                    if (nodeForStartPos.parent.parent.kind === SyntaxKind.ModuleDeclaration &&
+                        (<ModuleDeclaration>nodeForStartPos.parent.parent).body === nodeForStartPos.parent) {
+                        // Use parent module declarations name for start pos
+                        nodeForStartPos = (<ModuleDeclaration>nodeForStartPos.parent.parent).name;
+                    }
+                    else {
+                        // We have to use this name for start pos
+                        break;
+                    }
+                }
+                else {
+                    // Is not a member expression so we have found the node for start pos
+                    break;
+                }
+            }
+
+            return createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd());
+        }
+
+        function getBreakpointStatementAtPosition(fileName: string, position: number) {
+            // doesn't use compiler - no need to synchronize with host
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+
+            return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position);
+        }
+
+        function getNavigationBarItems(fileName: string): NavigationBarItem[]{
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+
+            return NavigationBar.getNavigationBarItems(sourceFile);
+        }
+
+        function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+            let typeChecker = program.getTypeChecker();
+
+            let result: ClassifiedSpan[] = [];
+            processNode(sourceFile);
+
+            return result;
+
+            function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning) {
+                let flags = symbol.getFlags();
+
+                if (flags & SymbolFlags.Class) {
+                    return ClassificationTypeNames.className;
+                }
+                else if (flags & SymbolFlags.Enum) {
+                    return ClassificationTypeNames.enumName;
+                }
+                else if (flags & SymbolFlags.TypeAlias) {
+                    return ClassificationTypeNames.typeAlias;
+                }
+                else if (meaningAtPosition & SemanticMeaning.Type) {
+                    if (flags & SymbolFlags.Interface) {
+                        return ClassificationTypeNames.interfaceName;
+                    }
+                    else if (flags & SymbolFlags.TypeParameter) {
+                        return ClassificationTypeNames.typeParameterName;
+                    }
+                }
+                else if (flags & SymbolFlags.Module) {
+                    // Only classify a module as such if
+                    //  - It appears in a namespace context.
+                    //  - There exists a module declaration which actually impacts the value side.
+                    if (meaningAtPosition & SemanticMeaning.Namespace ||
+                        (meaningAtPosition & SemanticMeaning.Value && hasValueSideModule(symbol))) {
+                        return ClassificationTypeNames.moduleName;
+                    }
+                }
+
+                return undefined;
+
+                /**
+                 * Returns true if there exists a module that introduces entities on the value side.
+                 */
+                function hasValueSideModule(symbol: Symbol): boolean {
+                    return forEach(symbol.declarations, declaration => {
+                        return declaration.kind === SyntaxKind.ModuleDeclaration && getModuleInstanceState(declaration) == ModuleInstanceState.Instantiated;
+                    });
+                }
+            }
+
+            function processNode(node: Node) {
+                // Only walk into nodes that intersect the requested span.
+                if (node && textSpanIntersectsWith(span, node.getStart(), node.getWidth())) {
+                    if (node.kind === SyntaxKind.Identifier && node.getWidth() > 0) {
+                        let symbol = typeChecker.getSymbolAtLocation(node);
+                        if (symbol) {
+                            let type = classifySymbol(symbol, getMeaningFromLocation(node));
+                            if (type) {
+                                result.push({
+                                    textSpan: createTextSpan(node.getStart(), node.getWidth()),
+                                    classificationType: type
+                                });
+                            }
+                        }
+                    }
+
+                    forEachChild(node, processNode);
+                }
+            }
+        }
+
+        function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
+            // doesn't use compiler - no need to synchronize with host
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+
+            // Make a scanner we can get trivia from.
+            let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
+            let mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
+
+            let result: ClassifiedSpan[] = [];
+            processElement(sourceFile);
+
+            return result;
+
+            function classifyLeadingTrivia(token: Node): void {
+                let tokenStart = skipTrivia(sourceFile.text, token.pos, /*stopAfterLineBreak:*/ false);
+                if (tokenStart === token.pos) {
+                    return;
+                }
+
+                // token has trivia.  Classify them appropriately.
+                triviaScanner.setTextPos(token.pos);
+                while (true) {
+                    let start = triviaScanner.getTextPos();
+                    let kind = triviaScanner.scan();
+                    let end = triviaScanner.getTextPos();
+                    let width = end - start;
+
+                    if (textSpanIntersectsWith(span, start, width)) {
+                        if (!isTrivia(kind)) {
+                            return;
+                        }
+
+                        if (isComment(kind)) {
+                            // Simple comment.  Just add as is.
+                            result.push({
+                                textSpan: createTextSpan(start, width),
+                                classificationType: ClassificationTypeNames.comment
+                            })
+                            continue;
+                        }
+
+                        if (kind === SyntaxKind.ConflictMarkerTrivia) {
+                            let text = sourceFile.text;
+                            let ch = text.charCodeAt(start);
+
+                            // for the <<<<<<< and >>>>>>> markers, we just add them in as comments
+                            // in the classification stream.
+                            if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
+                                result.push({
+                                    textSpan: createTextSpan(start, width),
+                                    classificationType: ClassificationTypeNames.comment
+                                });
+                                continue;
+                            }
+
+                            // for the ======== add a comment for the first line, and then lex all
+                            // subsequent lines up until the end of the conflict marker.
+                            Debug.assert(ch === CharacterCodes.equals);
+                            classifyDisabledMergeCode(text, start, end);
+                        }
+                    }
+                }
+            }
+
+            function classifyDisabledMergeCode(text: string, start: number, end: number) {
+                // Classify the line that the ======= marker is on as a comment.  Then just lex 
+                // all further tokens and add them to the result.
+                for (var i = start; i < end; i++) {
+                    if (isLineBreak(text.charCodeAt(i))) {
+                        break;
+                    }
+                }
+                result.push({
+                    textSpan: createTextSpanFromBounds(start, i),
+                    classificationType: ClassificationTypeNames.comment
+                });
+
+                mergeConflictScanner.setTextPos(i);
+
+                while (mergeConflictScanner.getTextPos() < end) {
+                    classifyDisabledCodeToken();
+                }
+            }
+
+            function classifyDisabledCodeToken() {
+                let start = mergeConflictScanner.getTextPos();
+                let tokenKind = mergeConflictScanner.scan();
+                let end = mergeConflictScanner.getTextPos();
+
+                let type = classifyTokenType(tokenKind);
+                if (type) {
+                    result.push({
+                        textSpan: createTextSpanFromBounds(start, end),
+                        classificationType: type
+                    });
+                }
+            }
+
+            function classifyToken(token: Node): void {
+                classifyLeadingTrivia(token);
+
+                if (token.getWidth() > 0) {
+                    let type = classifyTokenType(token.kind, token);
+                    if (type) {
+                        result.push({
+                            textSpan: createTextSpan(token.getStart(), token.getWidth()),
+                            classificationType: type
+                        });
+                    }
+                }
+            }
+
+            // for accurate classification, the actual token should be passed in.  however, for 
+            // cases like 'disabled merge code' classification, we just get the token kind and
+            // classify based on that instead.
+            function classifyTokenType(tokenKind: SyntaxKind, token?: Node): string {
+                if (isKeyword(tokenKind)) {
+                    return ClassificationTypeNames.keyword;
+                }
+
+                // Special case < and >  If they appear in a generic context they are punctuation,
+                // not operators.
+                if (tokenKind === SyntaxKind.LessThanToken || tokenKind === SyntaxKind.GreaterThanToken) {
+                    // If the node owning the token has a type argument list or type parameter list, then
+                    // we can effectively assume that a '<' and '>' belong to those lists.
+                    if (token && getTypeArgumentOrTypeParameterList(token.parent)) {
+                        return ClassificationTypeNames.punctuation;
+                    }
+                }
+
+                if (isPunctuation(tokenKind)) {
+                    if (token) {
+                        if (tokenKind === SyntaxKind.EqualsToken) {
+                            // the '=' in a variable declaration is special cased here.
+                            if (token.parent.kind === SyntaxKind.VariableDeclaration ||
+                                token.parent.kind === SyntaxKind.PropertyDeclaration ||
+                                token.parent.kind === SyntaxKind.Parameter) {
+                                return ClassificationTypeNames.operator;
+                            }
+                        }
+
+                        if (token.parent.kind === SyntaxKind.BinaryExpression ||
+                            token.parent.kind === SyntaxKind.PrefixUnaryExpression ||
+                            token.parent.kind === SyntaxKind.PostfixUnaryExpression ||
+                            token.parent.kind === SyntaxKind.ConditionalExpression) {
+                            return ClassificationTypeNames.operator;
+                        }
+                    }
+
+                    return ClassificationTypeNames.punctuation;
+                }
+                else if (tokenKind === SyntaxKind.NumericLiteral) {
+                    return ClassificationTypeNames.numericLiteral;
+                }
+                else if (tokenKind === SyntaxKind.StringLiteral) {
+                    return ClassificationTypeNames.stringLiteral;
+                }
+                else if (tokenKind === SyntaxKind.RegularExpressionLiteral) {
+                    // TODO: we should get another classification type for these literals.
+                    return ClassificationTypeNames.stringLiteral;
+                }
+                else if (isTemplateLiteralKind(tokenKind)) {
+                    // TODO (drosen): we should *also* get another classification type for these literals.
+                    return ClassificationTypeNames.stringLiteral;
+                }
+                else if (tokenKind === SyntaxKind.Identifier) {
+                    if (token) {
+                        switch (token.parent.kind) {
+                            case SyntaxKind.ClassDeclaration:
+                                if ((<ClassDeclaration>token.parent).name === token) {
+                                    return ClassificationTypeNames.className;
+                                }
+                                return;
+                            case SyntaxKind.TypeParameter:
+                                if ((<TypeParameterDeclaration>token.parent).name === token) {
+                                    return ClassificationTypeNames.typeParameterName;
+                                }
+                                return;
+                            case SyntaxKind.InterfaceDeclaration:
+                                if ((<InterfaceDeclaration>token.parent).name === token) {
+                                    return ClassificationTypeNames.interfaceName;
+                                }
+                                return;
+                            case SyntaxKind.EnumDeclaration:
+                                if ((<EnumDeclaration>token.parent).name === token) {
+                                    return ClassificationTypeNames.enumName;
+                                }
+                                return;
+                            case SyntaxKind.ModuleDeclaration:
+                                if ((<ModuleDeclaration>token.parent).name === token) {
+                                    return ClassificationTypeNames.moduleName;
+                                }
+                                return;
+                        }
+                    }
+
+                    return ClassificationTypeNames.text;
+                }
+            }
+
+            function processElement(element: Node) {
+                // Ignore nodes that don't intersect the original span to classify.
+                if (textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) {
+                    let children = element.getChildren();
+                    for (let child of children) {
+                        if (isToken(child)) {
+                            classifyToken(child);
+                        }
+                        else {
+                            // Recurse into our child nodes.
+                            processElement(child);
+                        }
+                    }
+                }
+            }
+        }
+
+        function getOutliningSpans(fileName: string): OutliningSpan[] {
+            // doesn't use compiler - no need to synchronize with host
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return OutliningElementsCollector.collectElements(sourceFile);
+        }
+
+        function getBraceMatchingAtPosition(fileName: string, position: number) {
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            let result: TextSpan[] = [];
+
+            let token = getTouchingToken(sourceFile, position);
+
+            if (token.getStart(sourceFile) === position) {
+                let matchKind = getMatchingTokenKind(token);
+
+                // Ensure that there is a corresponding token to match ours.
+                if (matchKind) {
+                    let parentElement = token.parent;
+
+                    let childNodes = parentElement.getChildren(sourceFile);
+                    for (let current of childNodes) {
+                        if (current.kind === matchKind) {
+                            let range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile));
+                            let range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile));
+
+                            // We want to order the braces when we return the result.
+                            if (range1.start < range2.start) {
+                                result.push(range1, range2);
+                            }
+                            else {
+                                result.push(range2, range1);
+                            }
+
+                            break;
+                        }
+                    }
+                }
+            }
+
+            return result;
+
+            function getMatchingTokenKind(token: Node): ts.SyntaxKind {
+                switch (token.kind) {
+                    case ts.SyntaxKind.OpenBraceToken:      return ts.SyntaxKind.CloseBraceToken
+                    case ts.SyntaxKind.OpenParenToken:      return ts.SyntaxKind.CloseParenToken;
+                    case ts.SyntaxKind.OpenBracketToken:    return ts.SyntaxKind.CloseBracketToken;
+                    case ts.SyntaxKind.LessThanToken:       return ts.SyntaxKind.GreaterThanToken;
+                    case ts.SyntaxKind.CloseBraceToken:     return ts.SyntaxKind.OpenBraceToken
+                    case ts.SyntaxKind.CloseParenToken:     return ts.SyntaxKind.OpenParenToken;
+                    case ts.SyntaxKind.CloseBracketToken:   return ts.SyntaxKind.OpenBracketToken;
+                    case ts.SyntaxKind.GreaterThanToken:    return ts.SyntaxKind.LessThanToken;
+                }
+
+                return undefined;
+            }
+        }
+
+        function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) {
+            let start = new Date().getTime();
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
+
+            start = new Date().getTime();
+
+            let result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions);
+            log("getIndentationAtPosition: computeIndentation  : " + (new Date().getTime() - start));
+
+            return result;
+        }
+
+        function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] {
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options);
+        }
+
+        function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+            return formatting.formatDocument(sourceFile, getRuleProvider(options), options);
+        }
+
+        function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] {
+            let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
+
+            if (key === "}") {
+                return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options);
+            }
+            else if (key === ";") {
+                return formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options);
+            }
+            else if (key === "\n") {
+                return formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options);
+            }
+
+            return [];
+        }
+
+        function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] {
+            // Note: while getting todo comments seems like a syntactic operation, we actually 
+            // treat it as a semantic operation here.  This is because we expect our host to call
+            // this on every single file.  If we treat this syntactically, then that will cause
+            // us to populate and throw away the tree in our syntax tree cache for each file.  By
+            // treating this as a semantic operation, we can access any tree without throwing 
+            // anything away.
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+
+            cancellationToken.throwIfCancellationRequested();
+
+            let fileContents = sourceFile.text;
+            let result: TodoComment[] = [];
+
+            if (descriptors.length > 0) {
+                let regExp = getTodoCommentsRegExp();
+
+                let matchArray: RegExpExecArray;
+                while (matchArray = regExp.exec(fileContents)) {
+                    cancellationToken.throwIfCancellationRequested();
+
+                    // If we got a match, here is what the match array will look like.  Say the source text is:
+                    //
+                    //      "    // hack   1"
+                    //
+                    // The result array with the regexp:    will be:
+                    //
+                    //      ["// hack   1", "// ", "hack   1", undefined, "hack"]
+                    //
+                    // Here are the relevant capture groups:
+                    //  0) The full match for the entire regexp.
+                    //  1) The preamble to the message portion.
+                    //  2) The message portion.
+                    //  3...N) The descriptor that was matched - by index.  'undefined' for each 
+                    //         descriptor that didn't match.  an actual value if it did match.
+                    //
+                    //  i.e. 'undefined' in position 3 above means TODO(jason) didn't match.
+                    //       "hack"      in position 4 means HACK did match.
+                    let firstDescriptorCaptureIndex = 3;
+                    Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex);
+
+                    let preamble = matchArray[1];
+                    let matchPosition = matchArray.index + preamble.length;
+
+                    // OK, we have found a match in the file.  This is only an acceptable match if
+                    // it is contained within a comment.
+                    let token = getTokenAtPosition(sourceFile, matchPosition);
+                    if (!isInsideComment(sourceFile, token, matchPosition)) {
+                        continue;
+                    }
+
+                    let descriptor: TodoCommentDescriptor = undefined;
+                    for (let i = 0, n = descriptors.length; i < n; i++) {
+                        if (matchArray[i + firstDescriptorCaptureIndex]) {
+                            descriptor = descriptors[i];
+                        }
+                    }
+                    Debug.assert(descriptor !== undefined);
+
+                    // We don't want to match something like 'TODOBY', so we make sure a non 
+                    // letter/digit follows the match.
+                    if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) {
+                        continue;
+                    }
+
+                    let message = matchArray[2];
+                    result.push({
+                        descriptor: descriptor,
+                        message: message,
+                        position: matchPosition
+                    });
+                }
+            }
+
+            return result;
+
+            function escapeRegExp(str: string): string {
+                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+            }
+
+            function getTodoCommentsRegExp(): RegExp {
+                // NOTE: ?:  means 'non-capture group'.  It allows us to have groups without having to
+                // filter them out later in the final result array.
+
+                // TODO comments can appear in one of the following forms:
+                //
+                //  1)      // TODO     or  /////////// TODO
+                //
+                //  2)      /* TODO     or  /********** TODO
+                //
+                //  3)      /*
+                //           *   TODO
+                //           */
+                //
+                // The following three regexps are used to match the start of the text up to the TODO
+                // comment portion.
+                let singleLineCommentStart = /(?:\/\/+\s*)/.source;
+                let multiLineCommentStart = /(?:\/\*+\s*)/.source;
+                let anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
+
+                // Match any of the above three TODO comment start regexps.
+                // Note that the outermost group *is* a capture group.  We want to capture the preamble
+                // so that we can determine the starting position of the TODO comment match.
+                let preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")";
+
+                // Takes the descriptors and forms a regexp that matches them as if they were literals.
+                // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be:
+                //
+                //      (?:(TODO\(jason\))|(HACK))
+                //
+                // Note that the outermost group is *not* a capture group, but the innermost groups
+                // *are* capture groups.  By capturing the inner literals we can determine after 
+                // matching which descriptor we are dealing with.
+                let literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")";
+
+                // After matching a descriptor literal, the following regexp matches the rest of the 
+                // text up to the end of the line (or */).
+                let endOfLineOrEndOfComment = /(?:$|\*\/)/.source
+                let messageRemainder = /(?:.*?)/.source
+
+                // This is the portion of the match we'll return as part of the TODO comment result. We
+                // match the literal portion up to the end of the line or end of comment.
+                let messagePortion = "(" + literals + messageRemainder + ")";
+                let regExpString = preamble + messagePortion + endOfLineOrEndOfComment;
+
+                // The final regexp will look like this:
+                // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim
+
+                // The flags of the regexp are important here.
+                //  'g' is so that we are doing a global search and can find matches several times
+                //  in the input.
+                //
+                //  'i' is for case insensitivity (We do this to match C# TODO comment code).
+                //
+                //  'm' is so we can find matches in a multi-line input.
+                return new RegExp(regExpString, "gim");
+            }
+
+            function isLetterOrDigit(char: number): boolean {
+                return (char >= CharacterCodes.a && char <= CharacterCodes.z) ||
+                    (char >= CharacterCodes.A && char <= CharacterCodes.Z) ||
+                    (char >= CharacterCodes._0 && char <= CharacterCodes._9);
+            }
+        }
+
+
+        function getRenameInfo(fileName: string, position: number): RenameInfo {
+            synchronizeHostData();
+
+            let sourceFile = getValidSourceFile(fileName);
+            let typeChecker = program.getTypeChecker();
+
+            let node = getTouchingWord(sourceFile, position);
+
+            // Can only rename an identifier.
+            if (node && node.kind === SyntaxKind.Identifier) {
+                let symbol = typeChecker.getSymbolAtLocation(node);
+
+                // Only allow a symbol to be renamed if it actually has at least one declaration.
+                if (symbol) {
+                    let declarations = symbol.getDeclarations();
+                    if (declarations && declarations.length > 0) {
+                        // Disallow rename for elements that are defined in the standard TypeScript library.
+                        let defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings());
+                        if (defaultLibFileName) {
+                            for (let current of declarations) {
+                                let sourceFile = current.getSourceFile();
+                                if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) {
+                                    return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library.key));
+                                }
+                            }
+                        }
+
+                        let kind = getSymbolKind(symbol, node);
+                        if (kind) {
+                            return {
+                                canRename: true,
+                                localizedErrorMessage: undefined,
+                                displayName: symbol.name,
+                                fullDisplayName: typeChecker.getFullyQualifiedName(symbol),
+                                kind: kind,
+                                kindModifiers: getSymbolModifiers(symbol),
+                                triggerSpan: createTextSpan(node.getStart(), node.getWidth())
+                            };
+                        }
+                    }
+                }
+            }
+
+            return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_this_element.key));
+
+            function getRenameInfoError(localizedErrorMessage: string): RenameInfo {
+                return {
+                    canRename: false,
+                    localizedErrorMessage: localizedErrorMessage,
+                    displayName: undefined,
+                    fullDisplayName: undefined,
+                    kind: undefined,
+                    kindModifiers: undefined,
+                    triggerSpan: undefined
+                };
+            }
+        }
+
+        return {
+            dispose,
+            cleanupSemanticCache,
+            getSyntacticDiagnostics,
+            getSemanticDiagnostics,
+            getCompilerOptionsDiagnostics,
+            getSyntacticClassifications,
+            getSemanticClassifications,
+            getCompletionsAtPosition,
+            getCompletionEntryDetails,
+            getSignatureHelpItems,
+            getQuickInfoAtPosition,
+            getDefinitionAtPosition,
+            getReferencesAtPosition,
+            findReferences,
+            getOccurrencesAtPosition,
+            getDocumentHighlights,
+            getNameOrDottedNameSpan,
+            getBreakpointStatementAtPosition,
+            getNavigateToItems,
+            getRenameInfo,
+            findRenameLocations,
+            getNavigationBarItems,
+            getOutliningSpans,
+            getTodoComments,
+            getBraceMatchingAtPosition,
+            getIndentationAtPosition,
+            getFormattingEditsForRange,
+            getFormattingEditsForDocument,
+            getFormattingEditsAfterKeystroke,
+            getEmitOutput,
+            getSourceFile,
+            getProgram
+        };
+    }
+
+    /* @internal */
+    export function getNameTable(sourceFile: SourceFile): Map<string> {
+        if (!sourceFile.nameTable) {
+            initializeNameTable(sourceFile)
+        }
+
+        return sourceFile.nameTable;
+    }
+
+    function initializeNameTable(sourceFile: SourceFile): void {
+        let nameTable: Map<string> = {};
+
+        walk(sourceFile);
+        sourceFile.nameTable = nameTable;
+
+        function walk(node: Node) {
+            switch (node.kind) {
+                case SyntaxKind.Identifier:
+                    nameTable[(<Identifier>node).text] = (<Identifier>node).text;
+                    break;
+                case SyntaxKind.StringLiteral:
+                case SyntaxKind.NumericLiteral:
+                    // We want to store any numbers/strings if they were a name that could be
+                    // related to a declaration.  So, if we have 'import x = require("something")'
+                    // then we want 'something' to be in the name table.  Similarly, if we have
+                    // "a['propname']" then we want to store "propname" in the name table.
+                    if (isDeclarationName(node) ||
+                        node.parent.kind === SyntaxKind.ExternalModuleReference ||
+                        isArgumentOfElementAccessExpression(node)) {
+
+                        nameTable[(<LiteralExpression>node).text] = (<LiteralExpression>node).text;
+                    }
+                    break;
+                default:
+                    forEachChild(node, walk);
+            }
+        }
+    }
+
+    function isArgumentOfElementAccessExpression(node: Node) {
+        return node &&
+            node.parent &&
+            node.parent.kind === SyntaxKind.ElementAccessExpression &&
+            (<ElementAccessExpression>node.parent).argumentExpression === node;
+    }
+
+    /// Classifier
+    export function createClassifier(): Classifier {
+        let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
+
+        /// We do not have a full parser support to know when we should parse a regex or not
+        /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where
+        /// we have a series of divide operator. this list allows us to be more accurate by ruling out 
+        /// locations where a regexp cannot exist.
+        let noRegexTable: boolean[] = [];
+        noRegexTable[SyntaxKind.Identifier] = true;
+        noRegexTable[SyntaxKind.StringLiteral] = true;
+        noRegexTable[SyntaxKind.NumericLiteral] = true;
+        noRegexTable[SyntaxKind.RegularExpressionLiteral] = true;
+        noRegexTable[SyntaxKind.ThisKeyword] = true;
+        noRegexTable[SyntaxKind.PlusPlusToken] = true;
+        noRegexTable[SyntaxKind.MinusMinusToken] = true;
+        noRegexTable[SyntaxKind.CloseParenToken] = true;
+        noRegexTable[SyntaxKind.CloseBracketToken] = true;
+        noRegexTable[SyntaxKind.CloseBraceToken] = true;
+        noRegexTable[SyntaxKind.TrueKeyword] = true;
+        noRegexTable[SyntaxKind.FalseKeyword] = true;
+
+        // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact)
+        // classification on template strings. Because of the context free nature of templates,
+        // the only precise way to classify a template portion would be by propagating the stack across
+        // lines, just as we do with the end-of-line state. However, this is a burden for implementers,
+        // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead
+        // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state.
+        // Situations in which this fails are
+        //  1) When template strings are nested across different lines:
+        //          `hello ${ `world
+        //          ` }`
+        //
+        //     Where on the second line, you will get the closing of a template,
+        //     a closing curly, and a new template.
+        //
+        //  2) When substitution expressions have curly braces and the curly brace falls on the next line:
+        //          `hello ${ () => {
+        //          return "world" } } `
+        //
+        //     Where on the second line, you will get the 'return' keyword,
+        //     a string literal, and a template end consisting of '} } `'.
+        let templateStack: SyntaxKind[] = [];
+
+        /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */
+        function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) {
+            if (isAccessibilityModifier(keyword1)) {
+                if (keyword2 === SyntaxKind.GetKeyword ||
+                    keyword2 === SyntaxKind.SetKeyword ||
+                    keyword2 === SyntaxKind.ConstructorKeyword ||
+                    keyword2 === SyntaxKind.StaticKeyword) {
+
+                    // Allow things like "public get", "public constructor" and "public static".  
+                    // These are all legal.
+                    return true;
+                }
+
+                // Any other keyword following "public" is actually an identifier an not a real
+                // keyword.
+                return false;
+            }
+
+            // Assume any other keyword combination is legal.  This can be refined in the future
+            // if there are more cases we want the classifier to be better at.
+            return true;
+        }
+        
+        // If there is a syntactic classifier ('syntacticClassifierAbsent' is false),
+        // we will be more conservative in order to avoid conflicting with the syntactic classifier.
+        function getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult {
+            let offset = 0;
+            let token = SyntaxKind.Unknown;
+            let lastNonTriviaToken = SyntaxKind.Unknown;
+
+            // Empty out the template stack for reuse.
+            while (templateStack.length > 0) {
+                templateStack.pop();
+            }
+
+            // If we're in a string literal, then prepend: "\
+            // (and a newline).  That way when we lex we'll think we're still in a string literal.
+            //
+            // If we're in a multiline comment, then prepend: /*
+            // (and a newline).  That way when we lex we'll think we're still in a multiline comment.
+            switch (lexState) {
+                case EndOfLineState.InDoubleQuoteStringLiteral:
+                    text = '"\\\n' + text;
+                    offset = 3;
+                    break;
+                case EndOfLineState.InSingleQuoteStringLiteral:
+                    text = "'\\\n" + text;
+                    offset = 3;
+                    break;
+                case EndOfLineState.InMultiLineCommentTrivia:
+                    text = "/*\n" + text;
+                    offset = 3;
+                    break;
+                case EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate:
+                    text = "`\n" + text;
+                    offset = 2;
+                    break;
+                case EndOfLineState.InTemplateMiddleOrTail:
+                    text = "}\n" + text;
+                    offset = 2;
+                    // fallthrough
+                case EndOfLineState.InTemplateSubstitutionPosition:
+                    templateStack.push(SyntaxKind.TemplateHead);
+                    break;
+            }
+
+            scanner.setText(text);
+
+            let result: ClassificationResult = {
+                finalLexState: EndOfLineState.Start,
+                entries: []
+            };
+
+            // We can run into an unfortunate interaction between the lexical and syntactic classifier
+            // when the user is typing something generic.  Consider the case where the user types:
+            //
+            //      Foo<number
+            //
+            // From the lexical classifier's perspective, 'number' is a keyword, and so the word will
+            // be classified as such.  However, from the syntactic classifier's tree-based perspective
+            // this is simply an expression with the identifier 'number' on the RHS of the less than
+            // token.  So the classification will go back to being an identifier.  The moment the user
+            // types again, number will become a keyword, then an identifier, etc. etc.
+            //
+            // To try to avoid this problem, we avoid classifying contextual keywords as keywords 
+            // when the user is potentially typing something generic.  We just can't do a good enough
+            // job at the lexical level, and so well leave it up to the syntactic classifier to make
+            // the determination.
+            //
+            // In order to determine if the user is potentially typing something generic, we use a 
+            // weak heuristic where we track < and > tokens.  It's a weak heuristic, but should
+            // work well enough in practice.
+            let angleBracketStack = 0;
+
+            do {
+                token = scanner.scan();
+
+                if (!isTrivia(token)) {
+                    if ((token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) && !noRegexTable[lastNonTriviaToken]) {
+                         if (scanner.reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
+                             token = SyntaxKind.RegularExpressionLiteral;
+                         }
+                    }
+                    else if (lastNonTriviaToken === SyntaxKind.DotToken && isKeyword(token)) {
+                        token = SyntaxKind.Identifier;
+                    }
+                    else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) {
+                        // We have two keywords in a row.  Only treat the second as a keyword if 
+                        // it's a sequence that could legally occur in the language.  Otherwise
+                        // treat it as an identifier.  This way, if someone writes "private var"
+                        // we recognize that 'var' is actually an identifier here.
+                        token = SyntaxKind.Identifier;
+                    }
+                    else if (lastNonTriviaToken === SyntaxKind.Identifier &&
+                             token === SyntaxKind.LessThanToken) {
+                        // Could be the start of something generic.  Keep track of that by bumping 
+                        // up the current count of generic contexts we may be in.
+                        angleBracketStack++;
+                    }
+                    else if (token === SyntaxKind.GreaterThanToken && angleBracketStack > 0) {
+                        // If we think we're currently in something generic, then mark that that
+                        // generic entity is complete.
+                        angleBracketStack--;
+                    }
+                    else if (token === SyntaxKind.AnyKeyword ||
+                             token === SyntaxKind.StringKeyword ||
+                             token === SyntaxKind.NumberKeyword ||
+                             token === SyntaxKind.BooleanKeyword ||
+                             token === SyntaxKind.SymbolKeyword) {
+                        if (angleBracketStack > 0 && !syntacticClassifierAbsent) {
+                            // If it looks like we're could be in something generic, don't classify this 
+                            // as a keyword.  We may just get overwritten by the syntactic classifier,
+                            // causing a noisy experience for the user.
+                            token = SyntaxKind.Identifier;
+                        }
+                    }
+                    else if (token === SyntaxKind.TemplateHead) {
+                        templateStack.push(token);
+                    }
+                    else if (token === SyntaxKind.OpenBraceToken) {
+                        // If we don't have anything on the template stack,
+                        // then we aren't trying to keep track of a previously scanned template head.
+                        if (templateStack.length > 0) {
+                            templateStack.push(token);
+                        }
+                    }
+                    else if (token === SyntaxKind.CloseBraceToken) {
+                        // If we don't have anything on the template stack,
+                        // then we aren't trying to keep track of a previously scanned template head.
+                        if (templateStack.length > 0) {
+                            let lastTemplateStackToken = lastOrUndefined(templateStack);
+
+                            if (lastTemplateStackToken === SyntaxKind.TemplateHead) {
+                                token = scanner.reScanTemplateToken();
+
+                                // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us.
+                                if (token === SyntaxKind.TemplateTail) {
+                                    templateStack.pop();
+                                }
+                                else {
+                                    Debug.assert(token === SyntaxKind.TemplateMiddle, "Should have been a template middle. Was " + token);
+                                }
+                            }
+                            else {
+                                Debug.assert(lastTemplateStackToken === SyntaxKind.OpenBraceToken, "Should have been an open brace. Was: " + token);
+                                templateStack.pop();
+                            }
+                        }
+                    }
+
+                    lastNonTriviaToken = token;
+                }
+
+                processToken();
+            }
+            while (token !== SyntaxKind.EndOfFileToken);
+
+            return result;
+
+            function processToken(): void {
+                let start = scanner.getTokenPos();
+                let end = scanner.getTextPos();
+
+                addResult(end - start, classFromKind(token));
+
+                if (end >= text.length) {
+                    if (token === SyntaxKind.StringLiteral) {
+                        // Check to see if we finished up on a multiline string literal.
+                        let tokenText = scanner.getTokenText();
+                        if (scanner.isUnterminated()) {
+                            let lastCharIndex = tokenText.length - 1;
+
+                            let numBackslashes = 0;
+                            while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) {
+                                numBackslashes++;
+                            }
+
+                            // If we have an odd number of backslashes, then the multiline string is unclosed
+                            if (numBackslashes & 1) {
+                                let quoteChar = tokenText.charCodeAt(0);
+                                result.finalLexState = quoteChar === CharacterCodes.doubleQuote
+                                    ? EndOfLineState.InDoubleQuoteStringLiteral
+                                    : EndOfLineState.InSingleQuoteStringLiteral;
+                            }
+                        }
+                    }
+                    else if (token === SyntaxKind.MultiLineCommentTrivia) {
+                        // Check to see if the multiline comment was unclosed.
+                        if (scanner.isUnterminated()) {
+                            result.finalLexState = EndOfLineState.InMultiLineCommentTrivia;
+                        }
+                    }
+                    else if (isTemplateLiteralKind(token)) {
+                        if (scanner.isUnterminated()) {
+                            if (token === SyntaxKind.TemplateTail) {
+                                result.finalLexState = EndOfLineState.InTemplateMiddleOrTail;
+                            }
+                            else if (token === SyntaxKind.NoSubstitutionTemplateLiteral) {
+                                result.finalLexState = EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate;
+                            }
+                            else {
+                                Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
+                            }
+                        }
+                    }
+                    else if (templateStack.length > 0 && lastOrUndefined(templateStack) === SyntaxKind.TemplateHead) {
+                        result.finalLexState = EndOfLineState.InTemplateSubstitutionPosition;
+                    }
+                }
+            }
+
+            function addResult(length: number, classification: TokenClass): void {
+                if (length > 0) {
+                    // If this is the first classification we're adding to the list, then remove any 
+                    // offset we have if we were continuing a construct from the previous line.
+                    if (result.entries.length === 0) {
+                        length -= offset;
+                    }
+
+                    result.entries.push({ length: length, classification: classification });
+                }
+            }
+        }
+
+        function isBinaryExpressionOperatorToken(token: SyntaxKind): boolean {
+            switch (token) {
+                case SyntaxKind.AsteriskToken:
+                case SyntaxKind.SlashToken:
+                case SyntaxKind.PercentToken:
+                case SyntaxKind.PlusToken:
+                case SyntaxKind.MinusToken:
+                case SyntaxKind.LessThanLessThanToken:
+                case SyntaxKind.GreaterThanGreaterThanToken:
+                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
+                case SyntaxKind.LessThanToken:
+                case SyntaxKind.GreaterThanToken:
+                case SyntaxKind.LessThanEqualsToken:
+                case SyntaxKind.GreaterThanEqualsToken:
+                case SyntaxKind.InstanceOfKeyword:
+                case SyntaxKind.InKeyword:
+                case SyntaxKind.EqualsEqualsToken:
+                case SyntaxKind.ExclamationEqualsToken:
+                case SyntaxKind.EqualsEqualsEqualsToken:
+                case SyntaxKind.ExclamationEqualsEqualsToken:
+                case SyntaxKind.AmpersandToken:
+                case SyntaxKind.CaretToken:
+                case SyntaxKind.BarToken:
+                case SyntaxKind.AmpersandAmpersandToken:
+                case SyntaxKind.BarBarToken:
+                case SyntaxKind.BarEqualsToken:
+                case SyntaxKind.AmpersandEqualsToken:
+                case SyntaxKind.CaretEqualsToken:
+                case SyntaxKind.LessThanLessThanEqualsToken:
+                case SyntaxKind.GreaterThanGreaterThanEqualsToken:
+                case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
+                case SyntaxKind.PlusEqualsToken:
+                case SyntaxKind.MinusEqualsToken:
+                case SyntaxKind.AsteriskEqualsToken:
+                case SyntaxKind.SlashEqualsToken:
+                case SyntaxKind.PercentEqualsToken:
+                case SyntaxKind.EqualsToken:
+                case SyntaxKind.CommaToken:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        function isPrefixUnaryExpressionOperatorToken(token: SyntaxKind): boolean {
+            switch (token) {
+                case SyntaxKind.PlusToken:
+                case SyntaxKind.MinusToken:
+                case SyntaxKind.TildeToken:
+                case SyntaxKind.ExclamationToken:
+                case SyntaxKind.PlusPlusToken:
+                case SyntaxKind.MinusMinusToken:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        function isKeyword(token: SyntaxKind): boolean {
+            return token >= SyntaxKind.FirstKeyword && token <= SyntaxKind.LastKeyword;
+        }
+
+        function classFromKind(token: SyntaxKind) {
+            if (isKeyword(token)) {
+                return TokenClass.Keyword;
+            }
+            else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) {
+                return TokenClass.Operator;
+            }
+            else if (token >= SyntaxKind.FirstPunctuation && token <= SyntaxKind.LastPunctuation) {
+                return TokenClass.Punctuation;
+            }
+
+            switch (token) {
+                case SyntaxKind.NumericLiteral:
+                    return TokenClass.NumberLiteral;
+                case SyntaxKind.StringLiteral:
+                    return TokenClass.StringLiteral;
+                case SyntaxKind.RegularExpressionLiteral:
+                    return TokenClass.RegExpLiteral;
+                case SyntaxKind.ConflictMarkerTrivia:
+                case SyntaxKind.MultiLineCommentTrivia:
+                case SyntaxKind.SingleLineCommentTrivia:
+                    return TokenClass.Comment;
+                case SyntaxKind.WhitespaceTrivia:
+                case SyntaxKind.NewLineTrivia:
+                    return TokenClass.Whitespace;
+                case SyntaxKind.Identifier:
+                default:
+                    if (isTemplateLiteralKind(token)) {
+                        return TokenClass.StringLiteral;
+                    }
+                    return TokenClass.Identifier;
+            }
+        }
+
+        return { getClassificationsForLine };
+    }
+
+    /// getDefaultLibraryFilePath
+    declare let __dirname: string;
+    
+    /**
+      * Get the path of the default library file (lib.d.ts) as distributed with the typescript
+      * node package.
+      * The functionality is not supported if the ts module is consumed outside of a node module. 
+      */
+    export function getDefaultLibFilePath(options: CompilerOptions): string {
+        // Check __dirname is defined and that we are on a node.js system.
+        if (typeof __dirname !== "undefined") {
+            return __dirname + directorySeparator + getDefaultLibFileName(options);
+        }
+
+        throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. ");
+    }
+
+    function initializeServices() {
+        objectAllocator = {
+            getNodeConstructor: kind => {
+                function Node() {
+                }
+                let proto = kind === SyntaxKind.SourceFile ? new SourceFileObject() : new NodeObject();
+                proto.kind = kind;
+                proto.pos = 0;
+                proto.end = 0;
+                proto.flags = 0;
+                proto.parent = undefined;
+                Node.prototype = proto;
+                return <any>Node;
+            },
+            getSymbolConstructor: () => SymbolObject,
+            getTypeConstructor: () => TypeObject,
+            getSignatureConstructor: () => SignatureObject,
+        };
+    }
+
+    initializeServices();
+}
diff --git a/lib/typescript/services/shims.ts b/lib/typescript/services/shims.ts
new file mode 100644
index 000000000..e0572b649
--- /dev/null
+++ b/lib/typescript/services/shims.ts
@@ -0,0 +1,918 @@
+//
+// Copyright (c) Microsoft Corporation.  All rights reserved.
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/// <reference path='services.ts' />
+
+/* @internal */
+var debugObjectHost = (<any>this);
+
+/* @internal */
+module ts {
+    export interface ScriptSnapshotShim {
+        /** Gets a portion of the script snapshot specified by [start, end). */
+        getText(start: number, end: number): string;
+
+        /** Gets the length of this script snapshot. */
+        getLength(): number;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         *   { span: { start: number; length: number }; newLength: number }
+         *
+         * Or undefined value if there was no change.
+         */
+        getChangeRange(oldSnapshot: ScriptSnapshotShim): string;
+    }
+
+    export interface Logger {
+        log(s: string): void;
+        trace(s: string): void;
+        error(s: string): void;
+    }
+
+    /** Public interface of the host of a language service shim instance.*/
+    export interface LanguageServiceShimHost extends Logger {
+        getCompilationSettings(): string;
+
+        /** Returns a JSON-encoded value of the type: string[] */
+        getScriptFileNames(): string;
+        getScriptVersion(fileName: string): string;
+        getScriptSnapshot(fileName: string): ScriptSnapshotShim;
+        getLocalizedDiagnosticMessages(): string;
+        getCancellationToken(): CancellationToken;
+        getCurrentDirectory(): string;
+        getDefaultLibFileName(options: string): string;
+        getNewLine?(): string;
+    }
+
+    /** Public interface of the the of a config service shim instance.*/
+    export interface CoreServicesShimHost extends Logger {
+        /** Returns a JSON-encoded value of the type: string[] */
+        readDirectory(rootDir: string, extension: string): string;
+    }
+
+    ///
+    /// Pre-processing
+    ///
+    // Note: This is being using by the host (VS) and is marshaled back and forth.
+    // When changing this make sure the changes are reflected in the managed side as well
+    export interface IFileReference {
+        path: string;
+        position: number;
+        length: number;
+    }
+
+    /** Public interface of a language service instance shim. */
+    export interface ShimFactory {
+        registerShim(shim: Shim): void;
+        unregisterShim(shim: Shim): void;
+    }
+
+    export interface Shim {
+        dispose(dummy: any): void;
+    }
+    
+    export interface LanguageServiceShim extends Shim {
+        languageService: LanguageService;
+
+        dispose(dummy: any): void;
+
+        refresh(throwOnError: boolean): void;
+
+        cleanupSemanticCache(): void;
+
+        getSyntacticDiagnostics(fileName: string): string;
+        getSemanticDiagnostics(fileName: string): string;
+        getCompilerOptionsDiagnostics(): string;
+
+        getSyntacticClassifications(fileName: string, start: number, length: number): string;
+        getSemanticClassifications(fileName: string, start: number, length: number): string;
+
+        getCompletionsAtPosition(fileName: string, position: number): string;
+        getCompletionEntryDetails(fileName: string, position: number, entryName: string): string;
+
+        getQuickInfoAtPosition(fileName: string, position: number): string;
+
+        getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string;
+        getBreakpointStatementAtPosition(fileName: string, position: number): string;
+
+        getSignatureHelpItems(fileName: string, position: number): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
+         */
+        getRenameInfo(fileName: string, position: number): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { fileName: string, textSpan: { start: number, length: number } }[]
+         */
+        findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { fileName: string; textSpan: { start: number; length: number}; kind: string; name: string; containerKind: string; containerName: string }
+         *
+         * Or undefined value if no definition can be found.
+         */
+        getDefinitionAtPosition(fileName: string, position: number): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
+         */
+        getReferencesAtPosition(fileName: string, position: number): string;
+        
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { definition: <encoded>; references: <encoded>[] }[]
+         */
+        findReferences(fileName: string, position: number): string;
+
+        /**
+         * @deprecated
+         * Returns a JSON-encoded value of the type:
+         * { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
+         */
+        getOccurrencesAtPosition(fileName: string, position: number): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { fileName: string; highlights: { start: number; length: number, isDefinition: boolean }[] }[]
+         * 
+         * @param fileToSearch A JSON encoded string[] containing the file names that should be 
+         *  considered when searching.
+         */
+        getDocumentHighlights(fileName: string, position: number, filesToSearch: string): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = [];
+         */
+        getNavigateToItems(searchValue: string, maxResultCount?: number): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { text: string; kind: string; kindModifiers: string; bolded: boolean; grayed: boolean; indent: number; spans: { start: number; length: number; }[]; childItems: <recursive use of this type>[] } [] = [];
+         */
+        getNavigationBarItems(fileName: string): string;
+
+        /**
+         * Returns a JSON-encoded value of the type:
+         * { textSpan: { start: number, length: number }; hintSpan: { start: number, length: number }; bannerText: string; autoCollapse: boolean } [] = [];
+         */
+        getOutliningSpans(fileName: string): string;
+
+        getTodoComments(fileName: string, todoCommentDescriptors: string): string;
+
+        getBraceMatchingAtPosition(fileName: string, position: number): string;
+        getIndentationAtPosition(fileName: string, position: number, options: string/*Services.EditorOptions*/): string;
+
+        getFormattingEditsForRange(fileName: string, start: number, end: number, options: string/*Services.FormatCodeOptions*/): string;
+        getFormattingEditsForDocument(fileName: string, options: string/*Services.FormatCodeOptions*/): string;
+        getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string/*Services.FormatCodeOptions*/): string;
+
+        getEmitOutput(fileName: string): string;
+    }
+
+    export interface ClassifierShim extends Shim {
+        getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string;
+    }
+
+    export interface CoreServicesShim extends Shim {
+        getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
+        getTSConfigFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
+        getDefaultCompilationSettings(): string;
+    }
+
+    function logInternalError(logger: Logger, err: Error) {
+        logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message);
+    }
+
+    class ScriptSnapshotShimAdapter implements IScriptSnapshot {
+        private lineStartPositions: number[] = null;
+
+        constructor(private scriptSnapshotShim: ScriptSnapshotShim) {
+        }
+
+        public getText(start: number, end: number): string {
+            return this.scriptSnapshotShim.getText(start, end);
+        }
+
+        public getLength(): number {
+            return this.scriptSnapshotShim.getLength();
+        }
+
+        public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
+            var oldSnapshotShim = <ScriptSnapshotShimAdapter>oldSnapshot;
+            var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
+            if (encoded == null) {
+                return null;
+            }
+
+            var decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded);
+            return createTextChangeRange(
+                createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
+        }
+    }
+
+    export class LanguageServiceShimHostAdapter implements LanguageServiceHost {
+        private files: string[];
+        
+        constructor(private shimHost: LanguageServiceShimHost) {
+        }
+
+        public log(s: string): void {
+            this.shimHost.log(s);
+        }
+
+        public trace(s: string): void {
+            this.shimHost.trace(s);
+        }
+        
+        public error(s: string): void {
+            this.shimHost.error(s);
+        }
+
+        public getCompilationSettings(): CompilerOptions {
+            var settingsJson = this.shimHost.getCompilationSettings();
+            if (settingsJson == null || settingsJson == "") {
+                throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings");
+                return null;
+            }
+            return <CompilerOptions>JSON.parse(settingsJson);
+        }
+
+        public getScriptFileNames(): string[] {
+            var encoded = this.shimHost.getScriptFileNames();
+            return this.files = JSON.parse(encoded);
+        }
+
+        public getScriptSnapshot(fileName: string): IScriptSnapshot {
+            // Shim the API changes for 1.5 release. This should be removed once
+            // TypeScript 1.5 has shipped.
+            if (this.files && this.files.indexOf(fileName) < 0) {
+                return undefined;
+            }
+            var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName);
+            return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
+        }
+
+        public getScriptVersion(fileName: string): string {
+            return this.shimHost.getScriptVersion(fileName);
+        }
+
+        public getLocalizedDiagnosticMessages(): any {
+            var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages();
+            if (diagnosticMessagesJson == null || diagnosticMessagesJson == "") {
+                return null;
+            }
+
+            try {
+                return JSON.parse(diagnosticMessagesJson);
+            }
+            catch (e) {
+                this.log(e.description || "diagnosticMessages.generated.json has invalid JSON format");
+                return null;
+            }
+        }
+
+        public getCancellationToken(): CancellationToken {
+            return this.shimHost.getCancellationToken();
+        }
+
+        public getCurrentDirectory(): string {
+            return this.shimHost.getCurrentDirectory();
+        }
+
+        public getDefaultLibFileName(options: CompilerOptions): string {
+            // Wrap the API changes for 1.5 release. This try/catch
+            // should be removed once TypeScript 1.5 has shipped.
+            try {
+                return this.shimHost.getDefaultLibFileName(JSON.stringify(options));
+            }
+            catch (e) {
+                return "";
+            }
+        }
+    }
+    
+    export class CoreServicesShimHostAdapter implements ParseConfigHost {
+
+        constructor(private shimHost: CoreServicesShimHost) {
+        }
+
+        public readDirectory(rootDir: string, extension: string): string[] {
+            var encoded = this.shimHost.readDirectory(rootDir, extension);
+            return JSON.parse(encoded);
+        }
+    }
+
+    function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any): any {
+        logger.log(actionDescription);
+        var start = Date.now();
+        var result = action();
+        var end = Date.now();
+        logger.log(actionDescription + " completed in " + (end - start) + " msec");
+        if (typeof (result) === "string") {
+            var str = <string>result;
+            if (str.length > 128) {
+                str = str.substring(0, 128) + "...";
+            }
+            logger.log("  result.length=" + str.length + ", result='" + JSON.stringify(str) + "'");
+        }
+        return result;
+    }
+
+    function forwardJSONCall(logger: Logger, actionDescription: string, action: () => any): string {
+        try {
+            var result = simpleForwardCall(logger, actionDescription, action);
+            return JSON.stringify({ result: result });
+        }
+        catch (err) {
+            if (err instanceof OperationCanceledException) {
+                return JSON.stringify({ canceled: true });
+            }
+            logInternalError(logger, err);
+            err.description = actionDescription;
+            return JSON.stringify({ error: err });
+        }
+    }
+
+    class ShimBase implements Shim {
+        constructor(private factory: ShimFactory) {
+            factory.registerShim(this);
+        }
+        public dispose(dummy: any): void {
+            this.factory.unregisterShim(this);
+        }
+    }
+
+    export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; } []{
+        return diagnostics.map(d => realizeDiagnostic(d, newLine));
+    }
+
+    function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; } {
+        return {
+            message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
+            start: diagnostic.start,
+            length: diagnostic.length,
+            /// TODO: no need for the tolowerCase call
+            category: DiagnosticCategory[diagnostic.category].toLowerCase(),
+            code: diagnostic.code
+        };
+    }
+
+    class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim {
+        private logger: Logger;
+
+        constructor(factory: ShimFactory,
+            private host: LanguageServiceShimHost,
+            public languageService: LanguageService) {
+            super(factory);
+            this.logger = this.host;
+        }
+
+        public forwardJSONCall(actionDescription: string, action: () => any): string {
+            return forwardJSONCall(this.logger, actionDescription, action);
+        }
+
+        /// DISPOSE
+
+        /**
+         * Ensure (almost) deterministic release of internal Javascript resources when
+         * some external native objects holds onto us (e.g. Com/Interop).
+         */
+        public dispose(dummy: any): void {
+            this.logger.log("dispose()");
+            this.languageService.dispose();
+            this.languageService = null;
+
+            // force a GC
+            if (debugObjectHost && debugObjectHost.CollectGarbage) {
+                debugObjectHost.CollectGarbage();
+                this.logger.log("CollectGarbage()");
+            }
+
+            this.logger = null;
+
+            super.dispose(dummy);
+        }
+
+        /// REFRESH
+
+        /**
+         * Update the list of scripts known to the compiler
+         */
+        public refresh(throwOnError: boolean): void {
+            this.forwardJSONCall(
+                "refresh(" + throwOnError + ")",
+                () => {
+                    return <any>null;
+                });
+        }
+
+        public cleanupSemanticCache(): void {
+            this.forwardJSONCall(
+                "cleanupSemanticCache()",
+                () => {
+                    this.languageService.cleanupSemanticCache();
+                    return <any>null;
+                });
+        }
+
+        private realizeDiagnostics(diagnostics: Diagnostic[]): { message: string; start: number; length: number; category: string; }[]{
+            var newLine = this.getNewLine();
+            return ts.realizeDiagnostics(diagnostics, newLine);
+        }
+
+        public getSyntacticClassifications(fileName: string, start: number, length: number): string {
+            return this.forwardJSONCall(
+                "getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")",
+                () => {
+                    var classifications = this.languageService.getSyntacticClassifications(fileName, createTextSpan(start, length));
+                    return classifications;
+                });
+        }
+
+        public getSemanticClassifications(fileName: string, start: number, length: number): string {
+            return this.forwardJSONCall(
+                "getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")",
+                () => {
+                    var classifications = this.languageService.getSemanticClassifications(fileName, createTextSpan(start, length));
+                    return classifications;
+                });
+        }
+
+        private getNewLine(): string {
+            return this.host.getNewLine ? this.host.getNewLine() : "\r\n";
+        }
+
+        public getSyntacticDiagnostics(fileName: string): string {
+            return this.forwardJSONCall(
+                "getSyntacticDiagnostics('" + fileName + "')",
+                () => {
+                    var diagnostics = this.languageService.getSyntacticDiagnostics(fileName);
+                    return this.realizeDiagnostics(diagnostics);
+                });
+        }
+
+        public getSemanticDiagnostics(fileName: string): string {
+            return this.forwardJSONCall(
+                "getSemanticDiagnostics('" + fileName + "')",
+                () => {
+                    var diagnostics = this.languageService.getSemanticDiagnostics(fileName);
+                    return this.realizeDiagnostics(diagnostics);
+                });
+        }
+
+        public getCompilerOptionsDiagnostics(): string {
+            return this.forwardJSONCall(
+                "getCompilerOptionsDiagnostics()",
+                () => {
+                    var diagnostics = this.languageService.getCompilerOptionsDiagnostics();
+                    return this.realizeDiagnostics(diagnostics);
+                });
+        }
+
+        /// QUICKINFO
+
+        /**
+         * Computes a string representation of the type at the requested position
+         * in the active file.
+         */
+        public getQuickInfoAtPosition(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getQuickInfoAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    var quickInfo = this.languageService.getQuickInfoAtPosition(fileName, position);
+                    return quickInfo;
+                });
+        }
+
+
+        /// NAMEORDOTTEDNAMESPAN
+
+        /**
+         * Computes span information of the name or dotted name at the requested position
+         * in the active file.
+         */
+        public getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string {
+            return this.forwardJSONCall(
+                "getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")",
+                () => {
+                    var spanInfo = this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos);
+                    return spanInfo;
+                });
+        }
+
+        /**
+         * STATEMENTSPAN
+         * Computes span information of statement at the requested position in the active file.
+         */
+        public getBreakpointStatementAtPosition(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getBreakpointStatementAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    var spanInfo = this.languageService.getBreakpointStatementAtPosition(fileName, position);
+                    return spanInfo;
+                });
+        }
+
+        /// SIGNATUREHELP
+
+        public getSignatureHelpItems(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getSignatureHelpItems('" + fileName + "', " + position + ")",
+                () => {
+                    var signatureInfo = this.languageService.getSignatureHelpItems(fileName, position);
+                    return signatureInfo;
+                });
+        }
+
+        /// GOTO DEFINITION
+
+        /**
+         * Computes the definition location and file for the symbol
+         * at the requested position. 
+         */
+        public getDefinitionAtPosition(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getDefinitionAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    return this.languageService.getDefinitionAtPosition(fileName, position);
+                });
+        }
+
+        public getRenameInfo(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getRenameInfo('" + fileName + "', " + position + ")",
+                () => {
+                    return this.languageService.getRenameInfo(fileName, position);
+                });
+        }
+
+        public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string {
+            return this.forwardJSONCall(
+                "findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")",
+                () => {
+                    return this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments);
+                });
+        }
+
+        /// GET BRACE MATCHING
+        public getBraceMatchingAtPosition(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getBraceMatchingAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    var textRanges = this.languageService.getBraceMatchingAtPosition(fileName, position);
+                    return textRanges;
+                });
+        }
+
+        /// GET SMART INDENT
+        public getIndentationAtPosition(fileName: string, position: number, options: string /*Services.EditorOptions*/): string {
+            return this.forwardJSONCall(
+                "getIndentationAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    var localOptions: EditorOptions = JSON.parse(options);
+                    return this.languageService.getIndentationAtPosition(fileName, position, localOptions);
+                });
+        }
+
+        /// GET REFERENCES
+
+        public getReferencesAtPosition(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getReferencesAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    return this.languageService.getReferencesAtPosition(fileName, position);
+                });
+        }
+
+        public findReferences(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "findReferences('" + fileName + "', " + position + ")",
+                () => {
+                    return this.languageService.findReferences(fileName, position);
+                });
+        }
+
+        public getOccurrencesAtPosition(fileName: string, position: number): string {
+            return this.forwardJSONCall(
+                "getOccurrencesAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    return this.languageService.getOccurrencesAtPosition(fileName, position);
+                });
+        }
+
+        public getDocumentHighlights(fileName: string, position: number, filesToSearch: string): string {
+            return this.forwardJSONCall(
+                "getDocumentHighlights('" + fileName + "', " + position + ")",
+                () => {
+                    return this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch));
+                });
+        }
+
+        /// COMPLETION LISTS
+
+        /**
+         * Get a string based representation of the completions 
+         * to provide at the given source position and providing a member completion 
+         * list if requested.
+         */
+        public getCompletionsAtPosition(fileName: string, position: number) {
+            return this.forwardJSONCall(
+                "getCompletionsAtPosition('" + fileName + "', " + position + ")",
+                () => {
+                    var completion = this.languageService.getCompletionsAtPosition(fileName, position);
+                    return completion;
+                });
+        }
+
+        /** Get a string based representation of a completion list entry details */
+        public getCompletionEntryDetails(fileName: string, position: number, entryName: string) {
+            return this.forwardJSONCall(
+                "getCompletionEntryDetails('" + fileName + "', " + position + ", " + entryName + ")",
+                () => {
+                    var details = this.languageService.getCompletionEntryDetails(fileName, position, entryName);
+                    return details;
+                });
+        }
+
+        public getFormattingEditsForRange(fileName: string, start: number, end: number, options: string/*Services.FormatCodeOptions*/): string {
+            return this.forwardJSONCall(
+                "getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")",
+                () => {
+                    var localOptions: ts.FormatCodeOptions = JSON.parse(options);
+                    var edits = this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions);
+                    return edits;
+                });
+        }
+
+        public getFormattingEditsForDocument(fileName: string, options: string/*Services.FormatCodeOptions*/): string {
+            return this.forwardJSONCall(
+                "getFormattingEditsForDocument('" + fileName + "')",
+                () => {
+                    var localOptions: ts.FormatCodeOptions = JSON.parse(options);
+                    var edits = this.languageService.getFormattingEditsForDocument(fileName, localOptions);
+                    return edits;
+                });
+        }
+
+        public getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string/*Services.FormatCodeOptions*/): string {
+            return this.forwardJSONCall(
+                "getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')",
+                () => {
+                    var localOptions: ts.FormatCodeOptions = JSON.parse(options);
+                    var edits = this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions);
+                    return edits;
+                });
+        }
+
+        /// NAVIGATE TO
+
+        /** Return a list of symbols that are interesting to navigate to */
+        public getNavigateToItems(searchValue: string, maxResultCount?: number): string {
+            return this.forwardJSONCall(
+                "getNavigateToItems('" + searchValue + "', " + maxResultCount+ ")",
+                () => {
+                    var items = this.languageService.getNavigateToItems(searchValue, maxResultCount);
+                    return items;
+                });
+        }
+
+        public getNavigationBarItems(fileName: string): string {
+            return this.forwardJSONCall(
+                "getNavigationBarItems('" + fileName + "')",
+                () => {
+                    var items = this.languageService.getNavigationBarItems(fileName);
+                    return items;
+                });
+        }
+
+        public getOutliningSpans(fileName: string): string {
+            return this.forwardJSONCall(
+                "getOutliningSpans('" + fileName + "')",
+                () => {
+                    var items = this.languageService.getOutliningSpans(fileName);
+                    return items;
+                });
+        }
+
+        public getTodoComments(fileName: string, descriptors: string): string {
+            return this.forwardJSONCall(
+                "getTodoComments('" + fileName + "')",
+                () => {
+                    var items = this.languageService.getTodoComments(fileName, JSON.parse(descriptors));
+                    return items;
+                });
+        }
+
+        /// Emit
+        public getEmitOutput(fileName: string): string {
+            return this.forwardJSONCall(
+                "getEmitOutput('" + fileName + "')",
+                () => {
+                    var output = this.languageService.getEmitOutput(fileName);
+                    // Shim the API changes for 1.5 release. This should be removed once
+                    // TypeScript 1.5 has shipped.
+                    (<any>output).emitOutputStatus = output.emitSkipped ? 1 : 0;
+                    return output;
+                });
+        }
+    }
+
+    class ClassifierShimObject extends ShimBase implements ClassifierShim {
+        public classifier: Classifier;
+
+        constructor(factory: ShimFactory) {
+            super(factory);
+            this.classifier = createClassifier();
+        }
+
+        /// COLORIZATION
+        public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): string {
+            var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics);
+            var items = classification.entries;
+            var result = "";
+            for (var i = 0; i < items.length; i++) {
+                result += items[i].length + "\n";
+                result += items[i].classification + "\n";
+            }
+            result += classification.finalLexState;
+            return result;
+        }
+    }
+
+    class CoreServicesShimObject extends ShimBase implements CoreServicesShim {
+
+        constructor(factory: ShimFactory, public logger: Logger, private host: CoreServicesShimHostAdapter) {
+            super(factory);
+        }
+
+        private forwardJSONCall(actionDescription: string, action: () => any): any {
+            return forwardJSONCall(this.logger, actionDescription, action);
+        }
+
+        public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string {
+            return this.forwardJSONCall(
+                "getPreProcessedFileInfo('" + fileName + "')",
+                () => {
+                    var result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()));
+                    var convertResult = {
+                        referencedFiles: <IFileReference[]>[],
+                        importedFiles: <IFileReference[]>[],
+                        isLibFile: result.isLibFile
+                    };
+
+                    forEach(result.referencedFiles, refFile => {
+                        convertResult.referencedFiles.push({
+                            path: normalizePath(refFile.fileName),
+                            position: refFile.pos,
+                            length: refFile.end - refFile.pos
+                        });
+                    });
+
+                    forEach(result.importedFiles, importedFile => {
+                        convertResult.importedFiles.push({
+                            path: normalizeSlashes(importedFile.fileName),
+                            position: importedFile.pos,
+                            length: importedFile.end - importedFile.pos
+                        });
+                    });
+                    return convertResult;
+                });
+        }
+
+        public getTSConfigFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string {
+            return this.forwardJSONCall(
+                "getTSConfigFileInfo('" + fileName + "')",
+                () => {
+                    let text = sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength());
+
+                    let result = parseConfigFileText(fileName, text);
+
+                    if (result.error) {
+                        return {
+                            options: {},
+                            files: [],
+                            errors: [realizeDiagnostic(result.error, '\r\n')]
+                        };
+                    }
+
+                    var configFile = parseConfigFile(result.config, this.host, getDirectoryPath(normalizeSlashes(fileName)));
+
+                    return {
+                        options: configFile.options,
+                        files: configFile.fileNames,
+                        errors: realizeDiagnostics(configFile.errors, '\r\n')
+                    };
+                });
+        }
+
+        public getDefaultCompilationSettings(): string {
+            return this.forwardJSONCall(
+                "getDefaultCompilationSettings()",
+                () => {
+                    return getDefaultCompilerOptions();
+                });
+        }
+    }
+
+    export class TypeScriptServicesFactory implements ShimFactory {
+        private _shims: Shim[] = [];
+        private documentRegistry: DocumentRegistry = createDocumentRegistry();
+
+        /*
+         * Returns script API version.
+         */
+        public getServicesVersion(): string {
+            return servicesVersion;
+        }
+
+        public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim {
+            try {
+                var hostAdapter = new LanguageServiceShimHostAdapter(host);
+                var languageService = createLanguageService(hostAdapter, this.documentRegistry);
+                return new LanguageServiceShimObject(this, host, languageService);
+            }
+            catch (err) {
+                logInternalError(host, err);
+                throw err;
+            }
+        }
+
+        public createClassifierShim(logger: Logger): ClassifierShim {
+            try {
+                return new ClassifierShimObject(this);
+            }
+            catch (err) {
+                logInternalError(logger, err);
+                throw err;
+            }
+        }
+
+        public createCoreServicesShim(host: CoreServicesShimHost): CoreServicesShim {
+            try {
+                var adapter = new CoreServicesShimHostAdapter(host);
+                return new CoreServicesShimObject(this, <Logger>host, adapter);
+            }
+            catch (err) {
+                logInternalError(<Logger>host, err);
+                throw err;
+            }
+        }
+
+        public close(): void {
+            // Forget all the registered shims
+            this._shims = [];
+            this.documentRegistry = createDocumentRegistry();
+        }
+
+        public registerShim(shim: Shim): void {
+            this._shims.push(shim);
+        }
+
+        public unregisterShim(shim: Shim): void {
+            for (var i = 0, n = this._shims.length; i < n; i++) {
+                if (this._shims[i] === shim) {
+                    delete this._shims[i];
+                    return;
+                }
+            }
+
+            throw new Error("Invalid operation");
+        }
+    }
+
+    // Here we expose the TypeScript services as an external module
+    // so that it may be consumed easily like a node module.
+    declare var module: any;
+    if (typeof module !== "undefined" && module.exports) {
+        module.exports = ts;
+    }
+}
+
+
+/// TODO: this is used by VS, clean this up on both sides of the interface
+/* @internal */
+module TypeScript.Services {
+    export var TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
+}
+
+/* @internal */
+let toolsVersion = "1.4";
diff --git a/lib/typescript/services/signatureHelp.ts b/lib/typescript/services/signatureHelp.ts
new file mode 100644
index 000000000..99ccb7166
--- /dev/null
+++ b/lib/typescript/services/signatureHelp.ts
@@ -0,0 +1,637 @@
+///<reference path='services.ts' />
+/* @internal */
+module ts.SignatureHelp {
+
+    // A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
+    // or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference. 
+    // To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it 
+    // will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through 
+    // looking up the type. The method will also keep track of the parameter index inside the expression.
+    //public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): any {
+    //    let token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
+
+    //    if (token && TypeScript.Syntax.hasAncestorOfKind(token, TypeScript.SyntaxKind.TypeParameterList)) {
+    //        // We are in the wrong generic list. bail out
+    //        return null;
+    //    }
+
+    //    let stack = 0;
+    //    let argumentIndex = 0;
+
+    //    whileLoop:
+    //    while (token) {
+    //        switch (token.kind()) {
+    //            case TypeScript.SyntaxKind.LessThanToken:
+    //                if (stack === 0) {
+    //                    // Found the beginning of the generic argument expression
+    //                    let lessThanToken = token;
+    //                    token = previousToken(token, /*includeSkippedTokens*/ true);
+    //                    if (!token || token.kind() !== TypeScript.SyntaxKind.IdentifierName) {
+    //                        break whileLoop;
+    //                    }
+
+    //                    // Found the name, return the data
+    //                    return {
+    //                        genericIdentifer: token,
+    //                        lessThanToken: lessThanToken,
+    //                        argumentIndex: argumentIndex
+    //                    };
+    //                }
+    //                else if (stack < 0) {
+    //                    // Seen one too many less than tokens, bail out
+    //                    break whileLoop;
+    //                }
+    //                else {
+    //                    stack--;
+    //                }
+
+    //                break;
+
+    //            case TypeScript.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
+    //                stack++;
+
+    //            // Intentaion fall through
+    //            case TypeScript.SyntaxKind.GreaterThanToken:
+    //                stack++;
+    //                break;
+
+    //            case TypeScript.SyntaxKind.CommaToken:
+    //                if (stack == 0) {
+    //                    argumentIndex++;
+    //                }
+
+    //                break;
+
+    //            case TypeScript.SyntaxKind.CloseBraceToken:
+    //                // This can be object type, skip untill we find the matching open brace token
+    //                let unmatchedOpenBraceTokens = 0;
+
+    //                // Skip untill the matching open brace token
+    //                token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseBraceToken, TypeScript.SyntaxKind.OpenBraceToken);
+    //                if (!token) {
+    //                    // No matching token was found. bail out
+    //                    break whileLoop;
+    //                }
+
+    //                break;
+
+    //            case TypeScript.SyntaxKind.EqualsGreaterThanToken:
+    //                // This can be a function type or a constructor type. In either case, we want to skip the function defintion
+    //                token = previousToken(token, /*includeSkippedTokens*/ true);
+
+    //                if (token && token.kind() === TypeScript.SyntaxKind.CloseParenToken) {
+    //                    // Skip untill the matching open paren token
+    //                    token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.CloseParenToken, TypeScript.SyntaxKind.OpenParenToken);
+
+    //                    if (token && token.kind() === TypeScript.SyntaxKind.GreaterThanToken) {
+    //                        // Another generic type argument list, skip it\
+    //                        token = SignatureInfoHelpers.moveBackUpTillMatchingTokenKind(token, TypeScript.SyntaxKind.GreaterThanToken, TypeScript.SyntaxKind.LessThanToken);
+    //                    }
+
+    //                    if (token && token.kind() === TypeScript.SyntaxKind.NewKeyword) {
+    //                        // In case this was a constructor type, skip the new keyword
+    //                        token = previousToken(token, /*includeSkippedTokens*/ true);
+    //                    }
+
+    //                    if (!token) {
+    //                        // No matching token was found. bail out
+    //                        break whileLoop;
+    //                    }
+    //                }
+    //                else {
+    //                    // This is not a funtion type. exit the main loop
+    //                    break whileLoop;
+    //                }
+
+    //                break;
+
+    //            case TypeScript.SyntaxKind.IdentifierName:
+    //            case TypeScript.SyntaxKind.AnyKeyword:
+    //            case TypeScript.SyntaxKind.NumberKeyword:
+    //            case TypeScript.SyntaxKind.StringKeyword:
+    //            case TypeScript.SyntaxKind.VoidKeyword:
+    //            case TypeScript.SyntaxKind.BooleanKeyword:
+    //            case TypeScript.SyntaxKind.DotToken:
+    //            case TypeScript.SyntaxKind.OpenBracketToken:
+    //            case TypeScript.SyntaxKind.CloseBracketToken:
+    //                // Valid tokens in a type name. Skip.
+    //                break;
+
+    //            default:
+    //                break whileLoop;
+    //        }
+
+    //        token = previousToken(token, /*includeSkippedTokens*/ true);
+    //    }
+
+    //    return null;
+    //}
+
+    //private static moveBackUpTillMatchingTokenKind(token: TypeScript.ISyntaxToken, tokenKind: TypeScript.SyntaxKind, matchingTokenKind: TypeScript.SyntaxKind): TypeScript.ISyntaxToken {
+    //    if (!token || token.kind() !== tokenKind) {
+    //        throw TypeScript.Errors.invalidOperation();
+    //    }
+
+    //    // Skip the current token
+    //    token = previousToken(token, /*includeSkippedTokens*/ true);
+
+    //    let stack = 0;
+
+    //    while (token) {
+    //        if (token.kind() === matchingTokenKind) {
+    //            if (stack === 0) {
+    //                // Found the matching token, return
+    //                return token;
+    //            }
+    //            else if (stack < 0) {
+    //                // tokens overlapped.. bail out.
+    //                break;
+    //            }
+    //            else {
+    //                stack--;
+    //            }
+    //        }
+    //        else if (token.kind() === tokenKind) {
+    //            stack++;
+    //        }
+
+    //        // Move back
+    //        token = previousToken(token, /*includeSkippedTokens*/ true);
+    //    }
+
+    //    // Did not find matching token
+    //    return null;
+    //}
+    let emptyArray: any[] = [];
+
+    const enum ArgumentListKind {
+        TypeArguments,
+        CallArguments,
+        TaggedTemplateArguments
+    }
+
+    interface ArgumentListInfo {
+        kind: ArgumentListKind;
+        invocation: CallLikeExpression;
+        argumentsSpan: TextSpan;
+        argumentIndex?: number;
+        argumentCount: number;
+    }
+
+    export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationTokenObject): SignatureHelpItems {
+        let typeChecker = program.getTypeChecker();
+
+        // Decide whether to show signature help
+        let startingToken = findTokenOnLeftOfPosition(sourceFile, position);
+        if (!startingToken) {
+            // We are at the beginning of the file
+            return undefined;
+        }
+
+        let argumentInfo = getContainingArgumentInfo(startingToken);
+        cancellationToken.throwIfCancellationRequested();
+
+        // Semantic filtering of signature help
+        if (!argumentInfo) {
+            return undefined;
+        }
+
+        let call = argumentInfo.invocation;
+        let candidates = <Signature[]>[];
+        let resolvedSignature = typeChecker.getResolvedSignature(call, candidates);
+        cancellationToken.throwIfCancellationRequested();
+
+        if (!candidates.length) {
+            // We didn't have any sig help items produced by the TS compiler.  If this is a JS 
+            // file, then see if we can figure out anything better.
+            if (isJavaScript(sourceFile.fileName)) {
+                return createJavaScriptSignatureHelpItems(argumentInfo);
+            }
+
+            return undefined;
+        }
+
+        return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
+
+        function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo): SignatureHelpItems {
+            if (argumentInfo.invocation.kind !== SyntaxKind.CallExpression) {
+                return undefined;
+            }
+
+            // See if we can find some symbol with the call expression name that has call signatures.
+            let callExpression = <CallExpression>argumentInfo.invocation;
+            let expression = callExpression.expression;
+            let name = expression.kind === SyntaxKind.Identifier
+                ? <Identifier> expression
+                : expression.kind === SyntaxKind.PropertyAccessExpression
+                    ? (<PropertyAccessExpression>expression).name
+                    : undefined;
+
+            if (!name || !name.text) {
+                return undefined;
+            }
+
+            let typeChecker = program.getTypeChecker();
+            for (let sourceFile of program.getSourceFiles()) {
+                let nameToDeclarations = sourceFile.getNamedDeclarations();
+                let declarations = getProperty(nameToDeclarations, name.text);
+
+                if (declarations) {
+                    for (let declaration of declarations) {
+                        let symbol = declaration.symbol;
+                        if (symbol) {
+                            let type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration);
+                            if (type) {
+                                let callSignatures = type.getCallSignatures();
+                                if (callSignatures && callSignatures.length) {
+                                    return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Returns relevant information for the argument list and the current argument if we are
+         * in the argument of an invocation; returns undefined otherwise.
+         */
+        function getImmediatelyContainingArgumentInfo(node: Node): ArgumentListInfo {
+            if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
+                let callExpression = <CallExpression>node.parent;
+                // There are 3 cases to handle:
+                //   1. The token introduces a list, and should begin a sig help session
+                //   2. The token is either not associated with a list, or ends a list, so the session should end
+                //   3. The token is buried inside a list, and should give sig help
+                //
+                // The following are examples of each:
+                //
+                //    Case 1:
+                //          foo<#T, U>(#a, b)    -> The token introduces a list, and should begin a sig help session
+                //    Case 2:
+                //          fo#o<T, U>#(a, b)#   -> The token is either not associated with a list, or ends a list, so the session should end
+                //    Case 3:
+                //          foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
+                // Find out if 'node' is an argument, a type argument, or neither
+                if (node.kind === SyntaxKind.LessThanToken ||
+                    node.kind === SyntaxKind.OpenParenToken) {
+                    // Find the list that starts right *after* the < or ( token.
+                    // If the user has just opened a list, consider this item 0.
+                    let list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
+                    let isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
+                    Debug.assert(list !== undefined);
+                    return {
+                        kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
+                        invocation: callExpression,
+                        argumentsSpan: getApplicableSpanForArguments(list),
+                        argumentIndex: 0,
+                        argumentCount: getArgumentCount(list)
+                    };
+                }
+
+                // findListItemInfo can return undefined if we are not in parent's argument list
+                // or type argument list. This includes cases where the cursor is:
+                //   - To the right of the closing paren, non-substitution template, or template tail.
+                //   - Between the type arguments and the arguments (greater than token)
+                //   - On the target of the call (parent.func)
+                //   - On the 'new' keyword in a 'new' expression
+                let listItemInfo = findListItemInfo(node);
+                if (listItemInfo) {
+                    let list = listItemInfo.list;
+                    let isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
+
+                    let argumentIndex = getArgumentIndex(list, node);
+                    let argumentCount = getArgumentCount(list);
+
+                    Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount,
+                        `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`); 
+
+                    return {
+                        kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
+                        invocation: callExpression,
+                        argumentsSpan: getApplicableSpanForArguments(list),
+                        argumentIndex: argumentIndex,
+                        argumentCount: argumentCount
+                    };
+                }
+            }
+            else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.parent.kind === SyntaxKind.TaggedTemplateExpression) {
+                // Check if we're actually inside the template;
+                // otherwise we'll fall out and return undefined.
+                if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
+                    return getArgumentListInfoForTemplate(<TaggedTemplateExpression>node.parent, /*argumentIndex*/ 0);
+                }
+            }
+            else if (node.kind === SyntaxKind.TemplateHead && node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
+                let templateExpression = <TemplateExpression>node.parent;
+                let tagExpression = <TaggedTemplateExpression>templateExpression.parent;
+                Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
+
+                let argumentIndex = isInsideTemplateLiteral(<LiteralExpression>node, position) ? 0 : 1;
+
+                return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
+            }
+            else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
+                let templateSpan = <TemplateSpan>node.parent;
+                let templateExpression = <TemplateExpression>templateSpan.parent;
+                let tagExpression = <TaggedTemplateExpression>templateExpression.parent;
+                Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
+
+                // If we're just after a template tail, don't show signature help.
+                if (node.kind === SyntaxKind.TemplateTail && !isInsideTemplateLiteral(<LiteralExpression>node, position)) {
+                    return undefined;
+                }
+
+                let spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
+                let argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
+
+                return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
+            }
+            
+            return undefined;
+        }
+
+        function getArgumentIndex(argumentsList: Node, node: Node) {
+            // The list we got back can include commas.  In the presence of errors it may 
+            // also just have nodes without commas.  For example "Foo(a b c)" will have 3 
+            // args without commas.   We want to find what index we're at.  So we count
+            // forward until we hit ourselves, only incrementing the index if it isn't a
+            // comma.
+            //
+            // Note: the subtlety around trailing commas (in getArgumentCount) does not apply
+            // here.  That's because we're only walking forward until we hit the node we're
+            // on.  In that case, even if we're after the trailing comma, we'll still see
+            // that trailing comma in the list, and we'll have generated the appropriate
+            // arg index.
+            let argumentIndex = 0;
+            let listChildren = argumentsList.getChildren();
+            for (let child of listChildren) {
+                if (child === node) {
+                    break;
+                }
+                if (child.kind !== SyntaxKind.CommaToken) {
+                    argumentIndex++;
+                }
+            }
+
+            return argumentIndex;
+        }
+
+        function getArgumentCount(argumentsList: Node) {
+            // The argument count for a list is normally the number of non-comma children it has.
+            // For example, if you have "Foo(a,b)" then there will be three children of the arg
+            // list 'a' '<comma>' 'b'.  So, in this case the arg count will be 2.  However, there
+            // is a small subtlety.  If you have  "Foo(a,)", then the child list will just have
+            // 'a' '<comma>'.  So, in the case where the last child is a comma, we increase the
+            // arg count by one to compensate.
+            //
+            // Note: this subtlety only applies to the last comma.  If you had "Foo(a,,"  then 
+            // we'll have:  'a' '<comma>' '<missing>' 
+            // That will give us 2 non-commas.  We then add one for the last comma, givin us an
+            // arg count of 3.
+            let listChildren = argumentsList.getChildren();
+
+            let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
+            if (listChildren.length > 0 && lastOrUndefined(listChildren).kind === SyntaxKind.CommaToken) {
+                argumentCount++;
+            }
+
+            return argumentCount;
+        }
+
+        // spanIndex is either the index for a given template span.
+        // This does not give appropriate results for a NoSubstitutionTemplateLiteral
+        function getArgumentIndexForTemplatePiece(spanIndex: number, node: Node): number {
+            // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1.
+            // There are three cases we can encounter:
+            //      1. We are precisely in the template literal (argIndex = 0).
+            //      2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1).
+            //      3. We are directly to the right of the template literal, but because we look for the token on the left,
+            //          not enough to put us in the substitution expression; we should consider ourselves part of
+            //          the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
+            //
+            // Example: f  `# abcd $#{#  1 + 1#  }# efghi ${ #"#hello"#  }  #  `
+            //              ^       ^ ^       ^   ^          ^ ^      ^     ^
+            // Case:        1       1 3       2   1          3 2      2     1
+            Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
+            if (isTemplateLiteralKind(node.kind)) {
+                if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
+                    return 0;
+                }
+                return spanIndex + 2;
+            }
+            return spanIndex + 1;
+        }
+
+        function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number): ArgumentListInfo {
+            // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
+            let argumentCount = tagExpression.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral
+                ? 1
+                : (<TemplateExpression>tagExpression.template).templateSpans.length + 1;
+
+            Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`); 
+
+            return {
+                kind: ArgumentListKind.TaggedTemplateArguments,
+                invocation: tagExpression,
+                argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression),
+                argumentIndex: argumentIndex,
+                argumentCount: argumentCount
+            };
+        }
+
+        function getApplicableSpanForArguments(argumentsList: Node): TextSpan {
+            // We use full start and skip trivia on the end because we want to include trivia on
+            // both sides. For example,
+            //
+            //    foo(   /*comment */     a, b, c      /*comment*/     )
+            //        |                                               |
+            //
+            // The applicable span is from the first bar to the second bar (inclusive,
+            // but not including parentheses)
+            let applicableSpanStart = argumentsList.getFullStart();
+            let applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
+            return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
+        }
+
+        function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression): TextSpan {
+            let template = taggedTemplate.template;
+            let applicableSpanStart = template.getStart();
+            let applicableSpanEnd = template.getEnd();
+
+            // We need to adjust the end position for the case where the template does not have a tail.
+            // Otherwise, we will not show signature help past the expression.
+            // For example,
+            //
+            //      `  ${ 1 + 1        foo(10)
+            //       |        |
+            //
+            // This is because a Missing node has no width. However, what we actually want is to include trivia
+            // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
+            if (template.kind === SyntaxKind.TemplateExpression) {
+                let lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
+                if (lastSpan.literal.getFullWidth() === 0) {
+                    applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
+                }
+            }
+
+            return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
+        }
+
+        function getContainingArgumentInfo(node: Node): ArgumentListInfo {
+            for (let n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
+                if (isFunctionBlock(n)) {
+                    return undefined;
+                }
+
+                // If the node is not a subspan of its parent, this is a big problem.
+                // There have been crashes that might be caused by this violation.
+                if (n.pos < n.parent.pos || n.end > n.parent.end) {
+                    Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
+                }
+
+                let argumentInfo = getImmediatelyContainingArgumentInfo(n);
+                if (argumentInfo) {
+                    return argumentInfo;
+                }
+
+
+                // TODO: Handle generic call with incomplete syntax
+            }
+            return undefined;
+        }
+
+        function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
+            let children = parent.getChildren(sourceFile);
+            let indexOfOpenerToken = children.indexOf(openerToken);
+            Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
+            return children[indexOfOpenerToken + 1];
+        }
+
+        /**
+         * The selectedItemIndex could be negative for several reasons.
+         *     1. There are too many arguments for all of the overloads
+         *     2. None of the overloads were type compatible
+         * The solution here is to try to pick the best overload by picking
+         * either the first one that has an appropriate number of parameters,
+         * or the one with the most parameters.
+         */
+        function selectBestInvalidOverloadIndex(candidates: Signature[], argumentCount: number): number {
+            let maxParamsSignatureIndex = -1;
+            let maxParams = -1;
+            for (let i = 0; i < candidates.length; i++) {
+                let candidate = candidates[i];
+
+                if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
+                    return i;
+                }
+
+                if (candidate.parameters.length > maxParams) {
+                    maxParams = candidate.parameters.length;
+                    maxParamsSignatureIndex = i;
+                }
+            }
+
+            return maxParamsSignatureIndex;
+        }
+
+        function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentListInfo: ArgumentListInfo): SignatureHelpItems {
+            let applicableSpan = argumentListInfo.argumentsSpan;
+            let isTypeParameterList = argumentListInfo.kind === ArgumentListKind.TypeArguments;
+
+            let invocation = argumentListInfo.invocation;
+            let callTarget = getInvokedExpression(invocation)
+            let callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget);
+            let callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
+            let items: SignatureHelpItem[] = map(candidates, candidateSignature => {
+                let signatureHelpParameters: SignatureHelpParameter[];
+                let prefixDisplayParts: SymbolDisplayPart[] = [];
+                let suffixDisplayParts: SymbolDisplayPart[] = [];
+
+                if (callTargetDisplayParts) {
+                    prefixDisplayParts.push.apply(prefixDisplayParts, callTargetDisplayParts);
+                }
+
+                if (isTypeParameterList) {
+                    prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
+                    let typeParameters = candidateSignature.typeParameters;
+                    signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
+                    suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
+                    let parameterParts = mapToDisplayParts(writer =>
+                        typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation));
+                    suffixDisplayParts.push.apply(suffixDisplayParts, parameterParts);
+                }
+                else {
+                    let typeParameterParts = mapToDisplayParts(writer =>
+                        typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation));
+                    prefixDisplayParts.push.apply(prefixDisplayParts, typeParameterParts);
+                    prefixDisplayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
+
+                    let parameters = candidateSignature.parameters;
+                    signatureHelpParameters = parameters.length > 0 ? map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
+                    suffixDisplayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
+                }
+
+                let returnTypeParts = mapToDisplayParts(writer =>
+                    typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation));
+                suffixDisplayParts.push.apply(suffixDisplayParts, returnTypeParts);
+                
+                return {
+                    isVariadic: candidateSignature.hasRestParameter,
+                    prefixDisplayParts,
+                    suffixDisplayParts,
+                    separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()],
+                    parameters: signatureHelpParameters,
+                    documentation: candidateSignature.getDocumentationComment()
+                };
+            });
+
+            let argumentIndex = argumentListInfo.argumentIndex;
+
+            // argumentCount is the *apparent* number of arguments.
+            let argumentCount = argumentListInfo.argumentCount;
+
+            let selectedItemIndex = candidates.indexOf(bestSignature);
+            if (selectedItemIndex < 0) {
+                selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
+            }
+
+            Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`); 
+
+            return {
+                items,
+                applicableSpan,
+                selectedItemIndex,
+                argumentIndex,
+                argumentCount
+            };
+
+            function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
+                let displayParts = mapToDisplayParts(writer =>
+                    typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation));
+
+                let isOptional = hasQuestionToken(parameter.valueDeclaration);
+
+                return {
+                    name: parameter.name,
+                    documentation: parameter.getDocumentationComment(),
+                    displayParts,
+                    isOptional
+                };
+            }
+
+            function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
+                let displayParts = mapToDisplayParts(writer =>
+                    typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation));
+
+                return {
+                    name: typeParameter.symbol.name,
+                    documentation: emptyArray,
+                    displayParts,
+                    isOptional: false
+                };
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/typescript/services/utilities.ts b/lib/typescript/services/utilities.ts
new file mode 100644
index 000000000..2e1ccfdf8
--- /dev/null
+++ b/lib/typescript/services/utilities.ts
@@ -0,0 +1,659 @@
+// These utilities are common to multiple language service features.
+/* @internal */
+module ts {
+    export interface ListItemInfo {
+        listItemIndex: number;
+        list: Node;
+    }
+
+    export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
+        Debug.assert(line >= 0);
+        let lineStarts = sourceFile.getLineStarts();
+        
+        let lineIndex = line;
+        if (lineIndex + 1 === lineStarts.length) {
+            // last line - return EOF
+            return sourceFile.text.length - 1;
+        }
+        else {
+            // current line start
+            let start = lineStarts[lineIndex];
+            // take the start position of the next line -1 = it should be some line break
+            let pos = lineStarts[lineIndex + 1] - 1;
+            Debug.assert(isLineBreak(sourceFile.text.charCodeAt(pos)));
+            // walk backwards skipping line breaks, stop the the beginning of current line.
+            // i.e:
+            // <some text>
+            // $ <- end of line for this position should match the start position
+            while (start <= pos && isLineBreak(sourceFile.text.charCodeAt(pos))) {
+                pos--;
+            }
+            return pos;
+        }
+    }
+
+    export function getLineStartPositionForPosition(position: number, sourceFile: SourceFile): number {
+        let lineStarts = sourceFile.getLineStarts();
+        let line = sourceFile.getLineAndCharacterOfPosition(position).line;
+        return lineStarts[line];
+    }
+
+    export function rangeContainsRange(r1: TextRange, r2: TextRange): boolean {
+        return startEndContainsRange(r1.pos, r1.end, r2);
+    }
+
+    export function startEndContainsRange(start: number, end: number, range: TextRange): boolean {
+        return start <= range.pos && end >= range.end;
+    }
+
+    export function rangeContainsStartEnd(range: TextRange, start: number, end: number): boolean {
+        return range.pos <= start && range.end >= end;
+    }
+
+    export function rangeOverlapsWithStartEnd(r1: TextRange, start: number, end: number) {
+        return startEndOverlapsWithStartEnd(r1.pos, r1.end, start, end);
+    }
+
+    export function startEndOverlapsWithStartEnd(start1: number, end1: number, start2: number, end2: number) {
+        let start = Math.max(start1, start2);
+        let end = Math.min(end1, end2);
+        return start < end;
+    }
+
+    export function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean {
+        return candidate.end > position || !isCompletedNode(candidate, sourceFile);
+    }
+
+    export function isCompletedNode(n: Node, sourceFile: SourceFile): boolean {
+        if (nodeIsMissing(n)) {
+            return false;
+        }
+
+        switch (n.kind) {
+            case SyntaxKind.ClassDeclaration:
+            case SyntaxKind.InterfaceDeclaration:
+            case SyntaxKind.EnumDeclaration:
+            case SyntaxKind.ObjectLiteralExpression:
+            case SyntaxKind.ObjectBindingPattern:
+            case SyntaxKind.TypeLiteral:
+            case SyntaxKind.Block:
+            case SyntaxKind.ModuleBlock:
+            case SyntaxKind.CaseBlock:
+                return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile);
+            case SyntaxKind.CatchClause:
+                return isCompletedNode((<CatchClause>n).block, sourceFile);
+            case SyntaxKind.NewExpression:
+                if (!(<NewExpression>n).arguments) {
+                    return true;
+                }
+            // fall through
+            case SyntaxKind.CallExpression:
+            case SyntaxKind.ParenthesizedExpression:
+            case SyntaxKind.ParenthesizedType:
+                return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
+
+            case SyntaxKind.FunctionType:
+            case SyntaxKind.ConstructorType:
+                return isCompletedNode((<SignatureDeclaration>n).type, sourceFile);
+
+            case SyntaxKind.Constructor:
+            case SyntaxKind.GetAccessor:
+            case SyntaxKind.SetAccessor:
+            case SyntaxKind.FunctionDeclaration:
+            case SyntaxKind.FunctionExpression:
+            case SyntaxKind.MethodDeclaration:
+            case SyntaxKind.MethodSignature:
+            case SyntaxKind.ConstructSignature:
+            case SyntaxKind.CallSignature:
+            case SyntaxKind.ArrowFunction:
+                if ((<FunctionLikeDeclaration>n).body) {
+                    return isCompletedNode((<FunctionLikeDeclaration>n).body, sourceFile);
+                }
+
+                if ((<FunctionLikeDeclaration>n).type) {
+                    return isCompletedNode((<FunctionLikeDeclaration>n).type, sourceFile);
+                }
+
+                // Even though type parameters can be unclosed, we can get away with
+                // having at least a closing paren.
+                return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile);
+
+            case SyntaxKind.ModuleDeclaration:
+                return (<ModuleDeclaration>n).body && isCompletedNode((<ModuleDeclaration>n).body, sourceFile);
+
+            case SyntaxKind.IfStatement:
+                if ((<IfStatement>n).elseStatement) {
+                    return isCompletedNode((<IfStatement>n).elseStatement, sourceFile);
+                }
+                return isCompletedNode((<IfStatement>n).thenStatement, sourceFile);
+
+            case SyntaxKind.ExpressionStatement:
+                return isCompletedNode((<ExpressionStatement>n).expression, sourceFile);
+
+            case SyntaxKind.ArrayLiteralExpression:
+            case SyntaxKind.ArrayBindingPattern:
+            case SyntaxKind.ElementAccessExpression:
+            case SyntaxKind.ComputedPropertyName:
+            case SyntaxKind.TupleType:
+                return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile);
+
+            case SyntaxKind.IndexSignature:
+                if ((<IndexSignatureDeclaration>n).type) {
+                    return isCompletedNode((<IndexSignatureDeclaration>n).type, sourceFile);
+                }
+
+                return hasChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
+
+            case SyntaxKind.CaseClause:
+            case SyntaxKind.DefaultClause:
+                // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed
+                return false;
+
+            case SyntaxKind.ForStatement:
+            case SyntaxKind.ForInStatement:
+            case SyntaxKind.ForOfStatement:
+            case SyntaxKind.WhileStatement:
+                return isCompletedNode((<IterationStatement>n).statement, sourceFile);
+            case SyntaxKind.DoStatement:
+                // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')';
+                let hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile);
+                if (hasWhileKeyword) {
+                    return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
+                }
+                return isCompletedNode((<DoStatement>n).statement, sourceFile);
+
+            case SyntaxKind.TypeQuery:
+                return isCompletedNode((<TypeQueryNode>n).exprName, sourceFile);
+
+            case SyntaxKind.TypeOfExpression:
+            case SyntaxKind.DeleteExpression:
+            case SyntaxKind.VoidExpression:
+            case SyntaxKind.YieldExpression:
+            case SyntaxKind.SpreadElementExpression:
+                let unaryWordExpression = (<TypeOfExpression|DeleteExpression|VoidExpression|YieldExpression|SpreadElementExpression>n);
+                return isCompletedNode(unaryWordExpression.expression, sourceFile);
+
+            case SyntaxKind.TaggedTemplateExpression:
+                return isCompletedNode((<TaggedTemplateExpression>n).template, sourceFile);
+            case SyntaxKind.TemplateExpression:
+                let lastSpan = lastOrUndefined((<TemplateExpression>n).templateSpans);
+                return isCompletedNode(lastSpan, sourceFile);
+            case SyntaxKind.TemplateSpan:
+                return nodeIsPresent((<TemplateSpan>n).literal);
+
+            case SyntaxKind.PrefixUnaryExpression:
+                return isCompletedNode((<PrefixUnaryExpression>n).operand, sourceFile);
+            case SyntaxKind.BinaryExpression:
+                return isCompletedNode((<BinaryExpression>n).right, sourceFile);
+            case SyntaxKind.ConditionalExpression:
+                return isCompletedNode((<ConditionalExpression>n).whenFalse, sourceFile);
+
+            default:
+                return true;
+        }
+    }
+
+    /*
+     * Checks if node ends with 'expectedLastToken'.
+     * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'.
+     */
+    function nodeEndsWith(n: Node, expectedLastToken: SyntaxKind, sourceFile: SourceFile): boolean {
+        let children = n.getChildren(sourceFile);
+        if (children.length) {
+            let last = children[children.length - 1];
+            if (last.kind === expectedLastToken) {
+                return true;
+            }
+            else if (last.kind === SyntaxKind.SemicolonToken && children.length !== 1) {
+                return children[children.length - 2].kind === expectedLastToken;
+            }
+        }
+        return false;
+    }
+
+    export function findListItemInfo(node: Node): ListItemInfo {
+        let list = findContainingList(node);
+
+        // It is possible at this point for syntaxList to be undefined, either if
+        // node.parent had no list child, or if none of its list children contained
+        // the span of node. If this happens, return undefined. The caller should
+        // handle this case.
+        if (!list) {
+            return undefined;
+        }
+
+        let children = list.getChildren();
+        let listItemIndex = indexOf(children, node);
+
+        return {
+            listItemIndex,
+            list
+        };
+    }
+
+    export function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): boolean {
+        return !!findChildOfKind(n, kind, sourceFile);
+    }
+
+    export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node {
+        return forEach(n.getChildren(sourceFile), c => c.kind === kind && c);
+    }
+
+    export function findContainingList(node: Node): Node {
+        // The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will
+        // be parented by the container of the SyntaxList, not the SyntaxList itself.
+        // In order to find the list item index, we first need to locate SyntaxList itself and then search
+        // for the position of the relevant node (or comma).
+        let syntaxList = forEach(node.parent.getChildren(), c => {
+            // find syntax list that covers the span of the node
+            if (c.kind === SyntaxKind.SyntaxList && c.pos <= node.pos && c.end >= node.end) {
+                return c;
+            }
+        });
+
+        // Either we didn't find an appropriate list, or the list must contain us.
+        Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node)); 
+        return syntaxList;
+    }
+
+    /* Gets the token whose text has range [start, end) and 
+     * position >= start and (position < end or (position === end && token is keyword or identifier))
+     */
+    export function getTouchingWord(sourceFile: SourceFile, position: number): Node {
+        return getTouchingToken(sourceFile, position, n => isWord(n.kind));
+    }
+
+    /* Gets the token whose text has range [start, end) and position >= start 
+     * and (position < end or (position === end && token is keyword or identifier or numeric\string litera))
+     */
+    export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node {
+        return getTouchingToken(sourceFile, position, n => isPropertyName(n.kind));
+    }
+
+    /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */
+    export function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean): Node {
+        return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition);
+    }
+
+    /** Returns a token if position is in [start-of-leading-trivia, end) */
+    export function getTokenAtPosition(sourceFile: SourceFile, position: number): Node {
+        return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined);
+    }
+
+    /** Get the token whose text contains the position */
+    function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean): Node {
+        let current: Node = sourceFile;
+        outer: while (true) {
+            if (isToken(current)) {
+                // exit early
+                return current;
+            }
+
+            // find the child that contains 'position'
+            for (let i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
+                let child = current.getChildAt(i);
+                let start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
+                if (start <= position) {
+                    let end = child.getEnd();
+                    if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) {
+                        current = child;
+                        continue outer;
+                    }
+                    else if (includeItemAtEndPosition && end === position) {
+                        let previousToken = findPrecedingToken(position, sourceFile, child);
+                        if (previousToken && includeItemAtEndPosition(previousToken)) {
+                            return previousToken;
+                        }
+                    }
+                }
+            }
+            return current;
+        }
+    }
+
+    /**
+      * The token on the left of the position is the token that strictly includes the position
+      * or sits to the left of the cursor if it is on a boundary. For example
+      *
+      *   fo|o               -> will return foo
+      *   foo <comment> |bar -> will return foo
+      *
+      */
+    export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node {
+        // Ideally, getTokenAtPosition should return a token. However, it is currently
+        // broken, so we do a check to make sure the result was indeed a token.
+        let tokenAtPosition = getTokenAtPosition(file, position);
+        if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) {
+            return tokenAtPosition;
+        }
+
+        return findPrecedingToken(position, file);
+    }
+
+    export function findNextToken(previousToken: Node, parent: Node): Node {
+        return find(parent);
+
+        function find(n: Node): Node {
+            if (isToken(n) && n.pos === previousToken.end) {
+                // this is token that starts at the end of previous token - return it
+                return n;
+            }
+
+            let children = n.getChildren();
+            for (let child of children) {
+                let shouldDiveInChildNode =
+                    // previous token is enclosed somewhere in the child
+                    (child.pos <= previousToken.pos && child.end > previousToken.end) ||
+                    // previous token ends exactly at the beginning of child
+                    (child.pos === previousToken.end);
+
+                if (shouldDiveInChildNode && nodeHasTokens(child)) {
+                    return find(child);
+                }
+            }
+
+            return undefined;
+        }
+    }
+
+    export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node): Node {
+        return find(startNode || sourceFile);
+
+        function findRightmostToken(n: Node): Node {
+            if (isToken(n)) {
+                return n;
+            }
+
+            let children = n.getChildren();
+            let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
+            return candidate && findRightmostToken(candidate);
+
+        }
+
+        function find(n: Node): Node {
+            if (isToken(n)) {
+                return n;
+            }
+
+            let children = n.getChildren();
+            for (let i = 0, len = children.length; i < len; i++) {
+                let child = children[i];
+                if (nodeHasTokens(child)) {
+                    if (position <= child.end) {
+                        if (child.getStart(sourceFile) >= position) {
+                            // actual start of the node is past the position - previous token should be at the end of previous child
+                            let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
+                            return candidate && findRightmostToken(candidate)
+                        }
+                        else {
+                            // candidate should be in this node
+                            return find(child);
+                        }
+                    }
+                }
+            }
+
+            Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile);
+
+            // Here we know that none of child token nodes embrace the position, 
+            // the only known case is when position is at the end of the file.
+            // Try to find the rightmost token in the file without filtering.
+            // Namely we are skipping the check: 'position < node.end'
+            if (children.length) {
+                let candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
+                return candidate && findRightmostToken(candidate);
+            }
+        }
+
+        /// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
+        function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node {
+            for (let i = exclusiveStartPosition - 1; i >= 0; --i) {
+                if (nodeHasTokens(children[i])) {
+                    return children[i];
+                }
+            }
+        }
+    }
+
+    function nodeHasTokens(n: Node): boolean {
+        // If we have a token or node that has a non-zero width, it must have tokens.
+        // Note, that getWidth() does not take trivia into account.
+        return n.getWidth() !== 0;
+    }
+
+    export function getNodeModifiers(node: Node): string {
+        let flags = getCombinedNodeFlags(node);
+        let result: string[] = [];
+
+        if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
+        if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier);
+        if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier);
+        if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
+        if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
+        if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier);
+
+        return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none;
+    }
+
+    export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray<Node> {
+        if (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.CallExpression) {
+            return (<CallExpression>node).typeArguments;
+        }
+
+        if (isFunctionLike(node) || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InterfaceDeclaration) {
+            return (<FunctionLikeDeclaration>node).typeParameters;
+        }
+
+        return undefined;
+    }
+
+    export function isToken(n: Node): boolean {
+        return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
+    }
+
+    export function isWord(kind: SyntaxKind): boolean {
+        return kind === SyntaxKind.Identifier || isKeyword(kind);
+    }
+
+    function isPropertyName(kind: SyntaxKind): boolean {
+        return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NumericLiteral || isWord(kind);
+    }
+
+    export function isComment(kind: SyntaxKind): boolean {
+        return kind === SyntaxKind.SingleLineCommentTrivia || kind === SyntaxKind.MultiLineCommentTrivia;
+    }
+
+    export function isPunctuation(kind: SyntaxKind): boolean {
+        return SyntaxKind.FirstPunctuation <= kind && kind <= SyntaxKind.LastPunctuation;
+    }
+
+    export function isInsideTemplateLiteral(node: LiteralExpression, position: number) {
+        return isTemplateLiteralKind(node.kind)
+            && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd());
+    }
+
+    export function isAccessibilityModifier(kind: SyntaxKind) {
+        switch (kind) {
+            case SyntaxKind.PublicKeyword:
+            case SyntaxKind.PrivateKeyword:
+            case SyntaxKind.ProtectedKeyword:
+                return true;
+        }
+
+        return false;
+    }
+
+    export function compareDataObjects(dst: any, src: any): boolean {
+        for (let e in dst) {
+            if (typeof dst[e] === "object") {
+                if (!compareDataObjects(dst[e], src[e])) {
+                    return false;
+                }
+            }
+            else if (typeof dst[e] !== "function") {
+                if (dst[e] !== src[e]) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
+
+// Display-part writer helpers
+/* @internal */
+module ts {
+    export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) {
+        return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
+    }
+
+    let displayPartWriter = getDisplayPartWriter();
+    function getDisplayPartWriter(): DisplayPartsSymbolWriter {
+        let displayParts: SymbolDisplayPart[];
+        let lineStart: boolean;
+        let indent: number;
+
+        resetWriter();
+        return {
+            displayParts: () => displayParts,
+            writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword),
+            writeOperator: text => writeKind(text, SymbolDisplayPartKind.operator),
+            writePunctuation: text => writeKind(text, SymbolDisplayPartKind.punctuation),
+            writeSpace: text => writeKind(text, SymbolDisplayPartKind.space),
+            writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral),
+            writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName),
+            writeSymbol,
+            writeLine,
+            increaseIndent: () => { indent++; },
+            decreaseIndent: () => { indent--; },
+            clear: resetWriter,
+            trackSymbol: () => { }
+        };
+
+        function writeIndent() {
+            if (lineStart) {
+                let indentString = getIndentString(indent);
+                if (indentString) {
+                    displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space));
+                }
+                lineStart = false;
+            }
+        }
+
+        function writeKind(text: string, kind: SymbolDisplayPartKind) {
+            writeIndent();
+            displayParts.push(displayPart(text, kind));
+        }
+
+        function writeSymbol(text: string, symbol: Symbol) {
+            writeIndent();
+            displayParts.push(symbolPart(text, symbol));
+        }
+
+        function writeLine() {
+            displayParts.push(lineBreakPart());
+            lineStart = true;
+        }
+
+        function resetWriter() {
+            displayParts = []
+            lineStart = true;
+            indent = 0;
+        }
+    }
+
+    export function symbolPart(text: string, symbol: Symbol) {
+        return displayPart(text, displayPartKind(symbol), symbol);
+
+        function displayPartKind(symbol: Symbol): SymbolDisplayPartKind {
+            let flags = symbol.flags;
+
+            if (flags & SymbolFlags.Variable) {
+                return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName;
+            }
+            else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; }
+            else if (flags & SymbolFlags.GetAccessor) { return SymbolDisplayPartKind.propertyName; }
+            else if (flags & SymbolFlags.SetAccessor) { return SymbolDisplayPartKind.propertyName; }
+            else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; }
+            else if (flags & SymbolFlags.Function) { return SymbolDisplayPartKind.functionName; }
+            else if (flags & SymbolFlags.Class) { return SymbolDisplayPartKind.className; }
+            else if (flags & SymbolFlags.Interface) { return SymbolDisplayPartKind.interfaceName; }
+            else if (flags & SymbolFlags.Enum) { return SymbolDisplayPartKind.enumName; }
+            else if (flags & SymbolFlags.Module) { return SymbolDisplayPartKind.moduleName; }
+            else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.methodName; }
+            else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.typeParameterName; }
+            else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; }
+            else if (flags & SymbolFlags.Alias) { return SymbolDisplayPartKind.aliasName; }
+
+
+            return SymbolDisplayPartKind.text;
+        }
+    }
+
+    export function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart {
+        return <SymbolDisplayPart> {
+            text: text,
+            kind: SymbolDisplayPartKind[kind]
+        };
+    }
+
+    export function spacePart() {
+        return displayPart(" ", SymbolDisplayPartKind.space);
+    }
+
+    export function keywordPart(kind: SyntaxKind) {
+        return displayPart(tokenToString(kind), SymbolDisplayPartKind.keyword);
+    }
+
+    export function punctuationPart(kind: SyntaxKind) {
+        return displayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation);
+    }
+
+    export function operatorPart(kind: SyntaxKind) {
+        return displayPart(tokenToString(kind), SymbolDisplayPartKind.operator);
+    }
+
+    export function textOrKeywordPart(text: string) {
+        var kind = stringToToken(text);
+        return kind === undefined
+            ? textPart(text)
+            : keywordPart(kind);
+    }
+
+    export function textPart(text: string) {
+        return displayPart(text, SymbolDisplayPartKind.text);
+    }
+
+    export function lineBreakPart() {
+        return displayPart("\n", SymbolDisplayPartKind.lineBreak);
+    }
+
+    export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
+        writeDisplayParts(displayPartWriter);
+        let result = displayPartWriter.displayParts();
+        displayPartWriter.clear();
+        return result;
+    }
+
+    export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
+        return mapToDisplayParts(writer => {
+            typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
+        });
+    }
+
+    export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] {
+        return mapToDisplayParts(writer => {
+            typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags);
+        });
+    }
+
+    export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
+        return mapToDisplayParts(writer => {
+            typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
+        });
+    }
+
+    export function isJavaScript(fileName: string) {
+        return fileExtensionIs(fileName, ".js");
+    }
+}
\ No newline at end of file
diff --git a/lib/worker/child.ts b/lib/worker/child.ts
index ef4f60016..35f54b765 100644
--- a/lib/worker/child.ts
+++ b/lib/worker/child.ts
@@ -1,6 +1,10 @@
 ///ts:ref=globals
 /// <reference path="../globals.ts"/> ///ts:ref:generated
 
+// setup typescript 
+import {makeTsGlobal} from "../typescript/makeTypeScriptGlobal";
+makeTsGlobal();
+
 import workerLib = require('./lib/workerLib');