From aa75de9c70ec2f316eb81336841f790322b9f4aa Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Aug 2014 11:45:35 -0700 Subject: [PATCH] Consolidate Document and SoruceFile --- src/compiler/parser.ts | 6 +- src/compiler/tc.ts | 2 +- src/compiler/types.ts | 4 + src/harness/fourslash.ts | 6 +- src/harness/harness.ts | 4 +- src/harness/harnessLanguageService.ts | 9 +- src/harness/projectsRunner.ts | 4 +- src/harness/rwcRunner.ts | 2 +- src/services/services.ts | 329 ++++++++++++-------------- 9 files changed, 168 insertions(+), 198 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6902ebc4835..4bd1a826567 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -417,7 +417,7 @@ module ts { nodeIsNestedInLabel(label: Identifier, requireIterationStatement: boolean, stopAtFunctionBoundary: boolean): ControlBlockContext; } - export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget): SourceFile { + export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, byteOrderMark: ByteOrderMark, version: number = 0, isOpen: boolean = false): SourceFile { var file: SourceFile; var scanner: Scanner; var token: SyntaxKind; @@ -3523,6 +3523,10 @@ module ts { file.externalModuleIndicator = getExternalModuleIndicator(); file.nodeCount = nodeCount; file.identifierCount = identifierCount; + file.version = version; + file.byteOrderMark = byteOrderMark; + file.isOpen = isOpen; + file.languageVersion = languageVersion; return file; } diff --git a/src/compiler/tc.ts b/src/compiler/tc.ts index e564002d03f..cbe9bcee6df 100644 --- a/src/compiler/tc.ts +++ b/src/compiler/tc.ts @@ -135,7 +135,7 @@ module ts { } text = ""; } - return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined; + return text !== undefined ? createSourceFile(filename, text, languageVersion, ByteOrderMark.None) : undefined; } function writeFile(fileName: string, data: string, onError?: (message: string) => void) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 10a358f379d..3411b3d2104 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -525,6 +525,10 @@ module ts { nodeCount: number; identifierCount: number; symbolCount: number; + byteOrderMark: ByteOrderMark; + isOpen: boolean; + version: number; + languageVersion: ScriptTarget; } export interface Program { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 30b70f1631e..25cc615c8e0 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1895,12 +1895,12 @@ module FourSlash { var result = ''; var fourslashFilename = 'fourslash.ts'; var tsFn = 'tests/cases/fourslash/' + fourslashFilename; - fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5); - libdtsSourceFile = libdtsSourceFile || ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, ts.ScriptTarget.ES3); + fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false); + libdtsSourceFile = libdtsSourceFile || ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, ts.ScriptTarget.ES3, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false); var files: { [filename: string]: ts.SourceFile; } = {}; files[fourslashFilename] = fourslashSourceFile; - files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5); + files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false); files['lib.d.ts'] = libdtsSourceFile; var host = Harness.Compiler.createCompilerHost(files, (fn, contents) => result = contents); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index f90d096f536..b77514611d5 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -544,7 +544,7 @@ module Harness { } else { var lib = 'lib.d.ts'; if (fn.substr(fn.length - lib.length) === lib) { - return filemap[fn] = ts.createSourceFile('lib.d.ts', libTextMinimal, languageVersion); + return filemap[fn] = ts.createSourceFile('lib.d.ts', libTextMinimal, languageVersion, ts.ByteOrderMark.None); } // Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC return null; @@ -720,7 +720,7 @@ module Harness { var filemap: { [name: string]: ts.SourceFile; } = {}; var register = (file: { unitName: string; content: string; }) => { var filename = Path.switchToForwardSlashes(file.unitName); - filemap[filename] = ts.createSourceFile(filename, file.content, options.target); + filemap[filename] = ts.createSourceFile(filename, file.content, options.target, ts.ByteOrderMark.None); }; inputFiles.forEach(register); otherFiles.forEach(register); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index e3646b98e03..400cae2abe1 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -147,20 +147,19 @@ module Harness.LanguageService { scriptSnapshot: TypeScript.IScriptSnapshot, byteOrderMark: ts.ByteOrderMark, version: number, - isOpen: boolean, - referencedFiles: string[]= []): ts.Document { - return ts.createDocument(compilationSettings, fileName, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles); + isOpen: boolean): ts.SourceFile { + return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, byteOrderMark, version, isOpen); } public updateDocument( - document: ts.Document, + document: ts.SourceFile, fileName: string, compilationSettings: ts.CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange - ): ts.Document { + ): ts.SourceFile { return document.update(scriptSnapshot, version, isOpen, textChangeRange); } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index f3fc650e55c..e6ec6d6f9de 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -139,7 +139,7 @@ class ProjectRunner extends RunnerBase { function getSourceFile(filename: string, languageVersion: ts.ScriptTarget): ts.SourceFile { var sourceFile: ts.SourceFile = undefined; if (filename === 'lib.d.ts') { - sourceFile = ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, languageVersion); + sourceFile = ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, languageVersion, ts.ByteOrderMark.None); } else { assert.isTrue(!ts.filter(readInputFiles, sourceFile => sourceFile.filename == filename).length, "Compiler trying to read same file again: " + filename); @@ -154,7 +154,7 @@ class ProjectRunner extends RunnerBase { } if (text !== undefined) { - sourceFile = ts.createSourceFile(filename, text, languageVersion) + sourceFile = ts.createSourceFile(filename, text, languageVersion, ts.ByteOrderMark.None); } } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index 576b06e3435..98006cd6bce 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -107,7 +107,7 @@ module RWC { catch (e) { // Leave fileContents undefined; } - return ts.createSourceFile(fileName, fileContents, languageVersion); + return ts.createSourceFile(fileName, fileContents, languageVersion, ts.ByteOrderMark.None); }, getDefaultLibFilename: () => libPath, writeFile: (fn, contents) => emitterIOHost.writeFile(fn, contents, false), diff --git a/src/services/services.ts b/src/services/services.ts index 1c60f2c6ba0..ef0526442e9 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -67,6 +67,13 @@ module ts { getReturnType(): Type; } + export interface SourceFile { + getSourceUnit(): TypeScript.SourceUnitSyntax; + getSyntaxTree(): TypeScript.SyntaxTree; + getBloomFilter(): TypeScript.BloomFilter; + update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile; + } + var scanner: Scanner = createScanner(ScriptTarget.ES5); var emptyArray: any [] = []; @@ -81,7 +88,6 @@ module ts { } class NodeObject implements Node { - public kind: SyntaxKind; public pos: number; public end: number; @@ -294,6 +300,130 @@ module ts { } } + var incrementalParse: IncrementalParse = TypeScript.IncrementalParser.parse; + + class SourceFileObject extends NodeObject implements SourceFile { + public filename: string; + public text: string; + public getLineAndCharacterFromPosition(position: number): { line: number; character: number } { return null; } + public amdDependencies: string[]; + public referencedFiles: FileReference[]; + public syntacticErrors: Diagnostic[]; + public semanticErrors: 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 statements: NodeArray; + public byteOrderMark: ByteOrderMark; + public version: number; + public isOpen: boolean; + public languageVersion: ScriptTarget; + + private bloomFilter: TypeScript.BloomFilter; + private syntaxTree: TypeScript.SyntaxTree; + private scriptSnapshot: TypeScript.IScriptSnapshot; + + public getSourceUnit(): TypeScript.SourceUnitSyntax { + // If we don't have a script, create one from our parse tree. + return this.getSyntaxTree().sourceUnit(); + } + + public getLineMap(): TypeScript.LineMap { + return this.getSyntaxTree().lineMap(); + } + + public getSyntaxTree(): TypeScript.SyntaxTree { + if (!this.syntaxTree) { + var start = new Date().getTime(); + + this.syntaxTree = TypeScript.Parser.parse( + this.filename, TypeScript.SimpleText.fromScriptSnapshot(this.scriptSnapshot), this.languageVersion, this.isDeclareFile()); + + var time = new Date().getTime() - start; + + //TypeScript.syntaxTreeParseTime += time; + } + + return this.syntaxTree; + } + + private isDeclareFile(): boolean { + return TypeScript.isDTSFile(this.filename); + } + + public getBloomFilter(): TypeScript.BloomFilter { + if (!this.bloomFilter) { + var identifiers = TypeScript.createIntrinsicsObject(); + var pre = function (cur: TypeScript.ISyntaxElement) { + if (TypeScript.ASTHelpers.isValidAstNode(cur)) { + if (cur.kind() === TypeScript.SyntaxKind.IdentifierName) { + var nodeText = TypeScript.tokenValueText((cur)); + + identifiers[nodeText] = true; + } + } + }; + + TypeScript.getAstWalkerFactory().simpleWalk(this.getSourceUnit(), pre, null, identifiers); + + var identifierCount = 0; + for (var name in identifiers) { + if (identifiers[name]) { + identifierCount++; + } + } + + this.bloomFilter = new TypeScript.BloomFilter(identifierCount); + this.bloomFilter.addKeys(identifiers); + } + return this.bloomFilter; + } + + public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile { + // See if we are currently holding onto a syntax tree. We may not be because we're + // either a closed file, or we've just been lazy and haven't had to create the syntax + // tree yet. Access the field instead of the method so we don't accidently realize + // the old syntax tree. + var oldSyntaxTree = this.syntaxTree; + + if (textChangeRange !== null && Debug.shouldAssert(AssertionLevel.Normal)) { + var oldText = this.scriptSnapshot; + var newText = scriptSnapshot; + + TypeScript.Debug.assert((oldText.getLength() - textChangeRange.span().length() + textChangeRange.newLength()) === newText.getLength()); + + if (Debug.shouldAssert(AssertionLevel.VeryAggressive)) { + var oldTextPrefix = oldText.getText(0, textChangeRange.span().start()); + var newTextPrefix = newText.getText(0, textChangeRange.span().start()); + TypeScript.Debug.assert(oldTextPrefix === newTextPrefix); + + var oldTextSuffix = oldText.getText(textChangeRange.span().end(), oldText.getLength()); + var newTextSuffix = newText.getText(textChangeRange.newSpan().end(), newText.getLength()); + TypeScript.Debug.assert(oldTextSuffix === newTextSuffix); + } + } + + var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot); + + // If we don't have a text change, or we don't have an old syntax tree, then do a full + // parse. Otherwise, do an incremental parse. + var newSyntaxTree = textChangeRange === null || oldSyntaxTree === null + ? TypeScript.Parser.parse(this.filename, text, this.languageVersion, TypeScript.isDTSFile(this.filename)) + : TypeScript.IncrementalParser.parse(oldSyntaxTree, textChangeRange, text); + + return SourceFileObject.createSourceFileObject(this.languageVersion, this.filename, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree); + } + + public static createSourceFileObject(languageVersion: ScriptTarget, filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, byteOrderMark: ByteOrderMark, version: number, isOpen: boolean, syntaxTree: TypeScript.SyntaxTree) { + var newSoruceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, byteOrderMark, version, isOpen); + newSoruceFile.scriptSnapshot = scriptSnapshot; + newSoruceFile.syntaxTree = syntaxTree; + return newSoruceFile; + } + } + export interface Logger { information(): boolean; debug(): boolean; @@ -563,17 +693,17 @@ module ts { byteOrderMark: ByteOrderMark, version: number, isOpen: boolean, - referencedFiles: string[]): Document; + referencedFiles: string[]): SourceFile; updateDocument( - document: Document, + document: SourceFile, filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange - ): Document; + ): SourceFile; releaseDocument(filename: string, compilationSettings: CompilerOptions): void } @@ -665,172 +795,6 @@ module ts { (oldSyntaxTree: TypeScript.SyntaxTree, textChangeRange: TypeScript.TextChangeRange, newText: TypeScript.ISimpleText): TypeScript.SyntaxTree } - export interface Document { - getFilename(): string; - getByteOrderMark(): ByteOrderMark; - getVersion(): number; - isOpen(): boolean; - getSourceUnit(): TypeScript.SourceUnitSyntax; - getSyntaxTree(): TypeScript.SyntaxTree; - getSourceFile(): SourceFile; - getBloomFilter(): TypeScript.BloomFilter; - update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): Document; - } - - class DocumentObject implements Document { - private bloomFilter: TypeScript.BloomFilter = null; - - // By default, our Document class doesn't support incremental update of its conten - // However, we enable other layers (like teh services layer) to inject the capability - // into us by setting this function. - public static incrementalParse: IncrementalParse = TypeScript.IncrementalParser.parse; - - constructor(private compilationSettings: CompilerOptions, - public filename: string, - public referencedFiles: string[], - private scriptSnapshot: TypeScript.IScriptSnapshot, - public byteOrderMark: ByteOrderMark, - public version: number, - public _isOpen: boolean, - private syntaxTree: TypeScript.SyntaxTree, - private soruceFile: SourceFile) { - } - - public getFilename(): string { - return this.filename; - } - - public getVersion(): number { - return this.version; - } - - public isOpen(): boolean { - return this._isOpen; - } - - public getByteOrderMark(): ByteOrderMark { - return this.byteOrderMark; - } - public isDeclareFile(): boolean { - return TypeScript.isDTSFile(this.filename); - } - - public getSourceUnit(): TypeScript.SourceUnitSyntax { - // If we don't have a script, create one from our parse tree. - return this.getSyntaxTree().sourceUnit(); - } - - public getLineMap(): TypeScript.LineMap { - return this.getSyntaxTree().lineMap(); - } - - public getSyntaxTree(): TypeScript.SyntaxTree { - if (!this.syntaxTree) { - var start = new Date().getTime(); - - this.syntaxTree = TypeScript.Parser.parse( - this.filename, TypeScript.SimpleText.fromScriptSnapshot(this.scriptSnapshot), this.compilationSettings.target, this.isDeclareFile()); - - var time = new Date().getTime() - start; - - //TypeScript.syntaxTreeParseTime += time; - } - - return this.syntaxTree; - } - - public getSourceFile(): SourceFile { - if (!this.soruceFile) { - var start = new Date().getTime(); - - this.soruceFile = createSourceFile(this.filename, this.scriptSnapshot.getText(0, this.scriptSnapshot.getLength()), this.compilationSettings.target); - - var time = new Date().getTime() - start; - - //TypeScript.astParseTime += time; - } - - return this.soruceFile; - } - - public getBloomFilter(): TypeScript.BloomFilter { - if (!this.bloomFilter) { - var identifiers = TypeScript.createIntrinsicsObject(); - var pre = function (cur: TypeScript.ISyntaxElement) { - if (TypeScript.ASTHelpers.isValidAstNode(cur)) { - if (cur.kind() === TypeScript.SyntaxKind.IdentifierName) { - var nodeText = TypeScript.tokenValueText((cur)); - - identifiers[nodeText] = true; - } - } - }; - - TypeScript.getAstWalkerFactory().simpleWalk(this.getSourceUnit(), pre, null, identifiers); - - var identifierCount = 0; - for (var name in identifiers) { - if (identifiers[name]) { - identifierCount++; - } - } - - this.bloomFilter = new TypeScript.BloomFilter(identifierCount); - this.bloomFilter.addKeys(identifiers); - } - return this.bloomFilter; - } - - // Returns true if this file should get emitted into its own unique output file. - // Otherwise, it should be written into a single output file along with the rest of hte - // documents in the compilation. - public emitToOwnOutputFile(): boolean { - // If we haven't specified an output file in our settings, then we're definitely - // emitting to our own file. Also, if we're an external module, then we're - // definitely emitting to our own file. - return !this.compilationSettings.out || this.getSyntaxTree().isExternalModule(); - } - - public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): Document { - // See if we are currently holding onto a syntax tree. We may not be because we're - // either a closed file, or we've just been lazy and haven't had to create the syntax - // tree yet. Access the field instead of the method so we don't accidently realize - // the old syntax tree. - var oldSyntaxTree = this.syntaxTree; - - if (textChangeRange !== null && Debug.shouldAssert(AssertionLevel.Normal)) { - var oldText = this.scriptSnapshot; - var newText = scriptSnapshot; - - TypeScript.Debug.assert((oldText.getLength() - textChangeRange.span().length() + textChangeRange.newLength()) === newText.getLength()); - - if (Debug.shouldAssert(AssertionLevel.VeryAggressive)) { - var oldTextPrefix = oldText.getText(0, textChangeRange.span().start()); - var newTextPrefix = newText.getText(0, textChangeRange.span().start()); - TypeScript.Debug.assert(oldTextPrefix === newTextPrefix); - - var oldTextSuffix = oldText.getText(textChangeRange.span().end(), oldText.getLength()); - var newTextSuffix = newText.getText(textChangeRange.newSpan().end(), newText.getLength()); - TypeScript.Debug.assert(oldTextSuffix === newTextSuffix); - } - } - - var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot); - - // If we don't have a text change, or we don't have an old syntax tree, then do a full - // parse. Otherwise, do an incremental parse. - var newSyntaxTree = textChangeRange === null || oldSyntaxTree === null || DocumentObject.incrementalParse === null - ? TypeScript.Parser.parse(this.filename, text, this.compilationSettings.target, TypeScript.isDTSFile(this.filename)) - : DocumentObject.incrementalParse(oldSyntaxTree, textChangeRange, text); - - return new DocumentObject(this.compilationSettings, this.filename, this.referencedFiles, scriptSnapshot, this.byteOrderMark, version, isOpen, newSyntaxTree, /*soruceFile*/ null); - } - } - - export function createDocument(compilationSettings: CompilerOptions, fileName: string, scriptSnapshot: TypeScript.IScriptSnapshot, byteOrderMark: ByteOrderMark, version: number, isOpen: boolean, referencedFiles: string[]): Document { - return new DocumentObject(compilationSettings, fileName, referencedFiles, scriptSnapshot, byteOrderMark, version, isOpen, /*syntaxTree:*/ null, /*soruceFile*/ null); - } - /// Language Service interface CompletionSession { @@ -859,7 +823,7 @@ module ts { } interface DocumentRegistryEntry { - document: Document; + document: SourceFile; refCount: number; owners: string[]; } @@ -1172,13 +1136,12 @@ module ts { scriptSnapshot: TypeScript.IScriptSnapshot, byteOrderMark: ByteOrderMark, version: number, - isOpen: boolean, - referencedFiles: string[]= []): Document { + isOpen: boolean): SourceFile { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); var entry = lookUp(bucket, filename); if (!entry) { - var document = createDocument(compilationSettings, filename, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles); + var document = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, byteOrderMark, version, isOpen); bucket[filename] = entry = { document: document, @@ -1192,21 +1155,21 @@ module ts { } function updateDocument( - document: Document, + document: SourceFile, filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange - ): Document { + ): SourceFile { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false); Debug.assert(bucket); var entry = lookUp(bucket, filename); Debug.assert(entry); - if (entry.document.isOpen() === isOpen && entry.document.getVersion() === version) { + if (entry.document.isOpen === isOpen && entry.document.version === version) { return entry.document; } @@ -1252,7 +1215,7 @@ module ts { var program: Program; var typeChecker: TypeChecker; var useCaseSensitivefilenames = false; - var documentsByName: Map = {}; + var documentsByName: Map = {}; var documentRegistry = documentRegistry; var cancellationToken = new CancellationTokenObject(host.getCancellationToken()); var activeCompletionSession: CompletionSession; // The current active completion session, used to get the completion entry details @@ -1262,7 +1225,7 @@ module ts { TypeScript.LocalizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); } - function getDocument(filename: string): Document { + function getDocument(filename: string): SourceFile { return lookUp(documentsByName, filename); } @@ -1339,12 +1302,12 @@ module ts { var isOpen = hostCache.isOpen(filename); var scriptSnapshot = hostCache.getScriptSnapshot(filename); - var document: Document = getDocument(filename); + var document: SourceFile = getDocument(filename); if (document) { // // If the document is the same, assume no update // - if (document.getVersion() === version && document.isOpen() === isOpen) { + if (document.version === version && document.isOpen === isOpen) { continue; } @@ -1356,7 +1319,7 @@ module ts { // new text buffer). var textChangeRange: TypeScript.TextChangeRange = null; if (document.isOpen && isOpen) { - textChangeRange = hostCache.getScriptTextChangeRangeSinceVersion(filename, document.getVersion()); + textChangeRange = hostCache.getScriptTextChangeRangeSinceVersion(filename, document.version); } document = documentRegistry.updateDocument(document, filename, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange); @@ -2217,7 +2180,7 @@ module ts { getNodeConstructor: kind => { function Node() { } - var proto = new NodeObject(); + var proto = kind === SyntaxKind.SourceFile ? new SourceFileObject() : new NodeObject(); proto.kind = kind; proto.pos = 0; proto.end = 0;