Skip to content

Commit 625bf95

Browse files
author
Christoph
committed
uses in more places to get the type of object literals
1 parent 9571de4 commit 625bf95

File tree

1 file changed

+14
-74
lines changed

1 file changed

+14
-74
lines changed

src/FileIndexer.ts

Lines changed: 14 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -147,25 +147,22 @@ export class FileIndexer {
147147
return false
148148
}
149149

150+
private getDeclarationsForPropertyAssignment(node: ts.Node, sym: ts.Symbol): ts.Declaration[] | undefined {
151+
if (!ts.isPropertyAssignment(node.parent)) {
152+
return
153+
}
154+
// { symbol: .... }
155+
// ^^^^^ this is symbol node we're pointing at
156+
const contextualType = this.checker.getContextualType(node.parent.parent)
157+
const property = contextualType?.getProperty(node.getText())
158+
return property?.getDeclarations()
159+
}
160+
150161
private visitSymbolOccurrence(node: ts.Node, sym: ts.Symbol): void {
151162
const range = Range.fromNode(node).toLsif()
152163
let role = 0
153-
let isDefinitionNode = isDefinition(node)
154-
let declarations: ts.Node[] = [];
155-
if (ts.isPropertyAssignment(node.parent)) {
156-
const contextualType = this.checker.getContextualType(node.parent.parent);
157-
if (contextualType != null) {
158-
const property = contextualType.getProperty(node.getText());
159-
if (property != null) {
160-
const decls = property.getDeclarations()
161-
if (decls != null && decls.length > 0) {
162-
isDefinitionNode = false;
163-
declarations = decls;
164-
}
165-
}
166-
}
167-
}
168-
164+
let declarations: ts.Node[] = this.getDeclarationsForPropertyAssignment(node, sym) ?? [];
165+
let isDefinitionNode = declarations.length == 0 && isDefinition(node);
169166
if (isDefinitionNode) {
170167
role |= scip.scip.SymbolRole.Definition
171168
}
@@ -682,10 +679,7 @@ export class FileIndexer {
682679
onAncestor(declaration)
683680
}
684681
if (ts.isObjectLiteralExpression(declaration)) {
685-
const tpe = this.inferredTypeOfObjectLiteral(
686-
declaration.parent,
687-
declaration
688-
)
682+
const tpe = this.checker.getContextualType(declaration) ?? this.checker.getTypeAtLocation(declaration);
689683
for (const symbolDeclaration of tpe.symbol?.declarations || []) {
690684
loop(symbolDeclaration)
691685
}
@@ -707,60 +701,6 @@ export class FileIndexer {
707701
}
708702
loop(node)
709703
}
710-
711-
// Returns the "inferred" type of the provided object literal, where
712-
// "inferred" is loosely defined as the type that is expected in the position
713-
// where the object literal appears. For example, the object literal in
714-
// `const x: SomeInterface = {y: 42}` has the inferred type `SomeInterface`
715-
// even if `this.checker.getTypeAtLocation({y: 42})` does not return
716-
// `SomeInterface`. The object literal could satisfy many types, but in this
717-
// particular location must only satisfy `SomeInterface`.
718-
private inferredTypeOfObjectLiteral(
719-
node: ts.Node,
720-
literal: ts.ObjectLiteralExpression
721-
): ts.Type {
722-
if (
723-
ts.isIfStatement(node) ||
724-
ts.isForStatement(node) ||
725-
ts.isForInStatement(node) ||
726-
ts.isForOfStatement(node) ||
727-
ts.isWhileStatement(node) ||
728-
ts.isDoStatement(node) ||
729-
ts.isReturnStatement(node) ||
730-
ts.isBlock(node)
731-
) {
732-
return this.inferredTypeOfObjectLiteral(node.parent, literal)
733-
}
734-
735-
if (ts.isVariableDeclaration(node)) {
736-
// Example, return `SomeInterface` from `const x: SomeInterface = {y: 42}`.
737-
return this.checker.getTypeAtLocation(node.name)
738-
}
739-
740-
if (ts.isFunctionLike(node)) {
741-
const functionType = this.checker.getTypeAtLocation(node)
742-
const callSignatures = functionType.getCallSignatures()
743-
if (callSignatures.length > 0) {
744-
return callSignatures[0].getReturnType()
745-
}
746-
}
747-
748-
if (ts.isCallOrNewExpression(node)) {
749-
// Example: return the type of the second parameter of `someMethod` from
750-
// the expression `someMethod(someParameter, {y: 42})`.
751-
const signature = this.checker.getResolvedSignature(node)
752-
for (const [index, argument] of (node.arguments || []).entries()) {
753-
if (argument === literal) {
754-
const parameterSymbol = signature?.getParameters()[index]
755-
if (parameterSymbol) {
756-
return this.checker.getTypeOfSymbolAtLocation(parameterSymbol, node)
757-
}
758-
}
759-
}
760-
}
761-
762-
return this.checker.getTypeAtLocation(literal)
763-
}
764704
}
765705

766706
function isAnonymousContainerOfSymbols(node: ts.Node): boolean {

0 commit comments

Comments
 (0)