Skip to content

Commit e0cc380

Browse files
authored
Merge pull request #218 from zardoy/develop
2 parents 0aa9607 + e71c7a6 commit e0cc380

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

typescript/src/definitions.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { join } from 'path-browserify'
22
import { GetConfig } from './types'
33
import { findChildContainingExactPosition } from './utils'
4+
import { eventDefinitions } from './eventsReferences'
45

56
export default (proxy: ts.LanguageService, languageService: ts.LanguageService, languageServiceHost: ts.LanguageServiceHost, c: GetConfig) => {
67
proxy.getDefinitionAndBoundSpan = (fileName, position, ...props) => {
@@ -26,6 +27,9 @@ export default (proxy: ts.LanguageService, languageService: ts.LanguageService,
2627
const noDefs = !prior?.definitions || prior.definitions.length === 0
2728
const tryFileResolve = noDefs || ['?', '#'].some(x => prior.definitions?.[0]?.fileName?.includes(x))
2829

30+
const eventDefs = eventDefinitions(languageService, fileName, position)
31+
if (eventDefs) return eventDefs
32+
2933
// Definition fallbacks
3034
if (noDefs || tryFileResolve) {
3135
const node = getNode()

typescript/src/eventsReferences.ts

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { findChildContainingExactPosition, matchParents } from './utils'
2+
3+
export const eventDefinitions = (languageService: ts.LanguageService, fileName: string, position: number): ts.DefinitionInfoAndBoundSpan | undefined => {
4+
const program = languageService.getProgram()!
5+
const sourceFile = program.getSourceFile(fileName)!
6+
const node = findChildContainingExactPosition(sourceFile, position)
7+
if (!node || !ts.isStringLiteral(node)) return
8+
const eventName = node.text
9+
const expr = matchParents(node, ['StringLiteral', 'CallExpression'])
10+
if (!expr) return
11+
if (!ts.isPropertyAccessExpression(expr.expression)) return
12+
const parentAccessEndPos = expr.expression.expression.getEnd()
13+
const method = expr.expression.name.text
14+
let lookForMethods: string[] | undefined
15+
const onMethods = ['on', 'once', 'off', 'addEventListener', 'removeEventListener', 'addListener', 'removeListener']
16+
const triggerMethods = ['trigger', 'emit', 'dispatchEvent']
17+
if (onMethods.includes(method)) {
18+
lookForMethods = triggerMethods
19+
}
20+
if (triggerMethods.includes(method)) {
21+
lookForMethods = onMethods
22+
}
23+
if (!lookForMethods) return
24+
const references = languageService.findReferences(fileName, parentAccessEndPos) ?? []
25+
const defs: ts.DefinitionInfo[] = references
26+
.flatMap(({ references }) => references)
27+
.map(({ fileName, textSpan }): ts.DefinitionInfo | undefined => {
28+
const sourceFile = program.getSourceFile(fileName)!
29+
const node = findChildContainingExactPosition(sourceFile, textSpan.start)
30+
if (!node) return
31+
if (!ts.isPropertyAccessExpression(node.parent)) return
32+
let upNode = node as ts.PropertyAccessExpression
33+
while (ts.isPropertyAccessExpression(upNode.parent)) {
34+
upNode = upNode.parent
35+
}
36+
if (!ts.isCallExpression(upNode.parent)) return
37+
if (!ts.isPropertyAccessExpression(upNode.parent.expression)) return
38+
const method = upNode.parent.expression.name.text
39+
if (!lookForMethods!.includes(method)) return
40+
const arg = upNode.parent.arguments[0]
41+
if (!arg || !ts.isStringLiteral(arg)) return
42+
const lastArgEnd = upNode.parent.arguments.at(-1)!.end
43+
const span = ts.createTextSpanFromBounds(arg.pos, lastArgEnd)
44+
if (arg.text !== eventName) return
45+
46+
return {
47+
kind: ts.ScriptElementKind.memberVariableElement,
48+
name: method,
49+
containerKind: ts.ScriptElementKind.variableElement,
50+
containerName: method,
51+
textSpan: span,
52+
fileName,
53+
}
54+
})
55+
.filter(a => a !== undefined)
56+
.map(a => a!)
57+
return {
58+
textSpan: ts.createTextSpanFromBounds(node.pos, node.end),
59+
definitions: defs,
60+
}
61+
}

0 commit comments

Comments
 (0)