diff --git a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt index 91456a5d884..8998dc638a0 100644 --- a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt +++ b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/impl/KotlinStaticDeclarationProvider.kt @@ -19,7 +19,7 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.stubs.StubElement import com.intellij.util.indexing.FileContent import com.intellij.util.indexing.FileContentImpl -import com.intellij.util.io.URLUtil +import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInsVirtualFileProvider import java.util.concurrent.ConcurrentHashMap import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInFileType @@ -137,24 +137,9 @@ public class KotlinStaticDeclarationProviderFactory( private val createdFakeKtFiles = mutableListOf() private fun loadBuiltIns(): Collection { - val classLoader = this::class.java.classLoader - return buildList { - StandardClassIds.builtInsPackages.forEach { builtInPackageFqName -> - val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(builtInPackageFqName) - classLoader.getResource(resourcePath)?.let { resourceUrl -> - // "file:///path/to/stdlib.jar!/builtin/package/.kotlin_builtins - // -> ("path/to/stdlib.jar", "builtin/package/.kotlin_builtins") - URLUtil.splitJarUrl(resourceUrl.path)?.let { - val jarPath = it.first - val builtInFile = it.second - val pathToQuery = jarPath + URLUtil.JAR_SEPARATOR + builtInFile - jarFileSystem.findFileByPath(pathToQuery)?.let { vf -> - val fileContent = FileContentImpl.createByFile(vf, project) - createKtFileStub(psiManager, builtInDecompiler, fileContent)?.let { file -> add(file) } - } - } - } - } + return BuiltInsVirtualFileProvider.getInstance().getBuiltInVirtualFiles().mapNotNull { virtualFile -> + val fileContent = FileContentImpl.createByFile(virtualFile, project) + createKtFileStub(psiManager, builtInDecompiler, fileContent) } } diff --git a/analysis/analysis-api-standalone/analysis-api-standalone-base/build.gradle.kts b/analysis/analysis-api-standalone/analysis-api-standalone-base/build.gradle.kts index 447908b6be1..e88e0707a22 100644 --- a/analysis/analysis-api-standalone/analysis-api-standalone-base/build.gradle.kts +++ b/analysis/analysis-api-standalone/analysis-api-standalone-base/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { implementation(project(":compiler:psi")) implementation(project(":analysis:analysis-api-impl-base")) implementation(project(":analysis:decompiled:decompiler-to-file-stubs")) + implementation(project(":analysis:decompiled:decompiler-to-psi")) api(project(":compiler:cli-base")) api(project(":analysis:analysis-api")) api(project(":analysis:analysis-api-impl-base")) diff --git a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/BuiltInsVirtualFileProviderImp.kt b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/BuiltInsVirtualFileProviderImp.kt new file mode 100644 index 00000000000..2a9a5ae4728 --- /dev/null +++ b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/BuiltInsVirtualFileProviderImp.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2023 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.analysis.api.standalone.base.project.structure + +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem +import com.intellij.util.io.URLUtil +import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInsVirtualFileProviderBaseImpl +import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment +import java.net.URL + +internal class BuiltInsVirtualFileProviderImp( + private val jarFileSystem: CoreJarFileSystem, +) : BuiltInsVirtualFileProviderBaseImpl() { + override fun findVirtualFile(url: URL): VirtualFile? { + val split = URLUtil.splitJarUrl(url.path) + ?: errorWithAttachment("URL for builtins does not contain jar separator") { + withEntry("url", url) { url.toString() } + } + val jarPath = split.first + val builtInFile = split.second + val pathToQuery = jarPath + URLUtil.JAR_SEPARATOR + builtInFile + return jarFileSystem.findFileByPath(pathToQuery) + } +} \ No newline at end of file diff --git a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt index cfa5ad693a8..2a7b03bcc11 100644 --- a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt +++ b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.roots.PackageIndex import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager +import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem import com.intellij.psi.* import com.intellij.psi.impl.file.impl.JavaFileManager import com.intellij.psi.impl.smartPointers.PsiClassReferenceTypePointerFactory @@ -32,6 +33,7 @@ import com.intellij.util.io.URLUtil.JAR_SEPARATOR import org.jetbrains.kotlin.analysis.api.impl.base.java.source.JavaElementSourceWithSmartPointerFactory import org.jetbrains.kotlin.analysis.api.impl.base.references.HLApiReferenceProviderService import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider +import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInsVirtualFileProvider import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache import org.jetbrains.kotlin.analysis.decompiler.stub.file.DummyFileAttributeService import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService @@ -67,7 +69,7 @@ object StandaloneProjectFactory { applicationDisposable: Disposable, unitTestMode: Boolean = false, compilerConfiguration: CompilerConfiguration = CompilerConfiguration(), - classLoader: ClassLoader = MockProject::class.java.classLoader + classLoader: ClassLoader = MockProject::class.java.classLoader, ): KotlinCoreProjectEnvironment { val applicationEnvironment = if (unitTestMode) KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForTests(applicationDisposable, compilerConfiguration) @@ -76,7 +78,7 @@ object StandaloneProjectFactory { registerApplicationExtensionPoints(applicationEnvironment, applicationDisposable) - registerApplicationServices(applicationEnvironment.application) + registerApplicationServices(applicationEnvironment) return object : KotlinCoreProjectEnvironment(projectDisposable, applicationEnvironment) { init { @@ -96,7 +98,8 @@ object StandaloneProjectFactory { } } - private fun registerApplicationServices(application: MockApplication) { + private fun registerApplicationServices(applicationEnvironment: KotlinCoreApplicationEnvironment) { + val application = applicationEnvironment.application if (application.getServiceIfCreated(KotlinFakeClsStubsCache::class.java) != null) { // application services already registered by som other threads, tests return @@ -109,6 +112,10 @@ object StandaloneProjectFactory { application.apply { registerService(KotlinFakeClsStubsCache::class.java, KotlinFakeClsStubsCache::class.java) registerService(ClsKotlinBinaryClassCache::class.java) + registerService( + BuiltInsVirtualFileProvider::class.java, + BuiltInsVirtualFileProviderImp(applicationEnvironment.jarFileSystem as CoreJarFileSystem) + ) registerService(FileAttributeService::class.java, DummyFileAttributeService::class.java) } } diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/BuiltInsVirtualFileProvider.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/BuiltInsVirtualFileProvider.kt new file mode 100644 index 00000000000..fa7cf81fecf --- /dev/null +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/BuiltInsVirtualFileProvider.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2023 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.analysis.decompiler.psi + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol +import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment +import java.net.URL + +abstract class BuiltInsVirtualFileProvider { + abstract fun getBuiltInVirtualFiles(): Set + + companion object { + fun getInstance(): BuiltInsVirtualFileProvider = + ApplicationManager.getApplication().getService(BuiltInsVirtualFileProvider::class.java) + } +} + +abstract class BuiltInsVirtualFileProviderBaseImpl : BuiltInsVirtualFileProvider() { + private val builtinFiles: Set by lazy { + val classLoader = this::class.java.classLoader + StandardClassIds.builtInsPackages.mapTo(mutableSetOf()) { builtInPackageFqName -> + val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(builtInPackageFqName) + val resourceUrl = classLoader.getResource(resourcePath) + ?: errorWithAttachment("Resource for builtin $builtInPackageFqName not found") { + withEntry("resourcePath", resourcePath) + } + findVirtualFile(resourceUrl) + ?: errorWithAttachment("Virtual file for builtin $builtInPackageFqName not found") { + withEntry("resourcePath", resourcePath) + withEntry("resourceUrl", resourceUrl) { it.toString() } + } + } + } + + protected abstract fun findVirtualFile(url: URL): VirtualFile? + + override fun getBuiltInVirtualFiles(): Set = builtinFiles +} + +