add ultra-light classes/members that work without backend in simple cases

This commit is contained in:
peter
2018-10-25 17:58:05 +02:00
parent 387efc3791
commit ebc998d710
48 changed files with 2502 additions and 98 deletions
@@ -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
@@ -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
@@ -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) {
@@ -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
)
@@ -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? = ""
} }
@@ -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
@@ -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") }
}
+43
View File
@@ -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
}
+27
View File
@@ -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
}
}
+11
View File
@@ -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
)
+31
View File
@@ -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
}
+104
View File
@@ -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)
} }
@@ -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("") +
"}"
}
}
@@ -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()
}
}
@@ -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)
}
}
+5
View File
@@ -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)
}
}
@@ -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");
}
}
@@ -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");
}
}
}