Skip to content

Commit 1178e84

Browse files
Don't cache the typechecker at the LS level. Just get it when needed from the program.
1 parent 4cdc970 commit 1178e84

3 files changed

Lines changed: 61 additions & 55 deletions

File tree

src/services/services.ts

Lines changed: 57 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,8 +2284,6 @@ module ts {
22842284
let ruleProvider: formatting.RulesProvider;
22852285
let program: Program;
22862286

2287-
// this checker is used to answer all LS questions except errors
2288-
let typeInfoResolver: TypeChecker;
22892287
let useCaseSensitivefileNames = false;
22902288
let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
22912289

@@ -2367,8 +2365,10 @@ module ts {
23672365
}
23682366

23692367
program = newProgram;
2370-
typeInfoResolver = program.getTypeChecker();
23712368

2369+
// Make sure all the nodes in the program are both bound, and have their parent
2370+
// pointers set property.
2371+
program.getTypeChecker();
23722372
return;
23732373

23742374
function getOrCreateSourceFile(fileName: string): SourceFile {
@@ -2452,15 +2452,8 @@ module ts {
24522452
return program;
24532453
}
24542454

2455-
/**
2456-
* Clean up any semantic caches that are not needed.
2457-
* The host can call this method if it wants to jettison unused memory.
2458-
* We will just dump the typeChecker and recreate a new one. this should have the effect of destroying all the semantic caches.
2459-
*/
24602455
function cleanupSemanticCache(): void {
2461-
if (program) {
2462-
typeInfoResolver = program.getTypeChecker();
2463-
}
2456+
// TODO: Should we jettison the program (or it's type checker) here?
24642457
}
24652458

24662459
function dispose(): void {
@@ -2728,32 +2721,8 @@ module ts {
27282721
return unescapeIdentifier(displayName);
27292722
}
27302723

2731-
function createCompletionEntry(symbol: Symbol, typeChecker: TypeChecker, location: Node): CompletionEntry {
2732-
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
2733-
// We would like to only show things that can be added after a dot, so for instance numeric properties can
2734-
// not be accessed with a dot (a.1 <- invalid)
2735-
let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true);
2736-
if (!displayName) {
2737-
return undefined;
2738-
}
2739-
2740-
// TODO(drosen): Right now we just permit *all* semantic meanings when calling
2741-
// 'getSymbolKind' which is permissible given that it is backwards compatible; but
2742-
// really we should consider passing the meaning for the node so that we don't report
2743-
// that a suggestion for a value is an interface. We COULD also just do what
2744-
// 'getSymbolModifiers' does, which is to use the first declaration.
2745-
2746-
// Use a 'sortText' of 0' so that all symbol completion entries come before any other
2747-
// entries (like JavaScript identifier entries).
2748-
return {
2749-
name: displayName,
2750-
kind: getSymbolKind(symbol, typeChecker, location),
2751-
kindModifiers: getSymbolModifiers(symbol),
2752-
sortText: "0",
2753-
};
2754-
}
2755-
27562724
function getCompletionData(fileName: string, position: number) {
2725+
let typeInfoResolver = program.getTypeChecker();
27572726
let syntacticStart = new Date().getTime();
27582727
let sourceFile = getValidSourceFile(fileName);
27592728

@@ -3307,14 +3276,39 @@ module ts {
33073276
return entries;
33083277
}
33093278

3279+
function createCompletionEntry(symbol: Symbol, location: Node): CompletionEntry {
3280+
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
3281+
// We would like to only show things that can be added after a dot, so for instance numeric properties can
3282+
// not be accessed with a dot (a.1 <- invalid)
3283+
let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true);
3284+
if (!displayName) {
3285+
return undefined;
3286+
}
3287+
3288+
// TODO(drosen): Right now we just permit *all* semantic meanings when calling
3289+
// 'getSymbolKind' which is permissible given that it is backwards compatible; but
3290+
// really we should consider passing the meaning for the node so that we don't report
3291+
// that a suggestion for a value is an interface. We COULD also just do what
3292+
// 'getSymbolModifiers' does, which is to use the first declaration.
3293+
3294+
// Use a 'sortText' of 0' so that all symbol completion entries come before any other
3295+
// entries (like JavaScript identifier entries).
3296+
return {
3297+
name: displayName,
3298+
kind: getSymbolKind(symbol, location),
3299+
kindModifiers: getSymbolModifiers(symbol),
3300+
sortText: "0",
3301+
};
3302+
}
3303+
33103304
function getCompletionEntriesFromSymbols(symbols: Symbol[]): CompletionEntry[] {
33113305
let start = new Date().getTime();
33123306
var entries: CompletionEntry[] = [];
33133307

33143308
if (symbols) {
33153309
var nameToSymbol: Map<Symbol> = {};
33163310
for (let symbol of symbols) {
3317-
let entry = createCompletionEntry(symbol, typeInfoResolver, location);
3311+
let entry = createCompletionEntry(symbol, location);
33183312
if (entry) {
33193313
let id = escapeIdentifier(entry.name);
33203314
if (!lookUp(nameToSymbol, id)) {
@@ -3346,7 +3340,7 @@ module ts {
33463340
let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false) === entryName ? s : undefined);
33473341

33483342
if (symbol) {
3349-
let displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, typeInfoResolver, location, SemanticMeaning.All);
3343+
let displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All);
33503344
return {
33513345
name: entryName,
33523346
kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
@@ -3373,7 +3367,7 @@ module ts {
33733367
}
33743368

33753369
// TODO(drosen): use contextual SemanticMeaning.
3376-
function getSymbolKind(symbol: Symbol, typeResolver: TypeChecker, location: Node): string {
3370+
function getSymbolKind(symbol: Symbol, location: Node): string {
33773371
let flags = symbol.getFlags();
33783372

33793373
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
@@ -3382,7 +3376,7 @@ module ts {
33823376
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
33833377
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
33843378

3385-
let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver, location);
3379+
let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location);
33863380
if (result === ScriptElementKind.unknown) {
33873381
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
33883382
if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
@@ -3393,7 +3387,9 @@ module ts {
33933387
return result;
33943388
}
33953389

3396-
function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, typeResolver: TypeChecker, location: Node) {
3390+
function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, location: Node) {
3391+
let typeResolver = program.getTypeChecker();
3392+
33973393
if (typeResolver.isUndefinedSymbol(symbol)) {
33983394
return ScriptElementKind.variableElement;
33993395
}
@@ -3421,7 +3417,7 @@ module ts {
34213417
if (flags & SymbolFlags.Property) {
34223418
if (flags & SymbolFlags.UnionProperty) {
34233419
// If union property is result of union of non method (property/accessors/variables), it is labeled as property
3424-
let unionPropertyKind = forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => {
3420+
let unionPropertyKind = forEach(typeResolver.getRootSymbols(symbol), rootSymbol => {
34253421
let rootSymbolFlags = rootSymbol.getFlags();
34263422
if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) {
34273423
return ScriptElementKind.memberVariableElement;
@@ -3431,7 +3427,7 @@ module ts {
34313427
if (!unionPropertyKind) {
34323428
// If this was union of all methods,
34333429
//make sure it has call signatures before we can label it as method
3434-
let typeOfUnionProperty = typeInfoResolver.getTypeOfSymbolAtLocation(symbol, location);
3430+
let typeOfUnionProperty = typeResolver.getTypeOfSymbolAtLocation(symbol, location);
34353431
if (typeOfUnionProperty.getCallSignatures().length) {
34363432
return ScriptElementKind.memberFunctionElement;
34373433
}
@@ -3464,15 +3460,16 @@ module ts {
34643460
: ScriptElementKindModifier.none;
34653461
}
34663462

3463+
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
34673464
function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node,
3468-
typeResolver: TypeChecker, location: Node,
3469-
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
3470-
semanticMeaning = getMeaningFromLocation(location)) {
3465+
location: Node, semanticMeaning = getMeaningFromLocation(location)) {
3466+
3467+
let typeResolver = program.getTypeChecker();
34713468

34723469
let displayParts: SymbolDisplayPart[] = [];
34733470
let documentation: SymbolDisplayPart[];
34743471
let symbolFlags = symbol.flags;
3475-
let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver, location);
3472+
let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location);
34763473
let hasAddedSymbolInfo: boolean;
34773474
let type: Type;
34783475

@@ -3738,7 +3735,7 @@ module ts {
37383735
}
37393736
}
37403737
else {
3741-
symbolKind = getSymbolKind(symbol, typeResolver, location);
3738+
symbolKind = getSymbolKind(symbol, location);
37423739
}
37433740
}
37443741

@@ -3817,6 +3814,7 @@ module ts {
38173814
return undefined;
38183815
}
38193816

3817+
let typeInfoResolver = program.getTypeChecker();
38203818
let symbol = typeInfoResolver.getSymbolAtLocation(node);
38213819
if (!symbol) {
38223820
// Try getting just type at this position and show
@@ -3842,7 +3840,7 @@ module ts {
38423840
return undefined;
38433841
}
38443842

3845-
let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), typeInfoResolver, node);
3843+
let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node);
38463844
return {
38473845
kind: displayPartsDocumentationsAndKind.symbolKind,
38483846
kindModifiers: getSymbolModifiers(symbol),
@@ -3898,6 +3896,7 @@ module ts {
38983896
return undefined;
38993897
}
39003898

3899+
let typeInfoResolver = program.getTypeChecker();
39013900
let symbol = typeInfoResolver.getSymbolAtLocation(node);
39023901

39033902
// Could not find a symbol e.g. node is string or number keyword,
@@ -3929,7 +3928,7 @@ module ts {
39293928
}
39303929

39313930
let shorthandDeclarations = shorthandSymbol.getDeclarations();
3932-
let shorthandSymbolKind = getSymbolKind(shorthandSymbol, typeInfoResolver, node);
3931+
let shorthandSymbolKind = getSymbolKind(shorthandSymbol, node);
39333932
let shorthandSymbolName = typeInfoResolver.symbolToString(shorthandSymbol);
39343933
let shorthandContainerName = typeInfoResolver.symbolToString(symbol.parent, node);
39353934
return map(shorthandDeclarations,
@@ -3939,7 +3938,7 @@ module ts {
39393938
let result: DefinitionInfo[] = [];
39403939
let declarations = symbol.getDeclarations();
39413940
let symbolName = typeInfoResolver.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
3942-
let symbolKind = getSymbolKind(symbol, typeInfoResolver, node);
3941+
let symbolKind = getSymbolKind(symbol, node);
39433942
let containerSymbol = symbol.parent;
39443943
let containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, node) : "";
39453944

@@ -4609,6 +4608,8 @@ module ts {
46094608
}
46104609

46114610
function getReferencesForNode(node: Node, sourceFiles: SourceFile[], searchOnlyInCurrentFile: boolean, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[]{
4611+
let typeInfoResolver = program.getTypeChecker();
4612+
46124613
// Labels
46134614
if (isLabelName(node)) {
46144615
if (isJumpStatementTarget(node)) {
@@ -4689,7 +4690,7 @@ module ts {
46894690
return result;
46904691

46914692
function getDefinition(symbol: Symbol): DefinitionInfo {
4692-
let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), typeInfoResolver, node);
4693+
let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node);
46934694
let name = map(info.displayParts, p => p.text).join("");
46944695
let declarations = symbol.declarations;
46954696
if (!declarations || declarations.length === 0) {
@@ -5615,7 +5616,7 @@ module ts {
56155616

56165617
let sourceFile = getValidSourceFile(fileName);
56175618

5618-
return SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken);
5619+
return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken);
56195620
}
56205621

56215622
/// Syntactic features
@@ -5696,6 +5697,7 @@ module ts {
56965697
synchronizeHostData();
56975698

56985699
let sourceFile = getValidSourceFile(fileName);
5700+
let typeInfoResolver = program.getTypeChecker();
56995701

57005702
let result: ClassifiedSpan[] = [];
57015703
processNode(sourceFile);
@@ -6230,6 +6232,7 @@ module ts {
62306232
synchronizeHostData();
62316233

62326234
let sourceFile = getValidSourceFile(fileName);
6235+
let typeInfoResolver = program.getTypeChecker();
62336236

62346237
let node = getTouchingWord(sourceFile, position);
62356238

@@ -6252,7 +6255,7 @@ module ts {
62526255
}
62536256
}
62546257

6255-
let kind = getSymbolKind(symbol, typeInfoResolver, node);
6258+
let kind = getSymbolKind(symbol, node);
62566259
if (kind) {
62576260
return {
62586261
canRename: true,

src/services/signatureHelp.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ module ts.SignatureHelp {
178178
argumentCount: number;
179179
}
180180

181-
export function getSignatureHelpItems(sourceFile: SourceFile, position: number, typeInfoResolver: TypeChecker, cancellationToken: CancellationTokenObject): SignatureHelpItems {
181+
export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationTokenObject): SignatureHelpItems {
182+
let typeInfoResolver = program.getTypeChecker();
183+
182184
// Decide whether to show signature help
183185
let startingToken = findTokenOnLeftOfPosition(sourceFile, position);
184186
if (!startingToken) {

tests/cases/fourslash/definitionNameOnEnumMember.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
////}
88
////var enumMember = e./*1*/thirdMember;
99

10+
debugger;
1011
goTo.marker("1");
1112
verify.verifyDefinitionsName("thirdMember", "e");

0 commit comments

Comments
 (0)