FIR/UAST: commonize base UClass (with bogus annotation abstraction)
This commit is contained in:
committed by
Ilya Kirillov
parent
06c20bb10e
commit
1749c90083
+111
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import org.jetbrains.uast.*
|
||||||
|
|
||||||
|
abstract class BaseKotlinUClass(
|
||||||
|
psi: KtLightClass,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : AbstractKotlinUClass(givenParent), PsiClass by psi {
|
||||||
|
final override val ktClass = psi.kotlinOrigin
|
||||||
|
|
||||||
|
override val javaPsi: KtLightClass = psi
|
||||||
|
|
||||||
|
override val sourcePsi: KtClassOrObject? = ktClass
|
||||||
|
|
||||||
|
override val psi = unwrap<UClass, PsiClass>(psi)
|
||||||
|
|
||||||
|
override fun getSourceElement() = sourcePsi ?: this
|
||||||
|
|
||||||
|
override fun getOriginalElement(): PsiElement? = super.getOriginalElement()
|
||||||
|
|
||||||
|
override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, ktClass)
|
||||||
|
|
||||||
|
override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile)
|
||||||
|
|
||||||
|
override val uastAnchor by lazy { getIdentifierSourcePsi()?.let { KotlinUIdentifier(nameIdentifier, it, this) } }
|
||||||
|
|
||||||
|
private fun getIdentifierSourcePsi(): PsiElement? {
|
||||||
|
ktClass?.nameIdentifier?.let { return it }
|
||||||
|
(ktClass as? KtObjectDeclaration)?.getObjectKeyword()?.let { return it }
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getInnerClasses(): Array<UClass> {
|
||||||
|
// filter DefaultImpls to avoid processing same methods from original interface multiple times
|
||||||
|
// filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class
|
||||||
|
return psi.innerClasses.filter {
|
||||||
|
it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass
|
||||||
|
}.mapNotNull {
|
||||||
|
languagePlugin?.convertOpt<UClass>(it, this)
|
||||||
|
}.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSuperClass(): UClass? = super.getSuperClass()
|
||||||
|
override fun getFields(): Array<UField> = super.getFields()
|
||||||
|
override fun getInitializers(): Array<UClassInitializer> = super.getInitializers()
|
||||||
|
|
||||||
|
override fun getMethods(): Array<UMethod> {
|
||||||
|
val hasPrimaryConstructor = ktClass?.hasPrimaryConstructor() ?: false
|
||||||
|
var secondaryConstructorsCount = 0
|
||||||
|
|
||||||
|
fun createUMethod(psiMethod: PsiMethod): UMethod {
|
||||||
|
return if (psiMethod is KtLightMethod &&
|
||||||
|
psiMethod.isConstructor) {
|
||||||
|
if (!hasPrimaryConstructor && secondaryConstructorsCount++ == 0)
|
||||||
|
buildSecondaryConstructorUMethod(ktClass, psiMethod, this)
|
||||||
|
else
|
||||||
|
buildPrimaryConstructorUMethod(ktClass, psiMethod, this)
|
||||||
|
} else {
|
||||||
|
languagePlugin?.convertOpt(psiMethod, this) ?: reportConvertFailure(psiMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isDelegatedMethod(psiMethod: PsiMethod) = psiMethod is KtLightMethod && psiMethod.isDelegated
|
||||||
|
|
||||||
|
val result = ArrayList<UMethod>(javaPsi.methods.size)
|
||||||
|
val handledKtDeclarations = mutableSetOf<PsiElement>()
|
||||||
|
|
||||||
|
for (lightMethod in javaPsi.methods) {
|
||||||
|
if (isDelegatedMethod(lightMethod)) continue
|
||||||
|
val uMethod = createUMethod(lightMethod)
|
||||||
|
result.add(uMethod)
|
||||||
|
|
||||||
|
// Ensure we pick the main Kotlin origin, not the auxiliary one
|
||||||
|
val kotlinOrigin = (lightMethod as? KtLightMethod)?.kotlinOrigin ?: uMethod.sourcePsi
|
||||||
|
handledKtDeclarations.addIfNotNull(kotlinOrigin)
|
||||||
|
}
|
||||||
|
|
||||||
|
val ktDeclarations: List<KtDeclaration> = run ktDeclarations@{
|
||||||
|
ktClass?.let { return@ktDeclarations it.declarations }
|
||||||
|
(javaPsi as? KtLightClassForFacade)?.let { facade ->
|
||||||
|
return@ktDeclarations facade.files.flatMap { file -> file.declarations }
|
||||||
|
}
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
ktDeclarations.asSequence()
|
||||||
|
.filterNot { handledKtDeclarations.contains(it) }
|
||||||
|
.mapNotNullTo(result) {
|
||||||
|
baseResolveProviderService.baseKotlinConverter.convertDeclaration(it, this, arrayOf(UElement::class.java)) as? UMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun buildPrimaryConstructorUMethod(ktClass: KtClassOrObject?, psi: KtLightMethod, givenParent: UElement?) : UMethod
|
||||||
|
abstract fun buildSecondaryConstructorUMethod(ktClass: KtClassOrObject?, psi: KtLightMethod, givenParent: UElement?) : UMethod
|
||||||
|
}
|
||||||
@@ -19,10 +19,12 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
import org.jetbrains.uast.expressions.UInjectionHost
|
import org.jetbrains.uast.expressions.UInjectionHost
|
||||||
|
import org.jetbrains.uast.kotlin.declarations.FirKotlinUAnnotation
|
||||||
|
|
||||||
internal object FirKotlinConverter : BaseKotlinConverter {
|
internal object FirKotlinConverter : BaseKotlinConverter {
|
||||||
override fun convertAnnotation(annotationEntry: KtAnnotationEntry, givenParent: UElement?): UAnnotation {
|
override fun convertAnnotation(annotationEntry: KtAnnotationEntry, givenParent: UElement?): UAnnotation {
|
||||||
TODO("Not yet implemented")
|
// TODO: need to polish/implement annotations more
|
||||||
|
return FirKotlinUAnnotation(annotationEntry, givenParent)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun convertDeclarationOrElement(
|
internal fun convertDeclarationOrElement(
|
||||||
|
|||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.uast.kotlin.declarations
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.ResolveResult
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightAnnotation
|
||||||
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
|
import org.jetbrains.uast.*
|
||||||
|
import org.jetbrains.uast.kotlin.KotlinAbstractUElement
|
||||||
|
|
||||||
|
class FirKotlinUAnnotation(
|
||||||
|
annotationEntry: KtAnnotationEntry,
|
||||||
|
givenParent: UElement?
|
||||||
|
) : KotlinAbstractUElement(givenParent), UAnnotation, UAnchorOwner, UMultiResolvable {
|
||||||
|
override val javaPsi = annotationEntry.toLightAnnotation()
|
||||||
|
|
||||||
|
override val psi: PsiElement = annotationEntry
|
||||||
|
|
||||||
|
override val attributeValues: List<UNamedExpression>
|
||||||
|
get() = listOf() // TODO("Not yet implemented")
|
||||||
|
|
||||||
|
override val qualifiedName: String?
|
||||||
|
get() = "not-implemented-annotation"
|
||||||
|
|
||||||
|
override val uastAnchor: UIdentifier?
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
|
||||||
|
override fun findAttributeValue(name: String?): UExpression? {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findDeclaredAttributeValue(name: String?): UExpression? {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolve(): PsiClass? {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun multiResolve(): Iterable<ResolveResult> {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-99
@@ -5,114 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.uast.kotlin
|
package org.jetbrains.uast.kotlin
|
||||||
|
|
||||||
import com.intellij.psi.*
|
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
|
|
||||||
// TODO: can be commonized once *KotlinUClass is commonized
|
|
||||||
class FirKotlinUClass(
|
class FirKotlinUClass(
|
||||||
override val javaPsi: KtLightClass,
|
psi: KtLightClass,
|
||||||
givenParent: UElement?,
|
givenParent: UElement?,
|
||||||
) : AbstractKotlinUClass(givenParent), PsiClass by javaPsi {
|
) : BaseKotlinUClass(psi, givenParent) {
|
||||||
override val ktClass: KtClassOrObject? = javaPsi.kotlinOrigin
|
override fun buildPrimaryConstructorUMethod(ktClass: KtClassOrObject?, psi: KtLightMethod, givenParent: UElement?): UMethod {
|
||||||
|
return FirKotlinConstructorUMethod(ktClass, psi, givenParent)
|
||||||
override val psi = unwrap<UClass, PsiClass>(javaPsi)
|
|
||||||
|
|
||||||
override fun getSourceElement() = sourcePsi
|
|
||||||
|
|
||||||
override fun getOriginalElement(): PsiElement? = sourcePsi?.originalElement
|
|
||||||
|
|
||||||
override fun getNameIdentifier(): PsiIdentifier = UastLightIdentifier(psi, ktClass)
|
|
||||||
|
|
||||||
override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile)
|
|
||||||
|
|
||||||
override val uastAnchor: UIdentifier? by lz {
|
|
||||||
getIdentifierSourcePsi()?.let {
|
|
||||||
KotlinUIdentifier(nameIdentifier, it, this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getIdentifierSourcePsi(): PsiElement? {
|
override fun buildSecondaryConstructorUMethod(ktClass: KtClassOrObject?, psi: KtLightMethod, givenParent: UElement?): UMethod {
|
||||||
ktClass?.nameIdentifier?.let { return it }
|
return FirKotlinSecondaryConstructorWithInitializersUMethod(ktClass, psi, givenParent)
|
||||||
(ktClass as? KtObjectDeclaration)?.getObjectKeyword()?.let { return it }
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getInnerClasses(): Array<UClass> {
|
|
||||||
// filter DefaultImpls to avoid processing same methods from original interface multiple times
|
|
||||||
// filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class
|
|
||||||
return psi.innerClasses.filter {
|
|
||||||
it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass
|
|
||||||
}.mapNotNull {
|
|
||||||
languagePlugin?.convertOpt<UClass>(it, this)
|
|
||||||
}.toTypedArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getSuperClass(): UClass? {
|
|
||||||
return super.getSuperClass()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFields(): Array<UField> {
|
|
||||||
return super.getFields()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getInitializers(): Array<UClassInitializer> {
|
|
||||||
// TODO: why not just emptyList()? Kotlin class won't have <clinit>?
|
|
||||||
return super.getInitializers()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getMethods(): Array<UMethod> {
|
|
||||||
val hasPrimaryConstructor = ktClass?.hasPrimaryConstructor() ?: false
|
|
||||||
var secondaryConstructorsCount = 0
|
|
||||||
|
|
||||||
fun createUMethod(psiMethod: PsiMethod): UMethod {
|
|
||||||
return if (psiMethod is KtLightMethod && psiMethod.isConstructor) {
|
|
||||||
if (!hasPrimaryConstructor && secondaryConstructorsCount++ == 0)
|
|
||||||
FirKotlinSecondaryConstructorWithInitializersUMethod(ktClass, psiMethod, this)
|
|
||||||
else
|
|
||||||
FirKotlinConstructorUMethod(ktClass, psiMethod, this)
|
|
||||||
} else {
|
|
||||||
languagePlugin?.convertOpt(psiMethod, this) ?: reportConvertFailure(psiMethod)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDelegatedMethod(psiMethod: PsiMethod) = psiMethod is KtLightMethod && psiMethod.isDelegated
|
|
||||||
|
|
||||||
val result = ArrayList<UMethod>(javaPsi.methods.size)
|
|
||||||
val handledKtDeclarations = mutableSetOf<PsiElement>()
|
|
||||||
|
|
||||||
for (lightMethod in javaPsi.methods) {
|
|
||||||
if (isDelegatedMethod(lightMethod)) continue
|
|
||||||
val uMethod = createUMethod(lightMethod)
|
|
||||||
result.add(uMethod)
|
|
||||||
|
|
||||||
// Ensure we pick the main Kotlin origin, not the auxiliary one
|
|
||||||
val kotlinOrigin = (lightMethod as? KtLightMethod)?.kotlinOrigin ?: uMethod.sourcePsi
|
|
||||||
handledKtDeclarations.addIfNotNull(kotlinOrigin)
|
|
||||||
}
|
|
||||||
|
|
||||||
val ktDeclarations: List<KtDeclaration> = run ktDeclarations@{
|
|
||||||
ktClass?.let { return@ktDeclarations it.declarations }
|
|
||||||
(javaPsi as? KtLightClassForFacade)?.let { facade ->
|
|
||||||
return@ktDeclarations facade.files.flatMap { file -> file.declarations }
|
|
||||||
}
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
ktDeclarations.asSequence()
|
|
||||||
.filterNot { handledKtDeclarations.contains(it) }
|
|
||||||
.mapNotNullTo(result) {
|
|
||||||
baseResolveProviderService.baseKotlinConverter.convertDeclaration(it, this, arrayOf(UElement::class.java)) as? UMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toTypedArray()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+5
@@ -2,16 +2,21 @@ UFile (package = )
|
|||||||
UClass (name = Annotation)
|
UClass (name = Annotation)
|
||||||
UMethod (name = strings)
|
UMethod (name = strings)
|
||||||
UClass (name = A)
|
UClass (name = A)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = A)
|
UMethod (name = A)
|
||||||
UClass (name = AnnotationInner)
|
UClass (name = AnnotationInner)
|
||||||
UMethod (name = value)
|
UMethod (name = value)
|
||||||
UClass (name = B1)
|
UClass (name = B1)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = B1)
|
UMethod (name = B1)
|
||||||
UClass (name = B2)
|
UClass (name = B2)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = B2)
|
UMethod (name = B2)
|
||||||
UClass (name = AnnotationArray)
|
UClass (name = AnnotationArray)
|
||||||
UMethod (name = value)
|
UMethod (name = value)
|
||||||
UClass (name = C)
|
UClass (name = C)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = C)
|
UMethod (name = C)
|
||||||
UClass (name = C2)
|
UClass (name = C2)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = C2)
|
UMethod (name = C2)
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
UFile (package = )
|
UFile (package = )
|
||||||
UClass (name = A)
|
UClass (name = A)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = A)
|
UMethod (name = A)
|
||||||
UClass (name = MyAnnotation)
|
UClass (name = MyAnnotation)
|
||||||
UMethod (name = text)
|
UMethod (name = text)
|
||||||
UClass (name = B)
|
UClass (name = B)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UField (name = Companion)
|
UField (name = Companion)
|
||||||
UMethod (name = B)
|
UMethod (name = B)
|
||||||
UClass (name = InB)
|
UClass (name = InB)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = InB)
|
UMethod (name = InB)
|
||||||
UClass (name = Companion)
|
UClass (name = Companion)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UMethod (name = Companion)
|
UMethod (name = Companion)
|
||||||
UClass (name = Obj)
|
UClass (name = Obj)
|
||||||
|
UAnnotation (fqName = not-implemented-annotation)
|
||||||
UField (name = INSTANCE)
|
UField (name = INSTANCE)
|
||||||
UMethod (name = Obj)
|
UMethod (name = Obj)
|
||||||
|
|||||||
@@ -2,16 +2,21 @@ UFile (package = ) [public abstract annotation Annotation {...]
|
|||||||
UClass (name = Annotation) [public abstract annotation Annotation {...}]
|
UClass (name = Annotation) [public abstract annotation Annotation {...}]
|
||||||
UMethod (name = strings) [public abstract fun strings() : java.lang.String[] = UastEmptyExpression]
|
UMethod (name = strings) [public abstract fun strings() : java.lang.String[] = UastEmptyExpression]
|
||||||
UClass (name = A) [public final class A {...}]
|
UClass (name = A) [public final class A {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
||||||
UClass (name = AnnotationInner) [public abstract annotation AnnotationInner {...}]
|
UClass (name = AnnotationInner) [public abstract annotation AnnotationInner {...}]
|
||||||
UMethod (name = value) [public abstract fun value() : Annotation = UastEmptyExpression]
|
UMethod (name = value) [public abstract fun value() : Annotation = UastEmptyExpression]
|
||||||
UClass (name = B1) [public final class B1 {...}]
|
UClass (name = B1) [public final class B1 {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = B1) [public fun B1() = UastEmptyExpression]
|
UMethod (name = B1) [public fun B1() = UastEmptyExpression]
|
||||||
UClass (name = B2) [public final class B2 {...}]
|
UClass (name = B2) [public final class B2 {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = B2) [public fun B2() = UastEmptyExpression]
|
UMethod (name = B2) [public fun B2() = UastEmptyExpression]
|
||||||
UClass (name = AnnotationArray) [public abstract annotation AnnotationArray {...}]
|
UClass (name = AnnotationArray) [public abstract annotation AnnotationArray {...}]
|
||||||
UMethod (name = value) [public abstract fun value() : Annotation[] = UastEmptyExpression]
|
UMethod (name = value) [public abstract fun value() : Annotation[] = UastEmptyExpression]
|
||||||
UClass (name = C) [public final class C {...}]
|
UClass (name = C) [public final class C {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = C) [public fun C() = UastEmptyExpression]
|
UMethod (name = C) [public fun C() = UastEmptyExpression]
|
||||||
UClass (name = C2) [public final class C2 {...}]
|
UClass (name = C2) [public final class C2 {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = C2) [public fun C2() = UastEmptyExpression]
|
UMethod (name = C2) [public fun C2() = UastEmptyExpression]
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
UFile (package = ) [public final class A {...]
|
UFile (package = ) [public final class A {...]
|
||||||
UClass (name = A) [public final class A {...}]
|
UClass (name = A) [public final class A {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
||||||
UClass (name = MyAnnotation) [public abstract annotation MyAnnotation {...}]
|
UClass (name = MyAnnotation) [public abstract annotation MyAnnotation {...}]
|
||||||
UMethod (name = text) [public abstract fun text() : java.lang.String = UastEmptyExpression]
|
UMethod (name = text) [public abstract fun text() : java.lang.String = UastEmptyExpression]
|
||||||
UClass (name = B) [public final class B {...}]
|
UClass (name = B) [public final class B {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UField (name = Companion) [public static final var Companion: B.Companion]
|
UField (name = Companion) [public static final var Companion: B.Companion]
|
||||||
UMethod (name = B) [public fun B() = UastEmptyExpression]
|
UMethod (name = B) [public fun B() = UastEmptyExpression]
|
||||||
UClass (name = InB) [public static final class InB {...}]
|
UClass (name = InB) [public static final class InB {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = InB) [public fun InB() = UastEmptyExpression]
|
UMethod (name = InB) [public fun InB() = UastEmptyExpression]
|
||||||
UClass (name = Companion) [public static final class Companion {...}]
|
UClass (name = Companion) [public static final class Companion {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = Companion) [private fun Companion() = UastEmptyExpression]
|
UMethod (name = Companion) [private fun Companion() = UastEmptyExpression]
|
||||||
UClass (name = Obj) [public final class Obj {...}]
|
UClass (name = Obj) [public final class Obj {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UField (name = INSTANCE) [public static final var INSTANCE: Obj]
|
UField (name = INSTANCE) [public static final var INSTANCE: Obj]
|
||||||
UMethod (name = Obj) [private fun Obj() = UastEmptyExpression]
|
UMethod (name = Obj) [private fun Obj() = UastEmptyExpression]
|
||||||
|
|||||||
+5
@@ -2,16 +2,21 @@ UFile (package = ) [public abstract annotation Annotation {...]
|
|||||||
UClass (name = Annotation) [public abstract annotation Annotation {...}]
|
UClass (name = Annotation) [public abstract annotation Annotation {...}]
|
||||||
UMethod (name = strings) [public abstract fun strings() : java.lang.String[] = UastEmptyExpression]
|
UMethod (name = strings) [public abstract fun strings() : java.lang.String[] = UastEmptyExpression]
|
||||||
UClass (name = A) [public final class A {...}]
|
UClass (name = A) [public final class A {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
||||||
UClass (name = AnnotationInner) [public abstract annotation AnnotationInner {...}]
|
UClass (name = AnnotationInner) [public abstract annotation AnnotationInner {...}]
|
||||||
UMethod (name = value) [public abstract fun value() : Annotation = UastEmptyExpression]
|
UMethod (name = value) [public abstract fun value() : Annotation = UastEmptyExpression]
|
||||||
UClass (name = B1) [public final class B1 {...}]
|
UClass (name = B1) [public final class B1 {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = B1) [public fun B1() = UastEmptyExpression]
|
UMethod (name = B1) [public fun B1() = UastEmptyExpression]
|
||||||
UClass (name = B2) [public final class B2 {...}]
|
UClass (name = B2) [public final class B2 {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = B2) [public fun B2() = UastEmptyExpression]
|
UMethod (name = B2) [public fun B2() = UastEmptyExpression]
|
||||||
UClass (name = AnnotationArray) [public abstract annotation AnnotationArray {...}]
|
UClass (name = AnnotationArray) [public abstract annotation AnnotationArray {...}]
|
||||||
UMethod (name = value) [public abstract fun value() : Annotation[] = UastEmptyExpression]
|
UMethod (name = value) [public abstract fun value() : Annotation[] = UastEmptyExpression]
|
||||||
UClass (name = C) [public final class C {...}]
|
UClass (name = C) [public final class C {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = C) [public fun C() = UastEmptyExpression]
|
UMethod (name = C) [public fun C() = UastEmptyExpression]
|
||||||
UClass (name = C2) [public final class C2 {...}]
|
UClass (name = C2) [public final class C2 {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = C2) [public fun C2() = UastEmptyExpression]
|
UMethod (name = C2) [public fun C2() = UastEmptyExpression]
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
UFile (package = ) [public final class A {...]
|
UFile (package = ) [public final class A {...]
|
||||||
UClass (name = A) [public final class A {...}]
|
UClass (name = A) [public final class A {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
UMethod (name = A) [public fun A() = UastEmptyExpression]
|
||||||
UClass (name = MyAnnotation) [public abstract annotation MyAnnotation {...}]
|
UClass (name = MyAnnotation) [public abstract annotation MyAnnotation {...}]
|
||||||
UMethod (name = text) [public abstract fun text() : java.lang.String = UastEmptyExpression]
|
UMethod (name = text) [public abstract fun text() : java.lang.String = UastEmptyExpression]
|
||||||
UClass (name = B) [public final class B {...}]
|
UClass (name = B) [public final class B {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UField (name = Companion) [public static final var Companion: B.Companion]
|
UField (name = Companion) [public static final var Companion: B.Companion]
|
||||||
UMethod (name = B) [public fun B() = UastEmptyExpression]
|
UMethod (name = B) [public fun B() = UastEmptyExpression]
|
||||||
UClass (name = InB) [public static final class InB {...}]
|
UClass (name = InB) [public static final class InB {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = InB) [public fun InB() = UastEmptyExpression]
|
UMethod (name = InB) [public fun InB() = UastEmptyExpression]
|
||||||
UClass (name = Companion) [public static final class Companion {...}]
|
UClass (name = Companion) [public static final class Companion {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UMethod (name = Companion) [private fun Companion() = UastEmptyExpression]
|
UMethod (name = Companion) [private fun Companion() = UastEmptyExpression]
|
||||||
UClass (name = Obj) [public final class Obj {...}]
|
UClass (name = Obj) [public final class Obj {...}]
|
||||||
|
UAnnotation (fqName = not-implemented-annotation) [@not-implemented-annotation]
|
||||||
UField (name = INSTANCE) [public static final var INSTANCE: Obj]
|
UField (name = INSTANCE) [public static final var INSTANCE: Obj]
|
||||||
UMethod (name = Obj) [private fun Obj() = UastEmptyExpression]
|
UMethod (name = Obj) [private fun Obj() = UastEmptyExpression]
|
||||||
|
|||||||
@@ -19,103 +19,21 @@ package org.jetbrains.uast.kotlin
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.light.LightPsiClassBuilder
|
import com.intellij.psi.impl.light.LightPsiClassBuilder
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
import org.jetbrains.uast.*
|
import org.jetbrains.uast.*
|
||||||
|
|
||||||
open class KotlinUClass(
|
class KotlinUClass(
|
||||||
psi: KtLightClass,
|
psi: KtLightClass,
|
||||||
givenParent: UElement?
|
givenParent: UElement?
|
||||||
) : AbstractKotlinUClass(givenParent), PsiClass by psi {
|
) : BaseKotlinUClass(psi, givenParent) {
|
||||||
|
override fun buildPrimaryConstructorUMethod(ktClass: KtClassOrObject?, psi: KtLightMethod, givenParent: UElement?): UMethod {
|
||||||
final override val ktClass = psi.kotlinOrigin
|
return KotlinConstructorUMethod(ktClass, psi, givenParent)
|
||||||
|
|
||||||
override val javaPsi: KtLightClass = psi
|
|
||||||
|
|
||||||
override val sourcePsi: KtClassOrObject? = ktClass
|
|
||||||
|
|
||||||
override val psi = unwrap<UClass, PsiClass>(psi)
|
|
||||||
|
|
||||||
override fun getSourceElement() = sourcePsi ?: this
|
|
||||||
|
|
||||||
override fun getOriginalElement(): PsiElement? = super.getOriginalElement()
|
|
||||||
|
|
||||||
override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, ktClass)
|
|
||||||
|
|
||||||
override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile)
|
|
||||||
|
|
||||||
override val uastAnchor by lazy { getIdentifierSourcePsi()?.let { KotlinUIdentifier(nameIdentifier, it, this) } }
|
|
||||||
|
|
||||||
private fun getIdentifierSourcePsi(): PsiElement? {
|
|
||||||
ktClass?.nameIdentifier?.let { return it }
|
|
||||||
(ktClass as? KtObjectDeclaration)?.getObjectKeyword()?.let { return it }
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getInnerClasses(): Array<UClass> {
|
override fun buildSecondaryConstructorUMethod(ktClass: KtClassOrObject?, psi: KtLightMethod, givenParent: UElement?): UMethod {
|
||||||
// filter DefaultImpls to avoid processing same methods from original interface multiple times
|
return KotlinSecondaryConstructorWithInitializersUMethod(ktClass, psi, givenParent)
|
||||||
// filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class
|
|
||||||
return psi.innerClasses.filter {
|
|
||||||
it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass
|
|
||||||
}.mapNotNull {
|
|
||||||
languagePlugin?.convertOpt<UClass>(it, this)
|
|
||||||
}.toTypedArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getSuperClass(): UClass? = super.getSuperClass()
|
|
||||||
override fun getFields(): Array<UField> = super.getFields()
|
|
||||||
override fun getInitializers(): Array<UClassInitializer> = super.getInitializers()
|
|
||||||
|
|
||||||
override fun getMethods(): Array<UMethod> {
|
|
||||||
val hasPrimaryConstructor = ktClass?.hasPrimaryConstructor() ?: false
|
|
||||||
var secondaryConstructorsCount = 0
|
|
||||||
|
|
||||||
fun createUMethod(psiMethod: PsiMethod): UMethod {
|
|
||||||
return if (psiMethod is KtLightMethod &&
|
|
||||||
psiMethod.isConstructor) {
|
|
||||||
if (!hasPrimaryConstructor && secondaryConstructorsCount++ == 0)
|
|
||||||
KotlinSecondaryConstructorWithInitializersUMethod(ktClass, psiMethod, this)
|
|
||||||
else
|
|
||||||
KotlinConstructorUMethod(ktClass, psiMethod, this)
|
|
||||||
} else {
|
|
||||||
languagePlugin?.convertOpt(psiMethod, this) ?: reportConvertFailure(psiMethod)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDelegatedMethod(psiMethod: PsiMethod) = psiMethod is KtLightMethod && psiMethod.isDelegated
|
|
||||||
|
|
||||||
val result = ArrayList<UMethod>(javaPsi.methods.size)
|
|
||||||
val handledKtDeclarations = mutableSetOf<PsiElement>()
|
|
||||||
|
|
||||||
for (lightMethod in javaPsi.methods) {
|
|
||||||
if (isDelegatedMethod(lightMethod)) continue
|
|
||||||
val uMethod = createUMethod(lightMethod)
|
|
||||||
result.add(uMethod)
|
|
||||||
|
|
||||||
// Ensure we pick the main Kotlin origin, not the auxiliary one
|
|
||||||
val kotlinOrigin = (lightMethod as? KtLightMethod)?.kotlinOrigin ?: uMethod.sourcePsi
|
|
||||||
handledKtDeclarations.addIfNotNull(kotlinOrigin)
|
|
||||||
}
|
|
||||||
|
|
||||||
val ktDeclarations: List<KtDeclaration> = run ktDeclarations@{
|
|
||||||
ktClass?.let { return@ktDeclarations it.declarations }
|
|
||||||
(javaPsi as? KtLightClassForFacade)?.let { facade ->
|
|
||||||
return@ktDeclarations facade.files.flatMap { file -> file.declarations }
|
|
||||||
}
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
ktDeclarations.asSequence()
|
|
||||||
.filterNot { handledKtDeclarations.contains(it) }
|
|
||||||
.mapNotNullTo(result) {
|
|
||||||
baseResolveProviderService.baseKotlinConverter.convertDeclaration(it, this, arrayOf(UElement::class.java)) as? UMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toTypedArray()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
Reference in New Issue
Block a user