Skip to content

Commit 9c755a7

Browse files
author
Christoph
committed
inlines definitions from the TS compiler to handle more cases
1 parent 950d671 commit 9c755a7

File tree

6 files changed

+102
-12
lines changed

6 files changed

+102
-12
lines changed

snapshots/input/syntax/src/property-assignment.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export function shorthandPropertyAssignment() {
55
const a = 'a'
66
return { a }
77
}
8-
type A = { a: string, b : number }
8+
type A = { a: string; b: number }
99
export function typedPropertyAssignment(): A {
1010
return { a: 'a', "b": 10 }
1111
}

snapshots/output/react/src/LoaderInput.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const LoaderInput2: React.FunctionComponent<Props> = props => {
4949
return <LoaderInput loading={true} key="key" children={props.children} />
5050
// ^^^^^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/LoaderInput.
5151
// ^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#loading.
52-
// ^^^ reference local 10
52+
// ^^^ reference @types/react 18.2.39 `index.d.ts`/React/Attributes#key.
5353
// ^^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#children.
5454
// ^^^^^ reference local 6
5555
// ^^^^^^^^ reference react-example 1.0.0 src/`LoaderInput.tsx`/Props#children.

snapshots/output/syntax/src/interface.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ export function newInterface(): Interface {
1919
property: 'a',
2020
// ^^^^^^^^ reference syntax 1.0.0 src/`interface.ts`/Interface#property.
2121
methodSignature(param: string): string {
22-
// ^^^^^^^^^^^^^^^ definition local 4
23-
// relationship implementation reference syntax 1.0.0 src/`interface.ts`/Interface#methodSignature().
22+
// ^^^^^^^^^^^^^^^ reference syntax 1.0.0 src/`interface.ts`/Interface#methodSignature().
2423
// ^^^^^ definition local 5
2524
return param
2625
// ^^^^^ reference local 5

snapshots/output/syntax/src/property-assignment.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function shorthandPropertyAssignment() {
1313
// ^ definition syntax 1.0.0 src/`property-assignment.ts`/a1:
1414
// ^ reference local 2
1515
}
16-
type A = { a: string, b : number }
16+
type A = { a: string; b: number }
1717
// ^ definition syntax 1.0.0 src/`property-assignment.ts`/A#
1818
// ^ definition syntax 1.0.0 src/`property-assignment.ts`/A#typeLiteral3:a.
1919
// ^ definition syntax 1.0.0 src/`property-assignment.ts`/A#typeLiteral3:b.
@@ -22,6 +22,6 @@ export function typedPropertyAssignment(): A {
2222
// ^ reference syntax 1.0.0 src/`property-assignment.ts`/A#
2323
return { a: 'a', "b": 10 }
2424
// ^ reference syntax 1.0.0 src/`property-assignment.ts`/A#typeLiteral3:a.
25-
// ^^^ definition syntax 1.0.0 src/`property-assignment.ts`/`"b"0`:
25+
// ^^^ reference syntax 1.0.0 src/`property-assignment.ts`/A#typeLiteral3:b.
2626
}
2727

src/FileIndexer.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,19 @@ export class FileIndexer {
150150
private getDeclarationsForPropertyAssignment(
151151
node: ts.Node
152152
): ts.Declaration[] | undefined {
153-
if (!ts.isPropertyAssignment(node.parent)) {
153+
const objectElement = ts_inline.getContainingObjectLiteralElement(node)
154+
if (!objectElement) {
154155
return
155156
}
156-
// { symbol: .... }
157-
// ^^^^^ this is symbol node we're pointing at
158-
const contextualType = this.checker.getContextualType(node.parent.parent)
159-
const property = contextualType?.getProperty(node.getText())
160-
return property?.getDeclarations()
157+
const contextualType = this.checker.getContextualType(objectElement.parent)
158+
if (contextualType === undefined) {
159+
return
160+
}
161+
const symbol = ts_inline.getPropertySymbolFromContextualType(
162+
objectElement,
163+
contextualType
164+
)
165+
return symbol?.getDeclarations()
161166
}
162167

163168
private visitSymbolOccurrence(node: ts.Node, sym: ts.Symbol): void {

src/TypeScriptInternal.ts

+86
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,89 @@ export function getTextOfJsxAttributeName(node: ts.JsxAttributeName): string {
6666
? ts.idText(node)
6767
: `${ts.idText(node.namespace)}:${ts.idText(node.name)}`
6868
}
69+
70+
type ObjectLiteralElementWithName = ts.ObjectLiteralElement & {
71+
name: ts.PropertyName
72+
parent: ts.ObjectLiteralExpression | ts.JsxAttributes
73+
}
74+
export function getContainingObjectLiteralElement(
75+
node: ts.Node
76+
): ObjectLiteralElementWithName | undefined {
77+
const element = getContainingObjectLiteralElementWorker(node)
78+
return element &&
79+
(ts.isObjectLiteralExpression(element.parent) ||
80+
ts.isJsxAttributes(element.parent))
81+
? (element as ObjectLiteralElementWithName)
82+
: undefined
83+
}
84+
85+
function getContainingObjectLiteralElementWorker(
86+
node: ts.Node
87+
): ts.ObjectLiteralElement | undefined {
88+
switch (node.kind) {
89+
case ts.SyntaxKind.StringLiteral:
90+
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
91+
case ts.SyntaxKind.NumericLiteral: {
92+
if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) {
93+
return ts.isObjectLiteralElement(node.parent.parent)
94+
? node.parent.parent
95+
: undefined
96+
}
97+
// falls through
98+
}
99+
100+
case ts.SyntaxKind.Identifier: {
101+
return ts.isObjectLiteralElement(node.parent) &&
102+
(node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression ||
103+
node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) &&
104+
node.parent.name === node
105+
? node.parent
106+
: undefined
107+
}
108+
}
109+
return undefined
110+
}
111+
112+
export function getPropertySymbolFromContextualType(
113+
node: ObjectLiteralElementWithName,
114+
contextualType: ts.Type
115+
): ts.Symbol | undefined {
116+
const name = getNameFromPropertyName(node.name)
117+
if (!name) {
118+
return undefined
119+
}
120+
return contextualType.getProperty(name)
121+
}
122+
123+
export function getNameFromPropertyName(
124+
name: ts.PropertyName
125+
): string | undefined {
126+
return name.kind === ts.SyntaxKind.ComputedPropertyName
127+
? // treat computed property names where expression is string/numeric literal as just string/numeric literal
128+
isStringOrNumericLiteralLike(name.expression)
129+
? name.expression.text
130+
: undefined
131+
: ts.isPrivateIdentifier(name)
132+
? ts.idText(name)
133+
: getTextOfIdentifierOrLiteral(name)
134+
}
135+
136+
export function isStringOrNumericLiteralLike(
137+
node: ts.Node
138+
): node is ts.StringLiteralLike | ts.NumericLiteral {
139+
return ts.isStringLiteralLike(node) || ts.isNumericLiteral(node)
140+
}
141+
142+
export function getTextOfIdentifierOrLiteral(
143+
node: ts.PropertyNameLiteral | ts.PrivateIdentifier
144+
): string {
145+
return ts.isMemberName(node)
146+
? ts.idText(node)
147+
: ts.isJsxNamespacedName(node)
148+
? getTextOfJsxNamespacedName(node)
149+
: node.text
150+
}
151+
152+
export function getTextOfJsxNamespacedName(node: ts.JsxNamespacedName): string {
153+
return `${ts.idText(node.namespace)}:${ts.idText(node.name)}`
154+
}

0 commit comments

Comments
 (0)