FIR: implement -Xfriend-paths
This commit is contained in:
+1
-1
@@ -328,7 +328,7 @@ object KotlinToJVMBytecodeCompiler {
|
||||
project, environment.createPackagePartProvider(librariesScope)
|
||||
)
|
||||
|
||||
val moduleInfo = FirJvmModuleInfo(module.getModuleName(), listOf(librariesModuleInfo))
|
||||
val moduleInfo = FirJvmModuleInfo(module, listOf(librariesModuleInfo))
|
||||
val session = FirSessionFactory.createJavaModuleBasedSession(moduleInfo, provider, scope, project) {
|
||||
if (extendedAnalysisMode) {
|
||||
registerExtendedCommonCheckers()
|
||||
|
||||
@@ -58,6 +58,7 @@ fun FirSession.registerResolveComponents() {
|
||||
@OptIn(SessionConfiguration::class)
|
||||
fun FirSession.registerJavaSpecificResolveComponents() {
|
||||
register(FirVisibilityChecker::class, FirJavaVisibilityChecker)
|
||||
register(FirModuleVisibilityChecker::class, FirJvmModuleVisibilityChecker(this))
|
||||
register(ConeCallConflictResolverFactory::class, JvmCallConflictResolverFactory)
|
||||
register(FirEffectiveVisibilityResolver::class, FirJvmEffectiveVisibilityResolver(this))
|
||||
register(FirPlatformClassMapper::class, FirJavaClassMapper(this))
|
||||
|
||||
@@ -6,23 +6,30 @@
|
||||
package org.jetbrains.kotlin.fir.session
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||
|
||||
class FirJvmModuleInfo(override val name: Name, val dependencies: List<ModuleInfo>) : ModuleInfo {
|
||||
class FirJvmModuleInfo(
|
||||
override val name: Name,
|
||||
val dependencies: List<ModuleInfo> = emptyList(),
|
||||
val friendPaths: List<String> = emptyList(),
|
||||
val outputDirectory: String? = null
|
||||
) : ModuleInfo {
|
||||
companion object {
|
||||
val LIBRARIES_MODULE_NAME = Name.special("<dependencies>")
|
||||
|
||||
fun createForLibraries(mainModuleName: String? = null): FirJvmModuleInfo {
|
||||
val name = mainModuleName?.let { Name.special("<dependencies of $it>") } ?: LIBRARIES_MODULE_NAME
|
||||
return FirJvmModuleInfo(name, emptyList())
|
||||
return FirJvmModuleInfo(name)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(moduleName: String, dependencies: List<ModuleInfo>) : this(Name.identifier(moduleName), dependencies)
|
||||
constructor(module: Module, dependencies: List<ModuleInfo>) :
|
||||
this(Name.identifier(module.getModuleName()), dependencies, module.getFriendPaths(), module.getOutputDirectory())
|
||||
|
||||
override val platform: TargetPlatform
|
||||
get() = JvmPlatforms.unspecifiedJvmPlatform
|
||||
@@ -30,7 +37,6 @@ class FirJvmModuleInfo(override val name: Name, val dependencies: List<ModuleInf
|
||||
override val analyzerServices: PlatformDependentAnalyzerServices
|
||||
get() = JvmPlatformAnalyzerServices
|
||||
|
||||
override fun dependencies(): List<ModuleInfo> {
|
||||
return dependencies
|
||||
}
|
||||
override fun dependencies(): List<ModuleInfo> =
|
||||
dependencies
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.session
|
||||
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import org.jetbrains.kotlin.fir.FirModuleVisibilityChecker
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.containerSource
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
|
||||
import java.nio.file.Paths
|
||||
|
||||
class FirJvmModuleVisibilityChecker(private val session: FirSession) : FirModuleVisibilityChecker {
|
||||
override fun isInFriendModule(declaration: FirMemberDeclaration): Boolean {
|
||||
val moduleInfo = session.moduleInfo as? FirJvmModuleInfo ?: return false
|
||||
val binaryClass = when (val source = declaration.containerSource) {
|
||||
is KotlinJvmBinarySourceElement -> source.binaryClass
|
||||
is JvmPackagePartSource -> source.knownJvmBinaryClass
|
||||
else -> null
|
||||
} as? VirtualFileKotlinClass ?: return false
|
||||
// For incremental compilation, the already compiled part of the module should be accessible.
|
||||
return moduleInfo.friendPaths.any { binaryClass.isIn(it) } || moduleInfo.outputDirectory?.let { binaryClass.isIn(it) } == true
|
||||
}
|
||||
|
||||
private fun VirtualFileKotlinClass.isIn(jarOrDirectory: String): Boolean =
|
||||
when (file.fileSystem.protocol) {
|
||||
StandardFileSystems.FILE_PROTOCOL ->
|
||||
VfsUtilCore.virtualToIoFile(file).toPath().startsWith(jarOrDirectory)
|
||||
StandardFileSystems.JAR_PROTOCOL ->
|
||||
VfsUtilCore.getVirtualFileForJar(file)?.let(VfsUtilCore::virtualToIoFile)?.toPath() == Paths.get(jarOrDirectory)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
+1
@@ -449,6 +449,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadConstructorAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||
containerSource = c.containerSource
|
||||
}.build().apply {
|
||||
containingClassAttr = c.dispatchReceiver!!.lookupTag
|
||||
versionRequirementsTable = c.versionRequirementTable
|
||||
|
||||
@@ -22,6 +22,10 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
interface FirModuleVisibilityChecker : FirSessionComponent {
|
||||
fun isInFriendModule(declaration: FirMemberDeclaration): Boolean
|
||||
}
|
||||
|
||||
abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
@NoMutableState
|
||||
object Default : FirVisibilityChecker() {
|
||||
@@ -54,14 +58,13 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
val session = callInfo.session
|
||||
val provider = session.firProvider
|
||||
|
||||
|
||||
return when (declaration.visibility) {
|
||||
Visibilities.Internal -> {
|
||||
declaration.session == callInfo.session
|
||||
declaration.session == session || session.moduleVisibilityChecker?.isInFriendModule(declaration) == true
|
||||
}
|
||||
Visibilities.Private, Visibilities.PrivateToThis -> {
|
||||
val ownerId = symbol.getOwnerId()
|
||||
if (declaration.session == callInfo.session) {
|
||||
if (declaration.session == session) {
|
||||
if (ownerId == null || declaration is FirConstructor && declaration.isFromSealedClass) {
|
||||
val candidateFile = when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> provider.getFirClassifierContainerFileIfAny(symbol)
|
||||
@@ -194,6 +197,7 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
||||
}
|
||||
}
|
||||
|
||||
val FirSession.moduleVisibilityChecker: FirModuleVisibilityChecker? by FirSession.nullableSessionComponentAccessor()
|
||||
val FirSession.visibilityChecker: FirVisibilityChecker by FirSession.sessionComponentAccessor()
|
||||
|
||||
fun AbstractFirBasedSymbol<*>.getOwnerId(): ClassId? {
|
||||
|
||||
@@ -132,6 +132,13 @@ fun FirRegularClass.addDeclaration(declaration: FirDeclaration) {
|
||||
private object SourceElementKey : FirDeclarationDataKey()
|
||||
var FirRegularClass.sourceElement: SourceElement? by FirDeclarationDataRegistry.data(SourceElementKey)
|
||||
|
||||
val FirMemberDeclaration.containerSource: SourceElement?
|
||||
get() = when (this) {
|
||||
is FirCallableMemberDeclaration<*> -> containerSource
|
||||
is FirRegularClass -> sourceElement
|
||||
else -> null
|
||||
}
|
||||
|
||||
private object IsFromVarargKey : FirDeclarationDataKey()
|
||||
var FirProperty.isFromVararg: Boolean? by FirDeclarationDataRegistry.data(IsFromVarargKey)
|
||||
private object IsReferredViaField : FirDeclarationDataKey()
|
||||
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
package a
|
||||
|
||||
internal interface InternalInterface
|
||||
|
||||
public class PublicClass internal constructor() {
|
||||
internal fun internalMemberFun() {}
|
||||
|
||||
internal companion object {}
|
||||
}
|
||||
|
||||
internal val internalVal = ""
|
||||
|
||||
internal fun internalFun(s: String): String = s
|
||||
|
||||
internal typealias InternalTypealias = InternalInterface
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
OK
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import a.*
|
||||
|
||||
private fun test(i: InternalInterface): InternalTypealias {
|
||||
PublicClass().internalMemberFun()
|
||||
PublicClass.Companion
|
||||
|
||||
internalFun(internalVal)
|
||||
|
||||
return i
|
||||
}
|
||||
+2
-5
@@ -27,16 +27,13 @@ class FirModuleInfoProvider(
|
||||
module.dependencies.mapTo(dependencies) {
|
||||
convertToFirModuleInfo(testServices.dependencyProvider.getTestModule(it.moduleName))
|
||||
}
|
||||
FirJvmModuleInfo(
|
||||
module.name,
|
||||
dependencies
|
||||
)
|
||||
FirJvmModuleInfo(Name.identifier(module.name), dependencies)
|
||||
}
|
||||
}
|
||||
|
||||
fun builtinsModuleInfoForModule(module: TestModule): FirJvmModuleInfo {
|
||||
return builtinsByModule.getOrPut(module) {
|
||||
FirJvmModuleInfo(Name.special("<built-ins>"), emptyList())
|
||||
FirJvmModuleInfo(Name.special("<built-ins>"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -626,6 +626,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
|
||||
compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xfriend-paths=${library.path}"))
|
||||
}
|
||||
|
||||
fun testInternalFromFriendModuleFir() {
|
||||
val library = compileLibrary("library")
|
||||
compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xfriend-paths=${library.path}", "-Xuse-fir"))
|
||||
}
|
||||
|
||||
fun testJvmDefaultClashWithOld() {
|
||||
val library = compileLibrary("library", additionalOptions = listOf("-Xjvm-default=disable"))
|
||||
compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-jvm-target", "1.8", "-Xjvm-default=all"))
|
||||
|
||||
Reference in New Issue
Block a user