-
Notifications
You must be signed in to change notification settings - Fork 380
/
RsAbstractable.kt
59 lines (50 loc) · 2.26 KB
/
RsAbstractable.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
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/
package org.rust.lang.core.psi.ext
import com.intellij.psi.PsiElement
import org.rust.lang.core.macros.RsExpandedElement
import org.rust.lang.core.psi.*
interface RsAbstractable : RsNameIdentifierOwner, RsExpandedElement {
val isAbstract: Boolean
}
sealed class RsAbstractableOwner {
object Free : RsAbstractableOwner()
object Foreign : RsAbstractableOwner()
class Trait(val trait: RsTraitItem) : RsAbstractableOwner()
class Impl(val impl: RsImplItem, val isInherent: Boolean) : RsAbstractableOwner()
val isInherentImpl: Boolean get() = this is Impl && isInherent
val isTraitImpl: Boolean get() = this is Impl && !isInherent
val isImplOrTrait: Boolean get() = this is Impl || this is Trait
}
val RsAbstractable.owner: RsAbstractableOwner get() = getOwner(PsiElement::getContext)
inline fun RsAbstractable.getOwner(getAncestor: PsiElement.() -> PsiElement?): RsAbstractableOwner {
return when (val ancestor = getAncestor()) {
is RsForeignModItem -> RsAbstractableOwner.Foreign
is RsMembers -> {
when (val traitOrImpl = ancestor.getAncestor()) {
is RsImplItem -> RsAbstractableOwner.Impl(traitOrImpl, isInherent = traitOrImpl.traitRef == null)
is RsTraitItem -> RsAbstractableOwner.Trait(traitOrImpl)
else -> error("unreachable")
}
}
else -> RsAbstractableOwner.Free
}
}
// Resolve a const, fn or type in a impl block to the corresponding item in the trait block
val RsAbstractable.superItem: RsAbstractable?
get() {
val impl = (owner as? RsAbstractableOwner.Impl)?.impl ?: return null
val superTrait = impl.traitRef?.resolveToTrait() ?: return null
return superTrait.findCorrespondingElement(this)
}
fun RsTraitOrImpl.findCorrespondingElement(element: RsAbstractable): RsAbstractable? {
val members = expandedMembers
return when (element) {
is RsConstant -> members.constants.find { it.name == element.name }
is RsFunction -> members.functions.find { it.name == element.name }
is RsTypeAlias -> members.types.find { it.name == element.name }
else -> error("unreachable")
}
}