Skip to content

Commit

Permalink
TypeScript to BrowserCallable symbol references
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcinVaadin committed Jan 2, 2025
1 parent 7ec5cad commit 13a665d
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ dependencies {
bundledPlugin("org.jetbrains.plugins.gradle")
bundledPlugin("com.intellij.properties")
bundledPlugin("com.intellij.microservices.jvm")
bundledPlugin("JavaScript")

pluginVerifier()
zipSigner()
Expand Down
34 changes: 34 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/symbols/HillaSymbol.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.vaadin.plugin.symbols

import com.intellij.model.Pointer
import com.intellij.model.Symbol
import com.intellij.navigation.NavigatableSymbol
import com.intellij.navigation.SymbolNavigationService
import com.intellij.openapi.project.Project
import com.intellij.platform.backend.navigation.NavigationTarget
import com.intellij.psi.PsiElement

class HillaSymbol(private val target: PsiElement) : NavigatableSymbol {

override fun createPointer(): Pointer<out Symbol> {
return Pointer.hardPointer(this)
}

override fun getNavigationTargets(project: Project): Collection<NavigationTarget> {
if (target.project != project) return emptyList()
return listOf(SymbolNavigationService.getInstance().psiElementNavigationTarget(target))
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as HillaSymbol

return target == other.target
}

override fun hashCode(): Int {
return target.hashCode()
}
}
73 changes: 73 additions & 0 deletions src/main/kotlin/com/vaadin/plugin/symbols/HillaSymbolReference.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.vaadin.plugin.symbols

import com.intellij.model.SingleTargetReference
import com.intellij.model.Symbol
import com.intellij.model.psi.PsiSymbolReference
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.TextRange
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import com.intellij.psi.search.searches.AnnotatedElementsSearch
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.vaadin.plugin.endpoints.HILLA_BROWSER_CALLABLE

class HillaSymbolReference(private val element: PsiElement) : SingleTargetReference(), PsiSymbolReference {

override fun resolveSingleTarget(): Symbol? {
return CachedValuesManager.getCachedValue(element, Key.create(element.text)) {
CachedValueProvider.Result.create(internalResolveSingleTarget(), element)
}
}

private fun internalResolveSingleTarget(): Symbol? {
val hillaBrowserCallableClass =
JavaPsiFacade.getInstance(element.project)
.findClass(HILLA_BROWSER_CALLABLE, ProjectScope.getLibrariesScope(element.project)) ?: return null

val scope = GlobalSearchScope.allScope(element.project)

var className = element.text
var methodName: String? = null

// method call
if (element.textContains('.')) {
element.text.split('.').let {
className = it[0]
methodName = it[1]
}
}

val psiClass =
AnnotatedElementsSearch.searchPsiClasses(hillaBrowserCallableClass, scope).firstOrNull {
it.name?.endsWith(className) == true
}

if (psiClass == null) {
return null
}

if (methodName != null) {
// search also in super classes
val psiMethod = psiClass?.findMethodsByName(methodName, true)?.firstOrNull()
if (psiMethod != null) {
return HillaSymbol(psiMethod)
}
}
return HillaSymbol(psiClass)
}

override fun getElement(): PsiElement {
return element
}

override fun getRangeInElement(): TextRange {
val indexOfDot = element.text.indexOf('.')
if (indexOfDot != -1) {
return TextRange.from(indexOfDot + 1, element.text.length - indexOfDot)
}
return TextRange.allOf(element.text)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.vaadin.plugin.symbols

import com.intellij.lang.javascript.psi.JSReferenceExpression
import com.intellij.model.Symbol
import com.intellij.model.psi.PsiExternalReferenceHost
import com.intellij.model.psi.PsiSymbolReference
import com.intellij.model.psi.PsiSymbolReferenceHints
import com.intellij.model.psi.PsiSymbolReferenceProvider
import com.intellij.model.search.SearchRequest
import com.intellij.openapi.project.Project

internal class HillaSymbolReferenceProvider : PsiSymbolReferenceProvider {

override fun getReferences(
host: PsiExternalReferenceHost,
hints: PsiSymbolReferenceHints
): Collection<PsiSymbolReference> {
if (host !is JSReferenceExpression) {
return emptyList()
}

return listOf(HillaSymbolReference(host))
}

override fun getSearchRequests(project: Project, symbol: Symbol): Collection<SearchRequest> {
return emptyList()
}
}
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<depends optional="true" config-file="vaadin-with-microservices.xml">com.intellij.modules.microservices</depends>
<depends optional="true" config-file="vaadin-with-microservices-jvm.xml">com.intellij.microservices.jvm</depends>
<depends optional="true" config-file="vaadin-with-ultimate.xml">com.intellij.modules.ultimate</depends>
<depends optional="true" config-file="vaadin-with-javascript.xml">JavaScript</depends>

<change-notes>
<![CDATA[
Expand Down
11 changes: 11 additions & 0 deletions src/main/resources/META-INF/vaadin-with-javascript.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<idea-plugin>

<extensions defaultExtensionNs="com.intellij">
<psi.symbolReferenceProvider hostLanguage="TypeScript"
hostElementClass="com.intellij.lang.javascript.psi.JSReferenceExpression"
referenceClass="com.vaadin.plugin.symbols.HillaSymbolReference"
targetClass="com.vaadin.plugin.symbols.HillaSymbol"
implementationClass="com.vaadin.plugin.symbols.HillaSymbolReferenceProvider"/>
</extensions>

</idea-plugin>

0 comments on commit 13a665d

Please sign in to comment.