From 02bedeca05b45fef99d9c8d2a15595e1a373fe99 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 5 Apr 2018 12:47:28 +0300 Subject: [PATCH] FIR: introduce Java type resolve and JavaSymbolProvider #KT-24098 Fixed --- .../jetbrains/kotlin/fir/types/ConeTypes.kt | 3 ++ compiler/fir/java/build.gradle.kts | 20 ++++++++ .../kotlin/fir/java/JavaSymbolProvider.kt | 51 +++++++++++++++++++ .../fir/java/symbols/JavaClassSymbol.kt | 34 +++++++++++++ .../java/symbols/JavaTypeParameterSymbol.kt | 11 ++++ .../transformers/FirTypeResolveTransformer.kt | 8 +-- compiler/testData/fir/resolve/treeSet.kt | 3 ++ compiler/testData/fir/resolve/treeSet.txt | 3 ++ compiler/tests-common/build.gradle.kts | 1 + compiler/tests-common/build.gradle.kts.173 | 1 + .../AbstractFirResolveWithSessionTestCase.kt | 5 +- .../fir/FirResolveTestCaseGenerated.java | 14 ++--- settings.gradle | 1 + 13 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 compiler/fir/java/build.gradle.kts create mode 100644 compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt create mode 100644 compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaClassSymbol.kt create mode 100644 compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaTypeParameterSymbol.kt create mode 100644 compiler/testData/fir/resolve/treeSet.kt create mode 100644 compiler/testData/fir/resolve/treeSet.txt diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index 25b1ea535ae..2cbe799b892 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -41,6 +41,9 @@ class ConeClassErrorType(val reason: String) : ConeClassLikeType() { override val typeArguments: List get() = emptyList() + override fun toString(): String { + return "" + } } sealed class ConeSymbolBasedType : ConeKotlinType() { diff --git a/compiler/fir/java/build.gradle.kts b/compiler/fir/java/build.gradle.kts new file mode 100644 index 00000000000..98069f67cfd --- /dev/null +++ b/compiler/fir/java/build.gradle.kts @@ -0,0 +1,20 @@ + +plugins { + kotlin("jvm") + id("jps-compatible") +} + +jvmTarget = "1.6" + +dependencies { + compile(project(":compiler:frontend.java")) + compile(project(":compiler:fir:resolve")) + + compileOnly(intellijCoreDep()) { includeJars("intellij-core", "annotations") } +} + + +sourceSets { + "main" { projectDefault() } + "test" {} +} \ No newline at end of file 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 new file mode 100644 index 00000000000..c2404016dab --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -0,0 +1,51 @@ +/* + * 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.java + +import com.intellij.openapi.project.Project +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.fir.java.symbols.JavaClassSymbol +import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.symbols.ConeSymbol +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade + +class JavaSymbolProvider(val project: Project) : FirSymbolProvider { + + // TODO: Concrete scope here + private val allScope = GlobalSearchScope.allScope(project) + + private val classCache = mutableMapOf() + private val packageCache = mutableMapOf() + + private inline fun MutableMap.lookupCacheOrCalculate(key: K, l: (K) -> V): V? { + return if (key in this.keys) { + this[key] + } else { + val calculated = l(key) + this[key] = calculated + calculated + } + } + + override fun getSymbolByFqName(classId: ClassId): ConeSymbol? { + return classCache.lookupCacheOrCalculate(classId) { + val facade = KotlinJavaPsiFacade.getInstance(project) + val foundClass = facade.findClass(classId, allScope) + foundClass?.let { javaClass -> JavaClassSymbol(javaClass) } + } + } + + override fun getPackage(fqName: FqName): FqName? { + return packageCache.lookupCacheOrCalculate(fqName) { + val facade = KotlinJavaPsiFacade.getInstance(project) + val javaPackage = facade.findPackage(fqName.asString(), allScope) ?: return@lookupCacheOrCalculate null + FqName(javaPackage.qualifiedName) + } + } +} + diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaClassSymbol.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaClassSymbol.kt new file mode 100644 index 00000000000..f6659471ffb --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaClassSymbol.kt @@ -0,0 +1,34 @@ +/* + * 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.java.symbols + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.fir.symbols.ConeClassSymbol +import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol +import org.jetbrains.kotlin.fir.types.ConeClassErrorType +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.load.java.structure.JavaClass +import org.jetbrains.kotlin.load.java.structure.classId +import org.jetbrains.kotlin.name.ClassId + +class JavaClassSymbol(javaClass: JavaClass) : ConeClassSymbol { + override val classId: ClassId = javaClass.classId ?: error("!") + + override val typeParameters: List = + javaClass.typeParameters.map { JavaTypeParameterSymbol(it.name) } + + override val kind: ClassKind = when { + javaClass.isEnum -> ClassKind.ENUM_CLASS + javaClass.isInterface -> ClassKind.INTERFACE + javaClass.isAnnotationType -> ClassKind.ANNOTATION_CLASS + else -> ClassKind.CLASS + } + + override val superTypes: List = + listOf(ConeClassErrorType("Not supported: Java class supertypes")) +} + + diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaTypeParameterSymbol.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaTypeParameterSymbol.kt new file mode 100644 index 00000000000..d5deef4e1ab --- /dev/null +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/symbols/JavaTypeParameterSymbol.kt @@ -0,0 +1,11 @@ +/* + * 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.java.symbols + +import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol +import org.jetbrains.kotlin.name.Name + +class JavaTypeParameterSymbol(override val name: Name) : ConeTypeParameterSymbol \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt index ae5f356ecf4..da62b50f1aa 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt @@ -192,9 +192,9 @@ open class FirTypeResolveTransformer : FirTransformer() { } else { if (symbol is ConeTypeAliasSymbol) { - symbol.expansionType?.let { walkSymbols(it.symbol) } + symbol.expansionType?.let { if (it !is ConeClassErrorType) walkSymbols(it.symbol) } } else if (symbol is ConeClassSymbol) { - symbol.superTypes.forEach { walkSymbols(it.symbol) } + symbol.superTypes.forEach { if (it !is ConeClassErrorType) walkSymbols(it.symbol) } } } } @@ -228,7 +228,9 @@ open class FirTypeResolveTransformer : FirTransformer() { val superClassType = this.superTypes .map { it.computePartialExpansion() } - .firstOrNull { (it?.symbol as? ConeClassSymbol)?.kind == ClassKind.CLASS } ?: return + .firstOrNull { + it !is ConeClassErrorType && (it?.symbol as? ConeClassSymbol)?.kind == ClassKind.CLASS + } ?: return list += superClassType superClassType.symbol.collectSuperTypes(list) } diff --git a/compiler/testData/fir/resolve/treeSet.kt b/compiler/testData/fir/resolve/treeSet.kt new file mode 100644 index 00000000000..06a7a6516b1 --- /dev/null +++ b/compiler/testData/fir/resolve/treeSet.kt @@ -0,0 +1,3 @@ +import java.util.* + +val x: SortedSet = TreeSet() \ No newline at end of file diff --git a/compiler/testData/fir/resolve/treeSet.txt b/compiler/testData/fir/resolve/treeSet.txt new file mode 100644 index 00000000000..dddea26980c --- /dev/null +++ b/compiler/testData/fir/resolve/treeSet.txt @@ -0,0 +1,3 @@ +FILE: treeSet.kt + public? final? property x(val): R|java/util/SortedSet| = STUB + public? get(): R|java/util/SortedSet| diff --git a/compiler/tests-common/build.gradle.kts b/compiler/tests-common/build.gradle.kts index 23ca6111713..33fd01d9469 100644 --- a/compiler/tests-common/build.gradle.kts +++ b/compiler/tests-common/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { testCompile(project(":compiler:fir:psi2fir")) testCompile(project(":compiler:fir:cones")) testCompile(project(":compiler:fir:resolve")) + testCompile(project(":compiler:fir:java")) testCompile(project(":compiler:ir.ir2cfg")) testCompile(project(":compiler:frontend")) testCompile(project(":compiler:frontend.java")) diff --git a/compiler/tests-common/build.gradle.kts.173 b/compiler/tests-common/build.gradle.kts.173 index 91c9f95304b..5f1a12de170 100644 --- a/compiler/tests-common/build.gradle.kts.173 +++ b/compiler/tests-common/build.gradle.kts.173 @@ -14,6 +14,7 @@ dependencies { testCompile(project(":compiler:fir:psi2fir")) testCompile(project(":compiler:fir:cones")) testCompile(project(":compiler:fir:resolve")) + testCompile(project(":compiler:fir:java")) testCompile(project(":compiler:ir.ir2cfg")) testCompile(project(":compiler:frontend")) testCompile(project(":compiler:frontend.java")) diff --git a/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithSessionTestCase.kt b/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithSessionTestCase.kt index ee1b3599c25..e4f42736a89 100644 --- a/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithSessionTestCase.kt +++ b/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveWithSessionTestCase.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir +import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.resolve.FirProvider import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider @@ -14,14 +15,14 @@ import org.jetbrains.kotlin.test.KotlinTestWithEnvironment abstract class AbstractFirResolveWithSessionTestCase : KotlinTestWithEnvironment() { - fun createSession(): FirSession { + open fun createSession(): FirSession { return object : FirSessionBase() { init { val firProvider = FirProviderImpl(this) registerComponent(FirProvider::class, firProvider) registerComponent( FirSymbolProvider::class, - FirCompositeSymbolProvider(listOf(firProvider, FirLibrarySymbolProviderImpl(this))) + FirCompositeSymbolProvider(listOf(firProvider, JavaSymbolProvider(project), FirLibrarySymbolProviderImpl(this))) ) registerComponent(FirQualifierResolver::class, FirQualifierResolverImpl(this)) registerComponent(FirTypeResolver::class, FirTypeResolverImpl()) diff --git a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java index 6ee45486bd2..bfc7f7a299c 100644 --- a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java @@ -41,14 +41,12 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { @TestMetadata("ft.kt") public void testFt() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/ft.kt"); - doTest(fileName); + runTest("compiler/testData/fir/resolve/ft.kt"); } @TestMetadata("functionTypes.kt") public void testFunctionTypes() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/functionTypes.kt"); - doTest(fileName); + runTest("compiler/testData/fir/resolve/functionTypes.kt"); } @TestMetadata("genericFunctions.kt") @@ -76,6 +74,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { runTest("compiler/testData/fir/resolve/simpleTypeAlias.kt"); } + @TestMetadata("treeSet.kt") + public void testTreeSet() throws Exception { + runTest("compiler/testData/fir/resolve/treeSet.kt"); + } + @TestMetadata("TwoDeclarationsInSameFile.kt") public void testTwoDeclarationsInSameFile() throws Exception { runTest("compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt"); @@ -123,8 +126,7 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { @TestMetadata("Annotations.kt") public void testAnnotations() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/Annotations.kt"); - doTest(fileName); + runTest("compiler/testData/fir/resolve/multifile/Annotations.kt"); } @TestMetadata("NestedSuperType.kt") diff --git a/settings.gradle b/settings.gradle index d2140a0a324..6cbae0bf19e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -33,6 +33,7 @@ include ":kotlin-build-common", ":compiler:fir:tree:visitors-generator", ":compiler:fir:psi2fir", ":compiler:fir:resolve", + ":compiler:fir:java", ":compiler:frontend", ":compiler:frontend.java", ":compiler:frontend.script",