Fix null Java type argument problem & add relevant test
This commit is contained in:
@@ -68,7 +68,7 @@ internal fun FirTypeRef.toNotNullConeKotlinType(): ConeKotlinType =
|
|||||||
else -> ConeKotlinErrorType("Unexpected type reference in JavaClassUseSiteScope: ${this::class.java}")
|
else -> ConeKotlinErrorType("Unexpected type reference in JavaClassUseSiteScope: ${this::class.java}")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun JavaType.toNotNullConeKotlinType(session: FirSession): ConeLookupTagBasedType {
|
internal fun JavaType?.toNotNullConeKotlinType(session: FirSession): ConeLookupTagBasedType {
|
||||||
return toConeKotlinTypeWithNullability(session, isNullable = false)
|
return toConeKotlinTypeWithNullability(session, isNullable = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ internal fun JavaClassifierType.toFirResolvedTypeRef(session: FirSession): FirRe
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun JavaType.toConeKotlinTypeWithNullability(session: FirSession, isNullable: Boolean): ConeLookupTagBasedType {
|
internal fun JavaType?.toConeKotlinTypeWithNullability(session: FirSession, isNullable: Boolean): ConeLookupTagBasedType {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is JavaClassifierType -> {
|
is JavaClassifierType -> {
|
||||||
toConeKotlinTypeWithNullability(session, isNullable)
|
toConeKotlinTypeWithNullability(session, isNullable)
|
||||||
@@ -118,6 +118,10 @@ internal fun JavaType.toConeKotlinTypeWithNullability(session: FirSession, isNul
|
|||||||
val classId = ClassId(FqName("kotlin"), FqName("Any"), false)
|
val classId = ClassId(FqName("kotlin"), FqName("Any"), false)
|
||||||
classId.toConeKotlinType(emptyArray(), isNullable)
|
classId.toConeKotlinType(emptyArray(), isNullable)
|
||||||
}
|
}
|
||||||
|
null -> {
|
||||||
|
val classId = ClassId(FqName("kotlin"), FqName("Any"), false)
|
||||||
|
classId.toConeKotlinType(emptyArray(), isNullable)
|
||||||
|
}
|
||||||
else -> error("Strange JavaType: ${this::class.java}")
|
else -> error("Strange JavaType: ${this::class.java}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,8 +176,9 @@ internal fun FirAbstractAnnotatedElement.addAnnotationsFrom(javaAnnotationOwner:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun JavaType.toConeProjection(session: FirSession, boundTypeParameter: FirTypeParameter?): ConeKotlinTypeProjection {
|
internal fun JavaType?.toConeProjection(session: FirSession, boundTypeParameter: FirTypeParameter?): ConeKotlinTypeProjection {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
|
null -> ConeStarProjection
|
||||||
is JavaWildcardType -> {
|
is JavaWildcardType -> {
|
||||||
val bound = this.bound
|
val bound = this.bound
|
||||||
val argumentVariance = if (isExtends) OUT_VARIANCE else IN_VARIANCE
|
val argumentVariance = if (isExtends) OUT_VARIANCE else IN_VARIANCE
|
||||||
|
|||||||
+2
-2
@@ -95,8 +95,8 @@ internal class EnhancementSignatureParts(
|
|||||||
|
|
||||||
if (type is FirJavaTypeRef) {
|
if (type is FirJavaTypeRef) {
|
||||||
for (arg in type.type.typeArguments()) {
|
for (arg in type.type.typeArguments()) {
|
||||||
if (arg is JavaWildcardType) {
|
if (arg is JavaWildcardType || arg == null) {
|
||||||
// TODO: wildcards
|
// TODO: wildcards / raw types
|
||||||
} else {
|
} else {
|
||||||
add(arg.toFirJavaTypeRef(context.session))
|
add(arg.toFirJavaTypeRef(context.session))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ internal fun FirJavaTypeRef.enhance(
|
|||||||
// Example: for `A<B, C<D, E>>`, indices go as follows: `0 - A<...>, 1 - B, 2 - C<D, E>, 3 - D, 4 - E`,
|
// Example: for `A<B, C<D, E>>`, indices go as follows: `0 - A<...>, 1 - B, 2 - C<D, E>, 3 - D, 4 - E`,
|
||||||
// which corresponds to the left-to-right breadth-first walk of the tree representation of the type.
|
// which corresponds to the left-to-right breadth-first walk of the tree representation of the type.
|
||||||
// For flexible types, both bounds are indexed in the same way: `(A<B>..C<D>)` gives `0 - (A<B>..C<D>), 1 - B and D`.
|
// For flexible types, both bounds are indexed in the same way: `(A<B>..C<D>)` gives `0 - (A<B>..C<D>), 1 - B and D`.
|
||||||
private fun JavaType.enhancePossiblyFlexible(
|
private fun JavaType?.enhancePossiblyFlexible(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
annotations: List<FirAnnotationCall>,
|
annotations: List<FirAnnotationCall>,
|
||||||
qualifiers: (Int) -> JavaTypeQualifiers,
|
qualifiers: (Int) -> JavaTypeQualifiers,
|
||||||
index: Int
|
index: Int
|
||||||
): FirResolvedTypeRef {
|
): FirResolvedTypeRef {
|
||||||
val type = this
|
val type = this
|
||||||
val arguments = typeArguments()
|
val arguments = this?.typeArguments().orEmpty()
|
||||||
return when (type) {
|
return when (type) {
|
||||||
is JavaClassifierType -> {
|
is JavaClassifierType -> {
|
||||||
val lowerResult = type.enhanceInflexibleType(
|
val lowerResult = type.enhanceInflexibleType(
|
||||||
@@ -76,9 +76,9 @@ private fun JavaType.enhancePossiblyFlexible(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JavaType.subtreeSize(): Int {
|
private fun JavaType?.subtreeSize(): Int {
|
||||||
if (this !is JavaClassifierType) return 1
|
if (this !is JavaClassifierType) return 1
|
||||||
return 1 + typeArguments.sumBy { it.subtreeSize() }
|
return 1 + typeArguments.sumBy { it?.subtreeSize() ?: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val KOTLIN_COLLECTIONS = FqName("kotlin.collections")
|
private val KOTLIN_COLLECTIONS = FqName("kotlin.collections")
|
||||||
@@ -102,7 +102,7 @@ private fun ClassId.mutableToReadOnly(): ClassId? {
|
|||||||
private fun JavaClassifierType.enhanceInflexibleType(
|
private fun JavaClassifierType.enhanceInflexibleType(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
annotations: List<FirAnnotationCall>,
|
annotations: List<FirAnnotationCall>,
|
||||||
arguments: List<JavaType>,
|
arguments: List<JavaType?>,
|
||||||
position: TypeComponentPosition,
|
position: TypeComponentPosition,
|
||||||
qualifiers: (Int) -> JavaTypeQualifiers,
|
qualifiers: (Int) -> JavaTypeQualifiers,
|
||||||
index: Int
|
index: Int
|
||||||
@@ -199,7 +199,7 @@ internal data class TypeAndDefaultQualifiers(
|
|||||||
internal fun FirTypeRef.typeArguments(): List<FirTypeProjection> =
|
internal fun FirTypeRef.typeArguments(): List<FirTypeProjection> =
|
||||||
(this as? FirUserTypeRef)?.qualifier?.lastOrNull()?.typeArguments.orEmpty()
|
(this as? FirUserTypeRef)?.qualifier?.lastOrNull()?.typeArguments.orEmpty()
|
||||||
|
|
||||||
internal fun JavaType.typeArguments(): List<JavaType> = (this as? JavaClassifierType)?.typeArguments.orEmpty()
|
internal fun JavaType.typeArguments(): List<JavaType?> = (this as? JavaClassifierType)?.typeArguments.orEmpty()
|
||||||
|
|
||||||
fun FirValueParameter.getDefaultValueFromAnnotation(): AnnotationDefaultValue? {
|
fun FirValueParameter.getDefaultValueFromAnnotation(): AnnotationDefaultValue? {
|
||||||
annotations.find { it.resolvedFqName == JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME }
|
annotations.find { it.resolvedFqName == JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME }
|
||||||
|
|||||||
+1
-1
@@ -102,7 +102,7 @@ class JavaClassEnhancementScope(
|
|||||||
original: ConeFunctionSymbol,
|
original: ConeFunctionSymbol,
|
||||||
name: Name
|
name: Name
|
||||||
): FirFunctionSymbol {
|
): FirFunctionSymbol {
|
||||||
val firMethod = (original as FirBasedSymbol<*>).fir as? FirJavaMethod ?: error("Can't make enhancement for $original")
|
val firMethod = (original as FirFunctionSymbol).fir as? FirJavaMethod ?: return original
|
||||||
|
|
||||||
val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firMethod.annotations)
|
val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firMethod.annotations)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -136,7 +136,7 @@ sealed class TreeBasedClassifierType<out T : JCTree>(
|
|||||||
override val presentableText: String
|
override val presentableText: String
|
||||||
get() = classifierQualifiedName
|
get() = classifierQualifiedName
|
||||||
|
|
||||||
override val typeArguments: List<JavaType>
|
override val typeArguments: List<JavaType?>
|
||||||
get() {
|
get() {
|
||||||
var tree: JCTree = tree
|
var tree: JCTree = tree
|
||||||
if (tree is JCTree.JCTypeApply) {
|
if (tree is JCTree.JCTypeApply) {
|
||||||
@@ -230,9 +230,9 @@ class TreeBasedGenericClassifierType(
|
|||||||
?: super.annotations
|
?: super.annotations
|
||||||
}
|
}
|
||||||
|
|
||||||
override val typeArguments: List<JavaType>
|
override val typeArguments: List<JavaType?>
|
||||||
get() = tree.arguments.map { create(it, compilationUnit, javac, emptyList(), containingElement) }
|
get() = tree.arguments.map { create(it, compilationUnit, javac, emptyList(), containingElement) }
|
||||||
.toMutableList()
|
.toMutableList<JavaType?>()
|
||||||
.apply { addAll(super.typeArguments) }
|
.apply { addAll(super.typeArguments) }
|
||||||
|
|
||||||
override val isRaw: Boolean
|
override val isRaw: Boolean
|
||||||
|
|||||||
+3
-2
@@ -42,7 +42,7 @@ class JavaTypeResolver(
|
|||||||
private val typeParameterResolver: TypeParameterResolver
|
private val typeParameterResolver: TypeParameterResolver
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun transformJavaType(javaType: JavaType, attr: JavaTypeAttributes): KotlinType {
|
fun transformJavaType(javaType: JavaType?, attr: JavaTypeAttributes): KotlinType {
|
||||||
return when (javaType) {
|
return when (javaType) {
|
||||||
is JavaPrimitiveType -> {
|
is JavaPrimitiveType -> {
|
||||||
val primitiveType = javaType.type
|
val primitiveType = javaType.type
|
||||||
@@ -53,6 +53,7 @@ class JavaTypeResolver(
|
|||||||
is JavaArrayType -> transformArrayType(javaType, attr)
|
is JavaArrayType -> transformArrayType(javaType, attr)
|
||||||
// Top level type can be a wildcard only in case of broken Java code, but we should not fail with exceptions in such cases
|
// Top level type can be a wildcard only in case of broken Java code, but we should not fail with exceptions in such cases
|
||||||
is JavaWildcardType -> javaType.bound?.let { transformJavaType(it, attr) } ?: c.module.builtIns.defaultBound
|
is JavaWildcardType -> javaType.bound?.let { transformJavaType(it, attr) } ?: c.module.builtIns.defaultBound
|
||||||
|
null -> c.module.builtIns.defaultBound
|
||||||
else -> throw UnsupportedOperationException("Unsupported type: " + javaType)
|
else -> throw UnsupportedOperationException("Unsupported type: " + javaType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +248,7 @@ class JavaTypeResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transformToTypeProjection(
|
private fun transformToTypeProjection(
|
||||||
javaType: JavaType,
|
javaType: JavaType?,
|
||||||
attr: JavaTypeAttributes,
|
attr: JavaTypeAttributes,
|
||||||
typeParameter: TypeParameterDescriptor
|
typeParameter: TypeParameterDescriptor
|
||||||
): TypeProjection {
|
): TypeProjection {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ interface JavaArrayType : JavaType {
|
|||||||
|
|
||||||
interface JavaClassifierType : JavaType, JavaAnnotationOwner {
|
interface JavaClassifierType : JavaType, JavaAnnotationOwner {
|
||||||
val classifier: JavaClassifier?
|
val classifier: JavaClassifier?
|
||||||
val typeArguments: List<JavaType>
|
val typeArguments: List<JavaType?>
|
||||||
|
|
||||||
val isRaw: Boolean
|
val isRaw: Boolean
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
public open class Some : R|java/lang/Object|, R|Strange<*>| {
|
||||||
|
public open operator function foo(): R|ft<kotlin/Any, kotlin/Any>|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
class Derived : Some()
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
FILE: Derived.kt
|
||||||
|
public final class Derived : R|Some| {
|
||||||
|
public constructor(): super<R|Some|>()
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
public class Some implements Strange {
|
||||||
|
public Object foo() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
interface Strange<out T> {
|
||||||
|
fun foo(): T
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
FILE: Strange.kt
|
||||||
|
<out T> public abstract interface Strange {
|
||||||
|
public abstract function foo(): R|T|
|
||||||
|
|
||||||
|
}
|
||||||
+5
@@ -59,6 +59,11 @@ public class FirMultiModuleResolveTestGenerated extends AbstractFirMultiModuleRe
|
|||||||
runTest("idea/testData/fir/multiModule/basicWithPrimitiveJava/");
|
runTest("idea/testData/fir/multiModule/basicWithPrimitiveJava/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaInheritsRawKotlin")
|
||||||
|
public void testJavaInheritsRawKotlin() throws Exception {
|
||||||
|
runTest("idea/testData/fir/multiModule/javaInheritsRawKotlin/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("mppFakeOverrides")
|
@TestMetadata("mppFakeOverrides")
|
||||||
public void testMppFakeOverrides() throws Exception {
|
public void testMppFakeOverrides() throws Exception {
|
||||||
runTest("idea/testData/fir/multiModule/mppFakeOverrides/");
|
runTest("idea/testData/fir/multiModule/mppFakeOverrides/");
|
||||||
|
|||||||
Reference in New Issue
Block a user