Skip to content

Commit 67f67dd

Browse files
committed
Merge pull request microsoft#1989 from Microsoft/hostCache
Simplify updating the host cache for syntactic LS features
2 parents 64dd747 + e504453 commit 67f67dd

File tree

1 file changed

+35
-89
lines changed

1 file changed

+35
-89
lines changed

src/services/services.ts

Lines changed: 35 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,78 +1552,49 @@ module ts {
15521552
var file = this.getEntry(fileName);
15531553
return file && file.scriptSnapshot;
15541554
}
1555-
1556-
public getChangeRange(fileName: string, lastKnownVersion: string, oldScriptSnapshot: IScriptSnapshot): TextChangeRange {
1557-
var currentVersion = this.getVersion(fileName);
1558-
if (lastKnownVersion === currentVersion) {
1559-
return unchangedTextChangeRange; // "No changes"
1560-
}
1561-
1562-
var scriptSnapshot = this.getScriptSnapshot(fileName);
1563-
return scriptSnapshot.getChangeRange(oldScriptSnapshot);
1564-
}
15651555
}
15661556

15671557
class SyntaxTreeCache {
1568-
private hostCache: HostCache;
1569-
15701558
// For our syntactic only features, we also keep a cache of the syntax tree for the
15711559
// currently edited file.
1572-
private currentFileName: string = "";
1573-
private currentFileVersion: string = null;
1574-
private currentSourceFile: SourceFile = null;
1560+
private currentFileName: string;
1561+
private currentFileVersion: string;
1562+
private currentFileScriptSnapshot: IScriptSnapshot;
1563+
private currentSourceFile: SourceFile;
15751564

15761565
constructor(private host: LanguageServiceHost) {
15771566
}
15781567

1579-
private log(message: string) {
1580-
if (this.host.log) {
1581-
this.host.log(message);
1568+
public getCurrentSourceFile(fileName: string): SourceFile {
1569+
var scriptSnapshot = this.host.getScriptSnapshot(fileName);
1570+
if (!scriptSnapshot) {
1571+
// The host does not know about this file.
1572+
throw new Error("Could not find file: '" + fileName + "'.");
15821573
}
1583-
}
1584-
1585-
private initialize(fileName: string) {
1586-
// ensure that both source file and syntax tree are either initialized or not initialized
1587-
var start = new Date().getTime();
1588-
this.hostCache = new HostCache(this.host);
1589-
this.log("SyntaxTreeCache.Initialize: new HostCache: " + (new Date().getTime() - start));
15901574

1591-
var version = this.hostCache.getVersion(fileName);
1575+
var version = this.host.getScriptVersion(fileName);
15921576
var sourceFile: SourceFile;
15931577

15941578
if (this.currentFileName !== fileName) {
1595-
var scriptSnapshot = this.hostCache.getScriptSnapshot(fileName);
1596-
1597-
var start = new Date().getTime();
1579+
// This is a new file, just parse it
15981580
sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true);
1599-
this.log("SyntaxTreeCache.Initialize: createSourceFile: " + (new Date().getTime() - start));
16001581
}
16011582
else if (this.currentFileVersion !== version) {
1602-
var scriptSnapshot = this.hostCache.getScriptSnapshot(fileName);
1603-
1604-
var editRange = this.hostCache.getChangeRange(fileName, this.currentFileVersion, this.currentSourceFile.scriptSnapshot);
1605-
1606-
var start = new Date().getTime();
1583+
// This is the same file, just a newer version. Incrementally parse the file.
1584+
var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
16071585
sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
1608-
this.log("SyntaxTreeCache.Initialize: updateSourceFile: " + (new Date().getTime() - start));
16091586
}
16101587

16111588
if (sourceFile) {
16121589
// All done, ensure state is up to date
16131590
this.currentFileVersion = version;
16141591
this.currentFileName = fileName;
1592+
this.currentFileScriptSnapshot = scriptSnapshot;
16151593
this.currentSourceFile = sourceFile;
16161594
}
1617-
}
16181595

1619-
public getCurrentSourceFile(fileName: string): SourceFile {
1620-
this.initialize(fileName);
16211596
return this.currentSourceFile;
16221597
}
1623-
1624-
public getCurrentScriptSnapshot(fileName: string): IScriptSnapshot {
1625-
return this.getCurrentSourceFile(fileName).scriptSnapshot;
1626-
}
16271598
}
16281599

16291600
function setSourceFileFields(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string) {
@@ -2069,6 +2040,7 @@ module ts {
20692040
}
20702041

20712042
function getValidSourceFile(fileName: string): SourceFile {
2043+
fileName = normalizeSlashes(fileName);
20722044
var sourceFile = program.getSourceFile(getCanonicalFileName(fileName));
20732045
if (!sourceFile) {
20742046
throw new Error("Could not find file: '" + fileName + "'.");
@@ -2157,7 +2129,7 @@ module ts {
21572129
}
21582130

21592131
// We have an older version of the sourceFile, incrementally parse the changes
2160-
var textChangeRange = hostCache.getChangeRange(fileName, oldSourceFile.version, oldSourceFile.scriptSnapshot);
2132+
var textChangeRange = hostFileInformation.scriptSnapshot.getChangeRange(oldSourceFile.scriptSnapshot);
21612133
return documentRegistry.updateDocument(oldSourceFile, fileName, newSettings, hostFileInformation.scriptSnapshot, hostFileInformation.version, textChangeRange);
21622134
}
21632135
}
@@ -2222,8 +2194,6 @@ module ts {
22222194
function getSyntacticDiagnostics(fileName: string) {
22232195
synchronizeHostData();
22242196

2225-
fileName = normalizeSlashes(fileName);
2226-
22272197
return program.getSyntacticDiagnostics(getValidSourceFile(fileName));
22282198
}
22292199

@@ -2234,7 +2204,6 @@ module ts {
22342204
function getSemanticDiagnostics(fileName: string) {
22352205
synchronizeHostData();
22362206

2237-
fileName = normalizeSlashes(fileName)
22382207
var targetSourceFile = getValidSourceFile(fileName);
22392208

22402209
// Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
@@ -2311,8 +2280,6 @@ module ts {
23112280
function getCompletionsAtPosition(fileName: string, position: number) {
23122281
synchronizeHostData();
23132282

2314-
fileName = normalizeSlashes(fileName);
2315-
23162283
var syntacticStart = new Date().getTime();
23172284
var sourceFile = getValidSourceFile(fileName);
23182285

@@ -2731,8 +2698,6 @@ module ts {
27312698
function getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {
27322699
// Note: No need to call synchronizeHostData, as we have captured all the data we need
27332700
// in the getCompletionsAtPosition earlier
2734-
fileName = normalizeSlashes(fileName);
2735-
27362701
var sourceFile = getValidSourceFile(fileName);
27372702

27382703
var session = activeCompletionSession;
@@ -3195,7 +3160,6 @@ module ts {
31953160
function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
31963161
synchronizeHostData();
31973162

3198-
fileName = normalizeSlashes(fileName);
31993163
var sourceFile = getValidSourceFile(fileName);
32003164
var node = getTouchingPropertyName(sourceFile, position);
32013165
if (!node) {
@@ -3241,7 +3205,6 @@ module ts {
32413205
function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
32423206
synchronizeHostData();
32433207

3244-
fileName = normalizeSlashes(fileName);
32453208
var sourceFile = getValidSourceFile(fileName);
32463209

32473210
var node = getTouchingPropertyName(sourceFile, position);
@@ -3377,7 +3340,6 @@ module ts {
33773340
function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
33783341
synchronizeHostData();
33793342

3380-
fileName = normalizeSlashes(fileName);
33813343
var sourceFile = getValidSourceFile(fileName);
33823344

33833345
var node = getTouchingWord(sourceFile, position);
@@ -3926,7 +3888,6 @@ module ts {
39263888
function findReferences(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferenceEntry[] {
39273889
synchronizeHostData();
39283890

3929-
fileName = normalizeSlashes(fileName);
39303891
var sourceFile = getValidSourceFile(fileName);
39313892

39323893
var node = getTouchingPropertyName(sourceFile, position);
@@ -4670,7 +4631,6 @@ module ts {
46704631
function getEmitOutput(fileName: string): EmitOutput {
46714632
synchronizeHostData();
46724633

4673-
fileName = normalizeSlashes(fileName);
46744634
var sourceFile = getValidSourceFile(fileName);
46754635

46764636
var outputFiles: OutputFile[] = [];
@@ -4814,23 +4774,21 @@ module ts {
48144774
function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
48154775
synchronizeHostData();
48164776

4817-
fileName = normalizeSlashes(fileName);
48184777
var sourceFile = getValidSourceFile(fileName);
48194778

48204779
return SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken);
48214780
}
48224781

48234782
/// Syntactic features
4824-
function getCurrentSourceFile(fileName: string): SourceFile {
4825-
fileName = normalizeSlashes(fileName);
4826-
var currentSourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
4827-
return currentSourceFile;
4783+
function getSourceFile(fileName: string): SourceFile {
4784+
return syntaxTreeCache.getCurrentSourceFile(fileName);
48284785
}
48294786

48304787
function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan {
4831-
fileName = ts.normalizeSlashes(fileName);
4788+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
4789+
48324790
// Get node at the location
4833-
var node = getTouchingPropertyName(getCurrentSourceFile(fileName), startPos);
4791+
var node = getTouchingPropertyName(sourceFile, startPos);
48344792

48354793
if (!node) {
48364794
return;
@@ -4884,19 +4842,19 @@ module ts {
48844842

48854843
function getBreakpointStatementAtPosition(fileName: string, position: number) {
48864844
// doesn't use compiler - no need to synchronize with host
4887-
fileName = ts.normalizeSlashes(fileName);
4888-
return BreakpointResolver.spanInSourceFileAtLocation(getCurrentSourceFile(fileName), position);
4845+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
4846+
4847+
return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position);
48894848
}
48904849

4891-
function getNavigationBarItems(fileName: string): NavigationBarItem[] {
4892-
fileName = normalizeSlashes(fileName);
4850+
function getNavigationBarItems(fileName: string): NavigationBarItem[]{
4851+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
48934852

4894-
return NavigationBar.getNavigationBarItems(getCurrentSourceFile(fileName));
4853+
return NavigationBar.getNavigationBarItems(sourceFile);
48954854
}
48964855

48974856
function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
48984857
synchronizeHostData();
4899-
fileName = normalizeSlashes(fileName);
49004858

49014859
var sourceFile = getValidSourceFile(fileName);
49024860

@@ -4970,8 +4928,7 @@ module ts {
49704928

49714929
function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] {
49724930
// doesn't use compiler - no need to synchronize with host
4973-
fileName = normalizeSlashes(fileName);
4974-
var sourceFile = getCurrentSourceFile(fileName);
4931+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
49754932

49764933
// Make a scanner we can get trivia from.
49774934
var triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
@@ -5189,13 +5146,12 @@ module ts {
51895146

51905147
function getOutliningSpans(fileName: string): OutliningSpan[] {
51915148
// doesn't use compiler - no need to synchronize with host
5192-
fileName = normalizeSlashes(fileName);
5193-
var sourceFile = getCurrentSourceFile(fileName);
5149+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
51945150
return OutliningElementsCollector.collectElements(sourceFile);
51955151
}
51965152

51975153
function getBraceMatchingAtPosition(fileName: string, position: number) {
5198-
var sourceFile = getCurrentSourceFile(fileName);
5154+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
51995155
var result: TextSpan[] = [];
52005156

52015157
var token = getTouchingToken(sourceFile, position);
@@ -5248,10 +5204,8 @@ module ts {
52485204
}
52495205

52505206
function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) {
5251-
fileName = normalizeSlashes(fileName);
5252-
52535207
var start = new Date().getTime();
5254-
var sourceFile = getCurrentSourceFile(fileName);
5208+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
52555209
log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
52565210

52575211
var start = new Date().getTime();
@@ -5263,22 +5217,17 @@ module ts {
52635217
}
52645218

52655219
function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] {
5266-
fileName = normalizeSlashes(fileName);
5267-
var sourceFile = getCurrentSourceFile(fileName);
5220+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
52685221
return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options);
52695222
}
52705223

52715224
function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
5272-
fileName = normalizeSlashes(fileName);
5273-
5274-
var sourceFile = getCurrentSourceFile(fileName);
5225+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
52755226
return formatting.formatDocument(sourceFile, getRuleProvider(options), options);
52765227
}
52775228

52785229
function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] {
5279-
fileName = normalizeSlashes(fileName);
5280-
5281-
var sourceFile = getCurrentSourceFile(fileName);
5230+
var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
52825231

52835232
if (key === "}") {
52845233
return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options);
@@ -5302,8 +5251,6 @@ module ts {
53025251
// anything away.
53035252
synchronizeHostData();
53045253

5305-
fileName = normalizeSlashes(fileName);
5306-
53075254
var sourceFile = getValidSourceFile(fileName);
53085255

53095256
cancellationToken.throwIfCancellationRequested();
@@ -5446,7 +5393,6 @@ module ts {
54465393
function getRenameInfo(fileName: string, position: number): RenameInfo {
54475394
synchronizeHostData();
54485395

5449-
fileName = normalizeSlashes(fileName);
54505396
var sourceFile = getValidSourceFile(fileName);
54515397

54525398
var node = getTouchingWord(sourceFile, position);
@@ -5530,7 +5476,7 @@ module ts {
55305476
getFormattingEditsForDocument,
55315477
getFormattingEditsAfterKeystroke,
55325478
getEmitOutput,
5533-
getSourceFile: getCurrentSourceFile,
5479+
getSourceFile,
55345480
getProgram
55355481
};
55365482
}

0 commit comments

Comments
 (0)