From 276c3931415ccd99e55517640209571a89e605b3 Mon Sep 17 00:00:00 2001 From: "simon.ogorodnik" Date: Thu, 9 Apr 2020 19:02:23 +0300 Subject: [PATCH] [FIR] Support captured type parameters in java symbol provider --- .../fir/backend/Fir2IrDeclarationStorage.kt | 2 +- .../kotlin/fir/java/JavaSymbolProvider.kt | 26 ++++++++------ .../tests/generics/innerClasses/j+k.fir.kt | 28 --------------- .../tests/generics/innerClasses/j+k.kt | 1 + .../generics/innerClasses/j+k_complex.fir.kt | 35 ------------------- .../generics/innerClasses/j+k_complex.kt | 1 + ...nstructorWithOwnTypeParametersCall.fir.txt | 11 ++++-- ...versionInGenericConstructorCall_NI.fir.txt | 17 ++++++--- .../javaConstructorWithTypeParameters.fir.txt | 21 +++++++---- 9 files changed, 53 insertions(+), 89 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/generics/innerClasses/j+k.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.fir.kt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 57ebe380f0b..717c2a0720e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -305,7 +305,7 @@ class Fir2IrDeclarationStorage( parentPropertyReceiverType: FirTypeRef? ) { val parent = this - if (function is FirSimpleFunction) { + if (function is FirSimpleFunction || function is FirConstructor) { with(classifierStorage) { setTypeParameters(function) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index 60af1d61500..c72de980ee1 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.addDefaultBoundIfNecessary import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder import org.jetbrains.kotlin.fir.declarations.builder.buildConstructedClassTypeParameterRef +import org.jetbrains.kotlin.fir.declarations.builder.buildOuterClassTypeParameterRef import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall import org.jetbrains.kotlin.fir.java.declarations.* import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider @@ -152,13 +153,13 @@ class JavaSymbolProvider( ) { firSymbol, foundClass -> foundClass?.let { javaClass -> val javaTypeParameterStack = JavaTypeParameterStack() - val parentFqName = classId.relativeClassName.parent() - val isTopLevel = parentFqName.isRoot - if (!isTopLevel) { - val parentId = ClassId(classId.packageFqName, parentFqName, false) - val parentClassSymbol = getClassLikeSymbolByFqName(parentId) + val outerClassId = classId.outerClassId + val parentClassSymbol = if (outerClassId != null) { + getClassLikeSymbolByFqName(outerClassId) + } else null + if (parentClassSymbol != null) { val parentStack = parentClassTypeParameterStackCache[parentClassSymbol] - ?: (parentClassSymbol?.fir as? FirJavaClass)?.javaTypeParameterStack + ?: (parentClassSymbol.fir as? FirJavaClass)?.javaTypeParameterStack if (parentStack != null) { javaTypeParameterStack.addStack(parentStack) } @@ -171,13 +172,19 @@ class JavaSymbolProvider( visibility = javaClass.visibility modality = javaClass.modality classKind = javaClass.classKind - this.isTopLevel = isTopLevel + this.isTopLevel = outerClassId == null isStatic = javaClass.isStatic this.javaTypeParameterStack = javaTypeParameterStack parentClassTypeParameterStackCache[firSymbol] = javaTypeParameterStack existingNestedClassifierNames += javaClass.innerClassNames scopeProvider = this@JavaSymbolProvider.scopeProvider - typeParameters += foundClass.typeParameters.convertTypeParameters(javaTypeParameterStack) + val classTypeParameters = foundClass.typeParameters.convertTypeParameters(javaTypeParameterStack) + typeParameters += classTypeParameters + if (!isStatic && parentClassSymbol != null) { + typeParameters += parentClassSymbol.fir.typeParameters.map { + buildOuterClassTypeParameterRef { symbol = it.symbol } + } + } addAnnotationsFrom(this@JavaSymbolProvider.session, javaClass, javaTypeParameterStack) // TODO: may be we can process fields & methods later. // However, they should be built up to override resolve stage @@ -234,7 +241,6 @@ class JavaSymbolProvider( isPrimary: Boolean = false, ): FirJavaConstructorBuilder { val constructorSymbol = FirConstructorSymbol(constructorId) - val classTypeParameters = javaClass.typeParameters.convertTypeParameters(javaTypeParameterStack) return FirJavaConstructorBuilder().apply { source = psi?.toFirPsiSourceElement() session = this@JavaSymbolProvider.session @@ -244,7 +250,7 @@ class JavaSymbolProvider( isInner = javaClass.outerClass != null && !javaClass.isStatic returnTypeRef = buildResolvedTypeRef { type = firSymbol.constructType( - classTypeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), + this@buildJavaClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), false, ) } diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k.fir.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/j+k.fir.kt deleted file mode 100644 index cbfc156e188..00000000000 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k.fir.kt +++ /dev/null @@ -1,28 +0,0 @@ -// !CHECK_TYPE -// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -// FILE: Outer.java - -public class Outer { - public class Inner { - E foo() {} - F bar() {} - - Outer outer() {} - } - - Inner baz() { } - void set(Inner x) {} -} - -// FILE: main.kt - -fun main() { - var outerStr: Outer = Outer() - outerStr.baz().checkType { _.Inner>() } - - val strInt: Outer.Inner = outerStr.Inner() - - strInt.foo().checkType { _() } - strInt.bar().checkType { _() } - strInt.outer().checkType { _>() } -} diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/j+k.kt index c8e48ba9b47..d339490b5ca 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/j+k.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !CHECK_TYPE // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER // FILE: Outer.java diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.fir.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.fir.kt deleted file mode 100644 index 22f0faaa562..00000000000 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.fir.kt +++ /dev/null @@ -1,35 +0,0 @@ -// !CHECK_TYPE -// FILE: BaseOuter.java -// See KT-10285 -public class BaseOuter { - abstract public class BaseInner { - public H foo1() { - return null; - } - - public E foo2() { - return null; - } - - public F foo3() { - return null; - } - } -} - -// FILE: Outer.java -public class Outer extends BaseOuter { - public BaseInner bar() { return null; } - public class Inner extends BaseOuter.BaseInner {} -} - -// FILE: main.kt -fun foo(x1: Outer, x2: Outer.Inner) { - x1.bar().foo1().checkType { _() } - x1.bar().foo2().checkType { _() } - x1.bar().foo3().checkType { _() } - - x2.foo1().checkType { _() } - x2.foo2().checkType { _() } - x2.foo3().checkType { _() } -} diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.kt index 2f3016a3c90..9fe7480c72e 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/j+k_complex.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !CHECK_TYPE // FILE: BaseOuter.java // See KT-10285 diff --git a/compiler/testData/ir/irText/expressions/constructorWithOwnTypeParametersCall.fir.txt b/compiler/testData/ir/irText/expressions/constructorWithOwnTypeParametersCall.fir.txt index c83664b958c..7092f3330e1 100644 --- a/compiler/testData/ir/irText/expressions/constructorWithOwnTypeParametersCall.fir.txt +++ b/compiler/testData/ir/irText/expressions/constructorWithOwnTypeParametersCall.fir.txt @@ -6,10 +6,15 @@ FILE fqName: fileName:/constructorWithOwnTypeParametersCall.kt : kotlin.String $outer: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .K1' type=.K1 origin=null : kotlin.Int - FUN name:testJava visibility:public modality:FINAL <> () returnType:.J1.J2 + FUN name:testJava visibility:public modality:FINAL <> () returnType:.J1.J2 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun testJava (): .J1.J2 declared in ' - ERROR_EXPR 'Cannot bind 2 type arguments to ??? call with 1 type parameters' type=.J1.J2 + RETURN type=kotlin.Nothing from='public final fun testJava (): .J1.J2 declared in ' + CONSTRUCTOR_CALL 'public constructor () declared in .J1.J2' type=.J1.J2 origin=null + : kotlin.Double? + : kotlin.CharSequence? + $outer: CONSTRUCTOR_CALL 'public constructor () declared in .J1' type=.J1 origin=null + : kotlin.Int? + : kotlin.String? CLASS CLASS name:K1 modality:FINAL visibility:public superTypes:[kotlin.Any] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.K1.K1> TYPE_PARAMETER name:T1 index:0 variance: superTypes:[kotlin.Number] diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.fir.txt index 098d533899d..d808da166c7 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.fir.txt @@ -1,10 +1,10 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall_NI.kt - FUN name:test3 visibility:public modality:FINAL <> (f1:kotlin.Function1, f2:kotlin.Function1) returnType:.C.D + FUN name:test3 visibility:public modality:FINAL <> (f1:kotlin.Function1, f2:kotlin.Function1) returnType:.C.D VALUE_PARAMETER name:f1 index:0 type:kotlin.Function1 VALUE_PARAMETER name:f2 index:1 type:kotlin.Function1 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test3 (f1: kotlin.Function1, f2: kotlin.Function1): .C.D declared in ' - CONSTRUCTOR_CALL 'public constructor (jxy: .J.C?, Y of .C.D?>?) declared in .C.D' type=.C.D origin=null + RETURN type=kotlin.Nothing from='public final fun test3 (f1: kotlin.Function1, f2: kotlin.Function1): .C.D declared in ' + CONSTRUCTOR_CALL 'public constructor (jxy: .J.C?, Y of .C.D?>?) declared in .C.D' type=.C.D origin=null : kotlin.Int? $outer: CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null : kotlin.String? @@ -90,10 +90,17 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall_NI.kt VALUE_PARAMETER name:f index:0 type:kotlin.Function1 BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun testGenericJavaCtor1 (f: kotlin.Function1): .G declared in ' - ERROR_EXPR 'Cannot bind 2 type arguments to ??? call with 1 type parameters' type=.G + CONSTRUCTOR_CALL 'public constructor (x: .J.G.?, TClass of .G?>?) declared in .G' type=.G origin=null + : kotlin.String? + : kotlin.Int? + x: GET_VAR 'f: kotlin.Function1 declared in .testGenericJavaCtor1' type=kotlin.Function1 origin=null FUN name:testGenericJavaCtor2 visibility:public modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:x index:0 type:kotlin.Any BLOCK_BODY TYPE_OP type=kotlin.Function1 origin=CAST typeOperand=kotlin.Function1 GET_VAR 'x: kotlin.Any declared in .testGenericJavaCtor2' type=kotlin.Any origin=null - ERROR_EXPR 'Cannot bind 2 type arguments to ??? call with 1 type parameters' type=.G + CONSTRUCTOR_CALL 'public constructor (x: .J.G.?, TClass of .G?>?) declared in .G' type=.G origin=null + : kotlin.String? + : kotlin.Int? + x: TYPE_OP type=kotlin.Function1 origin=IMPLICIT_CAST typeOperand=kotlin.Function1 + GET_VAR 'x: kotlin.Any declared in .testGenericJavaCtor2' type=kotlin.Any origin=null diff --git a/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.fir.txt b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.fir.txt index 03efd51f6b5..619385ad343 100644 --- a/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.fir.txt +++ b/compiler/testData/ir/irText/stubs/javaConstructorWithTypeParameters.fir.txt @@ -7,16 +7,23 @@ FILE fqName: fileName:/javaConstructorWithTypeParameters.kt FUN name:test2 visibility:public modality:FINAL <> () returnType:.J1 BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun test2 (): .J1 declared in ' - ERROR_EXPR 'Cannot bind 2 type arguments to ??? call with 1 type parameters' type=.J1 - FUN name:test3 visibility:public modality:FINAL <> (j1:.J1) returnType:.J1.J2 + CONSTRUCTOR_CALL 'public constructor (x1: X1 of .J1.?) declared in .J1' type=.J1 origin=null + : kotlin.Int? + : kotlin.Int? + x1: CONST Int type=kotlin.Int value=1 + FUN name:test3 visibility:public modality:FINAL <> (j1:.J1) returnType:.J1.J2 VALUE_PARAMETER name:j1 index:0 type:.J1 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test3 (j1: .J1): .J1.J2 declared in ' - CONSTRUCTOR_CALL 'public constructor () declared in .J1.J2' type=.J1.J2 origin=null + RETURN type=kotlin.Nothing from='public final fun test3 (j1: .J1): .J1.J2 declared in ' + CONSTRUCTOR_CALL 'public constructor () declared in .J1.J2' type=.J1.J2 origin=null : kotlin.Int? $outer: GET_VAR 'j1: .J1 declared in .test3' type=.J1 origin=null - FUN name:test4 visibility:public modality:FINAL <> (j1:.J1) returnType:.J1.J2 + FUN name:test4 visibility:public modality:FINAL <> (j1:.J1) returnType:.J1.J2 VALUE_PARAMETER name:j1 index:0 type:.J1 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun test4 (j1: .J1): .J1.J2 declared in ' - ERROR_EXPR 'Cannot bind 2 type arguments to ??? call with 1 type parameters' type=.J1.J2 + RETURN type=kotlin.Nothing from='public final fun test4 (j1: .J1): .J1.J2 declared in ' + CONSTRUCTOR_CALL 'public constructor (x2: X2 of .J1.J2.?) declared in .J1.J2' type=.J1.J2 origin=null + : kotlin.Int? + : kotlin.Int? + $outer: GET_VAR 'j1: .J1 declared in .test4' type=.J1 origin=null + x2: CONST Int type=kotlin.Int value=1