Generate Enum.getEntries method in ultra light classes
^KTIJ-23530 Fixed
This commit is contained in:
committed by
Space Team
parent
59663f4752
commit
e5d5cbc7a3
+23
-2
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull
|
|||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightParameter
|
import org.jetbrains.kotlin.asJava.elements.KtLightParameter
|
||||||
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
@@ -166,16 +167,33 @@ private class KotlinEnumSyntheticMethod(
|
|||||||
private val kind: Kind
|
private val kind: Kind
|
||||||
) : LightElement(enumClass.manager, enumClass.language), KtLightMethod, SyntheticElement {
|
) : LightElement(enumClass.manager, enumClass.language), KtLightMethod, SyntheticElement {
|
||||||
enum class Kind(val methodName: String) {
|
enum class Kind(val methodName: String) {
|
||||||
VALUE_OF("valueOf"), VALUES("values")
|
VALUE_OF("valueOf"), VALUES("values"), ENTRIES("getEntries"),
|
||||||
}
|
}
|
||||||
|
|
||||||
private val returnType = run {
|
private val returnType = run {
|
||||||
val enumType = JavaPsiFacade.getElementFactory(project).createType(enumClass)
|
val elementFactory = JavaPsiFacade.getElementFactory(project)
|
||||||
|
val enumTypeWithoutAnnotation = elementFactory.createType(enumClass)
|
||||||
|
val enumType = enumTypeWithoutAnnotation
|
||||||
.annotate { arrayOf(makeNotNullAnnotation(enumClass)) }
|
.annotate { arrayOf(makeNotNullAnnotation(enumClass)) }
|
||||||
|
|
||||||
when (kind) {
|
when (kind) {
|
||||||
Kind.VALUE_OF -> enumType
|
Kind.VALUE_OF -> enumType
|
||||||
Kind.VALUES -> enumType.createArrayType().annotate { arrayOf(makeNotNullAnnotation(enumClass)) }
|
Kind.VALUES -> enumType.createArrayType().annotate { arrayOf(makeNotNullAnnotation(enumClass)) }
|
||||||
|
Kind.ENTRIES -> {
|
||||||
|
val enumEntriesClass = JavaPsiFacade.getInstance(project).findClass(
|
||||||
|
/* qualifiedName = */ StandardClassIds.EnumEntries.asFqNameString(),
|
||||||
|
/* scope = */ resolveScope
|
||||||
|
)
|
||||||
|
val type = if (enumEntriesClass != null) {
|
||||||
|
elementFactory.createType(enumEntriesClass, enumTypeWithoutAnnotation)
|
||||||
|
} else {
|
||||||
|
elementFactory.createTypeFromText(
|
||||||
|
/* text = */ "${StandardClassIds.EnumEntries.asFqNameString()}<${enumClass.qualifiedName}>",
|
||||||
|
/* context = */ enumClass,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
type.annotate { arrayOf(makeNotNullAnnotation(enumClass)) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,3 +299,6 @@ private val PsiClass.isAnonymous: Boolean
|
|||||||
private fun <T> copy(value: Array<T>): Array<T> {
|
private fun <T> copy(value: Array<T>): Array<T> {
|
||||||
return if (value.isEmpty()) value else value.clone()
|
return if (value.isEmpty()) value else value.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getEnumEntriesPsiMethod(enumClass: KtExtensibleLightClass): PsiMethod =
|
||||||
|
KotlinEnumSyntheticMethod(enumClass, KotlinEnumSyntheticMethod.Kind.ENTRIES)
|
||||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||||
import org.jetbrains.kotlin.codegen.kotlinType
|
import org.jetbrains.kotlin.codegen.kotlinType
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
@@ -266,8 +267,8 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
|
|
||||||
private fun propertyParameters() = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() }
|
private fun propertyParameters() = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() }
|
||||||
|
|
||||||
private fun ownMethods(): List<KtLightMethod> {
|
private fun ownMethods(): List<PsiMethod> {
|
||||||
val result = mutableListOf<KtLightMethod>()
|
val result = mutableListOf<PsiMethod>()
|
||||||
|
|
||||||
for (declaration in this.classOrObject.declarations.filterNot { it.isHiddenByDeprecation(support) }) {
|
for (declaration in this.classOrObject.declarations.filterNot { it.isHiddenByDeprecation(support) }) {
|
||||||
if (declaration.hasModifier(PRIVATE_KEYWORD) && isInterface) continue
|
if (declaration.hasModifier(PRIVATE_KEYWORD) && isInterface) continue
|
||||||
@@ -319,18 +320,23 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
|
|
||||||
val lazyDescriptor = lazy { getDescriptor() }
|
val lazyDescriptor = lazy { getDescriptor() }
|
||||||
project.applyCompilerPlugins {
|
project.applyCompilerPlugins {
|
||||||
|
val methodsList = mutableListOf<KtLightMethod>()
|
||||||
it.interceptMethodsBuilding(
|
it.interceptMethodsBuilding(
|
||||||
declaration = kotlinOrigin,
|
declaration = kotlinOrigin,
|
||||||
descriptor = lazyDescriptor,
|
descriptor = lazyDescriptor,
|
||||||
containingDeclaration = this,
|
containingDeclaration = this,
|
||||||
methodsList = result
|
methodsList = methodsList
|
||||||
)
|
)
|
||||||
|
result.addAll(methodsList)
|
||||||
|
}
|
||||||
|
if (isEnum && support.languageVersionSettings.supportsFeature(LanguageFeature.EnumEntries)) {
|
||||||
|
result.add(getEnumEntriesPsiMethod(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _ownMethods: CachedValue<List<KtLightMethod>> = CachedValuesManager.getManager(project).createCachedValue(
|
private val _ownMethods: CachedValue<List<PsiMethod>> = CachedValuesManager.getManager(project).createCachedValue(
|
||||||
{
|
{
|
||||||
CachedValueProvider.Result.create(
|
CachedValueProvider.Result.create(
|
||||||
ownMethods(),
|
ownMethods(),
|
||||||
@@ -339,7 +345,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
}, false
|
}, false
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun addMethodsFromDataClass(result: MutableList<KtLightMethod>) {
|
private fun addMethodsFromDataClass(result: MutableList<PsiMethod>) {
|
||||||
if (!classOrObject.hasModifier(DATA_KEYWORD)) return
|
if (!classOrObject.hasModifier(DATA_KEYWORD)) return
|
||||||
val ktClass = classOrObject as? KtClass ?: return
|
val ktClass = classOrObject as? KtClass ?: return
|
||||||
val descriptor = classOrObject.resolve() as? ClassDescriptor ?: return
|
val descriptor = classOrObject.resolve() as? ClassDescriptor ?: return
|
||||||
@@ -381,7 +387,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
}.generate()
|
}.generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addDelegatesToInterfaceMethods(result: MutableList<KtLightMethod>) {
|
private fun addDelegatesToInterfaceMethods(result: MutableList<PsiMethod>) {
|
||||||
classOrObject.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>().forEach {
|
classOrObject.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>().forEach {
|
||||||
addDelegatesToInterfaceMethods(it, result)
|
addDelegatesToInterfaceMethods(it, result)
|
||||||
}
|
}
|
||||||
@@ -389,7 +395,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
|
|
||||||
private fun addDelegatesToInterfaceMethods(
|
private fun addDelegatesToInterfaceMethods(
|
||||||
superTypeEntry: KtDelegatedSuperTypeEntry,
|
superTypeEntry: KtDelegatedSuperTypeEntry,
|
||||||
result: MutableList<KtLightMethod>
|
result: MutableList<PsiMethod>
|
||||||
) {
|
) {
|
||||||
val classDescriptor = classOrObject.resolve() as? ClassDescriptor ?: return
|
val classDescriptor = classOrObject.resolve() as? ClassDescriptor ?: return
|
||||||
val typeReference = superTypeEntry.typeReference ?: return
|
val typeReference = superTypeEntry.typeReference ?: return
|
||||||
@@ -475,7 +481,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
|||||||
|
|
||||||
private fun isJvmStatic(declaration: KtAnnotated): Boolean = declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME)
|
private fun isJvmStatic(declaration: KtAnnotated): Boolean = declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME)
|
||||||
|
|
||||||
override fun getOwnMethods(): List<KtLightMethod> = _ownMethods.value
|
override fun getOwnMethods(): List<PsiMethod> = _ownMethods.value
|
||||||
|
|
||||||
private fun KtAnnotated.hasAnnotation(name: FqName) = support.findAnnotation(this, name) != null
|
private fun KtAnnotated.hasAnnotation(name: FqName) = support.findAnnotation(this, name) != null
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
public enum MyEnumClass /* one.MyEnumClass*/ {
|
|
||||||
Entry;
|
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
|
||||||
public static kotlin.enums.EnumEntries<one.MyEnumClass> getEntries();// getEntries()
|
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
|
||||||
public static one.MyEnumClass valueOf(java.lang.String) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;// valueOf(java.lang.String)
|
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
|
||||||
public static one.MyEnumClass[] values();// values()
|
|
||||||
|
|
||||||
private MyEnumClass();// .ctor()
|
|
||||||
|
|
||||||
public final int doo();// doo()
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
public enum MyEnumClass /* one.MyEnumClass*/ {
|
public enum MyEnumClass /* one.MyEnumClass*/ {
|
||||||
Entry;
|
Entry;
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public static kotlin.enums.EnumEntries<one.MyEnumClass> getEntries();// getEntries()
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
@org.jetbrains.annotations.NotNull()
|
||||||
public static one.MyEnumClass valueOf(java.lang.String) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;// valueOf(java.lang.String)
|
public static one.MyEnumClass valueOf(java.lang.String) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;// valueOf(java.lang.String)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// one.MyEnumClass
|
// one.MyEnumClass
|
||||||
// !LANGUAGE: +EnumEntries
|
// !LANGUAGE: +EnumEntries
|
||||||
|
// IDEA tests don't support !LANGUAGE directive:
|
||||||
|
// COMPILER_ARGUMENTS: -XXLanguage:+EnumEntries
|
||||||
|
|
||||||
package one
|
package one
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user