Skip to content

Commit

Permalink
Merge pull request #218 from zardoy/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
zardoy authored Oct 20, 2024
2 parents 0aa9607 + e71c7a6 commit e0cc380
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
4 changes: 4 additions & 0 deletions typescript/src/definitions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { join } from 'path-browserify'
import { GetConfig } from './types'
import { findChildContainingExactPosition } from './utils'
import { eventDefinitions } from './eventsReferences'

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

const eventDefs = eventDefinitions(languageService, fileName, position)
if (eventDefs) return eventDefs

// Definition fallbacks
if (noDefs || tryFileResolve) {
const node = getNode()
Expand Down
61 changes: 61 additions & 0 deletions typescript/src/eventsReferences.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { findChildContainingExactPosition, matchParents } from './utils'

export const eventDefinitions = (languageService: ts.LanguageService, fileName: string, position: number): ts.DefinitionInfoAndBoundSpan | undefined => {
const program = languageService.getProgram()!
const sourceFile = program.getSourceFile(fileName)!
const node = findChildContainingExactPosition(sourceFile, position)
if (!node || !ts.isStringLiteral(node)) return
const eventName = node.text
const expr = matchParents(node, ['StringLiteral', 'CallExpression'])
if (!expr) return
if (!ts.isPropertyAccessExpression(expr.expression)) return
const parentAccessEndPos = expr.expression.expression.getEnd()
const method = expr.expression.name.text
let lookForMethods: string[] | undefined
const onMethods = ['on', 'once', 'off', 'addEventListener', 'removeEventListener', 'addListener', 'removeListener']
const triggerMethods = ['trigger', 'emit', 'dispatchEvent']
if (onMethods.includes(method)) {
lookForMethods = triggerMethods
}
if (triggerMethods.includes(method)) {
lookForMethods = onMethods
}
if (!lookForMethods) return
const references = languageService.findReferences(fileName, parentAccessEndPos) ?? []
const defs: ts.DefinitionInfo[] = references
.flatMap(({ references }) => references)
.map(({ fileName, textSpan }): ts.DefinitionInfo | undefined => {
const sourceFile = program.getSourceFile(fileName)!
const node = findChildContainingExactPosition(sourceFile, textSpan.start)
if (!node) return
if (!ts.isPropertyAccessExpression(node.parent)) return
let upNode = node as ts.PropertyAccessExpression
while (ts.isPropertyAccessExpression(upNode.parent)) {
upNode = upNode.parent
}
if (!ts.isCallExpression(upNode.parent)) return
if (!ts.isPropertyAccessExpression(upNode.parent.expression)) return
const method = upNode.parent.expression.name.text
if (!lookForMethods!.includes(method)) return
const arg = upNode.parent.arguments[0]
if (!arg || !ts.isStringLiteral(arg)) return
const lastArgEnd = upNode.parent.arguments.at(-1)!.end
const span = ts.createTextSpanFromBounds(arg.pos, lastArgEnd)
if (arg.text !== eventName) return

return {
kind: ts.ScriptElementKind.memberVariableElement,
name: method,
containerKind: ts.ScriptElementKind.variableElement,
containerName: method,
textSpan: span,
fileName,
}
})
.filter(a => a !== undefined)
.map(a => a!)
return {
textSpan: ts.createTextSpanFromBounds(node.pos, node.end),
definitions: defs,
}
}

0 comments on commit e0cc380

Please sign in to comment.