Fix order of type parameters loaded from PSI
#KT-10285 Fixed
This commit is contained in:
+25
-10
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.load.java.structure.impl;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.load.java.structure.*;
|
||||
@@ -113,8 +112,8 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
|
||||
// parameters including ones from outer class
|
||||
Iterable<PsiTypeParameter> parameters = classifier instanceof JavaClassImpl
|
||||
? getReversedTypeParameters((JavaClassImpl) classifier)
|
||||
: Collections.<PsiTypeParameter>emptyList();
|
||||
? getTypeParameters(((JavaClassImpl) classifier).getPsi())
|
||||
: Collections.<PsiTypeParameter>emptyList();
|
||||
|
||||
JavaTypeSubstitutor substitutor = getSubstitutor();
|
||||
|
||||
@@ -126,16 +125,32 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Collection<PsiTypeParameter> getReversedTypeParameters(@NotNull JavaClassImpl classifier) {
|
||||
Iterable<PsiTypeParameter> parameters = PsiUtil.typeParametersIterable(classifier.getPsi());
|
||||
List<PsiTypeParameter> result = new ArrayList<PsiTypeParameter>();
|
||||
// Copy-pasted from PsiUtil.typeParametersIterable
|
||||
// The only change is using `Collections.addAll(result, typeParameters)` instead of reversing type parameters of `currentOwner`
|
||||
// Result differs in cases like:
|
||||
// class Outer<H1> {
|
||||
// class Inner<H2, H3> {}
|
||||
// }
|
||||
//
|
||||
// PsiUtil.typeParametersIterable returns H3, H2, H1
|
||||
// But we would like to have H2, H3, H1 as such order is consistent with our type representation
|
||||
@NotNull
|
||||
public static List<PsiTypeParameter> getTypeParameters(@NotNull PsiClass owner) {
|
||||
List<PsiTypeParameter> result = null;
|
||||
|
||||
for (PsiTypeParameter parameter : parameters) {
|
||||
result.add(parameter);
|
||||
PsiTypeParameterListOwner currentOwner = owner;
|
||||
while (currentOwner != null) {
|
||||
PsiTypeParameter[] typeParameters = currentOwner.getTypeParameters();
|
||||
if (typeParameters.length > 0) {
|
||||
if (result == null) result = new ArrayList<PsiTypeParameter>(typeParameters.length);
|
||||
Collections.addAll(result, typeParameters);
|
||||
}
|
||||
|
||||
if (currentOwner.hasModifierProperty(PsiModifier.STATIC)) break;
|
||||
currentOwner = currentOwner.getContainingClass();
|
||||
}
|
||||
|
||||
Collections.reverse(result);
|
||||
|
||||
if (result == null) return Collections.emptyList();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ public open class Outer</*0*/ E : kotlin.Any!> {
|
||||
public/*package*/ open fun baz(): Outer<E!>.Inner<E!>!
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public/*package*/ open fun set(/*0*/ x: Outer<kotlin.String!>.Inner<E!>!): kotlin.Unit
|
||||
public/*package*/ open fun set(/*0*/ x: Outer<E!>.Inner<kotlin.String!>!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public open inner class Inner</*0*/ F : kotlin.Any!> /*captured type parameters: /*1*/ E : kotlin.Any!*/ {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// !CHECK_TYPE
|
||||
// FILE: BaseOuter.java
|
||||
// See KT-10285
|
||||
public class BaseOuter<H> {
|
||||
abstract public class BaseInner<E, F> {
|
||||
public H foo1() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public E foo2() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public F foo3() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Outer.java
|
||||
public class Outer<H> extends BaseOuter<H> {
|
||||
public BaseInner<Double, String> bar() { return null; }
|
||||
public class Inner extends BaseOuter<H>.BaseInner<Double, String> {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun foo(x1: Outer<Int>, x2: Outer<Int>.Inner) {
|
||||
x1.bar().foo1().checkType { _<Int>() }
|
||||
x1.bar().foo2().checkType { _<Double>() }
|
||||
x1.bar().foo3().checkType { _<String>() }
|
||||
|
||||
x2.foo1().checkType { _<Int>() }
|
||||
x2.foo2().checkType { _<Double>() }
|
||||
x2.foo3().checkType { _<String>() }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x1: Outer<kotlin.Int>, /*1*/ x2: Outer<kotlin.Int>.Inner): kotlin.Unit
|
||||
|
||||
public open class BaseOuter</*0*/ H : kotlin.Any!> {
|
||||
public constructor BaseOuter</*0*/ H : kotlin.Any!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public abstract inner class BaseInner</*0*/ E : kotlin.Any!, /*1*/ F : kotlin.Any!> /*captured type parameters: /*2*/ H : kotlin.Any!*/ {
|
||||
public constructor BaseInner</*0*/ E : kotlin.Any!, /*1*/ F : kotlin.Any!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo1(): H!
|
||||
public open fun foo2(): E!
|
||||
public open fun foo3(): F!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public open class Outer</*0*/ H : kotlin.Any!> : BaseOuter<H!> {
|
||||
public constructor Outer</*0*/ H : kotlin.Any!>()
|
||||
public open fun bar(): BaseOuter<H!>.BaseInner<kotlin.Double!, kotlin.String!>!
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public open inner class Inner /*captured type parameters: /*0*/ H : kotlin.Any!*/ : BaseOuter<H!>.BaseInner<kotlin.Double!, kotlin.String!> {
|
||||
public constructor Inner()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun foo1(): H!
|
||||
public open override /*1*/ /*fake_override*/ fun foo2(): kotlin.Double!
|
||||
public open override /*1*/ /*fake_override*/ fun foo3(): kotlin.String!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package test;
|
||||
public class InnerClassTypeMultipleGeneric {
|
||||
public class BaseOuter<H1, H2> {
|
||||
abstract public class BaseInner<H3, H4> {
|
||||
}
|
||||
}
|
||||
|
||||
public class Outer<E1, E2> extends BaseOuter<Integer, E1> {
|
||||
public BaseInner<Class<?>, CharSequence> bar() { return null; }
|
||||
public class Inner<E3> extends BaseOuter<E2, E3>.BaseInner<Double, String> {}
|
||||
}
|
||||
|
||||
public Outer<Character, Boolean>.Inner<Byte> staticType() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package test
|
||||
|
||||
public open class InnerClassTypeMultipleGeneric {
|
||||
public constructor InnerClassTypeMultipleGeneric()
|
||||
public open fun staticType(): test.InnerClassTypeMultipleGeneric.Outer<kotlin.Char!, kotlin.Boolean!>.Inner<kotlin.Byte!>!
|
||||
|
||||
public open inner class BaseOuter</*0*/ H1 : kotlin.Any!, /*1*/ H2 : kotlin.Any!> {
|
||||
public constructor BaseOuter</*0*/ H1 : kotlin.Any!, /*1*/ H2 : kotlin.Any!>()
|
||||
|
||||
public abstract inner class BaseInner</*0*/ H3 : kotlin.Any!, /*1*/ H4 : kotlin.Any!> /*captured type parameters: /*2*/ H1 : kotlin.Any!, /*3*/ H2 : kotlin.Any!*/ {
|
||||
public constructor BaseInner</*0*/ H3 : kotlin.Any!, /*1*/ H4 : kotlin.Any!>()
|
||||
}
|
||||
}
|
||||
|
||||
public open inner class Outer</*0*/ E1 : kotlin.Any!, /*1*/ E2 : kotlin.Any!> : test.InnerClassTypeMultipleGeneric.BaseOuter<kotlin.Int!, E1!> {
|
||||
public constructor Outer</*0*/ E1 : kotlin.Any!, /*1*/ E2 : kotlin.Any!>()
|
||||
public open fun bar(): test.InnerClassTypeMultipleGeneric.BaseOuter<kotlin.Int!, E1!>.BaseInner<java.lang.Class<*>!, kotlin.CharSequence!>!
|
||||
|
||||
public open inner class Inner</*0*/ E3 : kotlin.Any!> /*captured type parameters: /*1*/ E1 : kotlin.Any!, /*2*/ E2 : kotlin.Any!*/ : test.InnerClassTypeMultipleGeneric.BaseOuter<E2!, E3!>.BaseInner<kotlin.Double!, kotlin.String!> {
|
||||
public constructor Inner</*0*/ E3 : kotlin.Any!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6797,6 +6797,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("j+k_complex.kt")
|
||||
public void testJ_k_complex() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt408.kt")
|
||||
public void testKt408() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/kt408.kt");
|
||||
|
||||
@@ -133,6 +133,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
doTestCompiledJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InnerClassTypeMultipleGeneric.java")
|
||||
public void testInnerClassTypeMultipleGeneric() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/InnerClassTypeMultipleGeneric.java");
|
||||
doTestCompiledJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InnerClassesInGeneric.java")
|
||||
public void testInnerClassesInGeneric() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/InnerClassesInGeneric.java");
|
||||
|
||||
+6
@@ -3199,6 +3199,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InnerClassTypeMultipleGeneric.java")
|
||||
public void testInnerClassTypeMultipleGeneric() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/InnerClassTypeMultipleGeneric.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InnerClassesInGeneric.java")
|
||||
public void testInnerClassesInGeneric() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/InnerClassesInGeneric.java");
|
||||
|
||||
Reference in New Issue
Block a user