diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 91a30143047..74b3f59bbd1 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: number = 0, isOpen: boolean = false): SourceFile { + export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: string, 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 054b76c55b2..85f9ce6fe32 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) : undefined; + return text !== undefined ? createSourceFile(filename, text, languageVersion, /*version:*/ "0") : 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 5cb80687d80..416a2960329 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -526,7 +526,7 @@ module ts { identifierCount: number; symbolCount: number; isOpen: boolean; - version: number; + version: string; languageVersion: ScriptTarget; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index da649f77dd9..fd91c7c70ec 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 dce80544222..e19777827d1 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); + export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.ES5, /*version:*/ "0"); 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); + filemap[filename] = ts.createSourceFile(filename, file.content, options.target, /*version:*/ "0"); }; inputFiles.forEach(register); otherFiles.forEach(register); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index cb8ef61f413..0f904b24a17 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -80,8 +80,9 @@ module Harness.LanguageService { return JSON.stringify(this.lineMap.lineStarts()); } - public getTextChangeRangeSinceVersion(scriptVersion: number): string { - var range = this.scriptInfo.getTextChangeRangeBetweenVersions(scriptVersion, this.version); + public getChangeRange(oldScript: ts.ScriptSnapshotShim): string { + var oldShim = oldScript; + var range = this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version); if (range === null) { return null; } @@ -101,50 +102,14 @@ 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: number, + version: string, isOpen: boolean): ts.SourceFile { return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen); } @@ -154,7 +119,7 @@ module Harness.LanguageService { fileName: string, compilationSettings: ts.CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: number, + version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange ): ts.SourceFile { @@ -252,8 +217,8 @@ module Harness.LanguageService { return new ScriptSnapshotShim(this.getScriptInfo(fileName)); } - public getScriptVersion(fileName: string): number { - return this.getScriptInfo(fileName).version; + public getScriptVersion(fileName: string): string { + return this.getScriptInfo(fileName).version.toString(); } public getScriptIsOpen(fileName: string): boolean { @@ -270,7 +235,7 @@ module Harness.LanguageService { public getLanguageService(): ts.LanguageServiceShim { var ls = new TypeScript.Services.TypeScriptServicesFactory().createLanguageServiceShim(this); this.ls = ls; - var hostAdapter = new LanguageServiceShimHostAdapter(this); + var hostAdapter = new ts.LanguageServiceShimHostAdapter(this); this.newLS = ts.createLanguageService(hostAdapter, NonCachingDocumentRegistry.Instance); return ls; diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 5b4b1712e8e..c76fbda1b96 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -152,7 +152,7 @@ class ProjectRunner extends RunnerBase { } if (text !== undefined) { - sourceFile = ts.createSourceFile(filename, text, languageVersion); + sourceFile = ts.createSourceFile(filename, text, languageVersion, /*version:*/ "0"); } } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index 576b06e3435..780b6d24588 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, /*version:*/ "0"); }, getDefaultLibFilename: () => libPath, writeFile: (fn, contents) => emitterIOHost.writeFile(fn, contents, false), diff --git a/src/services/services.ts b/src/services/services.ts index 06bfbd80e05..9ff6266d54e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -26,7 +26,6 @@ /// module ts { - export interface Node { getSourceFile(): SourceFile; getChildCount(): number; @@ -72,7 +71,8 @@ module ts { getSourceUnit(): TypeScript.SourceUnitSyntax; getSyntaxTree(): TypeScript.SyntaxTree; getBloomFilter(): TypeScript.BloomFilter; - update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile; + getScriptSnapshot(): TypeScript.IScriptSnapshot; + update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, 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: number; + public version: string; public isOpen: boolean; public languageVersion: ScriptTarget; @@ -333,6 +333,10 @@ module ts { return this.getSyntaxTree().sourceUnit(); } + public getScriptSnapshot(): TypeScript.IScriptSnapshot { + return this.scriptSnapshot; + } + public getLineMap(): TypeScript.LineMap { return this.getSyntaxTree().lineMap(); } @@ -384,7 +388,7 @@ module ts { return this.bloomFilter; } - public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile { + public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, 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 @@ -419,7 +423,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: number, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) { + public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) { var newSourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen); newSourceFile.scriptSnapshot = scriptSnapshot; newSourceFile.syntaxTree = syntaxTree; @@ -442,7 +446,7 @@ module ts { export interface LanguageServiceHost extends Logger { getCompilationSettings(): CompilerOptions; getScriptFileNames(): string[]; - getScriptVersion(fileName: string): number; + getScriptVersion(fileName: string): string; getScriptIsOpen(fileName: string): boolean; getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot; getLocalizedDiagnosticMessages(): any; @@ -692,7 +696,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: number, + version: string, isOpen: boolean, referencedFiles: string[]): SourceFile; @@ -701,7 +705,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: number, + version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange ): SourceFile; @@ -819,7 +823,7 @@ module ts { // Information about a specific host file. interface HostFileInformation { filename: string; - version: number; + version: string; isOpen: boolean; sourceText?: TypeScript.IScriptSnapshot; } @@ -928,7 +932,7 @@ module ts { return fileNames; } - public getVersion(filename: string): number { + public getVersion(filename: string): string { return this.getEntry(filename).version; } @@ -944,14 +948,14 @@ module ts { return file.sourceText; } - public getScriptTextChangeRangeSinceVersion(filename: string, lastKnownVersion: number): TypeScript.TextChangeRange { + public getChangeRange(filename: string, lastKnownVersion: string, oldScriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange { var currentVersion = this.getVersion(filename); if (lastKnownVersion === currentVersion) { return TypeScript.TextChangeRange.unchanged; // "No changes" } var scriptSnapshot = this.getScriptSnapshot(filename); - return scriptSnapshot.getTextChangeRangeSinceVersion(lastKnownVersion); + return scriptSnapshot.getChangeRange(oldScriptSnapshot); } } @@ -960,11 +964,10 @@ 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: number = -1; + private currentFilename: string = ""; + private currentFileVersion: string = null; private currentSourceFile: SourceFile = null; private currentFileSyntaxTree: TypeScript.SyntaxTree = null; - private currentFileScriptSnapshot: TypeScript.IScriptSnapshot = null; constructor(private host: LanguageServiceHost) { this.hostCache = new HostCache(host); @@ -979,7 +982,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); @@ -988,9 +991,10 @@ module ts { } else if (this.currentFileVersion !== version) { var scriptSnapshot = this.hostCache.getScriptSnapshot(filename); - syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot, this.currentFileSyntaxTree, this.currentFileVersion); + syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot, + this.currentSourceFile.getScriptSnapshot(), this.currentFileSyntaxTree, this.currentFileVersion); - var editRange = this.hostCache.getScriptTextChangeRangeSinceVersion(filename, this.currentFileVersion); + var editRange = this.hostCache.getChangeRange(filename, this.currentFileVersion, this.currentSourceFile.getScriptSnapshot()); sourceFile = !editRange ? createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true) : this.currentSourceFile.update(scriptSnapshot, version, /*isOpen*/ true, editRange); @@ -1001,9 +1005,8 @@ 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; } @@ -1038,7 +1041,7 @@ module ts { public getCurrentScriptSnapshot(filename: string): TypeScript.IScriptSnapshot { // update currentFileScriptSnapshot as a part of 'getCurrentFileSyntaxTree' call this.getCurrentFileSyntaxTree(filename); - return this.currentFileScriptSnapshot; + return this.getCurrentSourceFile(filename).getScriptSnapshot(); } private createSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.SyntaxTree { @@ -1052,8 +1055,8 @@ module ts { return syntaxTree; } - private updateSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, previousSyntaxTree: TypeScript.SyntaxTree, previousFileVersion: number): TypeScript.SyntaxTree { - var editRange = this.hostCache.getScriptTextChangeRangeSinceVersion(filename, previousFileVersion); + 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); // Debug.assert(newLength >= 0); @@ -1065,7 +1068,7 @@ module ts { var nextSyntaxTree = TypeScript.IncrementalParser.parse( previousSyntaxTree, editRange, TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot)); - this.ensureInvariants(filename, editRange, nextSyntaxTree, this.currentFileScriptSnapshot, scriptSnapshot); + this.ensureInvariants(filename, editRange, nextSyntaxTree, previousScriptSnapshot, scriptSnapshot); return nextSyntaxTree; } @@ -1133,7 +1136,7 @@ module ts { } } - function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: number, isOpen: boolean) { + function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: string, isOpen: boolean) { return SourceFileObject.createSourceFileObject(filename, scriptSnapshot, settings.target, version, isOpen); } @@ -1178,7 +1181,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: number, + version: string, isOpen: boolean): SourceFile { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); @@ -1202,7 +1205,7 @@ module ts { filename: string, compilationSettings: CompilerOptions, scriptSnapshot: TypeScript.IScriptSnapshot, - version: number, + version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange ): SourceFile { @@ -1388,7 +1391,7 @@ module ts { // new text buffer). var textChangeRange: TypeScript.TextChangeRange = null; if (sourceFile.isOpen && isOpen) { - textChangeRange = hostCache.getScriptTextChangeRangeSinceVersion(filename, sourceFile.version); + textChangeRange = hostCache.getChangeRange(filename, sourceFile.version, sourceFile.getScriptSnapshot()); } sourceFile = documentRegistry.updateDocument(sourceFile, filename, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange); diff --git a/src/services/shims.ts b/src/services/shims.ts index 523a0af5c91..d473a6979ee 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. - getTextChangeRangeSinceVersion(scriptVersion: number): string; + getChangeRange(oldSnapshot: ScriptSnapshotShim): string; } // @@ -48,7 +48,7 @@ module ts { // Returns a JSON encoded value of the type: // string[] getScriptFileNames(): string; - getScriptVersion(fileName: string): number; + getScriptVersion(fileName: string): string; getScriptIsOpen(fileName: string): boolean; getScriptSnapshot(fileName: string): ScriptSnapshotShim; getLocalizedDiagnosticMessages(): string; @@ -283,8 +283,9 @@ module ts { return this.lineStartPositions; } - public getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange { - var encoded = this.scriptSnapshotShim.getTextChangeRangeSinceVersion(scriptVersion); + public getChangeRange(oldSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange { + var oldSnapshotShim = oldSnapshot; + var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); if (encoded == null) { return null; } @@ -295,7 +296,7 @@ module ts { } } - class LanguageServiceShimHostAdapter implements LanguageServiceHost { + export class LanguageServiceShimHostAdapter implements LanguageServiceHost { constructor(private shimHost: LanguageServiceShimHost) { } @@ -349,7 +350,7 @@ module ts { return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName)); } - public getScriptVersion(fileName: string): number { + public getScriptVersion(fileName: string): string { return this.shimHost.getScriptVersion(fileName); } diff --git a/src/services/text/scriptSnapshot.ts b/src/services/text/scriptSnapshot.ts index 41b5ed37c41..1c7091d6cae 100644 --- a/src/services/text/scriptSnapshot.ts +++ b/src/services/text/scriptSnapshot.ts @@ -16,10 +16,12 @@ module TypeScript { // always determine this (albeit in a more expensive manner). getLineStartPositions(): number[]; - // 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; + // 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; } export module ScriptSnapshot { @@ -45,7 +47,7 @@ module TypeScript { return this._lineStartPositions; } - public getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange { + public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange { throw Errors.notYetImplemented(); } }