Support declarations returning object literals in ultra-light classes
This commit is contained in:
@@ -10,6 +10,7 @@ import com.intellij.psi.PsiElement;
|
||||
import kotlin.Pair;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment;
|
||||
@@ -89,6 +90,8 @@ public class KotlinTypeMapper {
|
||||
private final LanguageVersionSettings languageVersionSettings;
|
||||
private final boolean isReleaseCoroutines;
|
||||
private final boolean isIrBackend;
|
||||
@Nullable
|
||||
private final Function1<KotlinType, KotlinType> typePreprocessor;
|
||||
|
||||
private final TypeMappingConfiguration<Type> typeMappingConfiguration = new TypeMappingConfiguration<Type>() {
|
||||
@NotNull
|
||||
@@ -121,6 +124,13 @@ public class KotlinTypeMapper {
|
||||
public boolean releaseCoroutines() {
|
||||
return isReleaseCoroutines;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public KotlinType preprocessType(@NotNull KotlinType kotlinType) {
|
||||
if (typePreprocessor == null) return null;
|
||||
return typePreprocessor.invoke(kotlinType);
|
||||
}
|
||||
};
|
||||
|
||||
private static final TypeMappingConfiguration<Type> staticTypeMappingConfiguration = new TypeMappingConfiguration<Type>() {
|
||||
@@ -151,8 +161,35 @@ public class KotlinTypeMapper {
|
||||
public boolean releaseCoroutines() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public KotlinType preprocessType(@NotNull KotlinType kotlinType) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
public KotlinTypeMapper(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull ClassBuilderMode classBuilderMode,
|
||||
@NotNull IncompatibleClassTracker incompatibleClassTracker,
|
||||
@NotNull String moduleName,
|
||||
@NotNull JvmTarget jvmTarget,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
boolean isIrBackend,
|
||||
@Nullable Function1<KotlinType, KotlinType> typePreprocessor
|
||||
) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.classBuilderMode = classBuilderMode;
|
||||
this.incompatibleClassTracker = incompatibleClassTracker;
|
||||
this.moduleName = moduleName;
|
||||
this.jvmTarget = jvmTarget;
|
||||
this.languageVersionSettings = languageVersionSettings;
|
||||
this.isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines);
|
||||
this.isIrBackend = isIrBackend;
|
||||
this.typePreprocessor = typePreprocessor;
|
||||
}
|
||||
|
||||
public KotlinTypeMapper(
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull ClassBuilderMode classBuilderMode,
|
||||
@@ -162,14 +199,7 @@ public class KotlinTypeMapper {
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
boolean isIrBackend
|
||||
) {
|
||||
this.bindingContext = bindingContext;
|
||||
this.classBuilderMode = classBuilderMode;
|
||||
this.incompatibleClassTracker = incompatibleClassTracker;
|
||||
this.moduleName = moduleName;
|
||||
this.jvmTarget = jvmTarget;
|
||||
this.languageVersionSettings = languageVersionSettings;
|
||||
this.isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines);
|
||||
this.isIrBackend = isIrBackend;
|
||||
this(bindingContext, classBuilderMode, incompatibleClassTracker, moduleName, jvmTarget, languageVersionSettings, isIrBackend, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,13 +21,18 @@ 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.ClassDescriptor
|
||||
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.KtTypeParameterListOwner
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import java.text.StringCharacterIterator
|
||||
|
||||
internal fun buildTypeParameterList(
|
||||
@@ -105,5 +110,38 @@ internal fun typeMapper(support: UltraLightSupport): KotlinTypeMapper = KotlinTy
|
||||
IncompatibleClassTracker.DoNothing, support.moduleName,
|
||||
JvmTarget.JVM_1_8,
|
||||
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT, // TODO use proper LanguageVersionSettings
|
||||
false
|
||||
false,
|
||||
KotlinType::cleanFromAnonymousTypes
|
||||
)
|
||||
|
||||
// Returns null when type is unchanged
|
||||
fun KotlinType.cleanFromAnonymousTypes(): KotlinType? {
|
||||
val returnTypeClass = constructor.declarationDescriptor as? ClassDescriptor ?: return null
|
||||
if (DescriptorUtils.isAnonymousObject(returnTypeClass)) {
|
||||
// We choose just the first supertype because:
|
||||
// - In public declarations, object literals should always have a single supertype (otherwise it's an error)
|
||||
// - For private declarations, they might have more than one supertype
|
||||
// but it looks like it's not important how we choose a representative for them
|
||||
val representative = returnTypeClass.defaultType.supertypes().firstOrNull() ?: return null
|
||||
return representative.cleanFromAnonymousTypes() ?: representative
|
||||
}
|
||||
|
||||
if (arguments.isEmpty()) return null
|
||||
|
||||
var wasUpdates = false
|
||||
|
||||
val newArguments = arguments.map { typeProjection ->
|
||||
val updatedType =
|
||||
typeProjection.takeUnless { it.isStarProjection }
|
||||
?.type?.cleanFromAnonymousTypes()
|
||||
?: return@map typeProjection
|
||||
|
||||
wasUpdates = true
|
||||
|
||||
TypeProjectionImpl(typeProjection.projectionKind, updatedType)
|
||||
}
|
||||
|
||||
if (!wasUpdates) return null
|
||||
|
||||
return replace(newArguments = newArguments)
|
||||
}
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
public final class Prop /* Prop*/ {
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
private final java.lang.Object someProp;
|
||||
|
||||
@null()
|
||||
public Prop();
|
||||
|
||||
}
|
||||
|
||||
public final class Fun /* Fun*/ {
|
||||
@null()
|
||||
public Fun();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
private final java.lang.Object someFun();
|
||||
|
||||
}
|
||||
|
||||
public final class ArrayOfAnonymous /* ArrayOfAnonymous*/ {
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
private final java.lang.Object[] a1;
|
||||
|
||||
@null()
|
||||
public ArrayOfAnonymous();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public final java.lang.Object[] getA1();
|
||||
|
||||
}
|
||||
|
||||
final class C /* C*/ {
|
||||
@null()
|
||||
private final int y;
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
private final kotlin.jvm.functions.Function0<java.lang.Object> initChild;
|
||||
|
||||
@null()
|
||||
public C(@null() int);
|
||||
|
||||
@null()
|
||||
public final int getY();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public final kotlin.jvm.functions.Function0<java.lang.Object> getInitChild();
|
||||
|
||||
}
|
||||
|
||||
public abstract class Super /* Super*/ {
|
||||
@null()
|
||||
public Super();
|
||||
|
||||
@org.jetbrains.annotations.Nullable()
|
||||
public abstract java.lang.Object getA();
|
||||
|
||||
}
|
||||
|
||||
public final class Sub /* Sub*/ extends Super {
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
private final java.lang.Object[] a;
|
||||
|
||||
@null()
|
||||
public Sub();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public java.lang.Object[] getA();
|
||||
|
||||
}
|
||||
|
||||
public final class ValidPublicSupertype /* ValidPublicSupertype*/ {
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
private final java.lang.Runnable x;
|
||||
|
||||
@null()
|
||||
public ValidPublicSupertype();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public final java.lang.Runnable bar();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public final java.lang.Runnable getX();
|
||||
|
||||
}
|
||||
|
||||
public abstract interface I /* I*/ {
|
||||
}
|
||||
|
||||
public final class InvalidPublicSupertype /* InvalidPublicSupertype*/ {
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
private final java.lang.Runnable x;
|
||||
|
||||
@null()
|
||||
public InvalidPublicSupertype();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public final java.lang.Runnable bar();
|
||||
|
||||
@org.jetbrains.annotations.NotNull()
|
||||
public final java.lang.Runnable getX();
|
||||
|
||||
}
|
||||
+29
-10
@@ -1,22 +1,21 @@
|
||||
/** should load cls */
|
||||
class Prop {
|
||||
private val someProp = object { }
|
||||
}
|
||||
|
||||
|
||||
/** should load cls */
|
||||
|
||||
class Fun {
|
||||
private fun someFun() = object { }
|
||||
}
|
||||
|
||||
/** should load cls */
|
||||
class Array {
|
||||
|
||||
class ArrayOfAnonymous {
|
||||
val a1 = arrayOf(
|
||||
object { val fy = "text"}
|
||||
)
|
||||
}
|
||||
|
||||
/** should load cls */
|
||||
|
||||
private class C(val y: Int) {
|
||||
val initChild = { ->
|
||||
object {
|
||||
@@ -28,14 +27,34 @@ private class C(val y: Int) {
|
||||
}
|
||||
|
||||
|
||||
class Super {
|
||||
val a: Any?
|
||||
abstract class Super {
|
||||
abstract val a: Any?
|
||||
}
|
||||
|
||||
/** should load cls */
|
||||
class Sub {
|
||||
|
||||
class Sub : Super() {
|
||||
override val a = arrayOf(
|
||||
object { val fy = "text"}
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
class ValidPublicSupertype {
|
||||
val x = object : Runnable {
|
||||
override fun run() {}
|
||||
}
|
||||
|
||||
fun bar() = object : Runnable {
|
||||
override fun run() {}
|
||||
}
|
||||
}
|
||||
|
||||
interface I
|
||||
class InvalidPublicSupertype {
|
||||
val x = object : Runnable, I {
|
||||
override fun run() {}
|
||||
}
|
||||
|
||||
fun bar() = object : Runnable, I {
|
||||
override fun run() {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user