[Analysis API Standalone] fix exception on invalid KLib from symbol provider

^KT-62244 fixed
This commit is contained in:
Ilya Kirillov
2023-10-06 21:20:44 +02:00
committed by Space Team
parent d005d1cd68
commit 4d38cc4548
3 changed files with 54 additions and 8 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.api.standalone.base.project.structure
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySymbolProviderFactory
@@ -26,7 +27,7 @@ import org.jetbrains.kotlin.library.metadata.impl.KlibResolvedModuleDescriptorsF
import org.jetbrains.kotlin.load.kotlin.PackageAndMetadataPartProvider
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
import org.jetbrains.kotlin.util.DummyLogger
import java.lang.IllegalStateException
class LLFirStandaloneLibrarySymbolProviderFactory(private val project: Project) : LLFirLibrarySymbolProviderFactory() {
override fun createJvmLibrarySymbolProvider(
@@ -107,10 +108,35 @@ class LLFirStandaloneLibrarySymbolProviderFactory(private val project: Project)
private fun LLFirModuleData.getLibraryKLibs(): List<KotlinLibrary> {
val ktLibraryModule = ktModule as? KtLibraryModule ?: return emptyList()
val resolveResult = CommonKLibResolver.resolve(
ktLibraryModule.getBinaryRoots().map { it.toString() },
DummyLogger
IntellijLogBasedLogger,
lenient = true,
)
return resolveResult.getFullResolvedList().map { it.library }
}
}
companion object {
private val LOG = Logger.getInstance(LLFirStandaloneLibrarySymbolProviderFactory::class.java)
}
private object IntellijLogBasedLogger : org.jetbrains.kotlin.util.Logger {
override fun log(message: String) {
LOG.info(message)
}
override fun error(message: String) {
LOG.error(message)
}
override fun warning(message: String) {
LOG.warn(message)
}
override fun fatal(message: String): Nothing {
throw IllegalStateException(message)
}
}
}
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
@@ -92,6 +93,18 @@ class StandaloneSessionBuilderTest {
doTestKotlinStdLibResolve(JsPlatforms.defaultJsPlatform, Paths.get("dist/kotlinc/lib/kotlin-stdlib-js.jar"))
}
@Test
fun testKotlinStdLibJsWithInvalidKlib() {
doTestKotlinStdLibResolve(
JsPlatforms.defaultJsPlatform,
Paths.get("dist/kotlinc/lib/kotlin-stdlib-js.jar"),
additionalStdlibRoots = listOf(
Paths.get(System.getProperty("java.home")), // directory which exists and does not contain KLibs inside
ForTestCompileRuntime.runtimeJarForTests().toPath(), // file which exists and not a KLib
)
)
}
@Test
fun testKotlinSourceModuleSessionBuilder() {
lateinit var sourceModule: KtSourceModule
@@ -122,7 +135,10 @@ class StandaloneSessionBuilderTest {
ktCallExpression.assertIsCallOf(CallableId(FqName.ROOT, Name.identifier("foo")))
}
private fun doTestKotlinStdLibResolve(targetPlatform: TargetPlatform, platformStdlibPath: Path) {
private fun doTestKotlinStdLibResolve(
targetPlatform: TargetPlatform, platformStdlibPath: Path,
additionalStdlibRoots: List<Path> = emptyList(),
) {
lateinit var sourceModule: KtSourceModule
val session = buildStandaloneAnalysisAPISession {
registerProjectService(KtLifetimeTokenProvider::class.java, KtAlwaysAccessibleLifetimeTokenProvider())
@@ -132,6 +148,7 @@ class StandaloneSessionBuilderTest {
val stdlib = addModule(
buildKtLibraryModule {
addBinaryRoot(platformStdlibPath)
addBinaryRoots(additionalStdlibRoots)
platform = targetPlatform
libraryName = "stdlib"
}
@@ -20,20 +20,23 @@ object CommonKLibResolver {
fun resolve(
libraries: Collection<String>,
logger: Logger,
zipAccessor: ZipFileSystemAccessor? = null
zipAccessor: ZipFileSystemAccessor? = null,
lenient: Boolean = false,
): KotlinLibraryResolveResult =
resolveWithoutDependencies(
libraries,
logger,
zipAccessor
zipAccessor,
lenient,
).resolveWithDependencies()
fun resolveWithoutDependencies(
libraries: Collection<String>,
logger: Logger,
zipAccessor: ZipFileSystemAccessor?
zipAccessor: ZipFileSystemAccessor?,
lenient: Boolean = false,
): KLibResolution {
val unresolvedLibraries = libraries.map { UnresolvedLibrary(it, null) }
val unresolvedLibraries = libraries.map { UnresolvedLibrary(it, null, lenient) }
val libraryAbsolutePaths = libraries.map { File(it).absolutePath }
// Configure the resolver to only work with absolute paths for now.
val libraryResolver = KLibResolverHelper(