diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 74b3f59bbd1..91a30143047 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, version: string, isOpen: boolean = false): SourceFile { + export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: number = 0, isOpen: boolean = false): SourceFile { var file: SourceFile; var scanner: Scanner; var token: SyntaxKind; diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index a653126ef2f..af425c337aa 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -142,7 +142,7 @@ module ts { } text = ""; } - return text !== undefined ? createSourceFile(filename, text, languageVersion, /*version:*/ "0") : undefined; + return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined; } function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 11d30c33937..b8d6c05711a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -526,7 +526,7 @@ module ts { identifierCount: number; symbolCount: number; isOpen: boolean; - version: string; + version: number; languageVersion: ScriptTarget; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index fd91c7c70ec..da649f77dd9 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1895,11 +1895,11 @@ 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, /*version*/ "0", /*isOpen*/ false); + fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false); var files: { [filename: string]: ts.SourceFile; } = {}; files[fourslashFilename] = fourslashSourceFile; - files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, /*version*/ "0", /*isOpen*/ false); + files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false); files[Harness.Compiler.defaultLibFileName] = Harness.Compiler.defaultLibSourceFile; var host = Harness.Compiler.createCompilerHost(files, (fn, contents) => result = contents); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 863afe2f98d..3a768be0832 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -532,7 +532,7 @@ module Harness { } export var defaultLibFileName = 'lib.d.ts'; - export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.ES5, /*version:*/ "0"); + export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.ES5); export function createCompilerHost(filemap: { [filename: string]: ts.SourceFile; }, writeFile: (fn: string, contents: string, writeByteOrderMark:boolean) => void): ts.CompilerHost { return { @@ -724,7 +724,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, /*version:*/ "0"); + filemap[filename] = ts.createSourceFile(filename, file.content, options.target); }; inputFiles.forEach(register); otherFiles.forEach(register); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 0f904b24a17..cb8ef61f413 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -80,9 +80,8 @@ module Harness.LanguageService { return JSON.stringify(this.lineMap.lineStarts()); } - public getChangeRange(oldScript: ts.ScriptSnapshotShim): string { - var oldShim = oldScript; - var range = this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version); + public getTextChangeRangeSinceVersion(scriptVersion: number): string { + var range = this.scriptInfo.getTextChangeRangeBetweenVersions(scriptVersion, this.version); if (range === null) { return null; } @@ -102,14 +101,50 @@ module Harness.LanguageService { } } + class ScriptSnapshotShimAdapter implements TypeScript.IScriptSnapshot { + private lineStartPositions: number[] = null; + constructor(private scriptSnapshotShim: ts.ScriptSnapshotShim) {} + getText(start: number, end: number): string {return this.scriptSnapshotShim.getText(start, end);} + getLength(): number {return this.scriptSnapshotShim.getLength();} + getLineStartPositions(): number[] { return JSON.parse(this.scriptSnapshotShim.getLineStartPositions()); } + getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange { + var encoded = this.scriptSnapshotShim.getTextChangeRangeSinceVersion(scriptVersion); + if (encoded == null) { + return null; + } + + var decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded); + return new TypeScript.TextChangeRange( + new TypeScript.TextSpan(decoded.span.start, decoded.span.length), decoded.newLength); + } + } + + class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { + constructor(private shimHost: ts.LanguageServiceShimHost) { } + information(): boolean { return this.shimHost.information(); } + debug(): boolean { return this.shimHost.debug(); } + warning(): boolean { return this.shimHost.warning();} + error(): boolean { return this.shimHost.error(); } + fatal(): boolean { return this.shimHost.fatal(); } + log(s: string): void { this.shimHost.log(s); } + getCompilationSettings(): ts.CompilerOptions { return JSON.parse(this.shimHost.getCompilationSettings()); } + getScriptFileNames(): string[] { return JSON.parse(this.shimHost.getScriptFileNames());} + getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot { return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName));} + getScriptVersion(fileName: string): number { return this.shimHost.getScriptVersion(fileName);} + getScriptIsOpen(fileName: string): boolean { return this.shimHost.getScriptIsOpen(fileName); } + getLocalizedDiagnosticMessages(): any { JSON.parse(this.shimHost.getLocalizedDiagnosticMessages());} + getCancellationToken(): ts.CancellationToken { return this.shimHost.getCancellationToken(); } + } + export class NonCachingDocumentRegistry implements ts.DocumentRegistry { + public static Instance: ts.DocumentRegistry = new NonCachingDocumentRegistry(); public acquireDocument( fileName: string, compilationSettings: ts.CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: string, + version: number, isOpen: boolean): ts.SourceFile { return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen); } @@ -119,7 +154,7 @@ module Harness.LanguageService { fileName: string, compilationSettings: ts.CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: string, + version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange ): ts.SourceFile { @@ -217,8 +252,8 @@ module Harness.LanguageService { return new ScriptSnapshotShim(this.getScriptInfo(fileName)); } - public getScriptVersion(fileName: string): string { - return this.getScriptInfo(fileName).version.toString(); + public getScriptVersion(fileName: string): number { + return this.getScriptInfo(fileName).version; } public getScriptIsOpen(fileName: string): boolean { @@ -235,7 +270,7 @@ module Harness.LanguageService { public getLanguageService(): ts.LanguageServiceShim { var ls = new TypeScript.Services.TypeScriptServicesFactory().createLanguageServiceShim(this); this.ls = ls; - var hostAdapter = new ts.LanguageServiceShimHostAdapter(this); + var hostAdapter = new LanguageServiceShimHostAdapter(this); this.newLS = ts.createLanguageService(hostAdapter, NonCachingDocumentRegistry.Instance); return ls; diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 86c9f879f5c..37694e6aeaf 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -174,7 +174,7 @@ class ProjectRunner extends RunnerBase { else { var text = getSourceFileText(filename); if (text !== undefined) { - sourceFile = ts.createSourceFile(filename, text, languageVersion, /*version:*/ "0"); + sourceFile = ts.createSourceFile(filename, text, languageVersion); } } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index 780b6d24588..576b06e3435 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, /*version:*/ "0"); + return ts.createSourceFile(fileName, fileContents, languageVersion); }, getDefaultLibFilename: () => libPath, writeFile: (fn, contents) => emitterIOHost.writeFile(fn, contents, false), diff --git a/src/services/services.ts b/src/services/services.ts index 9ff6266d54e..06bfbd80e05 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -26,6 +26,7 @@ /// module ts { + export interface Node { getSourceFile(): SourceFile; getChildCount(): number; @@ -71,8 +72,7 @@ module ts { getSourceUnit(): TypeScript.SourceUnitSyntax; getSyntaxTree(): TypeScript.SyntaxTree; getBloomFilter(): TypeScript.BloomFilter; - getScriptSnapshot(): TypeScript.IScriptSnapshot; - update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile; + update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile; } var scanner: Scanner = createScanner(ScriptTarget.ES5); @@ -320,7 +320,7 @@ module ts { public identifierCount: number; public symbolCount: number; public statements: NodeArray; - public version: string; + public version: number; public isOpen: boolean; public languageVersion: ScriptTarget; @@ -333,10 +333,6 @@ module ts { return this.getSyntaxTree().sourceUnit(); } - public getScriptSnapshot(): TypeScript.IScriptSnapshot { - return this.scriptSnapshot; - } - public getLineMap(): TypeScript.LineMap { return this.getSyntaxTree().lineMap(); } @@ -388,7 +384,7 @@ module ts { return this.bloomFilter; } - public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile { + 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 @@ -423,7 +419,7 @@ module ts { return SourceFileObject.createSourceFileObject(this.filename, scriptSnapshot, this.languageVersion, version, isOpen, newSyntaxTree); } - public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) { + public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: number, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) { var newSourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen); newSourceFile.scriptSnapshot = scriptSnapshot; newSourceFile.syntaxTree = syntaxTree; @@ -446,7 +442,7 @@ module ts { export interface LanguageServiceHost extends Logger { getCompilationSettings(): CompilerOptions; getScriptFileNames(): string[]; - getScriptVersion(fileName: string): string; + getScriptVersion(fileName: string): number; getScriptIsOpen(fileName: string): boolean; getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot; getLocalizedDiagnosticMessages(): any; @@ -696,7 +692,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: string, + version: number, isOpen: boolean, referencedFiles: string[]): SourceFile; @@ -705,7 +701,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: string, + version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange ): SourceFile; @@ -823,7 +819,7 @@ module ts { // Information about a specific host file. interface HostFileInformation { filename: string; - version: string; + version: number; isOpen: boolean; sourceText?: TypeScript.IScriptSnapshot; } @@ -932,7 +928,7 @@ module ts { return fileNames; } - public getVersion(filename: string): string { + public getVersion(filename: string): number { return this.getEntry(filename).version; } @@ -948,14 +944,14 @@ module ts { return file.sourceText; } - public getChangeRange(filename: string, lastKnownVersion: string, oldScriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange { + public getScriptTextChangeRangeSinceVersion(filename: string, lastKnownVersion: number): TypeScript.TextChangeRange { var currentVersion = this.getVersion(filename); if (lastKnownVersion === currentVersion) { return TypeScript.TextChangeRange.unchanged; // "No changes" } var scriptSnapshot = this.getScriptSnapshot(filename); - return scriptSnapshot.getChangeRange(oldScriptSnapshot); + return scriptSnapshot.getTextChangeRangeSinceVersion(lastKnownVersion); } } @@ -964,10 +960,11 @@ module ts { // 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 = null; + private currentfilename: string = ""; + private currentFileVersion: number = -1; private currentSourceFile: SourceFile = null; private currentFileSyntaxTree: TypeScript.SyntaxTree = null; + private currentFileScriptSnapshot: TypeScript.IScriptSnapshot = null; constructor(private host: LanguageServiceHost) { this.hostCache = new HostCache(host); @@ -982,7 +979,7 @@ module ts { var syntaxTree: TypeScript.SyntaxTree = null; var sourceFile: SourceFile; - if (this.currentFileSyntaxTree === null || this.currentFilename !== filename) { + if (this.currentFileSyntaxTree === null || this.currentfilename !== filename) { var scriptSnapshot = this.hostCache.getScriptSnapshot(filename); syntaxTree = this.createSyntaxTree(filename, scriptSnapshot); sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true); @@ -991,10 +988,9 @@ module ts { } else if (this.currentFileVersion !== version) { var scriptSnapshot = this.hostCache.getScriptSnapshot(filename); - syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot, - this.currentSourceFile.getScriptSnapshot(), this.currentFileSyntaxTree, this.currentFileVersion); + syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot, this.currentFileSyntaxTree, this.currentFileVersion); - var editRange = this.hostCache.getChangeRange(filename, this.currentFileVersion, this.currentSourceFile.getScriptSnapshot()); + var editRange = this.hostCache.getScriptTextChangeRangeSinceVersion(filename, this.currentFileVersion); sourceFile = !editRange ? createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true) : this.currentSourceFile.update(scriptSnapshot, version, /*isOpen*/ true, editRange); @@ -1005,8 +1001,9 @@ module ts { if (syntaxTree !== null) { Debug.assert(sourceFile); // All done, ensure state is up to date + this.currentFileScriptSnapshot = scriptSnapshot; this.currentFileVersion = version; - this.currentFilename = filename; + this.currentfilename = filename; this.currentFileSyntaxTree = syntaxTree; this.currentSourceFile = sourceFile; } @@ -1041,7 +1038,7 @@ module ts { public getCurrentScriptSnapshot(filename: string): TypeScript.IScriptSnapshot { // update currentFileScriptSnapshot as a part of 'getCurrentFileSyntaxTree' call this.getCurrentFileSyntaxTree(filename); - return this.getCurrentSourceFile(filename).getScriptSnapshot(); + return this.currentFileScriptSnapshot; } private createSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.SyntaxTree { @@ -1055,8 +1052,8 @@ module ts { return syntaxTree; } - private updateSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, previousScriptSnapshot: TypeScript.IScriptSnapshot, previousSyntaxTree: TypeScript.SyntaxTree, previousFileVersion: string): TypeScript.SyntaxTree { - var editRange = this.hostCache.getChangeRange(filename, previousFileVersion, previousScriptSnapshot); + private updateSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, previousSyntaxTree: TypeScript.SyntaxTree, previousFileVersion: number): TypeScript.SyntaxTree { + var editRange = this.hostCache.getScriptTextChangeRangeSinceVersion(filename, previousFileVersion); // Debug.assert(newLength >= 0); @@ -1068,7 +1065,7 @@ module ts { var nextSyntaxTree = TypeScript.IncrementalParser.parse( previousSyntaxTree, editRange, TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot)); - this.ensureInvariants(filename, editRange, nextSyntaxTree, previousScriptSnapshot, scriptSnapshot); + this.ensureInvariants(filename, editRange, nextSyntaxTree, this.currentFileScriptSnapshot, scriptSnapshot); return nextSyntaxTree; } @@ -1136,7 +1133,7 @@ module ts { } } - function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: string, isOpen: boolean) { + function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: number, isOpen: boolean) { return SourceFileObject.createSourceFileObject(filename, scriptSnapshot, settings.target, version, isOpen); } @@ -1181,7 +1178,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: string, + version: number, isOpen: boolean): SourceFile { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); @@ -1205,7 +1202,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: string, + version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange ): SourceFile { @@ -1391,7 +1388,7 @@ module ts { // new text buffer). var textChangeRange: TypeScript.TextChangeRange = null; if (sourceFile.isOpen && isOpen) { - textChangeRange = hostCache.getChangeRange(filename, sourceFile.version, sourceFile.getScriptSnapshot()); + textChangeRange = hostCache.getScriptTextChangeRangeSinceVersion(filename, sourceFile.version); } sourceFile = documentRegistry.updateDocument(sourceFile, filename, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange); diff --git a/src/services/shims.ts b/src/services/shims.ts index d473a6979ee..523a0af5c91 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -36,7 +36,7 @@ module ts { // { span: { start: number; length: number }; newLength: number } // // Or null value if there was no change. - getChangeRange(oldSnapshot: ScriptSnapshotShim): string; + getTextChangeRangeSinceVersion(scriptVersion: number): string; } // @@ -48,7 +48,7 @@ module ts { // Returns a JSON encoded value of the type: // string[] getScriptFileNames(): string; - getScriptVersion(fileName: string): string; + getScriptVersion(fileName: string): number; getScriptIsOpen(fileName: string): boolean; getScriptSnapshot(fileName: string): ScriptSnapshotShim; getLocalizedDiagnosticMessages(): string; @@ -283,9 +283,8 @@ module ts { return this.lineStartPositions; } - public getChangeRange(oldSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange { - var oldSnapshotShim = oldSnapshot; - var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); + public getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange { + var encoded = this.scriptSnapshotShim.getTextChangeRangeSinceVersion(scriptVersion); if (encoded == null) { return null; } @@ -296,7 +295,7 @@ module ts { } } - export class LanguageServiceShimHostAdapter implements LanguageServiceHost { + class LanguageServiceShimHostAdapter implements LanguageServiceHost { constructor(private shimHost: LanguageServiceShimHost) { } @@ -350,7 +349,7 @@ module ts { return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName)); } - public getScriptVersion(fileName: string): string { + public getScriptVersion(fileName: string): number { return this.shimHost.getScriptVersion(fileName); } diff --git a/src/services/text/scriptSnapshot.ts b/src/services/text/scriptSnapshot.ts index 1c7091d6cae..41b5ed37c41 100644 --- a/src/services/text/scriptSnapshot.ts +++ b/src/services/text/scriptSnapshot.ts @@ -16,12 +16,10 @@ module TypeScript { // always determine this (albeit in a more expensive manner). getLineStartPositions(): number[]; - // Gets the TextChangeRange that describe how the text changed between this text and - // an older version. This informatoin is used by the incremental parser to determine - // what sections of the script need to be reparsed. 'null' 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 reparsed. - getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange; + // Returns a text change range representing what text has changed since the specified version. + // If the change cannot be determined (say, because a file was opened/closed), then 'null' + // should be returned. + getTextChangeRangeSinceVersion(scriptVersion: number): TextChangeRange; } export module ScriptSnapshot { @@ -47,7 +45,7 @@ module TypeScript { return this._lineStartPositions; } - public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange { + public getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange { throw Errors.notYetImplemented(); } }