[Analysis API Standalone] fix common code analysis against a klib

^KT-63007 fixed
This commit is contained in:
Ilya Kirillov
2023-10-30 17:48:33 +01:00
committed by Space Team
parent a3bfe58415
commit 834927a901
6 changed files with 85 additions and 8 deletions
@@ -60,15 +60,21 @@ class LLFirStandaloneLibrarySymbolProviderFactory(private val project: Project)
packagePartProvider: PackagePartProvider,
scope: GlobalSearchScope,
): List<FirSymbolProvider> {
return listOf(
MetadataSymbolProvider(
session,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider as PackageAndMetadataPartProvider,
VirtualFileFinderFactory.getInstance(project).create(scope),
return buildList {
add(
MetadataSymbolProvider(
session,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider as PackageAndMetadataPartProvider,
VirtualFileFinderFactory.getInstance(project).create(scope),
)
)
)
val kLibs = moduleData.getLibraryKLibs()
if (kLibs.isNotEmpty()) {
add(KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, kLibs))
}
}
}
override fun createNativeLibrarySymbolProvider(
@@ -0,0 +1,5 @@
package commonKLib
fun commonKLibFunction(arg: String): Int {
return 1
}
@@ -0,0 +1,5 @@
import commonKLib.commonKLibFunction
fun main() {
commonKLibFunction("aaa")
}
@@ -80,6 +80,38 @@ class StandaloneSessionBuilderTest {
}
}
@Test
fun testResolveAgainstCommonKlib() {
lateinit var sourceModule: KtSourceModule
val session = buildStandaloneAnalysisAPISession {
registerProjectService(KtLifetimeTokenProvider::class.java, KtAlwaysAccessibleLifetimeTokenProvider())
buildKtModuleProvider {
platform = CommonPlatforms.defaultCommonPlatform
val kLib = addModule(
buildKtLibraryModule {
val compiledKLibRoot = compileCommonKlib(testDataPath("resolveAgainstCommonKLib/klibSrc"))
addBinaryRoot(compiledKLibRoot)
platform = CommonPlatforms.defaultCommonPlatform
libraryName = "klib"
}
)
sourceModule = addModule(
buildKtSourceModule {
addSourceRoot(testDataPath("resolveAgainstCommonKLib/src"))
addRegularDependency(kLib)
platform = CommonPlatforms.defaultCommonPlatform
moduleName = "source"
}
)
}
}
val ktFile = session.modulesWithFiles.getValue(sourceModule).single() as KtFile
val ktCallExpression = ktFile.findDescendantOfType<KtCallExpression>()!!
ktCallExpression.assertIsCallOf(CallableId(FqName("commonKLib"), Name.identifier("commonKLibFunction")))
}
@Test
fun testKotlinStdlibJvm() {
doTestKotlinStdLibResolve(JvmPlatforms.defaultJvmPlatform, PathUtil.kotlinPathsForDistDirectory.stdlibPath.toPath())
@@ -5,9 +5,30 @@
package org.jetbrains.kotlin.analysis.api.standalone.fir.test.cases.session.builder
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.absolutePathString
import kotlin.io.path.extension
import kotlin.streams.asSequence
internal fun testDataPath(path: String): Path {
return Paths.get("analysis/analysis-api-standalone/testData/sessionBuilder").resolve(path)
}
internal fun compileCommonKlib(kLibSourcesRoot: Path): Path {
val ktFiles = Files.walk(kLibSourcesRoot).asSequence().filter { it.extension == "kt" }.toList()
val testKlib = KtTestUtil.tmpDir("testLibrary").resolve("library.klib").toPath()
val arguments = buildList {
ktFiles.mapTo(this) { it.absolutePathString() }
add("-d")
add(testKlib.absolutePathString())
}
MockLibraryUtil.runMetadataCompiler(arguments)
return testKlib
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.js.K2JSCompiler
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
import org.jetbrains.kotlin.preloading.Preloader
import org.jetbrains.kotlin.test.KtAssert.assertTrue
@@ -177,6 +178,10 @@ object MockLibraryUtil {
runCompiler(compiler2JSClass, args)
}
fun runMetadataCompiler(args: List<String>) {
runCompiler(compiler2MetadataClass, args)
}
// Runs compiler in custom class loader to avoid effects caused by replacing Application with another one created in compiler.
private fun runCompiler(compilerClass: Class<*>, args: List<String>) {
val outStream = ByteArrayOutputStream()
@@ -223,6 +228,9 @@ object MockLibraryUtil {
private val compiler2JSClass: Class<*>
@Synchronized get() = loadCompilerClass(K2JSCompiler::class)
private val compiler2MetadataClass: Class<*>
@Synchronized get() = loadCompilerClass(K2MetadataCompiler::class)
@Synchronized
private fun loadCompilerClass(compilerClass: KClass<out CLICompiler<*>>): Class<*> {
val classLoader = compilerClassLoader.get() ?: createCompilerClassLoader().also { classLoader ->