-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathStatePathReferenceContributor.kt
87 lines (76 loc) · 3.71 KB
/
StatePathReferenceContributor.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
84
85
86
87
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.transition.Lexeme
import com.justai.jaicf.plugin.scenarios.transition.StatePath
import com.justai.jaicf.plugin.scenarios.transition.plus
import com.justai.jaicf.plugin.scenarios.transition.statesOrSuggestions
import com.justai.jaicf.plugin.scenarios.transition.transit
import com.justai.jaicf.plugin.scenarios.transition.transitionsWithRanges
import com.justai.jaicf.plugin.utils.StatePathExpression.Joined
import com.justai.jaicf.plugin.utils.VersionService
import com.justai.jaicf.plugin.utils.boundedPathExpression
import com.justai.jaicf.plugin.utils.isJaicfInclude
import com.justai.jaicf.plugin.utils.isSimpleStringTemplate
import com.justai.jaicf.plugin.utils.rangeToEndOf
import com.justai.jaicf.plugin.utils.stringValueOrNull
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
class StatePathReferenceContributor : PsiReferenceContributor() {
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
registrar.registerReferenceProvider(
PlatformPatterns.psiElement(KtStringTemplateExpression::class.java),
StatePathReferenceProvider()
)
}
}
class StatePathReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
if (VersionService.getInstance(element)?.isJaicfInclude == false) return emptyArray()
val statePathExpression = element.boundedPathExpression as? Joined ?: return emptyArray()
val pathExpression = statePathExpression.declaration
val statePath = pathExpression.stringValueOrNull?.let { StatePath.parse(it) } ?: return emptyArray()
return if (pathExpression.isSimpleStringTemplate) {
var accPath = StatePath()
statePath.transitionsWithRanges()
.mapNotNull { (transition, range) ->
accPath += transition
if (transition is Lexeme.Transition.Root)
null
else
StatePsiReference(element, accPath, range.shiftRight(1))
}.toTypedArray()
} else {
arrayOf(StatePsiReference(element, statePath, element.rangeToEndOf(pathExpression)))
}
}
}
class StatePsiReference(
element: PsiElement,
private val path: StatePath,
textRange: TextRange = element.textRange,
) : PsiReferenceBase<PsiElement?>(element, textRange), PsiPolyVariantReference {
private val service = ReferenceContributorsAvailabilityService.getInstance(element)
override fun resolve() =
if (service?.available == true)
element.framingState?.transit(path)?.statesOrSuggestions()?.singleOrNull()?.stateExpression
else null
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> =
if (service?.available == true)
element.framingState?.transit(path)?.statesOrSuggestions()
?.map { it.stateExpression }
?.map(::PsiElementResolveResult)?.toTypedArray()
?: emptyArray()
else
emptyArray()
}