-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathStateIdentifierReferenceContributor.kt
83 lines (70 loc) · 3.36 KB
/
StateIdentifierReferenceContributor.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.justai.jaicf.plugin.providers
import com.intellij.openapi.util.TextRange
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementResolveResult
import com.intellij.psi.PsiPolyVariantReference
import com.intellij.psi.PsiReference
import com.intellij.psi.PsiReferenceBase
import com.intellij.psi.PsiReferenceContributor
import com.intellij.psi.PsiReferenceProvider
import com.intellij.psi.PsiReferenceRegistrar
import com.intellij.psi.ResolveResult
import com.intellij.util.ProcessingContext
import com.justai.jaicf.plugin.scenarios.linker.framingState
import com.justai.jaicf.plugin.scenarios.linker.usages
import com.justai.jaicf.plugin.scenarios.psi.builders.isStateDeclaration
import com.justai.jaicf.plugin.utils.STATE_NAME_ARGUMENT_NAME
import com.justai.jaicf.plugin.utils.StatePathExpression
import com.justai.jaicf.plugin.utils.VersionService
import com.justai.jaicf.plugin.utils.boundedCallExpressionOrNull
import com.justai.jaicf.plugin.utils.getBoundedValueArgumentOrNull
import com.justai.jaicf.plugin.utils.holderExpression
import com.justai.jaicf.plugin.utils.identifier
import com.justai.jaicf.plugin.utils.isJaicfInclude
import com.justai.jaicf.plugin.utils.rangeToEndOf
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.KtValueArgument
class StateIdentifierReferenceContributor : PsiReferenceContributor() {
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
registrar.registerReferenceProvider(
PlatformPatterns.psiElement(KtStringTemplateExpression::class.java),
StateIdentifierReferenceProvider()
)
}
}
class StateIdentifierReferenceProvider : PsiReferenceProvider() {
@ExperimentalStdlibApi
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
if (VersionService.getInstance(element)?.isJaicfInclude == false) return emptyArray()
val argument = element.getBoundedValueArgumentOrNull() ?: return emptyArray()
if (!argument.isNameOfStateDeclaration) return emptyArray()
return arrayOf(
MultiPsiReference(element, element.rangeToEndOf(argument)) {
argument.framingState?.usages
?: emptyList()
}
)
}
}
class MultiPsiReference(
element: PsiElement,
textRange: TextRange = element.textRange,
private val referencesProvider: () -> List<StatePathExpression>,
) : PsiReferenceBase<PsiElement?>(element, textRange), PsiPolyVariantReference {
private val service = ReferenceContributorsAvailabilityService.getInstance(element)
override fun resolve() =
if (service?.available == true)
referencesProvider().singleOrNull()?.holderExpression
else null
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> {
return if (service?.available == true)
referencesProvider().map { it.holderExpression }.map(::PsiElementResolveResult).toTypedArray()
else emptyArray()
}
override fun handleElementRename(newElementName: String): PsiElement {
return super.handleElementRename(newElementName)
}
}
val KtValueArgument.isNameOfStateDeclaration: Boolean
get() = boundedCallExpressionOrNull?.isStateDeclaration == true && identifier == STATE_NAME_ARGUMENT_NAME