From 1d8fab8168fb34c7c20b2e4c9b41843be64e8ae3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 9 Feb 2015 10:48:59 -0800 Subject: [PATCH 1/4] Remove host cache uses in syntactic features --- src/services/services.ts | 47 ++++++++++++---------------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 56e68b2f5a1..00cd814efb4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1548,65 +1548,46 @@ module ts { } class SyntaxTreeCache { - private hostCache: HostCache; - // 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 currentSourceFile: SourceFile = null; + private currentFileName: string; + private currentFileVersion: string; + private currentFileScriptSnapshot: IScriptSnapshot; + private currentSourceFile: SourceFile; constructor(private host: LanguageServiceHost) { } - private log(message: string) { - if (this.host.log) { - this.host.log(message); + public getCurrentSourceFile(fileName: string): SourceFile { + var scriptSnapshot = this.host.getScriptSnapshot(fileName); + if (!scriptSnapshot) { + // The host does not know about this file. + throw new Error("Could not find file: '" + fileName + "'."); } - } - private initialize(fileName: string) { - // ensure that both source file and syntax tree are either initialized or not initialized - var start = new Date().getTime(); - this.hostCache = new HostCache(this.host); - this.log("SyntaxTreeCache.Initialize: new HostCache: " + (new Date().getTime() - start)); - - var version = this.hostCache.getVersion(fileName); + var version = this.host.getScriptVersion(fileName); var sourceFile: SourceFile; if (this.currentFileName !== fileName) { - var scriptSnapshot = this.hostCache.getScriptSnapshot(fileName); - - var start = new Date().getTime(); + // This is a new file, just parse it sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true); - this.log("SyntaxTreeCache.Initialize: createSourceFile: " + (new Date().getTime() - start)); } else if (this.currentFileVersion !== version) { - var scriptSnapshot = this.hostCache.getScriptSnapshot(fileName); - - var editRange = this.hostCache.getChangeRange(fileName, this.currentFileVersion, this.currentSourceFile.scriptSnapshot); - - var start = new Date().getTime(); + // This is the same file, just a newer version. Incrementally parse the file. + var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); - this.log("SyntaxTreeCache.Initialize: updateSourceFile: " + (new Date().getTime() - start)); } if (sourceFile) { // All done, ensure state is up to date this.currentFileVersion = version; this.currentFileName = fileName; + this.currentFileScriptSnapshot = scriptSnapshot; this.currentSourceFile = sourceFile; } - } - public getCurrentSourceFile(fileName: string): SourceFile { - this.initialize(fileName); return this.currentSourceFile; } - - public getCurrentScriptSnapshot(fileName: string): IScriptSnapshot { - return this.getCurrentSourceFile(fileName).scriptSnapshot; - } } function setSourceFileFields(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string) { From c2c7b90b4f100aec00580bf16befffe11e4931f0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 9 Feb 2015 11:00:59 -0800 Subject: [PATCH 2/4] consolidate the use of normalizeSlashes in lookup helpers --- src/services/services.ts | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 00cd814efb4..b9e2f1e5433 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1977,6 +1977,7 @@ module ts { } function getValidSourceFile(fileName: string): SourceFile { + fileName = normalizeSlashes(fileName); var sourceFile = program.getSourceFile(getCanonicalFileName(fileName)); if (!sourceFile) { throw new Error("Could not find file: '" + fileName + "'."); @@ -2126,8 +2127,6 @@ module ts { function getSyntacticDiagnostics(fileName: string) { synchronizeHostData(); - fileName = normalizeSlashes(fileName); - return program.getSyntacticDiagnostics(getValidSourceFile(fileName)); } @@ -2138,7 +2137,6 @@ module ts { function getSemanticDiagnostics(fileName: string) { synchronizeHostData(); - fileName = normalizeSlashes(fileName) var targetSourceFile = getValidSourceFile(fileName); // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. @@ -2215,8 +2213,6 @@ module ts { function getCompletionsAtPosition(fileName: string, position: number) { synchronizeHostData(); - fileName = normalizeSlashes(fileName); - var syntacticStart = new Date().getTime(); var sourceFile = getValidSourceFile(fileName); @@ -2635,8 +2631,6 @@ module ts { function getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails { // Note: No need to call synchronizeHostData, as we have captured all the data we need // in the getCompletionsAtPosition earlier - fileName = normalizeSlashes(fileName); - var sourceFile = getValidSourceFile(fileName); var session = activeCompletionSession; @@ -3155,7 +3149,6 @@ module ts { function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); var node = getTouchingPropertyName(sourceFile, position); if (!node) { @@ -3201,7 +3194,6 @@ module ts { function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); var node = getTouchingPropertyName(sourceFile, position); @@ -3337,7 +3329,6 @@ module ts { function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); var node = getTouchingWord(sourceFile, position); @@ -3882,7 +3873,6 @@ module ts { function findReferences(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferenceEntry[] { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); var node = getTouchingPropertyName(sourceFile, position); @@ -4705,7 +4695,6 @@ module ts { function getEmitOutput(fileName: string): EmitOutput { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); var outputFiles: OutputFile[] = []; @@ -4849,7 +4838,6 @@ module ts { function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); return SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken); @@ -4857,13 +4845,10 @@ module ts { /// Syntactic features function getCurrentSourceFile(fileName: string): SourceFile { - fileName = normalizeSlashes(fileName); - var currentSourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return currentSourceFile; + return syntaxTreeCache.getCurrentSourceFile(fileName); } function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { - fileName = ts.normalizeSlashes(fileName); // Get node at the location var node = getTouchingPropertyName(getCurrentSourceFile(fileName), startPos); @@ -4919,19 +4904,15 @@ module ts { function getBreakpointStatementAtPosition(fileName: string, position: number) { // doesn't use compiler - no need to synchronize with host - fileName = ts.normalizeSlashes(fileName); return BreakpointResolver.spanInSourceFileAtLocation(getCurrentSourceFile(fileName), position); } function getNavigationBarItems(fileName: string): NavigationBarItem[] { - fileName = normalizeSlashes(fileName); - return NavigationBar.getNavigationBarItems(getCurrentSourceFile(fileName)); } function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); @@ -5005,7 +4986,6 @@ module ts { function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { // doesn't use compiler - no need to synchronize with host - fileName = normalizeSlashes(fileName); var sourceFile = getCurrentSourceFile(fileName); // Make a scanner we can get trivia from. @@ -5224,7 +5204,6 @@ module ts { function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host - fileName = normalizeSlashes(fileName); var sourceFile = getCurrentSourceFile(fileName); return OutliningElementsCollector.collectElements(sourceFile); } @@ -5283,8 +5262,6 @@ module ts { } function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { - fileName = normalizeSlashes(fileName); - var start = new Date().getTime(); var sourceFile = getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); @@ -5298,21 +5275,16 @@ module ts { } function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] { - fileName = normalizeSlashes(fileName); var sourceFile = getCurrentSourceFile(fileName); return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - fileName = normalizeSlashes(fileName); - var sourceFile = getCurrentSourceFile(fileName); return formatting.formatDocument(sourceFile, getRuleProvider(options), options); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] { - fileName = normalizeSlashes(fileName); - var sourceFile = getCurrentSourceFile(fileName); if (key === "}") { @@ -5337,8 +5309,6 @@ module ts { // anything away. synchronizeHostData(); - fileName = normalizeSlashes(fileName); - var sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); @@ -5484,7 +5454,6 @@ module ts { function getRenameInfo(fileName: string, position: number): RenameInfo { synchronizeHostData(); - fileName = normalizeSlashes(fileName); var sourceFile = getValidSourceFile(fileName); var node = getTouchingWord(sourceFile, position); From c37060a96d3a452e5e890d7e4e6cb58df4e19f9d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 9 Feb 2015 11:01:47 -0800 Subject: [PATCH 3/4] Remove getCurrentSourceFile and use syntaxTreeCache.getCurrentSourceFile instead --- src/services/services.ts | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index b9e2f1e5433..10769998e1a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4844,13 +4844,15 @@ module ts { } /// Syntactic features - function getCurrentSourceFile(fileName: string): SourceFile { + function getSourceFile(fileName: string): SourceFile { return syntaxTreeCache.getCurrentSourceFile(fileName); } function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + // Get node at the location - var node = getTouchingPropertyName(getCurrentSourceFile(fileName), startPos); + var node = getTouchingPropertyName(sourceFile, startPos); if (!node) { return; @@ -4904,11 +4906,15 @@ module ts { function getBreakpointStatementAtPosition(fileName: string, position: number) { // doesn't use compiler - no need to synchronize with host - return BreakpointResolver.spanInSourceFileAtLocation(getCurrentSourceFile(fileName), position); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + + return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } - function getNavigationBarItems(fileName: string): NavigationBarItem[] { - return NavigationBar.getNavigationBarItems(getCurrentSourceFile(fileName)); + function getNavigationBarItems(fileName: string): NavigationBarItem[]{ + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + + return NavigationBar.getNavigationBarItems(sourceFile); } function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { @@ -4986,7 +4992,7 @@ module ts { function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { // doesn't use compiler - no need to synchronize with host - var sourceFile = getCurrentSourceFile(fileName); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Make a scanner we can get trivia from. var triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text); @@ -5204,12 +5210,12 @@ module ts { function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host - var sourceFile = getCurrentSourceFile(fileName); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return OutliningElementsCollector.collectElements(sourceFile); } function getBraceMatchingAtPosition(fileName: string, position: number) { - var sourceFile = getCurrentSourceFile(fileName); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var result: TextSpan[] = []; var token = getTouchingToken(sourceFile, position); @@ -5263,7 +5269,7 @@ module ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { var start = new Date().getTime(); - var sourceFile = getCurrentSourceFile(fileName); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); var start = new Date().getTime(); @@ -5275,17 +5281,17 @@ module ts { } function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] { - var sourceFile = getCurrentSourceFile(fileName); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - var sourceFile = getCurrentSourceFile(fileName); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatDocument(sourceFile, getRuleProvider(options), options); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] { - var sourceFile = getCurrentSourceFile(fileName); + var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); if (key === "}") { return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); @@ -5539,7 +5545,7 @@ module ts { getFormattingEditsForDocument, getFormattingEditsAfterKeystroke, getEmitOutput, - getSourceFile: getCurrentSourceFile, + getSourceFile, getProgram }; } From d9eb63babc6ee06e11bff3e83c9e54854e05ed51 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 9 Feb 2015 11:09:31 -0800 Subject: [PATCH 4/4] Remove hostCache.getChangeRange --- src/services/services.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 10769998e1a..af180158a9b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1535,16 +1535,6 @@ module ts { var file = this.getEntry(fileName); return file && file.scriptSnapshot; } - - public getChangeRange(fileName: string, lastKnownVersion: string, oldScriptSnapshot: IScriptSnapshot): TextChangeRange { - var currentVersion = this.getVersion(fileName); - if (lastKnownVersion === currentVersion) { - return unchangedTextChangeRange; // "No changes" - } - - var scriptSnapshot = this.getScriptSnapshot(fileName); - return scriptSnapshot.getChangeRange(oldScriptSnapshot); - } } class SyntaxTreeCache { @@ -2062,7 +2052,7 @@ module ts { } // We have an older version of the sourceFile, incrementally parse the changes - var textChangeRange = hostCache.getChangeRange(fileName, oldSourceFile.version, oldSourceFile.scriptSnapshot); + var textChangeRange = hostFileInformation.scriptSnapshot.getChangeRange(oldSourceFile.scriptSnapshot); return documentRegistry.updateDocument(oldSourceFile, fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, textChangeRange); } }