Skip to content

Commit 604c37e

Browse files
Whenever a document is acquired, make sure it returns a source that corresponds to the version requested.
1 parent 505c1f2 commit 604c37e

File tree

1 file changed

+42
-29
lines changed

1 file changed

+42
-29
lines changed

src/services/services.ts

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,7 +1432,11 @@ module ts {
14321432

14331433
interface DocumentRegistryEntry {
14341434
sourceFile: SourceFile;
1435-
refCount: number;
1435+
1436+
// The number of language services that this source file is referenced in. When no more
1437+
// language services are referencing the file, then the file can be removed from the
1438+
// registry.
1439+
languageServiceRefCount: number;
14361440
owners: string[];
14371441
}
14381442

@@ -1661,6 +1665,8 @@ module ts {
16611665
}
16621666

16631667
export function createDocumentRegistry(): DocumentRegistry {
1668+
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
1669+
// for those settings.
16641670
var buckets: Map<Map<DocumentRegistryEntry>> = {};
16651671

16661672
function getKeyFromCompilationSettings(settings: CompilerOptions): string {
@@ -1684,7 +1690,7 @@ module ts {
16841690
var entry = entries[i];
16851691
sourceFiles.push({
16861692
name: i,
1687-
refCount: entry.refCount,
1693+
refCount: entry.languageServiceRefCount,
16881694
references: entry.owners.slice(0)
16891695
});
16901696
}
@@ -1697,45 +1703,52 @@ module ts {
16971703
return JSON.stringify(bucketInfoArray, null, 2);
16981704
}
16991705

1700-
function acquireDocument(
1706+
function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile {
1707+
return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ true);
1708+
}
1709+
1710+
function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile {
1711+
return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ false);
1712+
}
1713+
1714+
function acquireOrUpdateDocument(
17011715
fileName: string,
17021716
compilationSettings: CompilerOptions,
17031717
scriptSnapshot: IScriptSnapshot,
1704-
version: string): SourceFile {
1718+
version: string,
1719+
acquiring: boolean): SourceFile {
17051720

17061721
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
17071722
var entry = lookUp(bucket, fileName);
17081723
if (!entry) {
1724+
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
1725+
1726+
// Have never seen this file with these settings. Create a new source file for it.
17091727
var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false);
17101728

17111729
bucket[fileName] = entry = {
17121730
sourceFile: sourceFile,
1713-
refCount: 0,
1731+
languageServiceRefCount: 0,
17141732
owners: []
17151733
};
17161734
}
1717-
entry.refCount++;
1718-
1719-
return entry.sourceFile;
1720-
}
1721-
1722-
function updateDocument(
1723-
fileName: string,
1724-
compilationSettings: CompilerOptions,
1725-
scriptSnapshot: IScriptSnapshot,
1726-
version: string): SourceFile {
1727-
1728-
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false);
1729-
Debug.assert(bucket !== undefined);
1730-
var entry = lookUp(bucket, fileName);
1731-
Debug.assert(entry !== undefined);
1735+
else {
1736+
// We have an entry for this file. However, it may be for a different version of
1737+
// the script snapshot. If so, update it appropriately. Otherwise, we can just
1738+
// return it as is.
1739+
if (entry.sourceFile.version !== version) {
1740+
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
1741+
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
1742+
}
1743+
}
17321744

1733-
// Check with the host if anything actually changed.
1734-
if (entry.sourceFile.version !== version) {
1735-
// If so, ask the host for what changed between these two versions and then do the
1736-
// actual incremental parsing.
1737-
var textChangeRange = scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot);
1738-
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, textChangeRange);
1745+
// If we're acquiring, then this is the first time this LS is asking for this document.
1746+
// Increase our ref count so we know there's another LS using the document. If we're
1747+
// not acquiring, then that means the LS is 'updating' the file instead, and that means
1748+
// it has already acquired the document previously. As such, we do not need to increase
1749+
// the ref count.
1750+
if (acquiring) {
1751+
entry.languageServiceRefCount++;
17391752
}
17401753

17411754
return entry.sourceFile;
@@ -1746,10 +1759,10 @@ module ts {
17461759
Debug.assert(bucket !== undefined);
17471760

17481761
var entry = lookUp(bucket, fileName);
1749-
entry.refCount--;
1762+
entry.languageServiceRefCount--;
17501763

1751-
Debug.assert(entry.refCount >= 0);
1752-
if (entry.refCount === 0) {
1764+
Debug.assert(entry.languageServiceRefCount >= 0);
1765+
if (entry.languageServiceRefCount === 0) {
17531766
delete bucket[fileName];
17541767
}
17551768
}

0 commit comments

Comments
 (0)