From 9aaec1efdaada4fd99889c515d7dfd435dbe4853 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 21 Mar 2018 20:21:44 +0300 Subject: [PATCH] FIR: resolve function type parameters --- .../descriptors/FirTypeResolveTransformer.kt | 14 ++++++- .../impl/FirFunctionTypeParameterScope.kt | 40 +++++++++++++++++++ .../org/jetbrains/kotlin/fir/FirRenderer.kt | 3 ++ .../testData/fir/resolve/genericFunctions.kt | 7 ++++ .../testData/fir/resolve/genericFunctions.txt | 10 +++++ .../fir/FirResolveTestCaseGenerated.java | 6 +++ 6 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFunctionTypeParameterScope.kt create mode 100644 compiler/testData/fir/resolve/genericFunctions.kt create mode 100644 compiler/testData/fir/resolve/genericFunctions.txt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt index a773e9e6e5e..5fa8c7f0b75 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt @@ -6,14 +6,12 @@ package org.jetbrains.kotlin.descriptors import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.FirProvider import org.jetbrains.kotlin.fir.resolve.FirTypeResolver import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol -import org.jetbrains.kotlin.fir.symbols.ConeSymbol import org.jetbrains.kotlin.fir.transformSingle import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeImpl @@ -35,6 +33,7 @@ class FirTypeResolveTransformer(val superTypesOnly: Boolean = false) : FirTransf lateinit var scope: FirCompositeScope lateinit var packageFqName: FqName + lateinit var file: FirFile private var classLikeName: FqName = FqName.ROOT override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { @@ -45,6 +44,7 @@ class FirTypeResolveTransformer(val superTypesOnly: Boolean = false) : FirTransf ) ) packageFqName = file.packageFqName + this.file = file return super.transformFile(file, data) } @@ -93,6 +93,16 @@ class FirTypeResolveTransformer(val superTypesOnly: Boolean = false) : FirTransf return super.transformTypeAlias(typeAlias, data) } + override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Nothing?): CompositeTransformResult { + scope = FirCompositeScope(mutableListOf(scope)) + scope.scopes += FirFunctionTypeParameterScope(file, classLikeName, namedFunction.name, namedFunction.session) + + val result = super.transformNamedFunction(namedFunction, data) + scope = scope.scopes[0] as FirCompositeScope + + return result + } + override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult { val typeResolver = FirTypeResolver.getInstance(type.session) type.transformChildren(this, null) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFunctionTypeParameterScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFunctionTypeParameterScope.kt new file mode 100644 index 00000000000..be058460b49 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFunctionTypeParameterScope.kt @@ -0,0 +1,40 @@ +/* + * 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.fir.scopes.impl + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclarationContainer +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirNamedFunction +import org.jetbrains.kotlin.fir.resolve.FirProvider +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.symbols.ConeSymbol +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +class FirFunctionTypeParameterScope( + val file: FirFile, + val className: FqName, + val functionName: Name, + val session: FirSession +) : FirScope { + + private val firProvider = FirProvider.getInstance(session) + + val typeParameterContainer = when { + className.isRoot -> file + else -> firProvider.getFirClassifierByFqName(ClassId(file.packageFqName, className, false)) as? FirDeclarationContainer + }?.declarations?.filterIsInstance()?.find { it.name == functionName } + + val typeParameters = typeParameterContainer?.typeParameters.orEmpty().groupBy { it.name } + + override fun processClassifiersByName(name: Name, processor: (ConeSymbol) -> Boolean): Boolean { + val matchedTypeParameters = typeParameters[name] ?: return true + + return matchedTypeParameters.all { processor(it.symbol) } + } +} \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index c3a787dfc86..60d76a9ebe4 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -305,6 +305,9 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() { override fun visitTypeParameter(typeParameter: FirTypeParameter) { typeParameter.annotations.renderAnnotations() + if (typeParameter.isReified) { + print("reified ") + } typeParameter.variance.renderVariance() print(typeParameter.name) if (typeParameter.bounds.isNotEmpty()) { diff --git a/compiler/testData/fir/resolve/genericFunctions.kt b/compiler/testData/fir/resolve/genericFunctions.kt new file mode 100644 index 00000000000..a88e9c41a82 --- /dev/null +++ b/compiler/testData/fir/resolve/genericFunctions.kt @@ -0,0 +1,7 @@ +interface Any + +inline fun Any.safeAs(): T? = this as? T + +abstract class Summator { + abstract fun plus(first: T, second: T): T +} \ No newline at end of file diff --git a/compiler/testData/fir/resolve/genericFunctions.txt b/compiler/testData/fir/resolve/genericFunctions.txt new file mode 100644 index 00000000000..8418801ee01 --- /dev/null +++ b/compiler/testData/fir/resolve/genericFunctions.txt @@ -0,0 +1,10 @@ +FILE: genericFunctions.kt + (resolved) public? abstract interface Any() { + } + public? final? inline function safeAsR/Any/.(): R/T/ { + STUB + } + (resolved) public? abstract class Summator() { + public? abstract function plus(first: R/T/, second: R/T/): R/T/ + + } diff --git a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java index de0ba72c81f..d9a6bf656ea 100644 --- a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java @@ -31,6 +31,12 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { doTest(fileName); } + @TestMetadata("genericFunctions.kt") + public void testGenericFunctions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/genericFunctions.kt"); + doTest(fileName); + } + @TestMetadata("NestedOfAliasedType.kt") public void testNestedOfAliasedType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/NestedOfAliasedType.kt");