diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirClassifierResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirClassifierResolveTransformer.kt index 31ce397b465..8093221aa0a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirClassifierResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirClassifierResolveTransformer.kt @@ -13,6 +13,10 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedClassImpl import org.jetbrains.kotlin.fir.descriptors.ConeClassifierDescriptor import org.jetbrains.kotlin.fir.descriptors.ConeTypeParameterDescriptor import org.jetbrains.kotlin.fir.resolve.FirTypeResolver +import org.jetbrains.kotlin.fir.scopes.FirImportingScope +import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeImportingScope +import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitImportingScope +import org.jetbrains.kotlin.fir.scopes.impl.FirSelfImportingScope import org.jetbrains.kotlin.fir.types.FirResolvedType import org.jetbrains.kotlin.fir.types.FirType import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeImpl @@ -29,15 +33,27 @@ class FirClassifierResolveTransformer : FirTransformer() { lateinit var packageFqName: FqNameUnsafe + lateinit var importingScope: FirImportingScope + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { packageFqName = file.packageFqName.toUnsafe() + importingScope = FirCompositeImportingScope( + FirExplicitImportingScope(file.imports), + FirSelfImportingScope(file.packageFqName.toUnsafe(), file.session) + ) return file.also { it.acceptChildren(this, null) }.compose() } // TODO: Extract to separate transformer? override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult { val typeResolver = FirTypeResolver.getInstance(type.session) - return FirResolvedTypeImpl(type.session, type.psi, typeResolver.resolveType(type), false, type.annotations).compose() + return FirResolvedTypeImpl( + type.session, + type.psi, + typeResolver.resolveType(type, importingScope), + false, + type.annotations + ).compose() } override fun transformResolvedType(resolvedType: FirResolvedType, data: Nothing?): CompositeTransformResult { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirQualifierResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirQualifierResolver.kt index 74259ce7584..044bc2acefa 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirQualifierResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirQualifierResolver.kt @@ -6,14 +6,19 @@ package org.jetbrains.kotlin.fir.resolve import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.UnambiguousFqName import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirQualifierPart +import org.jetbrains.kotlin.name.FqName interface FirQualifierResolver { + fun resolveTypeWithPrefix(parts: List, prefix: UnambiguousFqName): ConeKotlinType? fun resolveType(parts: List): ConeKotlinType? + fun resolveImport(fqName: FqName): UnambiguousFqName? + companion object { fun getInstance(session: FirSession): FirQualifierResolver = session.service() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirQualifierResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirQualifierResolverImpl.kt deleted file mode 100644 index f232febb736..00000000000 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirQualifierResolverImpl.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.resolve - -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.UnambiguousFqName -import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl -import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionInImpl -import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionOutImpl -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.types.Variance - -class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver { - override fun resolveType(parts: List): ConeKotlinType? { - val firProvider = FirProvider.getInstance(session) - - if (parts.isNotEmpty()) { - val lastPart = mutableListOf() - val firstPart = parts.toMutableList() - - while (firstPart.isNotEmpty()) { - lastPart.add(0, firstPart.last()) - firstPart.removeAt(firstPart.lastIndex) - - val fqName = UnambiguousFqName(firstPart.toFqNameUnsafe(), lastPart.toFqName()) - val foundClassifier = firProvider.getFirClassifierByFqName(fqName) - - if (foundClassifier != null) { - return ConeClassTypeImpl(fqName, parts.flatMap { - it.typeArguments.map { - when (it) { - is FirStarProjection -> StarProjection - is FirTypeProjectionWithVariance -> { - val type = (it.type as FirResolvedType).type - when (it.variance) { - Variance.INVARIANT -> type - Variance.IN_VARIANCE -> ConeKotlinTypeProjectionInImpl(type) - Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOutImpl(type) - } - } - else -> error("!") - } - } - }) - } - } - return null - } else { - return null - } - } - - private fun List.toFqNameUnsafe() = toFqName().toUnsafe() - private fun List.toFqName() = fold(FqName.ROOT) { a, b -> a.child(b.name) } - - -} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt index 57190ee47a0..a93c9121d72 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirTypeResolver.kt @@ -6,13 +6,14 @@ package org.jetbrains.kotlin.fir.resolve import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.scopes.FirImportingScope import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.types.FirType import org.jetbrains.kotlin.fir.types.ConeKotlinType interface FirTypeResolver { - fun resolveType(type: FirType): ConeKotlinType + fun resolveType(type: FirType, importingScope: FirImportingScope): ConeKotlinType companion object { fun getInstance(session: FirSession): FirTypeResolver = session.service() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirQualifierResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirQualifierResolverImpl.kt new file mode 100644 index 00000000000..339f30b36a8 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirQualifierResolverImpl.kt @@ -0,0 +1,103 @@ +/* + * 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.resolve.impl + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.UnambiguousFqName +import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.resolve.FirProvider +import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl +import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionInImpl +import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionOutImpl +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.types.Variance + +class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver { + + private fun FirMemberDeclaration.toConeKotlinType(fqName: UnambiguousFqName, parts: List): ConeKotlinType? { + return ConeClassTypeImpl(fqName, parts.flatMap { + it.typeArguments.map { + when (it) { + is FirStarProjection -> StarProjection + is FirTypeProjectionWithVariance -> { + val type = (it.type as FirResolvedType).type + when (it.variance) { + Variance.INVARIANT -> type + Variance.IN_VARIANCE -> ConeKotlinTypeProjectionInImpl(type) + Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOutImpl(type) + } + } + else -> error("!") + } + } + }) + } + + override fun resolveTypeWithPrefix(parts: List, prefix: UnambiguousFqName): ConeKotlinType? { + val firProvider = FirProvider.getInstance(session) + + val fqName = UnambiguousFqName(prefix.packageFqName, parts.fold(prefix.classFqName) { prefix, suffix -> prefix.child(suffix.name) }) + val foundClassifier = firProvider.getFirClassifierByFqName(fqName) + + return foundClassifier?.toConeKotlinType(fqName, parts) + } + + override fun resolveType(parts: List): ConeKotlinType? { + val firProvider = FirProvider.getInstance(session) + + if (parts.isNotEmpty()) { + val lastPart = mutableListOf() + val firstPart = parts.toMutableList() + + while (firstPart.isNotEmpty()) { + lastPart.add(0, firstPart.last()) + firstPart.removeAt(firstPart.lastIndex) + + val fqName = UnambiguousFqName(firstPart.toFqNameUnsafe(), lastPart.toFqName()) + val foundClassifier = firProvider.getFirClassifierByFqName(fqName) + + if (foundClassifier != null) { + return foundClassifier.toConeKotlinType(fqName, parts) + } + } + return null + } else { + return null + } + } + + // TODO: extract common part from resolveType/Import + override fun resolveImport(fqName: FqName): UnambiguousFqName? { + val firProvider = FirProvider.getInstance(session) + + if (!fqName.isRoot) { + val lastPart = mutableListOf() + var firstPart = fqName + + while (!firstPart.isRoot) { + lastPart.add(0, firstPart.shortName().asString()) + firstPart = firstPart.parent() + + val fqName = UnambiguousFqName(firstPart.toUnsafe(), FqName.fromSegments(lastPart)) + val foundClassifier = firProvider.getFirClassifierByFqName(fqName) + + if (foundClassifier != null) { + return fqName + } + } + return null + } else { + return null + } + } + + private fun List.toFqNameUnsafe() = toFqName().toUnsafe() + private fun List.toFqName() = fold(FqName.ROOT) { a, b -> a.child(b.name) } + + +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirTypeResolverImpl.kt index c754fd3b4c8..e8ff8a999a5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirTypeResolverImpl.kt @@ -7,17 +7,26 @@ package org.jetbrains.kotlin.fir.resolve.impl import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver import org.jetbrains.kotlin.fir.resolve.FirTypeResolver +import org.jetbrains.kotlin.fir.scopes.FirImportingScope import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeKotlinErrorType class FirTypeResolverImpl : FirTypeResolver { - override fun resolveType(type: FirType): ConeKotlinType { + override fun resolveType(type: FirType, importingScope: FirImportingScope): ConeKotlinType { return when (type) { is FirResolvedType -> type.type is FirUserType -> { + val qualifierResolver = FirQualifierResolver.getInstance(type.session) + + var resolvedType: ConeKotlinType? = null + importingScope.processClassifiersByName(type.qualifier.first().name) { fqName -> + resolvedType = qualifierResolver.resolveTypeWithPrefix(type.qualifier.drop(1), fqName) + resolvedType == null + } + // TODO: Imports - qualifierResolver.resolveType(type.qualifier) ?: ConeKotlinErrorType("Failed to resolve qualified type") + resolvedType ?: qualifierResolver.resolveType(type.qualifier) ?: ConeKotlinErrorType("Failed to resolve qualified type") } is FirErrorType -> { ConeKotlinErrorType(type.reason) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/FirImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/FirImportingScope.kt new file mode 100644 index 00000000000..989a669ff1e --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/FirImportingScope.kt @@ -0,0 +1,13 @@ +/* + * 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 + +import org.jetbrains.kotlin.fir.UnambiguousFqName +import org.jetbrains.kotlin.name.Name + +interface FirImportingScope { + fun processClassifiersByName(name: Name, processor: (UnambiguousFqName) -> Boolean): Boolean +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirCompositeImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirCompositeImportingScope.kt new file mode 100644 index 00000000000..c2f979c7f42 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirCompositeImportingScope.kt @@ -0,0 +1,21 @@ +/* + * 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.UnambiguousFqName +import org.jetbrains.kotlin.fir.scopes.FirImportingScope +import org.jetbrains.kotlin.name.Name + +class FirCompositeImportingScope(vararg val scopes: FirImportingScope) : FirImportingScope { + override fun processClassifiersByName(name: Name, processor: (UnambiguousFqName) -> Boolean): Boolean { + for (scope in scopes) { + if (!scope.processClassifiersByName(name, processor)) { + return false + } + } + return true + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirExplicitImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirExplicitImportingScope.kt new file mode 100644 index 00000000000..18164b79d0b --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirExplicitImportingScope.kt @@ -0,0 +1,38 @@ +/* + * 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.UnambiguousFqName +import org.jetbrains.kotlin.fir.declarations.FirImport +import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver +import org.jetbrains.kotlin.fir.scopes.FirImportingScope +import org.jetbrains.kotlin.name.Name + +class FirExplicitImportingScope(imports: List) : FirImportingScope { + + // TODO: Resolve imports! Instead of computing it resolution results here + private val simpleImports = + imports.filter { !it.isAllUnder && it.aliasName == null && it.importedFqName != null } + .mapNotNull { it.resolve() } + .groupBy { it.classFqName.shortName() } + + private fun FirImport.resolve(): UnambiguousFqName? { + val session = session + val qualifierResolver = FirQualifierResolver.getInstance(session) + return qualifierResolver.resolveImport(importedFqName!!) + } + + override fun processClassifiersByName(name: Name, processor: (UnambiguousFqName) -> Boolean): Boolean { + val imports = simpleImports[name] ?: return true + for (import in imports) { + if (!processor(import)) { + return false + } + } + return true + } + +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSelfImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSelfImportingScope.kt new file mode 100644 index 00000000000..f5e2b94a835 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSelfImportingScope.kt @@ -0,0 +1,32 @@ +/* + * 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.UnambiguousFqName +import org.jetbrains.kotlin.fir.resolve.FirProvider +import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver +import org.jetbrains.kotlin.fir.scopes.FirImportingScope +import org.jetbrains.kotlin.fir.service +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.name.Name + +class FirSelfImportingScope(val fqName: FqNameUnsafe, val session: FirSession) : FirImportingScope { + override fun processClassifiersByName(name: Name, processor: (UnambiguousFqName) -> Boolean): Boolean { + + + val unambiguousFqName = UnambiguousFqName(fqName, FqName.topLevel(name)) + + val firProvider = session.service() + + if (firProvider.getFirClassifierByFqName(unambiguousFqName) != null) { + return processor(unambiguousFqName) + } else { + return true + } + } +} \ No newline at end of file diff --git a/compiler/testData/fir/resolve/NestedSuperType.kt b/compiler/testData/fir/resolve/NestedSuperType.kt new file mode 100644 index 00000000000..b0c32365dcb --- /dev/null +++ b/compiler/testData/fir/resolve/NestedSuperType.kt @@ -0,0 +1,9 @@ +package p + +abstract class My { + abstract class NestedOne : My() { + abstract class NestedTwo : NestedOne() { + + } + } +} \ No newline at end of file diff --git a/compiler/testData/fir/resolve/NestedSuperType.txt b/compiler/testData/fir/resolve/NestedSuperType.txt new file mode 100644 index 00000000000..e27c0724bd6 --- /dev/null +++ b/compiler/testData/fir/resolve/NestedSuperType.txt @@ -0,0 +1,9 @@ +FILE: NestedSuperType.kt + unknown abstract class My() { + unknown abstract class NestedOne() : R/p.My/ { + unknown abstract class NestedTwo() : R/error: Failed to resolve qualified type/ { + } + + } + + } diff --git a/compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt b/compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt new file mode 100644 index 00000000000..030f50027df --- /dev/null +++ b/compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt @@ -0,0 +1,6 @@ +package p + + +open class A + +class B : A() \ No newline at end of file diff --git a/compiler/testData/fir/resolve/TwoDeclarationsInSameFile.txt b/compiler/testData/fir/resolve/TwoDeclarationsInSameFile.txt new file mode 100644 index 00000000000..6a35faf12ed --- /dev/null +++ b/compiler/testData/fir/resolve/TwoDeclarationsInSameFile.txt @@ -0,0 +1,5 @@ +FILE: TwoDeclarationsInSameFile.kt + unknown open class A() { + } + unknown final class B() : R/p.A/ { + } diff --git a/compiler/testData/fir/resolve/multifile/simpleImport.1.kt b/compiler/testData/fir/resolve/multifile/simpleImport.1.kt new file mode 100644 index 00000000000..83ba1cf1ad1 --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImport.1.kt @@ -0,0 +1,3 @@ +package b + +abstract class MyClass \ No newline at end of file diff --git a/compiler/testData/fir/resolve/multifile/simpleImport.kt b/compiler/testData/fir/resolve/multifile/simpleImport.kt new file mode 100644 index 00000000000..f2ec0ea57b5 --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImport.kt @@ -0,0 +1,4 @@ +package a +import b.MyClass + +class YourClass : MyClass \ No newline at end of file diff --git a/compiler/testData/fir/resolve/multifile/simpleImport.txt b/compiler/testData/fir/resolve/multifile/simpleImport.txt new file mode 100644 index 00000000000..5fdf68bcdf6 --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImport.txt @@ -0,0 +1,3 @@ +FILE: simpleImport.kt + unknown final class YourClass() : R/b.MyClass/ { + } diff --git a/compiler/testData/fir/resolve/multifile/simpleImportNested.1.kt b/compiler/testData/fir/resolve/multifile/simpleImportNested.1.kt new file mode 100644 index 00000000000..e9b54c9a2df --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImportNested.1.kt @@ -0,0 +1,5 @@ +package a + +class MyClass { + open class MyNested +} \ No newline at end of file diff --git a/compiler/testData/fir/resolve/multifile/simpleImportNested.kt b/compiler/testData/fir/resolve/multifile/simpleImportNested.kt new file mode 100644 index 00000000000..f329620b08d --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImportNested.kt @@ -0,0 +1,5 @@ +package b + +import a.MyClass.MyNested + +class YourClass : MyNested() \ No newline at end of file diff --git a/compiler/testData/fir/resolve/multifile/simpleImportNested.txt b/compiler/testData/fir/resolve/multifile/simpleImportNested.txt new file mode 100644 index 00000000000..5aa9337ba6a --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImportNested.txt @@ -0,0 +1,3 @@ +FILE: simpleImportNested.kt + unknown final class YourClass() : R/a.MyClass.MyNested/ { + } diff --git a/compiler/testData/fir/resolve/multifile/simpleImportOuter.1.kt b/compiler/testData/fir/resolve/multifile/simpleImportOuter.1.kt new file mode 100644 index 00000000000..be937a512cb --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImportOuter.1.kt @@ -0,0 +1,5 @@ +package a + +class Outer { + open class Nested +} \ No newline at end of file diff --git a/compiler/testData/fir/resolve/multifile/simpleImportOuter.kt b/compiler/testData/fir/resolve/multifile/simpleImportOuter.kt new file mode 100644 index 00000000000..1c953ed57f5 --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImportOuter.kt @@ -0,0 +1,5 @@ +package b + +import a.Outer + +class My : Outer.Nested() \ No newline at end of file diff --git a/compiler/testData/fir/resolve/multifile/simpleImportOuter.txt b/compiler/testData/fir/resolve/multifile/simpleImportOuter.txt new file mode 100644 index 00000000000..5fc2b0658c0 --- /dev/null +++ b/compiler/testData/fir/resolve/multifile/simpleImportOuter.txt @@ -0,0 +1,3 @@ +FILE: simpleImportOuter.kt + unknown final class My() : R/a.Outer.Nested/ { + } diff --git a/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveTestCase.kt b/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveTestCase.kt index 7ce6b554685..19c011174d5 100644 --- a/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveTestCase.kt +++ b/compiler/tests/org/jetbrains/kotlin/fir/AbstractFirResolveTestCase.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl +import org.jetbrains.kotlin.fir.resolve.impl.FirQualifierResolverImpl import org.jetbrains.kotlin.fir.resolve.impl.FirTypeResolverImpl import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.KotlinTestUtils @@ -24,11 +25,18 @@ abstract class AbstractFirResolveTestCase : KotlinTestWithEnvironment() { fun doTest(path: String) { val file = File(path) - val text = KotlinTestUtils.doLoadFile(file) - val ktFile = KotlinTestUtils.createFile(file.name, text, project) + val allFiles = listOf(file) + file.parentFile.listFiles { sibling -> + sibling.name.removePrefix(file.nameWithoutExtension).removeSuffix(file.extension).matches("\\.[0-9]+\\.".toRegex()) + } + val ktFiles = allFiles.map { + val text = KotlinTestUtils.doLoadFile(it) + KotlinTestUtils.createFile(it.name, text, project) + + } + val session = object : FirSessionBase() { init { registerComponent(FirProvider::class, FirProviderImpl(this)) @@ -38,14 +46,17 @@ abstract class AbstractFirResolveTestCase : KotlinTestWithEnvironment() { } val builder = RawFirBuilder(session) - val firFile = builder.buildFirFile(ktFile) - - (session.service() as FirProviderImpl).recordFile(firFile) val transformer = FirClassifierResolveTransformer() - firFile.transform(transformer, null) + val firFiles = ktFiles.map { + val firFile = builder.buildFirFile(it) + (session.service() as FirProviderImpl).recordFile(firFile) + firFile + }.onEach { + it.transform(transformer, null) + } - val firFileDump = StringBuilder().also { firFile.accept(FirRenderer(it), null) }.toString() + val firFileDump = StringBuilder().also { firFiles.first().accept(FirRenderer(it), null) }.toString() val expectedPath = path.replace(".kt", ".txt") KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump) } diff --git a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java index 2d9b6bd42b7..319fe18df12 100644 --- a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java @@ -22,7 +22,7 @@ import java.util.regex.Pattern; @RunWith(JUnit3RunnerWithInners.class) public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { public void testAllFilesPresentInResolve() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/fir/resolve"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/fir/resolve"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true); } @TestMetadata("F.kt") @@ -30,4 +30,43 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/F.kt"); doTest(fileName); } + + @TestMetadata("NestedSuperType.kt") + public void testNestedSuperType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/NestedSuperType.kt"); + doTest(fileName); + } + + @TestMetadata("TwoDeclarationsInSameFile.kt") + public void testTwoDeclarationsInSameFile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt"); + doTest(fileName); + } + + @TestMetadata("compiler/testData/fir/resolve/multifile") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multifile extends AbstractFirResolveTestCase { + public void testAllFilesPresentInMultifile() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/fir/resolve/multifile"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("simpleImport.kt") + public void testSimpleImport() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/simpleImport.kt"); + doTest(fileName); + } + + @TestMetadata("simpleImportNested.kt") + public void testSimpleImportNested() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/simpleImportNested.kt"); + doTest(fileName); + } + + @TestMetadata("simpleImportOuter.kt") + public void testSimpleImportOuter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/simpleImportOuter.kt"); + doTest(fileName); + } + } } diff --git a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt index 211d0a13f8a..f0b66b38fb2 100644 --- a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt +++ b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.AbstractFirResolveTestCase import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase import org.jetbrains.kotlin.generators.tests.generator.testGroup import org.jetbrains.kotlin.generators.util.KT_OR_KTS_WITHOUT_DOTS_IN_NAME +import org.jetbrains.kotlin.generators.util.KT_WITHOUT_DOTS_IN_NAME import org.jetbrains.kotlin.integration.AbstractAntTaskTest import org.jetbrains.kotlin.ir.AbstractIrCfgTestCase import org.jetbrains.kotlin.ir.AbstractIrJsTextTestCase @@ -204,7 +205,7 @@ fun main(args: Array) { } testClass { - model("fir/resolve") + model("fir/resolve", pattern = KT_WITHOUT_DOTS_IN_NAME) } testClass {