FIR: implement -Xfriend-paths

This commit is contained in:
pyos
2021-01-07 14:25:24 +01:00
committed by Mikhail Glukhikh
parent bd708da82c
commit f618763250
12 changed files with 101 additions and 15 deletions
@@ -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
}
@@ -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
}
}
@@ -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()
@@ -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
@@ -0,0 +1,10 @@
import a.*
private fun test(i: InternalInterface): InternalTypealias {
PublicClass().internalMemberFun()
PublicClass.Companion
internalFun(internalVal)
return i
}
@@ -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>"))
}
}
}
@@ -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"))