add ultra-light classes/members that work without backend in simple cases
This commit is contained in:
@@ -64,7 +64,7 @@ public abstract class AnnotationCodegen {
|
|||||||
|
|
||||||
public static final List<JvmFlagAnnotation> FIELD_FLAGS = Arrays.asList(
|
public static final List<JvmFlagAnnotation> FIELD_FLAGS = Arrays.asList(
|
||||||
new JvmFlagAnnotation(JvmAnnotationUtilKt.VOLATILE_ANNOTATION_FQ_NAME.asString(), Opcodes.ACC_VOLATILE),
|
new JvmFlagAnnotation(JvmAnnotationUtilKt.VOLATILE_ANNOTATION_FQ_NAME.asString(), Opcodes.ACC_VOLATILE),
|
||||||
new JvmFlagAnnotation("kotlin.jvm.Transient", Opcodes.ACC_TRANSIENT)
|
new JvmFlagAnnotation(JvmAnnotationUtilKt.TRANSIENT_ANNOTATION_FQ_NAME.asString(), Opcodes.ACC_TRANSIENT)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final List<JvmFlagAnnotation> METHOD_FLAGS = Arrays.asList(
|
public static final List<JvmFlagAnnotation> METHOD_FLAGS = Arrays.asList(
|
||||||
|
|||||||
@@ -1112,34 +1112,37 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull KotlinTypeMapper typeMapper) {
|
public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull KotlinTypeMapper mapper) {
|
||||||
|
return ArrayUtil.toStringArray(CollectionsKt.map(getThrownExceptions(function), d -> mapper.mapClass(d).getInternalName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static List<ClassDescriptor> getThrownExceptions(@NotNull FunctionDescriptor function) {
|
||||||
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
|
AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
|
annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (annotation == null) return ArrayUtil.EMPTY_STRING_ARRAY;
|
if (annotation == null) return Collections.emptyList();
|
||||||
|
|
||||||
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
|
Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
|
||||||
if (values.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
|
if (values.isEmpty()) return Collections.emptyList();
|
||||||
|
|
||||||
Object value = values.iterator().next();
|
Object value = values.iterator().next();
|
||||||
if (!(value instanceof ArrayValue)) return ArrayUtil.EMPTY_STRING_ARRAY;
|
if (!(value instanceof ArrayValue)) return Collections.emptyList();
|
||||||
ArrayValue arrayValue = (ArrayValue) value;
|
ArrayValue arrayValue = (ArrayValue) value;
|
||||||
|
|
||||||
List<String> strings = CollectionsKt.mapNotNull(
|
return CollectionsKt.mapNotNull(
|
||||||
arrayValue.getValue(),
|
arrayValue.getValue(),
|
||||||
(ConstantValue<?> constant) -> {
|
(ConstantValue<?> constant) -> {
|
||||||
if (constant instanceof KClassValue) {
|
if (constant instanceof KClassValue) {
|
||||||
ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(
|
return DescriptorUtils.getClassDescriptorForType(
|
||||||
((KClassValue) constant).getArgumentType(DescriptorUtilsKt.getModule(function))
|
((KClassValue) constant).getArgumentType(DescriptorUtilsKt.getModule(function))
|
||||||
);
|
);
|
||||||
return typeMapper.mapClass(classDescriptor).getInternalName();
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return ArrayUtil.toStringArray(strings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void generateDefaultIfNeeded(
|
void generateDefaultIfNeeded(
|
||||||
|
|||||||
@@ -398,8 +398,8 @@ public class PropertyCodegen {
|
|||||||
modifiers |= ACC_SYNTHETIC;
|
modifiers |= ACC_SYNTHETIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotlinType kotlinType =
|
KotlinType kotlinType = isDelegate ? getDelegateTypeForProperty((KtProperty) element, propertyDescriptor, bindingContext)
|
||||||
isDelegate ? getDelegateTypeForProperty((KtProperty) element, propertyDescriptor) : propertyDescriptor.getType();
|
: propertyDescriptor.getType();
|
||||||
Type type = typeMapper.mapType(kotlinType);
|
Type type = typeMapper.mapType(kotlinType);
|
||||||
|
|
||||||
ClassBuilder builder = v;
|
ClassBuilder builder = v;
|
||||||
@@ -438,7 +438,11 @@ public class PropertyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private KotlinType getDelegateTypeForProperty(@NotNull KtProperty p, @NotNull PropertyDescriptor propertyDescriptor) {
|
public static KotlinType getDelegateTypeForProperty(
|
||||||
|
@NotNull KtProperty p,
|
||||||
|
@NotNull PropertyDescriptor propertyDescriptor,
|
||||||
|
@NotNull BindingContext bindingContext
|
||||||
|
) {
|
||||||
KotlinType delegateType = null;
|
KotlinType delegateType = null;
|
||||||
|
|
||||||
ResolvedCall<FunctionDescriptor> provideDelegateResolvedCall =
|
ResolvedCall<FunctionDescriptor> provideDelegateResolvedCall =
|
||||||
|
|||||||
@@ -1419,7 +1419,7 @@ public class KotlinTypeMapper {
|
|||||||
* In that case the generated method's return type should be boxed: otherwise it's not possible to use
|
* In that case the generated method's return type should be boxed: otherwise it's not possible to use
|
||||||
* this class from Java since javac issues errors when loading the class (incompatible return types)
|
* this class from Java since javac issues errors when loading the class (incompatible return types)
|
||||||
*/
|
*/
|
||||||
private boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
|
public boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
|
||||||
if (isBoxMethodForInlineClass(descriptor)) return true;
|
if (isBoxMethodForInlineClass(descriptor)) return true;
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
|||||||
+2
@@ -39,6 +39,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
* To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses
|
* To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses
|
||||||
*/
|
*/
|
||||||
class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() {
|
class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() {
|
||||||
|
override fun createUltraLightClass(element: KtClassOrObject) = null
|
||||||
|
|
||||||
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
|
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
|
||||||
//force resolve companion for light class generation
|
//force resolve companion for light class generation
|
||||||
traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
|
traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
|
||||||
|
|||||||
+3
@@ -27,6 +27,9 @@ val STRICTFP_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Strictfp")
|
|||||||
@JvmField
|
@JvmField
|
||||||
val VOLATILE_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Volatile")
|
val VOLATILE_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Volatile")
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val TRANSIENT_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Transient")
|
||||||
|
|
||||||
fun DeclarationDescriptor.findJvmOverloadsAnnotation(): AnnotationDescriptor? =
|
fun DeclarationDescriptor.findJvmOverloadsAnnotation(): AnnotationDescriptor? =
|
||||||
annotations.findAnnotation(JVM_OVERLOADS_FQ_NAME)
|
annotations.findAnnotation(JVM_OVERLOADS_FQ_NAME)
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult
|
import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -40,6 +41,8 @@ abstract class LightClassGenerationSupport {
|
|||||||
|
|
||||||
abstract fun analyzeWithContent(element: KtClassOrObject): BindingContext
|
abstract fun analyzeWithContent(element: KtClassOrObject): BindingContext
|
||||||
|
|
||||||
|
abstract fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass?
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getInstance(project: Project): LightClassGenerationSupport {
|
fun getInstance(project: Project): LightClassGenerationSupport {
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ object LightClassUtil {
|
|||||||
fun buildLightTypeParameterList(
|
fun buildLightTypeParameterList(
|
||||||
owner: PsiTypeParameterListOwner,
|
owner: PsiTypeParameterListOwner,
|
||||||
declaration: KtDeclaration): PsiTypeParameterList {
|
declaration: KtDeclaration): PsiTypeParameterList {
|
||||||
val builder = KotlinLightTypeParameterListBuilder(owner.manager)
|
val builder = KotlinLightTypeParameterListBuilder(owner)
|
||||||
if (declaration is KtTypeParameterListOwner) {
|
if (declaration is KtTypeParameterListOwner) {
|
||||||
val parameters = declaration.typeParameters
|
val parameters = declaration.typeParameters
|
||||||
for (i in parameters.indices) {
|
for (i in parameters.indices) {
|
||||||
|
|||||||
+27
-27
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Comparing
|
import com.intellij.openapi.util.Comparing
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
|
import com.intellij.openapi.util.registry.Registry
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.PsiSubstitutorImpl
|
import com.intellij.psi.impl.PsiSubstitutorImpl
|
||||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||||
@@ -37,6 +38,7 @@ import com.intellij.psi.util.CachedValuesManager
|
|||||||
import com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
import com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||||
import com.intellij.psi.util.PsiUtilCore
|
import com.intellij.psi.util.PsiUtilCore
|
||||||
import com.intellij.util.IncorrectOperationException
|
import com.intellij.util.IncorrectOperationException
|
||||||
|
import com.intellij.util.SystemProperties
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult
|
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult
|
||||||
@@ -73,15 +75,11 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
: KtLazyLightClass(classOrObject.manager), StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>> {
|
: KtLazyLightClass(classOrObject.manager), StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>> {
|
||||||
private val lightIdentifier = KtLightIdentifier(this, classOrObject)
|
private val lightIdentifier = KtLightIdentifier(this, classOrObject)
|
||||||
|
|
||||||
private val _extendsList by lazyPub {
|
private val _extendsList by lazyPub { createExtendsList() }
|
||||||
val listDelegate = super.getExtendsList() ?: return@lazyPub null
|
private val _implementsList by lazyPub { createImplementsList() }
|
||||||
KtLightPsiReferenceList(listDelegate, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val _implementsList by lazyPub {
|
protected open fun createExtendsList(): PsiReferenceList? = super.getExtendsList()?.let { KtLightPsiReferenceList(it, this) }
|
||||||
val listDelegate = super.getImplementsList() ?: return@lazyPub null
|
protected open fun createImplementsList(): PsiReferenceList? = super.getImplementsList()?.let { KtLightPsiReferenceList(it, this) }
|
||||||
KtLightPsiReferenceList(listDelegate, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val kotlinOrigin: KtClassOrObject = classOrObject
|
override val kotlinOrigin: KtClassOrObject = classOrObject
|
||||||
|
|
||||||
@@ -92,7 +90,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
override val lightClassData: LightClassData
|
override val lightClassData: LightClassData
|
||||||
get() = findLightClassData()
|
get() = findLightClassData()
|
||||||
|
|
||||||
open protected fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject)
|
protected open fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject)
|
||||||
|
|
||||||
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub
|
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub
|
||||||
|
|
||||||
@@ -110,9 +108,9 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
|
|
||||||
private val _containingFile: PsiFile by lazyPub {
|
private val _containingFile: PsiFile by lazyPub {
|
||||||
object : FakeFileForLightClass(
|
object : FakeFileForLightClass(
|
||||||
classOrObject.containingKtFile,
|
classOrObject.containingKtFile,
|
||||||
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! },
|
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! },
|
||||||
{ getJavaFileStub() }
|
{ getJavaFileStub() }
|
||||||
) {
|
) {
|
||||||
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
|
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
|
||||||
|
|
||||||
@@ -173,9 +171,9 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
return super.getContainingClass()
|
return super.getContainingClass()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _typeParameterList: PsiTypeParameterList by lazyPub {
|
private val _typeParameterList: PsiTypeParameterList by lazyPub { buildTypeParameterList() }
|
||||||
LightClassUtil.buildLightTypeParameterList(this, classOrObject)
|
|
||||||
}
|
open protected fun buildTypeParameterList() = LightClassUtil.buildLightTypeParameterList(this, classOrObject)
|
||||||
|
|
||||||
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
|
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
|
||||||
|
|
||||||
@@ -322,9 +320,8 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
|
|
||||||
override fun getNameIdentifier(): KtLightIdentifier? = lightIdentifier
|
override fun getNameIdentifier(): KtLightIdentifier? = lightIdentifier
|
||||||
|
|
||||||
override fun getExtendsList() = _extendsList
|
override fun getExtendsList(): PsiReferenceList? = _extendsList
|
||||||
|
override fun getImplementsList(): PsiReferenceList? = _implementsList
|
||||||
override fun getImplementsList() = _implementsList
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val JAVA_API_STUB = Key.create<CachedValue<LightClassDataHolder.ForClass>>("JAVA_API_STUB")
|
private val JAVA_API_STUB = Key.create<CachedValue<LightClassDataHolder.ForClass>>("JAVA_API_STUB")
|
||||||
@@ -347,6 +344,10 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Registry.`is`("kotlin.use.ultra.light.classes", false)) {
|
||||||
|
LightClassGenerationSupport.getInstance(classOrObject.project).createUltraLightClass(classOrObject)?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
classOrObject is KtObjectDeclaration && classOrObject.isObjectLiteral() ->
|
classOrObject is KtObjectDeclaration && classOrObject.isObjectLiteral() ->
|
||||||
KtLightClassForAnonymousDeclaration(classOrObject)
|
KtLightClassForAnonymousDeclaration(classOrObject)
|
||||||
@@ -456,17 +457,16 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
|||||||
|
|
||||||
private val modifiers by lazyPub { containingClass.computeModifiers() }
|
private val modifiers by lazyPub { containingClass.computeModifiers() }
|
||||||
|
|
||||||
override fun hasModifierProperty(name: String): Boolean {
|
override fun hasModifierProperty(name: String): Boolean =
|
||||||
if (name != PsiModifier.FINAL) {
|
if (name != PsiModifier.FINAL) name in modifiers else owner.isFinal(PsiModifier.FINAL in modifiers)
|
||||||
return name in modifiers
|
|
||||||
}
|
|
||||||
|
|
||||||
val isFinalByPsi = PsiModifier.FINAL in modifiers
|
}
|
||||||
// annotations can make class open via 'allopen' plugin
|
|
||||||
if (!owner.isPossiblyAffectedByAllOpen() || !isFinalByPsi) return isFinalByPsi
|
|
||||||
|
|
||||||
return clsDelegate.hasModifierProperty(PsiModifier.FINAL)
|
open fun isFinal(isFinalByPsi: Boolean): Boolean {
|
||||||
}
|
// annotations can make class open via 'allopen' plugin
|
||||||
|
if (!isPossiblyAffectedByAllOpen() || !isFinalByPsi) return isFinalByPsi
|
||||||
|
|
||||||
|
return clsDelegate.hasModifierProperty(PsiModifier.FINAL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.asJava.classes
|
|||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
|
||||||
// light class for top level or (inner/nested of top level) source declarations
|
// light class for top level or (inner/nested of top level) source declarations
|
||||||
class KtLightClassImpl(classOrObject: KtClassOrObject) : KtLightClassForSourceDeclaration(classOrObject) {
|
open class KtLightClassImpl(classOrObject: KtClassOrObject) : KtLightClassForSourceDeclaration(classOrObject) {
|
||||||
override fun getQualifiedName() = classOrObject.fqName?.asString()
|
override fun getQualifiedName() = classOrObject.fqName?.asString()
|
||||||
|
|
||||||
override fun getParent() = if (classOrObject.isTopLevel())
|
override fun getParent() = if (classOrObject.isTopLevel())
|
||||||
|
|||||||
@@ -0,0 +1,657 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.asJava.classes
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting
|
||||||
|
import com.intellij.lang.Language
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.impl.PsiClassImplUtil
|
||||||
|
import com.intellij.psi.impl.PsiImplUtil
|
||||||
|
import com.intellij.psi.impl.light.*
|
||||||
|
import com.intellij.psi.util.TypeConversionUtil
|
||||||
|
import org.jetbrains.annotations.NonNls
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
|
import org.jetbrains.kotlin.asJava.builder.LightClassData
|
||||||
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.*
|
||||||
|
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||||
|
import org.jetbrains.kotlin.codegen.PropertyCodegen
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.annotations.TRANSIENT_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
|
class KtUltraLightClass(classOrObject: KtClassOrObject, private val support: UltraLightSupport) :
|
||||||
|
KtLightClassImpl(classOrObject) {
|
||||||
|
private val tooComplex: Boolean by lazyPub { support.isTooComplexForUltraLightGeneration(classOrObject) }
|
||||||
|
|
||||||
|
override fun isFinal(isFinalByPsi: Boolean) = if (tooComplex) super.isFinal(isFinalByPsi) else isFinalByPsi
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
@VisibleForTesting
|
||||||
|
var isClsDelegateLoaded = false
|
||||||
|
|
||||||
|
override fun findLightClassData(): LightClassData = super.findLightClassData().also {
|
||||||
|
if (!isClsDelegateLoaded) {
|
||||||
|
isClsDelegateLoaded = true
|
||||||
|
check(tooComplex) { "Cls delegate shouldn't be loaded for not too complex ultra-light classes!" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun allSuperTypes() =
|
||||||
|
getDescriptor()?.typeConstructor?.supertypes?.mapNotNull {
|
||||||
|
it.asPsiType(classOrObject, support, TypeMappingMode.SUPER_TYPE) as? PsiClassType
|
||||||
|
}.orEmpty()
|
||||||
|
|
||||||
|
override fun createExtendsList(): PsiReferenceList? =
|
||||||
|
if (tooComplex) super.createExtendsList()
|
||||||
|
else LightReferenceListBuilder(manager, language, PsiReferenceList.Role.EXTENDS_LIST).also { list ->
|
||||||
|
allSuperTypes()
|
||||||
|
.filter { (isInterface || it.resolve()?.isInterface == false) && !it.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) }
|
||||||
|
.forEach(list::addReference)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createImplementsList(): PsiReferenceList? =
|
||||||
|
if (tooComplex) super.createImplementsList()
|
||||||
|
else LightReferenceListBuilder(manager, language, PsiReferenceList.Role.IMPLEMENTS_LIST).also { list ->
|
||||||
|
if (!isInterface) {
|
||||||
|
allSuperTypes()
|
||||||
|
.filter { it.resolve()?.isInterface == true }
|
||||||
|
.forEach(list::addReference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildTypeParameterList(): PsiTypeParameterList =
|
||||||
|
if (tooComplex) super.buildTypeParameterList() else buildTypeParameterList(classOrObject, this, support)
|
||||||
|
|
||||||
|
// the following logic should be in the platform (super), overrides can be removed once that happens
|
||||||
|
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
|
||||||
|
override fun getSuperClass(): PsiClass? = PsiClassImplUtil.getSuperClass(this)
|
||||||
|
override fun getSupers(): Array<PsiClass> = PsiClassImplUtil.getSupers(this)
|
||||||
|
override fun getSuperTypes(): Array<PsiClassType> = PsiClassImplUtil.getSuperTypes(this)
|
||||||
|
|
||||||
|
override fun getRBrace(): PsiElement? = null
|
||||||
|
override fun getLBrace(): PsiElement? = null
|
||||||
|
|
||||||
|
private val _ownFields: List<KtLightField> by lazyPub {
|
||||||
|
val result = arrayListOf<KtLightField>()
|
||||||
|
val usedNames = hashSetOf<String>()
|
||||||
|
|
||||||
|
fun generateUniqueName(base: String): String {
|
||||||
|
if (usedNames.add(base)) return base
|
||||||
|
var i = 1
|
||||||
|
while (true) {
|
||||||
|
val suggestion = "$base$$i"
|
||||||
|
if (usedNames.add(suggestion)) return suggestion
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (parameter in propertyParameters()) {
|
||||||
|
val modifiers = hashSetOf<String>()
|
||||||
|
modifiers.add(PsiModifier.PRIVATE)
|
||||||
|
if (!parameter.isMutable) {
|
||||||
|
modifiers.add(PsiModifier.FINAL)
|
||||||
|
}
|
||||||
|
result.add(KtUltraLightField(parameter, generateUniqueName(parameter.name.orEmpty()), this, support, modifiers))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.classOrObject.companionObjects.firstOrNull()?.let { companion ->
|
||||||
|
result.add(
|
||||||
|
KtUltraLightField(
|
||||||
|
companion,
|
||||||
|
generateUniqueName(companion.name.orEmpty()),
|
||||||
|
this,
|
||||||
|
support,
|
||||||
|
setOf(PsiModifier.STATIC, PsiModifier.FINAL, PsiModifier.PUBLIC)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (property in companion.declarations.filterIsInstance<KtProperty>()) {
|
||||||
|
if (isInterface && !property.hasModifier(CONST_KEYWORD)) continue
|
||||||
|
|
||||||
|
propertyField(property, ::generateUniqueName, true)?.let(result::add)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isInterface &&
|
||||||
|
!(this.classOrObject is KtObjectDeclaration && this.classOrObject.isCompanion() && containingClass?.isInterface == false)
|
||||||
|
) {
|
||||||
|
for (property in this.classOrObject.declarations.filterIsInstance<KtProperty>()) {
|
||||||
|
propertyField(property, ::generateUniqueName, forceStatic = this.classOrObject is KtObjectDeclaration)?.let(result::add)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNamedObject()) {
|
||||||
|
result.add(
|
||||||
|
KtUltraLightField(
|
||||||
|
this.classOrObject,
|
||||||
|
JvmAbi.INSTANCE_FIELD,
|
||||||
|
this,
|
||||||
|
support,
|
||||||
|
setOf(PsiModifier.STATIC, PsiModifier.FINAL, PsiModifier.PUBLIC)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isNamedObject() = classOrObject is KtObjectDeclaration && !classOrObject.isCompanion()
|
||||||
|
|
||||||
|
private fun propertyField(property: KtProperty, generateUniqueName: (String) -> String, forceStatic: Boolean): KtLightField? {
|
||||||
|
if (!hasBackingField(property)) return null
|
||||||
|
|
||||||
|
val hasDelegate = property.hasDelegate()
|
||||||
|
val fieldName = generateUniqueName((property.name ?: "") + (if (hasDelegate) "\$delegate" else ""))
|
||||||
|
|
||||||
|
val visibility = when {
|
||||||
|
property.hasModifier(PRIVATE_KEYWORD) -> PsiModifier.PRIVATE
|
||||||
|
property.hasModifier(PROTECTED_KEYWORD) && property.hasModifier(LATEINIT_KEYWORD) -> PsiModifier.PROTECTED
|
||||||
|
property.hasModifier(CONST_KEYWORD) || (property.hasModifier(LATEINIT_KEYWORD) && property.setter == null) -> PsiModifier.PUBLIC
|
||||||
|
else -> PsiModifier.PRIVATE
|
||||||
|
}
|
||||||
|
val modifiers = hashSetOf(visibility)
|
||||||
|
|
||||||
|
if (!property.isVar || property.hasModifier(CONST_KEYWORD) || hasDelegate) {
|
||||||
|
modifiers.add(PsiModifier.FINAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forceStatic || isNamedObject() && isJvmStatic(property)) {
|
||||||
|
modifiers.add(PsiModifier.STATIC)
|
||||||
|
}
|
||||||
|
|
||||||
|
return KtUltraLightField(property, fieldName, this, support, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasBackingField(property: KtProperty): Boolean {
|
||||||
|
if (property.hasModifier(ABSTRACT_KEYWORD)) return false
|
||||||
|
if (property.hasModifier(LATEINIT_KEYWORD) || property.accessors.isEmpty()) return true
|
||||||
|
|
||||||
|
val context = LightClassGenerationSupport.getInstance(project).analyze(property)
|
||||||
|
val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property)
|
||||||
|
return descriptor is PropertyDescriptor && context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] == true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOwnFields(): List<KtLightField> = if (tooComplex) super.getOwnFields() else _ownFields
|
||||||
|
|
||||||
|
private fun propertyParameters() = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() }
|
||||||
|
|
||||||
|
private val _ownMethods: List<KtLightMethod> by lazyPub {
|
||||||
|
val result = arrayListOf<KtLightMethod>()
|
||||||
|
for (declaration in this.classOrObject.declarations.filterNot { isHiddenByDeprecation(it) }) {
|
||||||
|
if (declaration.hasModifier(PRIVATE_KEYWORD) && isInterface) continue
|
||||||
|
when (declaration) {
|
||||||
|
is KtNamedFunction -> result.add(asJavaMethod(declaration, false))
|
||||||
|
is KtProperty -> result.addAll(propertyAccessors(declaration, declaration.isVar, false))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (parameter in propertyParameters()) {
|
||||||
|
result.addAll(propertyAccessors(parameter, parameter.isMutable, false))
|
||||||
|
}
|
||||||
|
if (!isInterface) {
|
||||||
|
result.addAll(createConstructors())
|
||||||
|
}
|
||||||
|
this.classOrObject.companionObjects.firstOrNull()?.let { companion ->
|
||||||
|
for (declaration in companion.declarations.filterNot { isHiddenByDeprecation(it) }) {
|
||||||
|
when (declaration) {
|
||||||
|
is KtNamedFunction -> if (isJvmStatic(declaration)) result.add(asJavaMethod(declaration, true))
|
||||||
|
is KtProperty -> result.addAll(propertyAccessors(declaration, declaration.isVar, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createConstructors(): List<KtLightMethod> {
|
||||||
|
val result = arrayListOf<KtLightMethod>()
|
||||||
|
val constructors = classOrObject.allConstructors
|
||||||
|
if (constructors.isEmpty()) {
|
||||||
|
result.add(defaultConstructor())
|
||||||
|
}
|
||||||
|
for (constructor in constructors.filterNot { isHiddenByDeprecation(it) }) {
|
||||||
|
result.add(asJavaMethod(constructor, false))
|
||||||
|
}
|
||||||
|
val primary = classOrObject.primaryConstructor
|
||||||
|
if (primary != null && shouldGenerateNoArgOverload(primary)) {
|
||||||
|
result.add(noArgConstructor(simpleVisibility(primary), primary))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldGenerateNoArgOverload(primary: KtPrimaryConstructor): Boolean {
|
||||||
|
return !primary.hasModifier(PRIVATE_KEYWORD) &&
|
||||||
|
primary.valueParameters.isNotEmpty() &&
|
||||||
|
primary.valueParameters.all { it.defaultValue != null } &&
|
||||||
|
classOrObject.allConstructors.none { it.valueParameters.isEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun defaultConstructor(): KtUltraLightMethod {
|
||||||
|
val visibility =
|
||||||
|
if (classOrObject is KtObjectDeclaration || classOrObject.hasModifier(SEALED_KEYWORD)) PsiModifier.PRIVATE
|
||||||
|
else PsiModifier.PUBLIC
|
||||||
|
return noArgConstructor(visibility, classOrObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun simpleVisibility(declaration: KtDeclaration): String = when {
|
||||||
|
declaration.hasModifier(PRIVATE_KEYWORD) -> PsiModifier.PRIVATE
|
||||||
|
declaration.hasModifier(PROTECTED_KEYWORD) -> PsiModifier.PROTECTED
|
||||||
|
else -> PsiModifier.PUBLIC
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun noArgConstructor(visibility: String, declaration: KtDeclaration): KtUltraLightMethod = KtUltraLightMethod(
|
||||||
|
LightMethodBuilder(manager, language, name.orEmpty()).setConstructor(true).addModifier(visibility),
|
||||||
|
declaration,
|
||||||
|
support,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun isHiddenByDeprecation(declaration: KtDeclaration): Boolean {
|
||||||
|
val deprecated = support.findAnnotation(declaration, FqName("kotlin.Deprecated"))?.second
|
||||||
|
return (deprecated?.argumentValue("level") as? EnumValue)?.enumEntryName?.asString() == "HIDDEN"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isJvmStatic(declaration: KtAnnotated): Boolean = declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME)
|
||||||
|
|
||||||
|
override fun getOwnMethods(): List<KtLightMethod> = if (tooComplex) super.getOwnMethods() else _ownMethods
|
||||||
|
|
||||||
|
private fun asJavaMethod(f: KtFunction, forceStatic: Boolean): KtLightMethod {
|
||||||
|
val isConstructor = f is KtConstructor<*>
|
||||||
|
val name = if (isConstructor) this.name else mangleIfNeeded(listOf(f), f.name ?: SpecialNames.NO_NAME_PROVIDED.asString())
|
||||||
|
val method = lightMethod(name.orEmpty(), f, forceStatic)
|
||||||
|
val wrapper = KtUltraLightMethod(method, f, support, this)
|
||||||
|
addReceiverParameter(f, wrapper)
|
||||||
|
for (parameter in f.valueParameters) {
|
||||||
|
method.addParameter(KtUltraLightParameter(parameter.name.orEmpty(), parameter, support, wrapper, null))
|
||||||
|
}
|
||||||
|
val returnType: PsiType? by lazyPub {
|
||||||
|
if (isConstructor) null
|
||||||
|
else methodReturnType(f)
|
||||||
|
}
|
||||||
|
method.setMethodReturnType { returnType }
|
||||||
|
return wrapper
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addReceiverParameter(f: KtDeclaration, method: KtUltraLightMethod) {
|
||||||
|
val receiver = (f as? KtCallableDeclaration)?.receiverTypeReference
|
||||||
|
if (receiver != null) {
|
||||||
|
method.delegate.addParameter(KtUltraLightParameter("\$self", f, support, method, receiver))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun methodReturnType(f: KtDeclaration): PsiType {
|
||||||
|
val desc = f.resolve()?.let { if (it is PropertyDescriptor) it.getter else it }
|
||||||
|
val kotlinType = (desc as? FunctionDescriptor)?.returnType ?: return PsiType.NULL
|
||||||
|
val mode = when {
|
||||||
|
typeMapper(support).forceBoxedReturnType(desc) -> TypeMappingMode.RETURN_TYPE_BOXED
|
||||||
|
else -> TypeMappingMode.getOptimalModeForReturnType(kotlinType, false)
|
||||||
|
}
|
||||||
|
return kotlinType.asPsiType(f, support, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lightMethod(name: String, declaration: KtDeclaration, forceStatic: Boolean): LightMethodBuilder {
|
||||||
|
val accessedProperty = if (declaration is KtPropertyAccessor) declaration.property else null
|
||||||
|
val outer = accessedProperty ?: declaration
|
||||||
|
return LightMethodBuilder(
|
||||||
|
manager, language, name,
|
||||||
|
LightParameterListBuilder(manager, language),
|
||||||
|
object : LightModifierList(manager, language) {
|
||||||
|
override fun hasModifierProperty(name: String): Boolean {
|
||||||
|
if (name == PsiModifier.PUBLIC || name == PsiModifier.PROTECTED || name == PsiModifier.PRIVATE) {
|
||||||
|
if (declaration.isPrivate() || accessedProperty?.isPrivate() == true) {
|
||||||
|
return name == PsiModifier.PRIVATE
|
||||||
|
}
|
||||||
|
if (declaration.hasModifier(PROTECTED_KEYWORD) || accessedProperty?.hasModifier(PROTECTED_KEYWORD) == true) {
|
||||||
|
return name == PsiModifier.PROTECTED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outer.hasModifier(OVERRIDE_KEYWORD)) {
|
||||||
|
when ((outer.resolve() as? CallableDescriptor)?.visibility) {
|
||||||
|
Visibilities.PUBLIC -> return name == PsiModifier.PUBLIC
|
||||||
|
Visibilities.PRIVATE -> return name == PsiModifier.PRIVATE
|
||||||
|
Visibilities.PROTECTED -> return name == PsiModifier.PROTECTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name == PsiModifier.PUBLIC
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (name) {
|
||||||
|
PsiModifier.FINAL -> !isInterface && outer !is KtConstructor<*> && isFinal(outer)
|
||||||
|
PsiModifier.ABSTRACT -> isInterface || outer.hasModifier(ABSTRACT_KEYWORD)
|
||||||
|
PsiModifier.STATIC -> forceStatic || isNamedObject() && isJvmStatic(outer)
|
||||||
|
PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME)
|
||||||
|
PsiModifier.SYNCHRONIZED -> declaration is KtFunction && declaration.hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME)
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtDeclaration.isPrivate() =
|
||||||
|
hasModifier(PRIVATE_KEYWORD) ||
|
||||||
|
this is KtConstructor<*> && classOrObject.hasModifier(SEALED_KEYWORD) ||
|
||||||
|
this is KtFunction && typeParameters.any { it.hasModifier(REIFIED_KEYWORD) }
|
||||||
|
}
|
||||||
|
).setConstructor(declaration is KtConstructor<*>)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mangleIfNeeded(declarations: List<KtDeclaration>, name: String): String {
|
||||||
|
for (declaration in declarations) {
|
||||||
|
if (declaration.hasModifier(PRIVATE_KEYWORD) ||
|
||||||
|
declaration.hasModifier(PROTECTED_KEYWORD) ||
|
||||||
|
declaration.hasModifier(PUBLIC_KEYWORD)
|
||||||
|
) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
if (isInternal(declaration) && declaration.resolve()?.isPublishedApi() != true) {
|
||||||
|
return KotlinTypeMapper.InternalNameMapper.mangleInternalName(name, support.moduleName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtAnnotated.hasAnnotation(name: FqName) = support.findAnnotation(this, name) != null
|
||||||
|
|
||||||
|
private fun isInternal(f: KtDeclaration): Boolean {
|
||||||
|
if (f.hasModifier(OVERRIDE_KEYWORD)) {
|
||||||
|
val desc = f.resolve()
|
||||||
|
return desc is CallableDescriptor &&
|
||||||
|
desc.visibility.effectiveVisibility(desc, false) == EffectiveVisibility.Internal
|
||||||
|
}
|
||||||
|
return f.hasModifier(INTERNAL_KEYWORD)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun propertyAccessors(declaration: KtNamedDeclaration, mutable: Boolean, onlyJvmStatic: Boolean): List<KtLightMethod> {
|
||||||
|
val propertyName = declaration.name
|
||||||
|
if (declaration.hasModifier(CONST_KEYWORD) || propertyName == null) return emptyList()
|
||||||
|
|
||||||
|
val ktGetter = (declaration as? KtProperty)?.getter
|
||||||
|
val ktSetter = (declaration as? KtProperty)?.setter
|
||||||
|
|
||||||
|
val isPrivate = declaration.hasModifier(PRIVATE_KEYWORD)
|
||||||
|
if (isPrivate && declaration !is KtProperty) return emptyList()
|
||||||
|
|
||||||
|
fun needsAccessor(accessor: KtPropertyAccessor?): Boolean {
|
||||||
|
if (!onlyJvmStatic || isJvmStatic(declaration) || accessor != null && isJvmStatic(accessor)) {
|
||||||
|
if (declaration is KtProperty && declaration.hasDelegate()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (accessor?.hasModifier(PRIVATE_KEYWORD) == true) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!isPrivate || accessor?.hasBody() == true) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = arrayListOf<KtLightMethod>()
|
||||||
|
|
||||||
|
if (needsAccessor(ktGetter)) {
|
||||||
|
val getterName = mangleIfNeeded(listOfNotNull(ktGetter, declaration), JvmAbi.getterName(propertyName))
|
||||||
|
val getterType: PsiType by lazyPub { methodReturnType(declaration) }
|
||||||
|
val getterPrototype = lightMethod(getterName, ktGetter ?: declaration, onlyJvmStatic)
|
||||||
|
.setMethodReturnType { getterType }
|
||||||
|
val getterWrapper = KtUltraLightMethod(getterPrototype, declaration, support, this)
|
||||||
|
addReceiverParameter(declaration, getterWrapper)
|
||||||
|
result.add(getterWrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutable && needsAccessor(ktSetter)) {
|
||||||
|
val setterName = mangleIfNeeded(listOfNotNull(ktSetter, declaration), JvmAbi.setterName(propertyName))
|
||||||
|
val setterPrototype = lightMethod(setterName, ktSetter ?: declaration, onlyJvmStatic)
|
||||||
|
.setMethodReturnType(PsiType.VOID)
|
||||||
|
val setterWrapper = KtUltraLightMethod(setterPrototype, declaration, support, this)
|
||||||
|
addReceiverParameter(declaration, setterWrapper)
|
||||||
|
val parameterOrigin = ktSetter?.parameter ?: declaration
|
||||||
|
setterPrototype.addParameter(KtUltraLightParameter(propertyName, parameterOrigin, support, setterWrapper, null))
|
||||||
|
result.add(setterWrapper)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isFinal(declaration: KtDeclaration): Boolean {
|
||||||
|
if (declaration.hasModifier(FINAL_KEYWORD)) return true
|
||||||
|
return declaration !is KtPropertyAccessor &&
|
||||||
|
!declaration.hasModifier(OPEN_KEYWORD) &&
|
||||||
|
!declaration.hasModifier(OVERRIDE_KEYWORD) &&
|
||||||
|
!declaration.hasModifier(ABSTRACT_KEYWORD)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getInitializers(): Array<PsiClassInitializer> = emptyArray()
|
||||||
|
|
||||||
|
override fun getContainingClass(): PsiClass? =
|
||||||
|
if (tooComplex) super.getContainingClass() else classOrObject.containingClass()?.let(KtLightClassForSourceDeclaration::create)
|
||||||
|
|
||||||
|
override fun getParent(): PsiElement? = if (tooComplex) super.getParent() else containingClass ?: containingFile
|
||||||
|
|
||||||
|
override fun getScope(): PsiElement? = if (tooComplex) super.getScope() else parent
|
||||||
|
override fun copy(): KtLightClassImpl = KtUltraLightClass(classOrObject.copy() as KtClassOrObject, support)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class KtUltraLightField(
|
||||||
|
private val declaration: KtNamedDeclaration,
|
||||||
|
name: String,
|
||||||
|
private val containingClass: KtUltraLightClass,
|
||||||
|
private val support: UltraLightSupport,
|
||||||
|
modifiers: Set<String>
|
||||||
|
) : LightFieldBuilder(name, PsiType.NULL, declaration), KtLightField {
|
||||||
|
private val modList = object : KtLightSimpleModifierList(this, modifiers) {
|
||||||
|
override fun hasModifierProperty(name: String): Boolean = when (name) {
|
||||||
|
PsiModifier.VOLATILE -> hasFieldAnnotation(VOLATILE_ANNOTATION_FQ_NAME)
|
||||||
|
PsiModifier.TRANSIENT -> hasFieldAnnotation(TRANSIENT_ANNOTATION_FQ_NAME)
|
||||||
|
else -> super.hasModifierProperty(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasFieldAnnotation(fqName: FqName): Boolean {
|
||||||
|
val annotation = support.findAnnotation(declaration, fqName)?.first ?: return false
|
||||||
|
val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: return true
|
||||||
|
val expectedTarget =
|
||||||
|
if (declaration is KtProperty && declaration.hasDelegate()) AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
|
||||||
|
else AnnotationUseSiteTarget.FIELD
|
||||||
|
return target == expectedTarget
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getModifierList(): PsiModifierList = modList
|
||||||
|
override fun hasModifierProperty(name: String): Boolean =
|
||||||
|
modifierList.hasModifierProperty(name) //can be removed after IDEA platform does the same
|
||||||
|
|
||||||
|
override fun getLanguage(): Language = KotlinLanguage.INSTANCE
|
||||||
|
|
||||||
|
private val _type: PsiType by lazyPub {
|
||||||
|
fun nonExistent() = JavaPsiFacade.getElementFactory(project).createTypeFromText("error.NonExistentClass", declaration)
|
||||||
|
when {
|
||||||
|
declaration is KtProperty && declaration.hasDelegate() ->
|
||||||
|
(declaration.resolve() as? PropertyDescriptor)
|
||||||
|
?.let {
|
||||||
|
val context = LightClassGenerationSupport.getInstance(project).analyze(declaration)
|
||||||
|
PropertyCodegen.getDelegateTypeForProperty(declaration, it, context)
|
||||||
|
}
|
||||||
|
?.let { it.asPsiType(declaration, support, TypeMappingMode.getOptimalModeForValueParameter(it), this) }
|
||||||
|
?.let(TypeConversionUtil::erasure)
|
||||||
|
?: nonExistent()
|
||||||
|
declaration is KtObjectDeclaration ->
|
||||||
|
KtLightClassForSourceDeclaration.create(declaration)?.let { JavaPsiFacade.getElementFactory(project).createType(it) }
|
||||||
|
?: nonExistent()
|
||||||
|
else ->
|
||||||
|
declaration.getKotlinType()?.let {
|
||||||
|
val mode = when {
|
||||||
|
(declaration.resolve() as? PropertyDescriptor)?.isVar == true -> TypeMappingMode.getOptimalModeForValueParameter(it)
|
||||||
|
else -> TypeMappingMode.getOptimalModeForReturnType(it, false)
|
||||||
|
}
|
||||||
|
it.asPsiType(declaration, support, mode, this)
|
||||||
|
} ?: PsiType.NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(): PsiType = _type
|
||||||
|
|
||||||
|
override fun getParent() = containingClass
|
||||||
|
override fun getContainingClass() = containingClass
|
||||||
|
override fun getContainingFile(): PsiFile? = containingClass.containingFile
|
||||||
|
|
||||||
|
override fun computeConstantValue(): Any? =
|
||||||
|
if (hasModifierProperty(PsiModifier.FINAL) &&
|
||||||
|
(TypeConversionUtil.isPrimitiveAndNotNull(_type) || _type.equalsToText(CommonClassNames.JAVA_LANG_STRING))
|
||||||
|
)
|
||||||
|
(declaration.resolve() as? VariableDescriptor)?.compileTimeInitializer?.value
|
||||||
|
else null
|
||||||
|
|
||||||
|
override fun computeConstantValue(visitedVars: MutableSet<PsiVariable>?): Any? = computeConstantValue()
|
||||||
|
|
||||||
|
override val kotlinOrigin = declaration
|
||||||
|
override val clsDelegate: PsiField
|
||||||
|
get() = throw IllegalStateException("Cls delegate shouldn't be loaded for ultra-light PSI!")
|
||||||
|
override val lightMemberOrigin = LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER)
|
||||||
|
|
||||||
|
override fun setName(@NonNls name: String): PsiElement {
|
||||||
|
(kotlinOrigin as? KtNamedDeclaration)?.setName(name)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setInitializer(initializer: PsiExpression?) = cannotModify()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class KtUltraLightMethod(
|
||||||
|
internal val delegate: LightMethodBuilder,
|
||||||
|
originalElement: KtDeclaration,
|
||||||
|
private val support: UltraLightSupport,
|
||||||
|
containingClass: KtUltraLightClass
|
||||||
|
) : KtLightMethodImpl({ delegate }, LightMemberOriginForDeclaration(originalElement, JvmDeclarationOriginKind.OTHER), containingClass) {
|
||||||
|
|
||||||
|
override fun getReturnTypeElement(): PsiTypeElement? = null
|
||||||
|
override fun getReturnType(): PsiType? = clsDelegate.returnType
|
||||||
|
override fun getParameterList(): PsiParameterList = clsDelegate.parameterList
|
||||||
|
|
||||||
|
// should be in super
|
||||||
|
override fun isVarArgs() = PsiImplUtil.isVarArgs(this)
|
||||||
|
|
||||||
|
override fun buildTypeParameterList(): PsiTypeParameterList {
|
||||||
|
val origin = kotlinOrigin
|
||||||
|
return if (origin is KtFunction || origin is KtProperty)
|
||||||
|
buildTypeParameterList(origin as KtTypeParameterListOwner, this, support)
|
||||||
|
else LightTypeParameterListBuilder(manager, language)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _throwsList: PsiReferenceList by lazyPub {
|
||||||
|
val list = LightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST)
|
||||||
|
(kotlinOrigin?.resolve() as? FunctionDescriptor)?.let {
|
||||||
|
for (ex in FunctionCodegen.getThrownExceptions(it)) {
|
||||||
|
list.addReference(ex.fqNameSafe.asString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getThrowsList(): PsiReferenceList = _throwsList
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class KtUltraLightParameter(
|
||||||
|
name: String,
|
||||||
|
override val kotlinOrigin: KtDeclaration,
|
||||||
|
private val support: UltraLightSupport,
|
||||||
|
method: KtLightMethod,
|
||||||
|
private val receiver: KtTypeReference?
|
||||||
|
) : org.jetbrains.kotlin.asJava.elements.LightParameter(
|
||||||
|
name,
|
||||||
|
PsiType.NULL,
|
||||||
|
method,
|
||||||
|
method.language
|
||||||
|
),
|
||||||
|
KtLightDeclaration<KtDeclaration, PsiParameter> {
|
||||||
|
|
||||||
|
override val clsDelegate: PsiParameter
|
||||||
|
get() = throw IllegalStateException("Cls delegate shouldn't be loaded for ultra-light PSI!")
|
||||||
|
|
||||||
|
private val lightModifierList by lazyPub { KtLightSimpleModifierList(this, emptySet()) }
|
||||||
|
|
||||||
|
override fun isVarArgs(): Boolean =
|
||||||
|
kotlinOrigin is KtParameter && kotlinOrigin.isVarArg && method.parameterList.parameters.last() == this
|
||||||
|
|
||||||
|
override fun getModifierList(): PsiModifierList = lightModifierList
|
||||||
|
|
||||||
|
override fun getNavigationElement(): PsiElement = kotlinOrigin
|
||||||
|
|
||||||
|
private val kotlinType: KotlinType? by lazyPub {
|
||||||
|
when {
|
||||||
|
receiver != null -> (kotlinOrigin.resolve() as? CallableMemberDescriptor)?.extensionReceiverParameter?.type
|
||||||
|
else -> kotlinOrigin.getKotlinType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private val _type: PsiType by lazyPub {
|
||||||
|
kotlinType?.let { it.asPsiType(kotlinOrigin, support, TypeMappingMode.getOptimalModeForValueParameter(it), this) } ?: PsiType.NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(): PsiType = _type
|
||||||
|
|
||||||
|
override fun setName(@NonNls name: String): PsiElement {
|
||||||
|
(kotlinOrigin as? KtVariableDeclaration)?.setName(name)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getContainingFile(): PsiFile = method.containingFile
|
||||||
|
override fun getParent(): PsiElement = method.parameterList
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean = other is KtUltraLightParameter && other.kotlinOrigin == this.kotlinOrigin
|
||||||
|
override fun hashCode(): Int = kotlinOrigin.hashCode()
|
||||||
|
|
||||||
|
internal fun annotatedOrigin(): KtAnnotated? {
|
||||||
|
if (receiver != null) return receiver
|
||||||
|
|
||||||
|
if (kotlinOrigin is KtProperty) {
|
||||||
|
return null // we're a setter of a property with no explicit declaration, so we don't have annotation
|
||||||
|
}
|
||||||
|
return kotlinOrigin
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun getTypeForNullability(): KotlinType? {
|
||||||
|
if (receiver != null) return kotlinType
|
||||||
|
if (kotlinOrigin is KtProperty) {
|
||||||
|
if (kotlinOrigin.setter?.hasModifier(PRIVATE_KEYWORD) == true) return null
|
||||||
|
return kotlinType
|
||||||
|
}
|
||||||
|
if (kotlinOrigin is KtParameter) {
|
||||||
|
val reference = kotlinOrigin.typeReference
|
||||||
|
if (kotlinOrigin.isVarArg && reference != null) {
|
||||||
|
LightClassGenerationSupport.getInstance(project).analyze(reference)[BindingContext.TYPE, reference]?.let { return it }
|
||||||
|
}
|
||||||
|
if (reference != null || kotlinOrigin.parent?.parent is KtPropertyAccessor) {
|
||||||
|
return kotlinType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UltraLightSupport {
|
||||||
|
val moduleName: String
|
||||||
|
fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>?
|
||||||
|
fun isTooComplexForUltraLightGeneration(element: KtClassOrObject): Boolean
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.asJava.classes
|
||||||
|
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.impl.cache.TypeInfo
|
||||||
|
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||||
|
import com.intellij.psi.impl.compiled.SignatureParsing
|
||||||
|
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||||
|
import com.intellij.psi.impl.light.LightReferenceListBuilder
|
||||||
|
import com.intellij.psi.impl.light.LightTypeParameterBuilder
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
|
||||||
|
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||||
|
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||||
|
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
|
import org.jetbrains.kotlin.config.JvmTarget
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtFunction
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import java.text.StringCharacterIterator
|
||||||
|
|
||||||
|
internal fun buildTypeParameterList(
|
||||||
|
declaration: KtTypeParameterListOwner,
|
||||||
|
owner: PsiTypeParameterListOwner,
|
||||||
|
support: UltraLightSupport
|
||||||
|
): PsiTypeParameterList {
|
||||||
|
val tpList = KotlinLightTypeParameterListBuilder(owner)
|
||||||
|
for ((i, ktParam) in declaration.typeParameters.withIndex()) {
|
||||||
|
tpList.addParameter(object : LightTypeParameterBuilder(ktParam.name.orEmpty(), owner, i) {
|
||||||
|
private val superList: LightReferenceListBuilder by lazyPub {
|
||||||
|
val boundList = LightReferenceListBuilder(manager, PsiReferenceList.Role.EXTENDS_BOUNDS_LIST)
|
||||||
|
if (ktParam.extendsBound != null || declaration.typeConstraints.isNotEmpty()) {
|
||||||
|
val boundTypes = (ktParam.resolve() as? TypeParameterDescriptor)?.upperBounds.orEmpty()
|
||||||
|
.mapNotNull { it.asPsiType(ktParam, support, TypeMappingMode.DEFAULT, this) as? PsiClassType }
|
||||||
|
val hasDefaultBound = boundTypes.size == 1 && boundTypes[0].equalsToText(CommonClassNames.JAVA_LANG_OBJECT)
|
||||||
|
if (!hasDefaultBound) {
|
||||||
|
boundTypes.forEach(boundList::addReference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boundList
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getExtendsList(): LightReferenceListBuilder = superList
|
||||||
|
|
||||||
|
override fun getParent(): PsiElement = tpList
|
||||||
|
override fun getContainingFile(): PsiFile = owner.containingFile
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return tpList
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KtDeclaration.getKotlinType(): KotlinType? {
|
||||||
|
val descriptor = resolve()
|
||||||
|
return when (descriptor) {
|
||||||
|
is ValueDescriptor -> descriptor.type
|
||||||
|
is CallableDescriptor -> descriptor.returnType
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KtDeclaration.resolve() = LightClassGenerationSupport.getInstance(project).resolveToDescriptor(this)
|
||||||
|
|
||||||
|
// copy-pasted from kotlinInternalUastUtils.kt and post-processed
|
||||||
|
internal fun KotlinType.asPsiType(
|
||||||
|
declaration: KtDeclaration,
|
||||||
|
support: UltraLightSupport,
|
||||||
|
mode: TypeMappingMode,
|
||||||
|
psiContext: PsiElement = declaration
|
||||||
|
): PsiType {
|
||||||
|
val typeFqName = constructor.declarationDescriptor?.fqNameSafe?.asString()
|
||||||
|
if (typeFqName == "kotlin.Unit" && declaration is KtFunction) return PsiType.VOID
|
||||||
|
|
||||||
|
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||||
|
typeMapper(support).mapType(this, signatureWriter, mode)
|
||||||
|
val signature = StringCharacterIterator(signatureWriter.toString())
|
||||||
|
|
||||||
|
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
|
||||||
|
val typeInfo = TypeInfo.fromString(javaType, false)
|
||||||
|
val typeText = TypeInfo.createTypeText(typeInfo) ?: return PsiType.NULL
|
||||||
|
|
||||||
|
val type = ClsTypeElementImpl(psiContext, typeText, '\u0000').type
|
||||||
|
if (type is PsiArrayType && psiContext is KtUltraLightParameter && psiContext.isVarArgs) {
|
||||||
|
return PsiEllipsisType(type.componentType, type.annotationProvider)
|
||||||
|
}
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun typeMapper(support: UltraLightSupport): KotlinTypeMapper = KotlinTypeMapper(
|
||||||
|
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
|
||||||
|
IncompatibleClassTracker.DoNothing, support.moduleName,
|
||||||
|
JvmTarget.JVM_1_8,
|
||||||
|
true, false
|
||||||
|
)
|
||||||
+7
-2
@@ -17,16 +17,21 @@
|
|||||||
package org.jetbrains.kotlin.asJava.elements
|
package org.jetbrains.kotlin.asJava.elements
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.PsiTypeParameterListOwner
|
||||||
import com.intellij.psi.ResolveState
|
import com.intellij.psi.ResolveState
|
||||||
import com.intellij.psi.impl.light.LightTypeParameterListBuilder
|
import com.intellij.psi.impl.light.LightTypeParameterListBuilder
|
||||||
import com.intellij.psi.scope.PsiScopeProcessor
|
import com.intellij.psi.scope.PsiScopeProcessor
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
|
|
||||||
class KotlinLightTypeParameterListBuilder(manager: PsiManager): LightTypeParameterListBuilder(manager, KotlinLanguage.INSTANCE) {
|
class KotlinLightTypeParameterListBuilder(private val owner: PsiTypeParameterListOwner) :
|
||||||
|
LightTypeParameterListBuilder(owner.manager, KotlinLanguage.INSTANCE) {
|
||||||
override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean {
|
override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean {
|
||||||
return typeParameters.all { processor.execute(it, state) }
|
return typeParameters.all { processor.execute(it, state) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getParent(): PsiElement = owner
|
||||||
|
override fun getContainingFile(): PsiFile = owner.containingFile
|
||||||
|
|
||||||
override fun getText(): String? = ""
|
override fun getText(): String? = ""
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-22
@@ -19,7 +19,9 @@ package org.jetbrains.kotlin.asJava.elements
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||||
import com.intellij.psi.scope.PsiScopeProcessor
|
import com.intellij.psi.scope.PsiScopeProcessor
|
||||||
import com.intellij.psi.util.*
|
import com.intellij.psi.util.MethodSignature
|
||||||
|
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||||
@@ -36,7 +38,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||||
|
|
||||||
class KtLightMethodImpl private constructor(
|
open class KtLightMethodImpl protected constructor(
|
||||||
computeRealDelegate: () -> PsiMethod,
|
computeRealDelegate: () -> PsiMethod,
|
||||||
lightMemberOrigin: LightMemberOrigin?,
|
lightMemberOrigin: LightMemberOrigin?,
|
||||||
containingClass: KtLightClass,
|
containingClass: KtLightClass,
|
||||||
@@ -55,25 +57,15 @@ class KtLightMethodImpl private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val typeParamsList: CachedValue<PsiTypeParameterList> by lazyPub {
|
private val typeParamsList: PsiTypeParameterList? by lazyPub { buildTypeParameterList() }
|
||||||
val cacheManager = CachedValuesManager.getManager(clsDelegate.project)
|
|
||||||
cacheManager.createCachedValue<PsiTypeParameterList>(
|
protected open fun buildTypeParameterList(): PsiTypeParameterList? {
|
||||||
{
|
val origin = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement
|
||||||
val origin = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement
|
return when {
|
||||||
val list = if (origin != null) {
|
origin is KtClassOrObject -> KotlinLightTypeParameterListBuilder(this)
|
||||||
if (origin is KtClassOrObject) {
|
origin != null -> LightClassUtil.buildLightTypeParameterList(this, origin)
|
||||||
KotlinLightTypeParameterListBuilder(manager)
|
else -> clsDelegate.typeParameterList
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
LightClassUtil.buildLightTypeParameterList(this@KtLightMethodImpl, origin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clsDelegate.typeParameterList
|
|
||||||
}
|
|
||||||
CachedValueProvider.Result.create(list, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
|
|
||||||
}, false
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun accept(visitor: PsiElementVisitor) {
|
override fun accept(visitor: PsiElementVisitor) {
|
||||||
@@ -128,7 +120,7 @@ class KtLightMethodImpl private constructor(
|
|||||||
|
|
||||||
override fun getParameterList() = paramsList
|
override fun getParameterList() = paramsList
|
||||||
|
|
||||||
override fun getTypeParameterList() = typeParamsList.value
|
override fun getTypeParameterList() = typeParamsList
|
||||||
|
|
||||||
override fun getTypeParameters(): Array<PsiTypeParameter> =
|
override fun getTypeParameters(): Array<PsiTypeParameter> =
|
||||||
typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
|
typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
|
||||||
|
|||||||
+31
-26
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiModifierListOwner
|
|||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtUltraLightParameter
|
||||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
@@ -37,7 +38,7 @@ import org.jetbrains.kotlin.resolve.source.getPsi
|
|||||||
abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(protected val owner: T)
|
abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(protected val owner: T)
|
||||||
: KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierList> {
|
: KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierList> {
|
||||||
override val clsDelegate by lazyPub { owner.clsDelegate.modifierList!! }
|
override val clsDelegate by lazyPub { owner.clsDelegate.modifierList!! }
|
||||||
private val _annotations by lazyPub { computeAnnotations(this) }
|
private val _annotations by lazyPub { computeAnnotations() }
|
||||||
|
|
||||||
override val kotlinOrigin: KtModifierList?
|
override val kotlinOrigin: KtModifierList?
|
||||||
get() = owner.kotlinOrigin?.modifierList
|
get() = owner.kotlinOrigin?.modifierList
|
||||||
@@ -61,9 +62,28 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
|
|||||||
override fun isWritable() = false
|
override fun isWritable() = false
|
||||||
|
|
||||||
override fun toString() = "Light modifier list of $owner"
|
override fun toString() = "Light modifier list of $owner"
|
||||||
|
|
||||||
|
protected open fun computeAnnotations(): List<KtLightAbstractAnnotation> {
|
||||||
|
val annotationsForEntries = lightAnnotationsForEntries(this)
|
||||||
|
val modifierListOwner = parent
|
||||||
|
if (modifierListOwner is KtLightClassForSourceDeclaration && modifierListOwner.isAnnotationType) {
|
||||||
|
val sourceAnnotationNames = annotationsForEntries.mapTo(mutableSetOf()) { it.qualifiedName }
|
||||||
|
val specialAnnotationsOnAnnotationClass = modifierListOwner.clsDelegate.modifierList?.annotations.orEmpty().filter {
|
||||||
|
it.qualifiedName !in sourceAnnotationNames
|
||||||
|
}.map { KtLightNonSourceAnnotation(this, it) }
|
||||||
|
return annotationsForEntries + specialAnnotationsOnAnnotationClass
|
||||||
|
}
|
||||||
|
if ((modifierListOwner is KtLightMember<*> && modifierListOwner !is KtLightFieldImpl.KtLightEnumConstant)
|
||||||
|
|| modifierListOwner is LightParameter) {
|
||||||
|
return annotationsForEntries +
|
||||||
|
listOf(KtLightNullabilityAnnotation(modifierListOwner as KtLightElement<*, PsiModifierListOwner>, this))
|
||||||
|
}
|
||||||
|
return annotationsForEntries
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class KtLightSimpleModifierList(
|
open class KtLightSimpleModifierList(
|
||||||
owner: KtLightElement<KtModifierListOwner, PsiModifierListOwner>, private val modifiers: Set<String>
|
owner: KtLightElement<KtModifierListOwner, PsiModifierListOwner>, private val modifiers: Set<String>
|
||||||
) : KtLightModifierList<KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(owner) {
|
) : KtLightModifierList<KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(owner) {
|
||||||
override fun hasModifierProperty(name: String) = name in modifiers
|
override fun hasModifierProperty(name: String) = name in modifiers
|
||||||
@@ -71,31 +91,14 @@ class KtLightSimpleModifierList(
|
|||||||
override fun copy() = KtLightSimpleModifierList(owner, modifiers)
|
override fun copy() = KtLightSimpleModifierList(owner, modifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeAnnotations(lightModifierList: KtLightModifierList<*>): List<KtLightAbstractAnnotation> {
|
|
||||||
val annotationsForEntries = lightAnnotationsForEntries(lightModifierList)
|
|
||||||
val modifierListOwner = lightModifierList.parent
|
|
||||||
if (modifierListOwner is KtLightClassForSourceDeclaration && modifierListOwner.isAnnotationType) {
|
|
||||||
val sourceAnnotationNames = annotationsForEntries.mapTo(mutableSetOf()) { it.qualifiedName }
|
|
||||||
val specialAnnotationsOnAnnotationClass = modifierListOwner.clsDelegate.modifierList?.annotations.orEmpty().filter {
|
|
||||||
it.qualifiedName !in sourceAnnotationNames
|
|
||||||
}.map { KtLightNonSourceAnnotation(lightModifierList, it) }
|
|
||||||
return annotationsForEntries + specialAnnotationsOnAnnotationClass
|
|
||||||
}
|
|
||||||
if ((modifierListOwner is KtLightMember<*> && modifierListOwner !is KtLightFieldImpl.KtLightEnumConstant)
|
|
||||||
|| modifierListOwner is KtLightParameter) {
|
|
||||||
return annotationsForEntries +
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
listOf(KtLightNullabilityAnnotation(modifierListOwner as KtLightElement<*, PsiModifierListOwner>, lightModifierList))
|
|
||||||
}
|
|
||||||
return annotationsForEntries
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun lightAnnotationsForEntries(lightModifierList: KtLightModifierList<*>): List<KtLightAnnotationForSourceEntry> {
|
private fun lightAnnotationsForEntries(lightModifierList: KtLightModifierList<*>): List<KtLightAnnotationForSourceEntry> {
|
||||||
val lightModifierListOwner = lightModifierList.parent
|
val lightModifierListOwner = lightModifierList.parent
|
||||||
|
|
||||||
if (!isFromSources(lightModifierList)) return emptyList()
|
if (!isFromSources(lightModifierList)) return emptyList()
|
||||||
|
|
||||||
val annotatedKtDeclaration = lightModifierListOwner.kotlinOrigin as? KtDeclaration
|
val annotatedKtDeclaration =
|
||||||
|
if (lightModifierListOwner is KtUltraLightParameter) lightModifierListOwner.annotatedOrigin()
|
||||||
|
else lightModifierListOwner.kotlinOrigin as? KtDeclaration
|
||||||
|
|
||||||
if (annotatedKtDeclaration == null || !annotatedKtDeclaration.isValid || !hasAnnotationsInSource(annotatedKtDeclaration)) {
|
if (annotatedKtDeclaration == null || !annotatedKtDeclaration.isValid || !hasAnnotationsInSource(annotatedKtDeclaration)) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
@@ -128,11 +131,11 @@ fun isFromSources(lightElement: KtLightElement<*, *>): Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAnnotationDescriptors(declaration: KtDeclaration, annotatedLightElement: KtLightElement<*, *>): List<AnnotationDescriptor> {
|
private fun getAnnotationDescriptors(declaration: KtAnnotated, annotatedLightElement: KtLightElement<*, *>): List<AnnotationDescriptor> {
|
||||||
val context = LightClassGenerationSupport.getInstance(declaration.project).analyze(declaration)
|
val context = LightClassGenerationSupport.getInstance(declaration.project).analyze(declaration)
|
||||||
|
|
||||||
val descriptor = if (declaration is KtParameter && declaration.isPropertyParameter()) {
|
val descriptor = if (declaration is KtParameter && declaration.isPropertyParameter()) {
|
||||||
if (annotatedLightElement is KtLightParameter && annotatedLightElement.method.isConstructor)
|
if (annotatedLightElement is LightParameter && annotatedLightElement.method.isConstructor)
|
||||||
context[BindingContext.VALUE_PARAMETER, declaration]
|
context[BindingContext.VALUE_PARAMETER, declaration]
|
||||||
else
|
else
|
||||||
context[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, declaration]
|
context[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, declaration]
|
||||||
@@ -145,7 +148,8 @@ private fun getAnnotationDescriptors(declaration: KtDeclaration, annotatedLightE
|
|||||||
descriptor is ClassDescriptor && annotatedLightElement is KtLightMethod && annotatedLightElement.isConstructor ->
|
descriptor is ClassDescriptor && annotatedLightElement is KtLightMethod && annotatedLightElement.isConstructor ->
|
||||||
descriptor.unsubstitutedPrimaryConstructor
|
descriptor.unsubstitutedPrimaryConstructor
|
||||||
descriptor !is PropertyDescriptor -> descriptor
|
descriptor !is PropertyDescriptor -> descriptor
|
||||||
annotatedLightElement is KtLightFieldImpl.KtLightFieldForDeclaration -> descriptor.backingField
|
annotatedLightElement is KtLightFieldImpl.KtLightEnumConstant -> descriptor
|
||||||
|
annotatedLightElement is KtLightField -> descriptor.backingField
|
||||||
annotatedLightElement !is KtLightMethod -> descriptor
|
annotatedLightElement !is KtLightMethod -> descriptor
|
||||||
annotatedLightElement.isGetter -> descriptor.getter
|
annotatedLightElement.isGetter -> descriptor.getter
|
||||||
annotatedLightElement.isSetter -> descriptor.setter
|
annotatedLightElement.isSetter -> descriptor.setter
|
||||||
@@ -164,7 +168,7 @@ private fun getAnnotationDescriptors(declaration: KtDeclaration, annotatedLightE
|
|||||||
return annotations
|
return annotations
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
|
private fun hasAnnotationsInSource(declaration: KtAnnotated): Boolean {
|
||||||
if (declaration.annotationEntries.isNotEmpty()) {
|
if (declaration.annotationEntries.isNotEmpty()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -175,3 +179,4 @@ private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
|||||||
class KtLightParameter(
|
class KtLightParameter(
|
||||||
override val clsDelegate: PsiParameter,
|
override val clsDelegate: PsiParameter,
|
||||||
private val index: Int,
|
private val index: Int,
|
||||||
val method: KtLightMethod
|
method: KtLightMethod
|
||||||
) : LightParameter(clsDelegate.name ?: "p$index", clsDelegate.type, method, KotlinLanguage.INSTANCE),
|
) : LightParameter(clsDelegate.name ?: "p$index", clsDelegate.type, method, KotlinLanguage.INSTANCE),
|
||||||
KtLightDeclaration<KtParameter, PsiParameter> {
|
KtLightDeclaration<KtParameter, PsiParameter> {
|
||||||
|
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ public class LightParameter extends LightVariableBuilder implements PsiParameter
|
|||||||
public static final LightParameter[] EMPTY_ARRAY = new LightParameter[0];
|
public static final LightParameter[] EMPTY_ARRAY = new LightParameter[0];
|
||||||
|
|
||||||
private final String myName;
|
private final String myName;
|
||||||
private final PsiElement myDeclarationScope;
|
private final KtLightMethod myDeclarationScope;
|
||||||
private final boolean myVarArgs;
|
private final boolean myVarArgs;
|
||||||
|
|
||||||
public LightParameter(@NotNull String name, @NotNull PsiType type, PsiElement declarationScope, Language language) {
|
public LightParameter(@NotNull String name, @NotNull PsiType type, @NotNull KtLightMethod declarationScope, Language language) {
|
||||||
this(name, type, declarationScope, language, type instanceof PsiEllipsisType);
|
this(name, type, declarationScope, language, type instanceof PsiEllipsisType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LightParameter(@NotNull String name, @NotNull PsiType type, PsiElement declarationScope, Language language, boolean isVarArgs) {
|
public LightParameter(@NotNull String name, @NotNull PsiType type, @NotNull KtLightMethod declarationScope, Language language, boolean isVarArgs) {
|
||||||
super(declarationScope.getManager(), name, type, language);
|
super(declarationScope.getManager(), name, type, language);
|
||||||
myName = name;
|
myName = name;
|
||||||
myDeclarationScope = declarationScope;
|
myDeclarationScope = declarationScope;
|
||||||
@@ -41,7 +41,11 @@ public class LightParameter extends LightVariableBuilder implements PsiParameter
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public PsiElement getDeclarationScope() {
|
public KtLightMethod getDeclarationScope() {
|
||||||
|
return myDeclarationScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KtLightMethod getMethod() {
|
||||||
return myDeclarationScope;
|
return myDeclarationScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull
|
|||||||
import org.jetbrains.annotations.Nullable
|
import org.jetbrains.annotations.Nullable
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtUltraLightParameter
|
||||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
@@ -298,6 +299,10 @@ class KtLightNullabilityAnnotation(val member: KtLightElement<*, PsiModifierList
|
|||||||
internal fun KtTypeReference.getType(): KotlinType? = analyze()[BindingContext.TYPE, this]
|
internal fun KtTypeReference.getType(): KotlinType? = analyze()[BindingContext.TYPE, this]
|
||||||
|
|
||||||
private fun getTargetType(annotatedElement: PsiElement): KotlinType? {
|
private fun getTargetType(annotatedElement: PsiElement): KotlinType? {
|
||||||
|
if (member is KtUltraLightParameter) {
|
||||||
|
return member.getTypeForNullability()
|
||||||
|
}
|
||||||
|
|
||||||
if (annotatedElement is KtTypeReference) {
|
if (annotatedElement is KtTypeReference) {
|
||||||
annotatedElement.getType()?.let { return it }
|
annotatedElement.getType()?.let { return it }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
annotation class Anno(val p: String = "", val x: Array<Anno> = arrayOf(Anno(p="a"), Anno(p="b")))
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
|
||||||
|
AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
@MustBeDocumented
|
||||||
|
@Deprecated("This anno is deprecated, use === instead", ReplaceWith("this === other"))
|
||||||
|
annotation class Fancy
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
annotation class ReplaceWith(val expression: String)
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
annotation class Deprecated(
|
||||||
|
val message: String,
|
||||||
|
val replaceWith: ReplaceWith = ReplaceWith(""))
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any>)
|
||||||
|
|
||||||
|
|
||||||
|
@Anno class F: Runnable {
|
||||||
|
@Anno("f") fun f(@Anno p: String) {}
|
||||||
|
@Anno("p") var prop = "x"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Foo @Anno constructor(dependency: MyDependency) {
|
||||||
|
var x: String? = null
|
||||||
|
@Anno set
|
||||||
|
|
||||||
|
@Anno
|
||||||
|
fun String.f4() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ann(String::class, Int::class) class MyClass
|
||||||
|
|
||||||
|
class Example(@field:Ann val foo, // annotate Java field
|
||||||
|
@get:Ann val bar, // annotate Java getter
|
||||||
|
@param:Ann val quux) // annotate Java constructor parameter
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
package pkg
|
||||||
|
|
||||||
|
open class Open {
|
||||||
|
private class Private: Open {}
|
||||||
|
protected inner class Private2 {}
|
||||||
|
internal class StaticInternal {}
|
||||||
|
}
|
||||||
|
internal class OuterInternal {}
|
||||||
|
private class TopLevelPrivate {}
|
||||||
|
|
||||||
|
sealed class Season {
|
||||||
|
class Nested: Season()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class SealedWithArgs(val a: Int)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
class TestConstructor private constructor(p: Int = 1)
|
||||||
|
class A(vararg a: Int, f: () -> Unit) {}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
@Deprecated("", level = DeprecationLevel.HIDDEN)
|
||||||
|
constructor()
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/** should load cls */
|
||||||
|
class Foo {
|
||||||
|
suspend fun doSomething(foo: Foo): Bar {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
class Bar {
|
||||||
|
fun <T> async(block: suspend () -> T)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
interface Base {
|
||||||
|
suspend fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
class Derived: Base {
|
||||||
|
override suspend fun foo() { ... }
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/** should load cls */
|
||||||
|
data class User(val name: String = "", val age: Int = 0)
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
data class Person(val name: String) {
|
||||||
|
var age: Int = 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
interface Base {
|
||||||
|
fun printMessage()
|
||||||
|
fun printMessageLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseImpl(val x: Int) : Base {
|
||||||
|
override fun printMessage() { print(x) }
|
||||||
|
override fun printMessageLine() { println(x) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
class Derived(b: Base) : Base by b {
|
||||||
|
override fun printMessage() { print("abc") }
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
import java.util.function.*
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
enum class Direction {
|
||||||
|
NORTH, SOUTH, WEST, EAST
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
enum class Color(val rgb: Int) {
|
||||||
|
RED(0xFF0000),
|
||||||
|
GREEN(0x00FF00),
|
||||||
|
BLUE(0x0000FF)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
enum class ProtocolState {
|
||||||
|
WAITING {
|
||||||
|
override fun signal() = TALKING
|
||||||
|
},
|
||||||
|
|
||||||
|
TALKING {
|
||||||
|
override fun signal() = WAITING
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract fun signal(): ProtocolState
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
|
||||||
|
PLUS {
|
||||||
|
override fun apply(t: Int, u: Int): Int = t + u
|
||||||
|
},
|
||||||
|
TIMES {
|
||||||
|
override fun apply(t: Int, u: Int): Int = t * u
|
||||||
|
};
|
||||||
|
|
||||||
|
override fun applyAsInt(t: Int, u: Int) = apply(t, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
val enumConst: Direction? = Direction.EAST
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
abstract class C<T>(var constructorParam: List<CharSequence>) {
|
||||||
|
fun foo<V, U : V>(p1: V, p2: C<V>, p4: Sequence<V>): T {}
|
||||||
|
|
||||||
|
inline fun <reified T : Enum<T>> printAllValues() {
|
||||||
|
print(enumValues<T>().joinToString { it.name })
|
||||||
|
}
|
||||||
|
|
||||||
|
val <Q : T> Q.w: Q get() = null!!
|
||||||
|
|
||||||
|
var sListProp: List<String>?
|
||||||
|
var sSetProp: Set<String>?
|
||||||
|
var sMutableSetProp: MutableSet<String>?
|
||||||
|
var sHashSetProp: HashSet<String>?
|
||||||
|
var csListProp: List<CharSequence>?
|
||||||
|
|
||||||
|
abstract fun listCS(l: List<CharSequence>): List<CharSequence>
|
||||||
|
abstract fun listS(l: List<String>): List<String>
|
||||||
|
abstract fun mutables(cin: MutableCollection<in Number>, sOut: MutableList<out C<*>>): MutableSet<CharSequence>
|
||||||
|
abstract fun nested(l: List<List<CharSequence>>): Collection<Collection<CharSequence>>
|
||||||
|
|
||||||
|
fun <T : Any?> max(p0 : Collection<T>?): T? where T : Comparable<T>? {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open class K<out T: K<T>> { }
|
||||||
|
class Sub: K<K<*>>()
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
class MyList : List<String> {
|
||||||
|
override operator fun get(index: Int): String {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
interface ASet<T> : MutableCollection<T> {}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
abstract class MySet<T> : ASet<T> {
|
||||||
|
override fun remove(elem: String): Boolean {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
abstract class SmartSet<T> private constructor() : AbstractSet<T>() {
|
||||||
|
override fun iterator(): MutableIterator<T> = unresolved
|
||||||
|
|
||||||
|
override fun add(element: T): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contains(element: T): Boolean = true
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import kotlin.jvm.JvmStatic as JS
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
object O {
|
||||||
|
@JS fun foo() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/** should load cls */
|
||||||
|
class Prop {
|
||||||
|
private val someProp = object { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
class Fun {
|
||||||
|
private fun someFun() = object { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
class Array {
|
||||||
|
val a1 = arrayOf(
|
||||||
|
object { val fy = "text"}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
private class C(val y: Int) {
|
||||||
|
val initChild = { ->
|
||||||
|
object {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "child" + y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Super {
|
||||||
|
val a: Any?
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
class Sub {
|
||||||
|
override val a = arrayOf(
|
||||||
|
object { val fy = "text"}
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
interface Intf {
|
||||||
|
fun v(): Int
|
||||||
|
}
|
||||||
|
interface IntfWithProp : Intf {
|
||||||
|
val x: Int
|
||||||
|
}
|
||||||
|
abstract class Base(p: Int) {
|
||||||
|
open protected fun v(): Int? { }
|
||||||
|
fun nv() { }
|
||||||
|
abstract fun abs(): Int
|
||||||
|
|
||||||
|
internal open val x: Int get() { }
|
||||||
|
open var y = 1
|
||||||
|
open protected var z = 1
|
||||||
|
}
|
||||||
|
class Derived(p: Int) : Base(p), IntfWithProp {
|
||||||
|
override fun v() = unknown()
|
||||||
|
override val x = 3
|
||||||
|
override fun abs() = 0
|
||||||
|
}
|
||||||
|
abstract class AnotherDerived(override val x: Int, override val y: Int, override val z: Int) : Base(2) {
|
||||||
|
final override fun v() { }
|
||||||
|
abstract fun noReturn(s: String)
|
||||||
|
abstract val abstractProp: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Private {
|
||||||
|
override val overridesNothing: Boolean
|
||||||
|
get() = false
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/** should load cls */
|
||||||
|
inline class UInt(private val value: Int) { }
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
inline enum class Foo(val x: Int) {
|
||||||
|
A(0), B(1);
|
||||||
|
|
||||||
|
fun example() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
inline class InlinedDelegate<T>(var node: T) {
|
||||||
|
operator fun setValue(thisRef: A, property: KProperty<*>, value: T) {
|
||||||
|
if (node !== value) {
|
||||||
|
thisRef.notify(node, value)
|
||||||
|
}
|
||||||
|
node = value
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun getValue(thisRef: A, property: KProperty<*>): T {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/** should load cls */
|
||||||
|
class C {
|
||||||
|
var rwProp: Int
|
||||||
|
@JvmName("get_rwProp")
|
||||||
|
get() = 0
|
||||||
|
@JvmName("set_rwProp")
|
||||||
|
set(v) {}
|
||||||
|
|
||||||
|
fun getRwProp(): Int = 123
|
||||||
|
fun setRwProp(v: Int) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/** should load cls */
|
||||||
|
class C @JvmOverloads constructor(
|
||||||
|
val type: String?,
|
||||||
|
val p1: Boolean = false,
|
||||||
|
val p2: String = type
|
||||||
|
)
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
class C {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic fun foo() {}
|
||||||
|
fun bar() {}
|
||||||
|
@JvmStatic var x: String = ""
|
||||||
|
|
||||||
|
var I.c: String
|
||||||
|
@JvmStatic get() = "OK"
|
||||||
|
@JvmStatic set(t: String) {}
|
||||||
|
|
||||||
|
var c1: String
|
||||||
|
get() = "OK"
|
||||||
|
@JvmStatic set(t: String) {}
|
||||||
|
}
|
||||||
|
companion object Factory {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C1 {
|
||||||
|
private companion object {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
companion object { }
|
||||||
|
}
|
||||||
|
|
||||||
|
object Obj : java.lang.Runnable {
|
||||||
|
@JvmStatic var x: String = ""
|
||||||
|
override fun run() {}
|
||||||
|
@JvmStatic fun zoo(): Int = 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class Foo(a: Int, val b:Foo, var c:Boolean, private val d: List, protected val e: Long = 2) {
|
||||||
|
val f1 = 2
|
||||||
|
|
||||||
|
val intConst: dynamic = 30
|
||||||
|
val arrayConst: Any = byteArrayOf(1,2)
|
||||||
|
|
||||||
|
protected var f2 = 3
|
||||||
|
|
||||||
|
var name: String = "x"
|
||||||
|
|
||||||
|
val isEmpty get() = false
|
||||||
|
var isEmptyMutable: Boolean?
|
||||||
|
var islowercase: Boolean?
|
||||||
|
var isEmptyInt: Int?
|
||||||
|
var getInt: Int?
|
||||||
|
private var noAccessors: String
|
||||||
|
|
||||||
|
internal var stringRepresentation: String
|
||||||
|
get() = this.toString()
|
||||||
|
set(value) {
|
||||||
|
setDataFromString(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
|
||||||
|
|
||||||
|
var counter = 0
|
||||||
|
set(value) {
|
||||||
|
if (value >= 0) field = value
|
||||||
|
}
|
||||||
|
var counter2 : Int?
|
||||||
|
get() = field
|
||||||
|
set(value) {
|
||||||
|
if (value >= 0) field = value
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var subject: Unresolved
|
||||||
|
internal lateinit var internalVarPrivateSet: String
|
||||||
|
private set
|
||||||
|
protected lateinit var protectedLateinitVar: String
|
||||||
|
|
||||||
|
var delegatedProp: String by Delegate()
|
||||||
|
var delegatedProp2 by MyProperty()
|
||||||
|
private var privateDelegated: Int by Delegate()
|
||||||
|
var lazyProp: String by lazy { "abc" }
|
||||||
|
|
||||||
|
val Int.intProp: Int
|
||||||
|
get() = 1
|
||||||
|
|
||||||
|
final internal var internalWithPrivateSet: Int = 1
|
||||||
|
private set
|
||||||
|
|
||||||
|
protected var protectedWithPrivateSet: String = ""
|
||||||
|
private set
|
||||||
|
|
||||||
|
private var privateVarWithPrivateSet = { 0 }()
|
||||||
|
private set
|
||||||
|
|
||||||
|
private val privateValWithGet: String?
|
||||||
|
get() = ""
|
||||||
|
|
||||||
|
private var privateVarWithGet: Object = Object()
|
||||||
|
get
|
||||||
|
|
||||||
|
val sum: (Int)->Int = { x: Int -> sum(x - 1) + x }
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
public val prop3: Int = { 12 }()
|
||||||
|
get() {
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
public var prop7 : Int = { 20 }()
|
||||||
|
set(i: Int) {
|
||||||
|
field++
|
||||||
|
}
|
||||||
|
private const val contextBean = Context.BEAN
|
||||||
|
|
||||||
|
val f1 = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyProperty<T> {
|
||||||
|
operator fun getValue(t: T, p: KProperty<*>): Int = 42
|
||||||
|
operator fun setValue(t: T, p: KProperty<*>, i: Int) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Modifiers {
|
||||||
|
@delegate:Transient
|
||||||
|
val plainField: Int = 1
|
||||||
|
|
||||||
|
@delegate:Transient
|
||||||
|
val lazy by lazy { 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
public var int1: Int
|
||||||
|
private set
|
||||||
|
protected get
|
||||||
|
public var int2: Int
|
||||||
|
public get
|
||||||
|
internal set
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class Foo {
|
||||||
|
open fun bar(a: Int, b:Any, c:Foo): Unit {}
|
||||||
|
internal fun bar2(a: Sequence, b: Unresolved) {}
|
||||||
|
private fun bar3(x: Foo.Inner, vararg y: Inner) = "str"
|
||||||
|
fun bar4() = 42
|
||||||
|
|
||||||
|
public fun nullableVararg(vararg o: Any?): Unit
|
||||||
|
|
||||||
|
operator fun plus(increment: Int): Foo {}
|
||||||
|
fun String.onString(a: (Int) -> Any?): Foo {}
|
||||||
|
|
||||||
|
class Inner {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
class MyException : Exception
|
||||||
|
class C @Throws(Exception::class) constructor(a: Int = 1) {
|
||||||
|
@Throws(java.io.IOException::class, MyException::class)
|
||||||
|
fun readFile(name: String): String {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
typealias JO = JvmOverloads
|
||||||
|
|
||||||
|
/** should load cls */
|
||||||
|
object O {
|
||||||
|
@JO fun foo(a: Int = 1, b: String = "") {}
|
||||||
|
}
|
||||||
@@ -32,6 +32,8 @@ import org.jetbrains.kotlin.android.quickfix.AbstractAndroidQuickFixMultiFileTes
|
|||||||
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBoxTest
|
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBoxTest
|
||||||
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBytecodeShapeTest
|
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidBytecodeShapeTest
|
||||||
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidSyntheticPropertyDescriptorTest
|
import org.jetbrains.kotlin.android.synthetic.test.AbstractAndroidSyntheticPropertyDescriptorTest
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.AbstractUltraLightClassLoadingTest
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.AbstractUltraLightClassSanityTest
|
||||||
import org.jetbrains.kotlin.checkers.AbstractJavaAgainstKotlinBinariesCheckerTest
|
import org.jetbrains.kotlin.checkers.AbstractJavaAgainstKotlinBinariesCheckerTest
|
||||||
import org.jetbrains.kotlin.checkers.AbstractJavaAgainstKotlinSourceCheckerTest
|
import org.jetbrains.kotlin.checkers.AbstractJavaAgainstKotlinSourceCheckerTest
|
||||||
import org.jetbrains.kotlin.checkers.AbstractJsCheckerTest
|
import org.jetbrains.kotlin.checkers.AbstractJsCheckerTest
|
||||||
@@ -825,6 +827,13 @@ fun main(args: Array<String>) {
|
|||||||
model("asJava/lightClasses", excludeDirs = listOf("delegation"), pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME)
|
model("asJava/lightClasses", excludeDirs = listOf("delegation"), pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractUltraLightClassSanityTest> {
|
||||||
|
model("asJava/lightClasses", pattern = KT_OR_KTS)
|
||||||
|
}
|
||||||
|
testClass<AbstractUltraLightClassLoadingTest> {
|
||||||
|
model("asJava/ultraLightClasses", pattern = KT_OR_KTS)
|
||||||
|
}
|
||||||
|
|
||||||
testClass<AbstractIdeCompiledLightClassTest> {
|
testClass<AbstractIdeCompiledLightClassTest> {
|
||||||
model("asJava/lightClasses", excludeDirs = listOf("local", "compilationErrors", "ideRegression"), pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME)
|
model("asJava/lightClasses", excludeDirs = listOf("local", "compilationErrors", "ideRegression"), pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME)
|
||||||
}
|
}
|
||||||
|
|||||||
+149
-1
@@ -16,23 +16,171 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.caches.resolve
|
package org.jetbrains.kotlin.idea.caches.resolve
|
||||||
|
|
||||||
|
import com.intellij.openapi.diagnostic.debug
|
||||||
|
import com.intellij.openapi.module.ModuleUtilCore
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import com.intellij.psi.util.CachedValueProvider
|
||||||
|
import com.intellij.psi.util.CachedValuesManager
|
||||||
|
import com.intellij.psi.util.PsiModificationTracker
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import com.intellij.util.containers.ConcurrentFactoryMap
|
||||||
import org.jetbrains.kotlin.asJava.LightClassBuilder
|
import org.jetbrains.kotlin.asJava.LightClassBuilder
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
|
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.UltraLightSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
|
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
|
||||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.lightClasses.IDELightClassContexts
|
import org.jetbrains.kotlin.idea.caches.lightClasses.IDELightClassContexts
|
||||||
import org.jetbrains.kotlin.idea.caches.lightClasses.LazyLightClassDataHolder
|
import org.jetbrains.kotlin.idea.caches.lightClasses.LazyLightClassDataHolder
|
||||||
|
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||||
|
import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasShortNameIndex
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
|
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
|
||||||
|
import java.util.concurrent.ConcurrentMap
|
||||||
|
|
||||||
|
class IDELightClassGenerationSupport(private val project: Project) : LightClassGenerationSupport() {
|
||||||
|
override fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? {
|
||||||
|
if (element.shouldNotBeVisibleAsLightClass() ||
|
||||||
|
element is KtObjectDeclaration && element.isObjectLiteral() ||
|
||||||
|
element.isLocal ||
|
||||||
|
element is KtEnumEntry
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return null
|
||||||
|
return KtUltraLightClass(element, object : UltraLightSupport {
|
||||||
|
override fun isTooComplexForUltraLightGeneration(element: KtClassOrObject): Boolean {
|
||||||
|
val facet = KotlinFacet.get(module)
|
||||||
|
val pluginClasspath = facet?.configuration?.settings?.compilerArguments?.pluginClasspaths
|
||||||
|
if (!pluginClasspath.isNullOrEmpty()) {
|
||||||
|
LOG.debug { "Using heavy light classes for ${element.fqName?.asString()} because of compiler plugins $pluginClasspath" }
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
val problem = findTooComplexDeclaration(element)
|
||||||
|
if (problem != null) {
|
||||||
|
LOG.debug {
|
||||||
|
"Using heavy light classes for ${element.fqName?.asString()} because of ${StringUtil.trimLog(problem.text, 100)}"
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override val moduleName: String = module.name
|
||||||
|
|
||||||
|
override fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>? {
|
||||||
|
val candidates = owner.annotationEntries.filter { it.shortName == fqName.shortName() || hasAlias(owner, fqName.shortName()) }
|
||||||
|
for (entry in candidates) {
|
||||||
|
val descriptor = analyze(entry).get(BindingContext.ANNOTATION, entry)
|
||||||
|
if (descriptor?.fqName == fqName) {
|
||||||
|
return Pair(entry, descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findTooComplexDeclaration(declaration: KtDeclaration): PsiElement? {
|
||||||
|
fun KtAnnotationEntry.seemsNonTrivial(): Boolean {
|
||||||
|
val name = shortName
|
||||||
|
return name == null || hasAlias(declaration, name) || name.asString().startsWith("Jvm") && name.asString() != "JvmStatic"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration.hasExpectModifier() ||
|
||||||
|
declaration.hasModifier(KtTokens.ANNOTATION_KEYWORD) ||
|
||||||
|
declaration.hasModifier(KtTokens.INLINE_KEYWORD) && declaration is KtClassOrObject ||
|
||||||
|
declaration.hasModifier(KtTokens.DATA_KEYWORD) ||
|
||||||
|
declaration.hasModifier(KtTokens.ENUM_KEYWORD) ||
|
||||||
|
declaration.hasModifier(KtTokens.SUSPEND_KEYWORD)) {
|
||||||
|
return declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
declaration.annotationEntries.find(KtAnnotationEntry::seemsNonTrivial)?.let { return it }
|
||||||
|
|
||||||
|
if (declaration is KtClassOrObject) {
|
||||||
|
declaration.superTypeListEntries.find { it is KtDelegatedSuperTypeEntry }?.let { return it }
|
||||||
|
|
||||||
|
declaration.primaryConstructor?.let { findTooComplexDeclaration(it) }?.let { return it }
|
||||||
|
|
||||||
|
for (d in declaration.declarations) {
|
||||||
|
if (d is KtClassOrObject && !(d is KtObjectDeclaration && d.isCompanion())) continue
|
||||||
|
|
||||||
|
findTooComplexDeclaration(d)?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (implementsKotlinCollection(declaration)) {
|
||||||
|
return declaration.getSuperTypeList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (declaration is KtCallableDeclaration) {
|
||||||
|
declaration.valueParameters.mapNotNull { findTooComplexDeclaration(it) }.firstOrNull()?.let { return it }
|
||||||
|
if (declaration.typeReference == null && (declaration as? KtFunction)?.hasBlockBody() != true) {
|
||||||
|
findPotentiallyReturnedAnonymousObject(declaration)?.let { return it }
|
||||||
|
}
|
||||||
|
if (declaration.typeReference?.hasModifier(KtTokens.SUSPEND_KEYWORD) == true) {
|
||||||
|
return declaration.typeReference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (declaration is KtProperty) {
|
||||||
|
declaration.accessors.mapNotNull { findTooComplexDeclaration(it) }.firstOrNull()?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findPotentiallyReturnedAnonymousObject(declaration: KtDeclaration): KtObjectDeclaration? {
|
||||||
|
val spine = declaration.containingKtFile.stubbedSpine
|
||||||
|
for (i in 0 until spine.stubCount) {
|
||||||
|
if (spine.getStubType(i) == KtStubElementTypes.OBJECT_DECLARATION) {
|
||||||
|
val obj = spine.getStubPsi(i) as KtObjectDeclaration
|
||||||
|
if (obj.isObjectLiteral() && PsiTreeUtil.isContextAncestor(declaration, obj, true)) {
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun implementsKotlinCollection(classOrObject: KtClassOrObject): Boolean {
|
||||||
|
if (classOrObject.superTypeListEntries.isEmpty()) return false
|
||||||
|
|
||||||
|
return (resolveToDescriptor(classOrObject) as? ClassifierDescriptor)?.getAllSuperClassifiers()?.any {
|
||||||
|
it.fqNameSafe.asString().startsWith("kotlin.collections.")
|
||||||
|
} == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasAlias(element: KtElement, shortName: Name): Boolean = allAliases(element.containingKtFile)[shortName.asString()] == true
|
||||||
|
|
||||||
|
private fun allAliases(file: KtFile): ConcurrentMap<String, Boolean> = CachedValuesManager.getCachedValue(file) {
|
||||||
|
val importAliases = file.importDirectives.mapNotNull { it.aliasName }.toSet()
|
||||||
|
val map = ConcurrentFactoryMap.createMap<String, Boolean> { s ->
|
||||||
|
s in importAliases || KotlinTypeAliasShortNameIndex.getInstance().get(s, project, file.resolveScope).isNotEmpty()
|
||||||
|
}
|
||||||
|
CachedValueProvider.Result.create<ConcurrentMap<String, Boolean>>(map, PsiModificationTracker.MODIFICATION_COUNT)
|
||||||
|
}
|
||||||
|
|
||||||
class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSupport() {
|
|
||||||
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
|
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
|
||||||
|
|
||||||
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
|
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.idea.perf
|
||||||
|
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.junit.Assert
|
||||||
|
|
||||||
|
@TestOnly
|
||||||
|
object UltraLightChecker {
|
||||||
|
fun checkClassEquivalence(file: KtFile) {
|
||||||
|
for (ktClass in allClasses(file)) {
|
||||||
|
checkClassEquivalence(ktClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun allClasses(file: KtFile): List<KtClassOrObject> =
|
||||||
|
SyntaxTraverser.psiTraverser(file).filter(KtClassOrObject::class.java).toList()
|
||||||
|
|
||||||
|
fun checkClassEquivalence(ktClass: KtClassOrObject): KtUltraLightClass? {
|
||||||
|
val gold = KtLightClassForSourceDeclaration.create(ktClass)
|
||||||
|
val ultraLightClass = LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass) ?: return null
|
||||||
|
|
||||||
|
if (gold != null) {
|
||||||
|
Assert.assertFalse(gold.javaClass.name.contains("Ultra"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val goldText = gold?.renderClass().orEmpty()
|
||||||
|
val ultraText = ultraLightClass.renderClass()
|
||||||
|
|
||||||
|
if (goldText != ultraText) {
|
||||||
|
Assert.assertEquals(
|
||||||
|
"// Classic implementation:\n$goldText",
|
||||||
|
"// Ultra-light implementation:\n$ultraText"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return ultraLightClass
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiAnnotation.renderAnnotation() =
|
||||||
|
"@" + qualifiedName + "(" + parameterList.attributes.joinToString { it.name + "=" + (it.value?.text ?: "?") } + ")"
|
||||||
|
|
||||||
|
private fun PsiModifierListOwner.renderModifiers(): String {
|
||||||
|
val buffer = StringBuilder()
|
||||||
|
for (annotation in annotations) {
|
||||||
|
buffer.append(annotation.renderAnnotation())
|
||||||
|
buffer.append(if (this is PsiParameter) " " else "\n")
|
||||||
|
}
|
||||||
|
for (modifier in PsiModifier.MODIFIERS.filter(::hasModifierProperty)) {
|
||||||
|
buffer.append(modifier).append(" ")
|
||||||
|
}
|
||||||
|
return buffer.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiType.renderType() = getCanonicalText(true)
|
||||||
|
|
||||||
|
private fun PsiReferenceList?.renderRefList(keyword: String): String {
|
||||||
|
if (this == null || this.referencedTypes.isEmpty()) return ""
|
||||||
|
return " " + keyword + " " + referencedTypes.joinToString { it.renderType() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiVariable.renderVar(): String {
|
||||||
|
var result = this.renderModifiers() + type.renderType() + " " + name
|
||||||
|
if (this is PsiParameter && this.isVarArgs) {
|
||||||
|
result += " /* vararg */"
|
||||||
|
}
|
||||||
|
computeConstantValue()?.let { result += " /* constant value $it */" }
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiTypeParameterListOwner.renderTypeParams() =
|
||||||
|
if (typeParameters.isEmpty()) ""
|
||||||
|
else "<" + typeParameters.joinToString {
|
||||||
|
val bounds =
|
||||||
|
if (it.extendsListTypes.isNotEmpty())
|
||||||
|
" extends " + it.extendsListTypes.joinToString(" & ", transform = { it.renderType() })
|
||||||
|
else ""
|
||||||
|
it.name!! + bounds
|
||||||
|
} + "> "
|
||||||
|
|
||||||
|
private fun PsiMethod.renderMethod() =
|
||||||
|
renderModifiers() +
|
||||||
|
(if (isVarArgs) "/* vararg */ " else "") +
|
||||||
|
renderTypeParams() +
|
||||||
|
(returnType?.renderType() ?: "") + " " +
|
||||||
|
name +
|
||||||
|
"(" + parameterList.parameters.joinToString { it.renderModifiers() + it.type.renderType() } + ")" +
|
||||||
|
(this as? PsiAnnotationMethod)?.defaultValue?.let { " default " + it.text }.orEmpty() +
|
||||||
|
throwsList.referencedTypes.let { thrownTypes ->
|
||||||
|
if (thrownTypes.isEmpty()) ""
|
||||||
|
else " throws " + thrownTypes.joinToString { it.renderType() }
|
||||||
|
} +
|
||||||
|
";"
|
||||||
|
|
||||||
|
private fun PsiClass.renderClass(): String {
|
||||||
|
val classWord = when {
|
||||||
|
isAnnotationType -> "@interface"
|
||||||
|
isInterface -> "interface"
|
||||||
|
isEnum -> "enum"
|
||||||
|
else -> "class"
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderModifiers() +
|
||||||
|
classWord + " " +
|
||||||
|
name + " /* " + qualifiedName + "*/" +
|
||||||
|
renderTypeParams() +
|
||||||
|
extendsList.renderRefList("extends") +
|
||||||
|
implementsList.renderRefList("implements") +
|
||||||
|
" {\n" +
|
||||||
|
(if (isEnum) fields.filterIsInstance<PsiEnumConstant>().joinToString(",\n") { it.name } + ";\n\n" else "") +
|
||||||
|
fields.filterNot { it is PsiEnumConstant }.map { it.renderVar().prependIndent(" ") + ";\n\n" }.sorted().joinToString("") +
|
||||||
|
methods.map { it.renderMethod().prependIndent(" ") + "\n\n" }.sorted().joinToString("") +
|
||||||
|
innerClasses.map { "class ${it.name} ...\n\n".prependIndent(" ") }.sorted().joinToString("") +
|
||||||
|
"}"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.idea.perf
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.registry.Registry
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
|
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.system.measureNanoTime
|
||||||
|
|
||||||
|
class WholeProjectLightClassTest : WholeProjectPerformanceTest(), WholeProjectKotlinFileProvider {
|
||||||
|
|
||||||
|
override fun doTest(file: VirtualFile): PerFileTestResult {
|
||||||
|
val results = mutableMapOf<String, Long>()
|
||||||
|
var totalNs = 0L
|
||||||
|
|
||||||
|
val psiFile = file.toPsiFile(project) ?: run {
|
||||||
|
return WholeProjectPerformanceTest.PerFileTestResult(results, totalNs, listOf(AssertionError("PsiFile not found for $file")))
|
||||||
|
}
|
||||||
|
|
||||||
|
val errors = mutableListOf<Throwable>()
|
||||||
|
|
||||||
|
fun buildAllLightClasses(name: String, predicate: (KtClassOrObject) -> Boolean) {
|
||||||
|
val result = measureNanoTime {
|
||||||
|
try {
|
||||||
|
// Build light class by PsiFile
|
||||||
|
psiFile.acceptRecursively(object : KtVisitorVoid() {
|
||||||
|
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||||
|
if (!predicate(classOrObject)) return
|
||||||
|
val lightClass = classOrObject.toLightClass() as? KtLightClassForSourceDeclaration ?: return
|
||||||
|
Arrays.hashCode(lightClass.superTypes)
|
||||||
|
Arrays.hashCode(lightClass.fields)
|
||||||
|
Arrays.hashCode(lightClass.methods)
|
||||||
|
// Just to be sure: access types
|
||||||
|
lightClass.fields.map { it.type }.hashCode()
|
||||||
|
lightClass.methods.map { it.returnType }.hashCode()
|
||||||
|
lightClass.hashCode()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
t.printStackTrace()
|
||||||
|
errors += t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results[name] = result
|
||||||
|
totalNs += result
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAllLightClasses("LightClasses_Top") {
|
||||||
|
it.containingDeclarationForPseudocode == null
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAllLightClasses("LightClasses_Members") {
|
||||||
|
!it.isLocal && it.containingDeclarationForPseudocode is KtClassOrObject
|
||||||
|
}
|
||||||
|
|
||||||
|
return PerFileTestResult(results, totalNs, errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testUltraLightPerformance() {
|
||||||
|
Registry.get("kotlin.use.ultra.light.classes").setValue(true, testRootDisposable)
|
||||||
|
testWholeProjectPerformance()
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.idea.perf
|
||||||
|
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import kotlin.system.measureNanoTime
|
||||||
|
|
||||||
|
// abstract so that it doesn't run in CI until known issues (JDK absence in the test project, different module names in mangled methods) are addressed
|
||||||
|
abstract class WholeProjectUltraLightClassTest : WholeProjectPerformanceTest(), WholeProjectKotlinFileProvider {
|
||||||
|
|
||||||
|
override fun doTest(file: VirtualFile): PerFileTestResult {
|
||||||
|
val psiFile = file.toPsiFile(project) as? KtFile ?: run {
|
||||||
|
return WholeProjectPerformanceTest.PerFileTestResult(mapOf(), 0, listOf(AssertionError("PsiFile not found for $file")))
|
||||||
|
}
|
||||||
|
|
||||||
|
val errors = mutableListOf<Throwable>()
|
||||||
|
val elapsed = measureNanoTime {
|
||||||
|
try {
|
||||||
|
UltraLightChecker.checkClassEquivalence(psiFile)
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
t.printStackTrace()
|
||||||
|
errors += t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PerFileTestResult(mapOf("ultraLightEquivalence" to elapsed), elapsed, errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -170,5 +170,10 @@
|
|||||||
|
|
||||||
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
|
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
|
||||||
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
|
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
|
||||||
|
|
||||||
|
<registryKey key="kotlin.use.ultra.light.classes"
|
||||||
|
description="Whether to use an experimental implementation of Kotlin-as-Java classes"
|
||||||
|
defaultValue="false"
|
||||||
|
restartRequired="false"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.asJava.classes
|
||||||
|
|
||||||
|
import com.intellij.testFramework.LightProjectDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.perf.UltraLightChecker
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class AbstractUltraLightClassLoadingTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
|
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||||
|
|
||||||
|
fun doTest(testDataPath: String) {
|
||||||
|
val file = myFixture.addFileToProject(testDataPath, File(testDataPath).readText()) as KtFile
|
||||||
|
for (ktClass in UltraLightChecker.allClasses(file)) {
|
||||||
|
val clsLoadingExpected = ktClass.docComment?.text?.contains("should load cls") == true
|
||||||
|
val ultraLightClass = UltraLightChecker.checkClassEquivalence(ktClass)
|
||||||
|
if (ultraLightClass != null) {
|
||||||
|
assertEquals(
|
||||||
|
"Cls-loaded status differs from expected for ${ultraLightClass.qualifiedName}",
|
||||||
|
clsLoadingExpected,
|
||||||
|
ultraLightClass.isClsDelegateLoaded
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.asJava.classes
|
||||||
|
|
||||||
|
import com.intellij.testFramework.LightProjectDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.perf.UltraLightChecker
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class AbstractUltraLightClassSanityTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
|
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||||
|
|
||||||
|
fun doTest(testDataPath: String) {
|
||||||
|
val ioFile = File(testDataPath)
|
||||||
|
if (ioFile.name == "AllOpenAnnotatedClasses.kt") {
|
||||||
|
return //tests allopen compiler plugin that we don't have in this test
|
||||||
|
}
|
||||||
|
|
||||||
|
val file = myFixture.addFileToProject(testDataPath, ioFile.readText()) as KtFile
|
||||||
|
UltraLightChecker.checkClassEquivalence(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.asJava.classes;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("compiler/testData/asJava/ultraLightClasses")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public class UltraLightClassLoadingTestGenerated extends AbstractUltraLightClassLoadingTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInUltraLightClasses() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/ultraLightClasses"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotations.kt")
|
||||||
|
public void testAnnotations() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/annotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classModifiers.kt")
|
||||||
|
public void testClassModifiers() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/classModifiers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("constructors.kt")
|
||||||
|
public void testConstructors() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/constructors.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("coroutines.kt")
|
||||||
|
public void testCoroutines() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/coroutines.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("dataClasses.kt")
|
||||||
|
public void testDataClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/dataClasses.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("delegatingToInterfaces.kt")
|
||||||
|
public void testDelegatingToInterfaces() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/delegatingToInterfaces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("enums.kt")
|
||||||
|
public void testEnums() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/enums.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("generics.kt")
|
||||||
|
public void testGenerics() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/generics.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("implementingKotlinCollections.kt")
|
||||||
|
public void testImplementingKotlinCollections() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/implementingKotlinCollections.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("importAliases.kt")
|
||||||
|
public void testImportAliases() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/importAliases.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inferringAnonymousObjectTypes.kt")
|
||||||
|
public void testInferringAnonymousObjectTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/inferringAnonymousObjectTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritance.kt")
|
||||||
|
public void testInheritance() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/inheritance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineClasses.kt")
|
||||||
|
public void testInlineClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/inlineClasses.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmName.kt")
|
||||||
|
public void testJvmName() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/jvmName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jvmOverloads.kt")
|
||||||
|
public void testJvmOverloads() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/jvmOverloads.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objects.kt")
|
||||||
|
public void testObjects() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/objects.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("properties.kt")
|
||||||
|
public void testProperties() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/properties.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleFunctions.kt")
|
||||||
|
public void testSimpleFunctions() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/simpleFunctions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("throwsAnnotation.kt")
|
||||||
|
public void testThrowsAnnotation() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/throwsAnnotation.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeAliases.kt")
|
||||||
|
public void testTypeAliases() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/ultraLightClasses/typeAliases.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+548
@@ -0,0 +1,548 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.kotlin.asJava.classes;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public class UltraLightClassSanityTestGenerated extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInLightClasses() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AnnotationClass.kt")
|
||||||
|
public void testAnnotationClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/AnnotationClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DataClassWithCustomImplementedMembers.kt")
|
||||||
|
public void testDataClassWithCustomImplementedMembers() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/DataClassWithCustomImplementedMembers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DelegatedNested.kt")
|
||||||
|
public void testDelegatedNested() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/DelegatedNested.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Delegation.kt")
|
||||||
|
public void testDelegation() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/Delegation.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DeprecatedEnumEntry.kt")
|
||||||
|
public void testDeprecatedEnumEntry() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DeprecatedNotHiddenInClass.kt")
|
||||||
|
public void testDeprecatedNotHiddenInClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/DeprecatedNotHiddenInClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DollarsInName.kt")
|
||||||
|
public void testDollarsInName() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/DollarsInName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DollarsInNameNoPackage.kt")
|
||||||
|
public void testDollarsInNameNoPackage() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/DollarsInNameNoPackage.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ExtendingInterfaceWithDefaultImpls.kt")
|
||||||
|
public void testExtendingInterfaceWithDefaultImpls() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ExtendingInterfaceWithDefaultImpls.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("HiddenDeprecated.kt")
|
||||||
|
public void testHiddenDeprecated() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/HiddenDeprecated.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("HiddenDeprecatedInClass.kt")
|
||||||
|
public void testHiddenDeprecatedInClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/HiddenDeprecatedInClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritingInterfaceDefaultImpls.kt")
|
||||||
|
public void testInheritingInterfaceDefaultImpls() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/InheritingInterfaceDefaultImpls.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JvmNameOnMember.kt")
|
||||||
|
public void testJvmNameOnMember() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/JvmNameOnMember.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JvmStatic.kt")
|
||||||
|
public void testJvmStatic() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/JvmStatic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NestedObjects.kt")
|
||||||
|
public void testNestedObjects() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/NestedObjects.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NonDataClassWithComponentFunctions.kt")
|
||||||
|
public void testNonDataClassWithComponentFunctions() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/NonDataClassWithComponentFunctions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PublishedApi.kt")
|
||||||
|
public void testPublishedApi() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/PublishedApi.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SpecialAnnotationsOnAnnotationClass.kt")
|
||||||
|
public void testSpecialAnnotationsOnAnnotationClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("StubOrderForOverloads.kt")
|
||||||
|
public void testStubOrderForOverloads() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VarArgs.kt")
|
||||||
|
public void testVarArgs() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/VarArgs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/compilationErrors")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class CompilationErrors extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ActualClass.kt")
|
||||||
|
public void testActualClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ActualClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ActualTypeAlias.kt")
|
||||||
|
public void testActualTypeAlias() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ActualTypeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ActualTypeAliasCustomJvmPackageName.kt")
|
||||||
|
public void testActualTypeAliasCustomJvmPackageName() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ActualTypeAliasCustomJvmPackageName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInCompilationErrors() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/compilationErrors"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AllInlineOnly.kt")
|
||||||
|
public void testAllInlineOnly() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/AllInlineOnly.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AnnotationModifiers.kt")
|
||||||
|
public void testAnnotationModifiers() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/AnnotationModifiers.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ExpectClass.kt")
|
||||||
|
public void testExpectClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ExpectObject.kt")
|
||||||
|
public void testExpectObject() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ExpectedNestedClass.kt")
|
||||||
|
public void testExpectedNestedClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectedNestedClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ExpectedNestedClassInObject.kt")
|
||||||
|
public void testExpectedNestedClassInObject() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectedNestedClassInObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JvmPackageName.kt")
|
||||||
|
public void testJvmPackageName() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/JvmPackageName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("LocalInAnnotation.kt")
|
||||||
|
public void testLocalInAnnotation() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/LocalInAnnotation.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PrivateInTrait.kt")
|
||||||
|
public void testPrivateInTrait() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/PrivateInTrait.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("RepetableAnnotations.kt")
|
||||||
|
public void testRepetableAnnotations() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/RepetableAnnotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SameName.kt")
|
||||||
|
public void testSameName() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/SameName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("TopLevelDestructuring.kt")
|
||||||
|
public void testTopLevelDestructuring() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/TopLevelDestructuring.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("TraitClassObjectField.kt")
|
||||||
|
public void testTraitClassObjectField() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/TraitClassObjectField.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("WrongAnnotations.kt")
|
||||||
|
public void testWrongAnnotations() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/compilationErrors/WrongAnnotations.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/delegation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Delegation extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInDelegation() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/delegation"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Function.kt")
|
||||||
|
public void testFunction() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/delegation/Function.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Property.kt")
|
||||||
|
public void testProperty() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/delegation/Property.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("WithPlatformTypes.NoCompile.kt")
|
||||||
|
public void testWithPlatformTypes_NoCompile() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/delegation/WithPlatformTypes.NoCompile.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/facades")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Facades extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInFacades() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/facades"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AllPrivate.kt")
|
||||||
|
public void testAllPrivate() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/facades/AllPrivate.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EmptyFile.NoCompile.kt")
|
||||||
|
public void testEmptyFile_NoCompile() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/facades/EmptyFile.NoCompile.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MultiFile.kt")
|
||||||
|
public void testMultiFile() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/facades/MultiFile.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SingleFile.kt")
|
||||||
|
public void testSingleFile() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/facades/SingleFile.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SingleJvmClassName.kt")
|
||||||
|
public void testSingleJvmClassName() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/facades/SingleJvmClassName.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/ideRegression")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class IdeRegression extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInIdeRegression() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/ideRegression"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AllOpenAnnotatedClasses.kt")
|
||||||
|
public void testAllOpenAnnotatedClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/AllOpenAnnotatedClasses.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplementingCharSequenceAndNumber.kt")
|
||||||
|
public void testImplementingCharSequenceAndNumber() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplementingMap.kt")
|
||||||
|
public void testImplementingMap() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ImplementingMutableSet.kt")
|
||||||
|
public void testImplementingMutableSet() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMutableSet.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InheritingInterfaceDefaultImpls.kt")
|
||||||
|
public void testInheritingInterfaceDefaultImpls() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/InheritingInterfaceDefaultImpls.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverridingFinalInternal.kt")
|
||||||
|
public void testOverridingFinalInternal() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverridingFinalInternal.extra.kt")
|
||||||
|
public void testOverridingFinalInternal_extra() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.extra.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverridingInternal.kt")
|
||||||
|
public void testOverridingInternal() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverridingInternal.extra.kt")
|
||||||
|
public void testOverridingInternal_extra() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.extra.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverridingProtected.kt")
|
||||||
|
public void testOverridingProtected() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingProtected.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverridingProtected.extra.kt")
|
||||||
|
public void testOverridingProtected_extra() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingProtected.extra.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/local")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Local extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInLocal() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/local"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DollarsInNameLocal.kt")
|
||||||
|
public void testDollarsInNameLocal() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/local/DollarsInNameLocal.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/nullabilityAnnotations")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class NullabilityAnnotations extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInNullabilityAnnotations() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/nullabilityAnnotations"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Class.kt")
|
||||||
|
public void testClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassObjectField.kt")
|
||||||
|
public void testClassObjectField() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassWithConstructor.kt")
|
||||||
|
public void testClassWithConstructor() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassWithConstructorAndProperties.kt")
|
||||||
|
public void testClassWithConstructorAndProperties() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FileFacade.kt")
|
||||||
|
public void testFileFacade() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/FileFacade.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Generic.kt")
|
||||||
|
public void testGeneric() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Generic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("IntOverridesAny.kt")
|
||||||
|
public void testIntOverridesAny() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("JvmOverloads.kt")
|
||||||
|
public void testJvmOverloads() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/JvmOverloads.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NullableUnitReturn.kt")
|
||||||
|
public void testNullableUnitReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OverrideAnyWithUnit.kt")
|
||||||
|
public void testOverrideAnyWithUnit() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PlatformTypes.kt")
|
||||||
|
public void testPlatformTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/PlatformTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Primitives.kt")
|
||||||
|
public void testPrimitives() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PrivateInClass.kt")
|
||||||
|
public void testPrivateInClass() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/PrivateInClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Synthetic.kt")
|
||||||
|
public void testSynthetic() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Trait.kt")
|
||||||
|
public void testTrait() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UnitAsGenericArgument.kt")
|
||||||
|
public void testUnitAsGenericArgument() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UnitParameter.kt")
|
||||||
|
public void testUnitParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VoidReturn.kt")
|
||||||
|
public void testVoidReturn() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/object")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Object extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInObject() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/object"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SimpleObject.kt")
|
||||||
|
public void testSimpleObject() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/object/SimpleObject.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/publicField")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class PublicField extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInPublicField() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/publicField"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("CompanionObject.kt")
|
||||||
|
public void testCompanionObject() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/publicField/CompanionObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/publicField/Simple.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/asJava/lightClasses/script")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Script extends AbstractUltraLightClassSanityTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInScript() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/script"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("HelloWorld.kts")
|
||||||
|
public void testHelloWorld() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/script/HelloWorld.kts");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InnerClasses.kts")
|
||||||
|
public void testInnerClasses() throws Exception {
|
||||||
|
runTest("compiler/testData/asJava/lightClasses/script/InnerClasses.kts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user