FIR: implement -Xfriend-paths
This commit is contained in:
+1
-1
@@ -328,7 +328,7 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
project, environment.createPackagePartProvider(librariesScope)
|
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) {
|
val session = FirSessionFactory.createJavaModuleBasedSession(moduleInfo, provider, scope, project) {
|
||||||
if (extendedAnalysisMode) {
|
if (extendedAnalysisMode) {
|
||||||
registerExtendedCommonCheckers()
|
registerExtendedCommonCheckers()
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ fun FirSession.registerResolveComponents() {
|
|||||||
@OptIn(SessionConfiguration::class)
|
@OptIn(SessionConfiguration::class)
|
||||||
fun FirSession.registerJavaSpecificResolveComponents() {
|
fun FirSession.registerJavaSpecificResolveComponents() {
|
||||||
register(FirVisibilityChecker::class, FirJavaVisibilityChecker)
|
register(FirVisibilityChecker::class, FirJavaVisibilityChecker)
|
||||||
|
register(FirModuleVisibilityChecker::class, FirJvmModuleVisibilityChecker(this))
|
||||||
register(ConeCallConflictResolverFactory::class, JvmCallConflictResolverFactory)
|
register(ConeCallConflictResolverFactory::class, JvmCallConflictResolverFactory)
|
||||||
register(FirEffectiveVisibilityResolver::class, FirJvmEffectiveVisibilityResolver(this))
|
register(FirEffectiveVisibilityResolver::class, FirJvmEffectiveVisibilityResolver(this))
|
||||||
register(FirPlatformClassMapper::class, FirJavaClassMapper(this))
|
register(FirPlatformClassMapper::class, FirJavaClassMapper(this))
|
||||||
|
|||||||
@@ -6,23 +6,30 @@
|
|||||||
package org.jetbrains.kotlin.fir.session
|
package org.jetbrains.kotlin.fir.session
|
||||||
|
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
|
import org.jetbrains.kotlin.modules.Module
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
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 {
|
companion object {
|
||||||
val LIBRARIES_MODULE_NAME = Name.special("<dependencies>")
|
val LIBRARIES_MODULE_NAME = Name.special("<dependencies>")
|
||||||
|
|
||||||
fun createForLibraries(mainModuleName: String? = null): FirJvmModuleInfo {
|
fun createForLibraries(mainModuleName: String? = null): FirJvmModuleInfo {
|
||||||
val name = mainModuleName?.let { Name.special("<dependencies of $it>") } ?: LIBRARIES_MODULE_NAME
|
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
|
override val platform: TargetPlatform
|
||||||
get() = JvmPlatforms.unspecifiedJvmPlatform
|
get() = JvmPlatforms.unspecifiedJvmPlatform
|
||||||
@@ -30,7 +37,6 @@ class FirJvmModuleInfo(override val name: Name, val dependencies: List<ModuleInf
|
|||||||
override val analyzerServices: PlatformDependentAnalyzerServices
|
override val analyzerServices: PlatformDependentAnalyzerServices
|
||||||
get() = JvmPlatformAnalyzerServices
|
get() = JvmPlatformAnalyzerServices
|
||||||
|
|
||||||
override fun dependencies(): List<ModuleInfo> {
|
override fun dependencies(): List<ModuleInfo> =
|
||||||
return dependencies
|
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 +=
|
annotations +=
|
||||||
c.annotationDeserializer.loadConstructorAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
c.annotationDeserializer.loadConstructorAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||||
|
containerSource = c.containerSource
|
||||||
}.build().apply {
|
}.build().apply {
|
||||||
containingClassAttr = c.dispatchReceiver!!.lookupTag
|
containingClassAttr = c.dispatchReceiver!!.lookupTag
|
||||||
versionRequirementsTable = c.versionRequirementTable
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
interface FirModuleVisibilityChecker : FirSessionComponent {
|
||||||
|
fun isInFriendModule(declaration: FirMemberDeclaration): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
abstract class FirVisibilityChecker : FirSessionComponent {
|
abstract class FirVisibilityChecker : FirSessionComponent {
|
||||||
@NoMutableState
|
@NoMutableState
|
||||||
object Default : FirVisibilityChecker() {
|
object Default : FirVisibilityChecker() {
|
||||||
@@ -54,14 +58,13 @@ abstract class FirVisibilityChecker : FirSessionComponent {
|
|||||||
val session = callInfo.session
|
val session = callInfo.session
|
||||||
val provider = session.firProvider
|
val provider = session.firProvider
|
||||||
|
|
||||||
|
|
||||||
return when (declaration.visibility) {
|
return when (declaration.visibility) {
|
||||||
Visibilities.Internal -> {
|
Visibilities.Internal -> {
|
||||||
declaration.session == callInfo.session
|
declaration.session == session || session.moduleVisibilityChecker?.isInFriendModule(declaration) == true
|
||||||
}
|
}
|
||||||
Visibilities.Private, Visibilities.PrivateToThis -> {
|
Visibilities.Private, Visibilities.PrivateToThis -> {
|
||||||
val ownerId = symbol.getOwnerId()
|
val ownerId = symbol.getOwnerId()
|
||||||
if (declaration.session == callInfo.session) {
|
if (declaration.session == session) {
|
||||||
if (ownerId == null || declaration is FirConstructor && declaration.isFromSealedClass) {
|
if (ownerId == null || declaration is FirConstructor && declaration.isFromSealedClass) {
|
||||||
val candidateFile = when (symbol) {
|
val candidateFile = when (symbol) {
|
||||||
is FirClassLikeSymbol<*> -> provider.getFirClassifierContainerFileIfAny(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()
|
val FirSession.visibilityChecker: FirVisibilityChecker by FirSession.sessionComponentAccessor()
|
||||||
|
|
||||||
fun AbstractFirBasedSymbol<*>.getOwnerId(): ClassId? {
|
fun AbstractFirBasedSymbol<*>.getOwnerId(): ClassId? {
|
||||||
|
|||||||
@@ -132,6 +132,13 @@ fun FirRegularClass.addDeclaration(declaration: FirDeclaration) {
|
|||||||
private object SourceElementKey : FirDeclarationDataKey()
|
private object SourceElementKey : FirDeclarationDataKey()
|
||||||
var FirRegularClass.sourceElement: SourceElement? by FirDeclarationDataRegistry.data(SourceElementKey)
|
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()
|
private object IsFromVarargKey : FirDeclarationDataKey()
|
||||||
var FirProperty.isFromVararg: Boolean? by FirDeclarationDataRegistry.data(IsFromVarargKey)
|
var FirProperty.isFromVararg: Boolean? by FirDeclarationDataRegistry.data(IsFromVarargKey)
|
||||||
private object IsReferredViaField : FirDeclarationDataKey()
|
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) {
|
module.dependencies.mapTo(dependencies) {
|
||||||
convertToFirModuleInfo(testServices.dependencyProvider.getTestModule(it.moduleName))
|
convertToFirModuleInfo(testServices.dependencyProvider.getTestModule(it.moduleName))
|
||||||
}
|
}
|
||||||
FirJvmModuleInfo(
|
FirJvmModuleInfo(Name.identifier(module.name), dependencies)
|
||||||
module.name,
|
|
||||||
dependencies
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun builtinsModuleInfoForModule(module: TestModule): FirJvmModuleInfo {
|
fun builtinsModuleInfoForModule(module: TestModule): FirJvmModuleInfo {
|
||||||
return builtinsByModule.getOrPut(module) {
|
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}"))
|
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() {
|
fun testJvmDefaultClashWithOld() {
|
||||||
val library = compileLibrary("library", additionalOptions = listOf("-Xjvm-default=disable"))
|
val library = compileLibrary("library", additionalOptions = listOf("-Xjvm-default=disable"))
|
||||||
compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-jvm-target", "1.8", "-Xjvm-default=all"))
|
compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-jvm-target", "1.8", "-Xjvm-default=all"))
|
||||||
|
|||||||
Reference in New Issue
Block a user