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(
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(
@@ -1112,34 +1112,37 @@ public class FunctionCodegen {
}
@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"));
if (annotation == null) {
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();
if (values.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
if (values.isEmpty()) return Collections.emptyList();
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;
List<String> strings = CollectionsKt.mapNotNull(
return CollectionsKt.mapNotNull(
arrayValue.getValue(),
(ConstantValue<?> constant) -> {
if (constant instanceof KClassValue) {
ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(
return DescriptorUtils.getClassDescriptorForType(
((KClassValue) constant).getArgumentType(DescriptorUtilsKt.getModule(function))
);
return typeMapper.mapClass(classDescriptor).getInternalName();
}
return null;
}
);
return ArrayUtil.toStringArray(strings);
}
void generateDefaultIfNeeded(
@@ -398,8 +398,8 @@ public class PropertyCodegen {
modifiers |= ACC_SYNTHETIC;
}
KotlinType kotlinType =
isDelegate ? getDelegateTypeForProperty((KtProperty) element, propertyDescriptor) : propertyDescriptor.getType();
KotlinType kotlinType = isDelegate ? getDelegateTypeForProperty((KtProperty) element, propertyDescriptor, bindingContext)
: propertyDescriptor.getType();
Type type = typeMapper.mapType(kotlinType);
ClassBuilder builder = v;
@@ -438,7 +438,11 @@ public class PropertyCodegen {
}
@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;
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
* 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;
//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
*/
class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() {
override fun createUltraLightClass(element: KtClassOrObject) = null
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
//force resolve companion for light class generation
traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
@@ -27,6 +27,9 @@ val STRICTFP_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Strictfp")
@JvmField
val VOLATILE_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Volatile")
@JvmField
val TRANSIENT_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Transient")
fun DeclarationDescriptor.findJvmOverloadsAnnotation(): AnnotationDescriptor? =
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.LightClassConstructionContext
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
@@ -40,6 +41,8 @@ abstract class LightClassGenerationSupport {
abstract fun analyzeWithContent(element: KtClassOrObject): BindingContext
abstract fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass?
companion object {
@JvmStatic
fun getInstance(project: Project): LightClassGenerationSupport {
@@ -209,7 +209,7 @@ object LightClassUtil {
fun buildLightTypeParameterList(
owner: PsiTypeParameterListOwner,
declaration: KtDeclaration): PsiTypeParameterList {
val builder = KotlinLightTypeParameterListBuilder(owner.manager)
val builder = KotlinLightTypeParameterListBuilder(owner)
if (declaration is KtTypeParameterListOwner) {
val parameters = declaration.typeParameters
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.util.Comparing
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.*
import com.intellij.psi.impl.PsiSubstitutorImpl
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.PsiUtilCore
import com.intellij.util.IncorrectOperationException
import com.intellij.util.SystemProperties
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult
@@ -73,15 +75,11 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
: KtLazyLightClass(classOrObject.manager), StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>> {
private val lightIdentifier = KtLightIdentifier(this, classOrObject)
private val _extendsList by lazyPub {
val listDelegate = super.getExtendsList() ?: return@lazyPub null
KtLightPsiReferenceList(listDelegate, this)
}
private val _extendsList by lazyPub { createExtendsList() }
private val _implementsList by lazyPub { createImplementsList() }
private val _implementsList by lazyPub {
val listDelegate = super.getImplementsList() ?: return@lazyPub null
KtLightPsiReferenceList(listDelegate, this)
}
protected open fun createExtendsList(): PsiReferenceList? = super.getExtendsList()?.let { KtLightPsiReferenceList(it, this) }
protected open fun createImplementsList(): PsiReferenceList? = super.getImplementsList()?.let { KtLightPsiReferenceList(it, this) }
override val kotlinOrigin: KtClassOrObject = classOrObject
@@ -92,7 +90,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
override val lightClassData: LightClassData
get() = findLightClassData()
open protected fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject)
protected open fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject)
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub
@@ -110,9 +108,9 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
private val _containingFile: PsiFile by lazyPub {
object : FakeFileForLightClass(
classOrObject.containingKtFile,
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! },
{ getJavaFileStub() }
classOrObject.containingKtFile,
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! },
{ getJavaFileStub() }
) {
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
@@ -173,9 +171,9 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
return super.getContainingClass()
}
private val _typeParameterList: PsiTypeParameterList by lazyPub {
LightClassUtil.buildLightTypeParameterList(this, classOrObject)
}
private val _typeParameterList: PsiTypeParameterList by lazyPub { buildTypeParameterList() }
open protected fun buildTypeParameterList() = LightClassUtil.buildLightTypeParameterList(this, classOrObject)
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
@@ -322,9 +320,8 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
override fun getNameIdentifier(): KtLightIdentifier? = lightIdentifier
override fun getExtendsList() = _extendsList
override fun getImplementsList() = _implementsList
override fun getExtendsList(): PsiReferenceList? = _extendsList
override fun getImplementsList(): PsiReferenceList? = _implementsList
companion object {
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
}
if (Registry.`is`("kotlin.use.ultra.light.classes", false)) {
LightClassGenerationSupport.getInstance(classOrObject.project).createUltraLightClass(classOrObject)?.let { return it }
}
return when {
classOrObject is KtObjectDeclaration && classOrObject.isObjectLiteral() ->
KtLightClassForAnonymousDeclaration(classOrObject)
@@ -456,17 +457,16 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
private val modifiers by lazyPub { containingClass.computeModifiers() }
override fun hasModifierProperty(name: String): Boolean {
if (name != PsiModifier.FINAL) {
return name in modifiers
}
override fun hasModifierProperty(name: String): Boolean =
if (name != PsiModifier.FINAL) name in modifiers else owner.isFinal(PsiModifier.FINAL 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
// 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 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
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.impl.light.LightTypeParameterListBuilder
import com.intellij.psi.scope.PsiScopeProcessor
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 {
return typeParameters.all { processor.execute(it, state) }
}
override fun getParent(): PsiElement = owner
override fun getContainingFile(): PsiFile = owner.containingFile
override fun getText(): String? = ""
}
@@ -19,7 +19,9 @@ package org.jetbrains.kotlin.asJava.elements
import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
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.builder.LightMemberOrigin
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.jvm.KotlinJavaPsiFacade
class KtLightMethodImpl private constructor(
open class KtLightMethodImpl protected constructor(
computeRealDelegate: () -> PsiMethod,
lightMemberOrigin: LightMemberOrigin?,
containingClass: KtLightClass,
@@ -55,25 +57,15 @@ class KtLightMethodImpl private constructor(
}
}
private val typeParamsList: CachedValue<PsiTypeParameterList> by lazyPub {
val cacheManager = CachedValuesManager.getManager(clsDelegate.project)
cacheManager.createCachedValue<PsiTypeParameterList>(
{
val origin = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement
val list = if (origin != null) {
if (origin is KtClassOrObject) {
KotlinLightTypeParameterListBuilder(manager)
}
else {
LightClassUtil.buildLightTypeParameterList(this@KtLightMethodImpl, origin)
}
}
else {
clsDelegate.typeParameterList
}
CachedValueProvider.Result.create(list, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
}, false
)
private val typeParamsList: PsiTypeParameterList? by lazyPub { buildTypeParameterList() }
protected open fun buildTypeParameterList(): PsiTypeParameterList? {
val origin = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement
return when {
origin is KtClassOrObject -> KotlinLightTypeParameterListBuilder(this)
origin != null -> LightClassUtil.buildLightTypeParameterList(this, origin)
else -> clsDelegate.typeParameterList
}
}
override fun accept(visitor: PsiElementVisitor) {
@@ -128,7 +120,7 @@ class KtLightMethodImpl private constructor(
override fun getParameterList() = paramsList
override fun getTypeParameterList() = typeParamsList.value
override fun getTypeParameterList() = typeParamsList
override fun getTypeParameters(): Array<PsiTypeParameter> =
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.builder.LightMemberOriginForDeclaration
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.descriptors.ClassDescriptor
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)
: KtLightElementBase(owner), PsiModifierList, KtLightElement<KtModifierList, PsiModifierList> {
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?
get() = owner.kotlinOrigin?.modifierList
@@ -61,9 +62,28 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
override fun isWritable() = false
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>
) : KtLightModifierList<KtLightElement<KtModifierListOwner, PsiModifierListOwner>>(owner) {
override fun hasModifierProperty(name: String) = name in modifiers
@@ -71,31 +91,14 @@ class KtLightSimpleModifierList(
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> {
val lightModifierListOwner = lightModifierList.parent
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)) {
return emptyList()
@@ -128,11 +131,11 @@ fun isFromSources(lightElement: KtLightElement<*, *>): Boolean {
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 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]
else
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.unsubstitutedPrimaryConstructor
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.isGetter -> descriptor.getter
annotatedLightElement.isSetter -> descriptor.setter
@@ -164,7 +168,7 @@ private fun getAnnotationDescriptors(declaration: KtDeclaration, annotatedLightE
return annotations
}
private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
private fun hasAnnotationsInSource(declaration: KtAnnotated): Boolean {
if (declaration.annotationEntries.isNotEmpty()) {
return true
}
@@ -175,3 +179,4 @@ private fun hasAnnotationsInSource(declaration: KtDeclaration): Boolean {
return false
}
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
class KtLightParameter(
override val clsDelegate: PsiParameter,
private val index: Int,
val method: KtLightMethod
method: KtLightMethod
) : LightParameter(clsDelegate.name ?: "p$index", clsDelegate.type, method, KotlinLanguage.INSTANCE),
KtLightDeclaration<KtParameter, PsiParameter> {
@@ -25,14 +25,14 @@ public class LightParameter extends LightVariableBuilder implements PsiParameter
public static final LightParameter[] EMPTY_ARRAY = new LightParameter[0];
private final String myName;
private final PsiElement myDeclarationScope;
private final KtLightMethod myDeclarationScope;
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);
}
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);
myName = name;
myDeclarationScope = declarationScope;
@@ -41,7 +41,11 @@ public class LightParameter extends LightVariableBuilder implements PsiParameter
@NotNull
@Override
public PsiElement getDeclarationScope() {
public KtLightMethod getDeclarationScope() {
return myDeclarationScope;
}
public KtLightMethod getMethod() {
return myDeclarationScope;
}
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.annotations.TestOnly
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.lazyPub
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]
private fun getTargetType(annotatedElement: PsiElement): KotlinType? {
if (member is KtUltraLightParameter) {
return member.getTypeForNullability()
}
if (annotatedElement is KtTypeReference) {
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.AbstractAndroidBytecodeShapeTest
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.AbstractJavaAgainstKotlinSourceCheckerTest
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)
}
testClass<AbstractUltraLightClassSanityTest> {
model("asJava/lightClasses", pattern = KT_OR_KTS)
}
testClass<AbstractUltraLightClassLoadingTest> {
model("asJava/ultraLightClasses", pattern = KT_OR_KTS)
}
testClass<AbstractIdeCompiledLightClassTest> {
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
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.module.ModuleUtilCore
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.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.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
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.finder.JavaElementFinder
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
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.LazyLightClassDataHolder
import org.jetbrains.kotlin.idea.facet.KotlinFacet
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.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.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))
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.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>
</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");
}
}
}