REPL: Fix REPL scripts metadata to be correctly recognized by class file decompiler
This commit is contained in:
+1
-1
@@ -149,7 +149,7 @@ private data class TestData(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object DummyFileAttributeService : FileAttributeService {
|
object DummyFileAttributeService : FileAttributeService {
|
||||||
override fun <T> write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData<T> {
|
override fun <T> write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData<T> {
|
||||||
return CachedAttributeData(value, 0)
|
return CachedAttributeData(value, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ dependencies {
|
|||||||
implementation(intellijCore())
|
implementation(intellijCore())
|
||||||
|
|
||||||
testImplementation(project(":analysis:decompiled:decompiler-to-file-stubs"))
|
testImplementation(project(":analysis:decompiled:decompiler-to-file-stubs"))
|
||||||
|
testImplementation(projectTests(":analysis:decompiled:decompiler-to-file-stubs"))
|
||||||
testImplementation(projectTests(":analysis:analysis-api-impl-base"))
|
testImplementation(projectTests(":analysis:analysis-api-impl-base"))
|
||||||
testImplementation(projectTests(":analysis:analysis-api-fir"))
|
testImplementation(projectTests(":analysis:analysis-api-fir"))
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-14
@@ -10,7 +10,6 @@ import com.intellij.mock.MockApplication
|
|||||||
import com.intellij.mock.MockProject
|
import com.intellij.mock.MockProject
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.extensions.LoadingOrder
|
import com.intellij.openapi.extensions.LoadingOrder
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.ClassFileViewProviderFactory
|
import com.intellij.psi.ClassFileViewProviderFactory
|
||||||
import com.intellij.psi.FileTypeFileViewProviders
|
import com.intellij.psi.FileTypeFileViewProviders
|
||||||
import com.intellij.psi.compiled.ClassFileDecompilers
|
import com.intellij.psi.compiled.ClassFileDecompilers
|
||||||
@@ -19,13 +18,11 @@ import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfi
|
|||||||
import org.jetbrains.kotlin.analysis.decompiled.light.classes.ClsJavaStubByVirtualFileCache
|
import org.jetbrains.kotlin.analysis.decompiled.light.classes.ClsJavaStubByVirtualFileCache
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
|
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler
|
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.CachedAttributeData
|
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
|
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService
|
import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService
|
||||||
|
import org.jetbrains.kotlin.analysis.decompiler.stub.files.DummyFileAttributeService
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
import java.io.DataInput
|
|
||||||
import java.io.DataOutput
|
|
||||||
|
|
||||||
object SymbolLightClassesForLibraryFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorService {
|
object SymbolLightClassesForLibraryFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorService {
|
||||||
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
|
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
|
||||||
@@ -56,13 +53,3 @@ object SymbolLightClassesForLibraryFrontendApiTestConfiguratorService : Frontend
|
|||||||
FirFrontendApiTestConfiguratorService.doOutOfBlockModification(file)
|
FirFrontendApiTestConfiguratorService.doOutOfBlockModification(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object DummyFileAttributeService : FileAttributeService {
|
|
||||||
override fun <T> write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData<T> {
|
|
||||||
return CachedAttributeData(value, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T> read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData<T>? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-1
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.addImportingScope
|
|||||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||||
import org.jetbrains.kotlin.scripting.definitions.*
|
import org.jetbrains.kotlin.scripting.definitions.*
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
@@ -328,7 +329,7 @@ class LazyScriptDescriptor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val earlierScriptsParameter = if (isReplScript) {
|
val earlierScriptsParameter = if (isReplScript) {
|
||||||
createValueParameter(Name.special("<earlierScripts>") to builtIns.array.defaultType)
|
createValueParameter(Name.special("<earlierScripts>") to builtIns.getArrayType(Variance.INVARIANT, builtIns.anyType))
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
val explicitParameters = baseExplicitParameters.map { it.copy(constructorDescriptor, it.name, paramsIndexBase++) }
|
val explicitParameters = baseExplicitParameters.map { it.copy(constructorDescriptor, it.name, paramsIndexBase++) }
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ dependencies {
|
|||||||
testImplementation(commonDependency("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
|
testImplementation(commonDependency("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
|
||||||
testImplementation(commonDependency("org.jetbrains.kotlinx", "kotlinx-coroutines-core-jvm"))
|
testImplementation(commonDependency("org.jetbrains.kotlinx", "kotlinx-coroutines-core-jvm"))
|
||||||
testImplementation(project(":kotlin-reflect"))
|
testImplementation(project(":kotlin-reflect"))
|
||||||
|
testImplementation(project(":analysis:decompiled:decompiler-to-psi"))
|
||||||
|
testImplementation(project(":analysis:decompiled:decompiler-to-file-stubs"))
|
||||||
|
testImplementation(intellijCore())
|
||||||
|
testImplementation(projectTests(":analysis:decompiled:decompiler-to-file-stubs"))
|
||||||
testRuntimeOnly(project(":kotlin-compiler"))
|
testRuntimeOnly(project(":kotlin-compiler"))
|
||||||
testRuntimeOnly(commonDependency("org.jetbrains.intellij.deps", "trove4j"))
|
testRuntimeOnly(commonDependency("org.jetbrains.intellij.deps", "trove4j"))
|
||||||
testRuntimeOnly(project(":kotlin-scripting-ide-common")) { isTransitive = false }
|
testRuntimeOnly(project(":kotlin-scripting-ide-common")) { isTransitive = false }
|
||||||
|
|||||||
+51
-1
@@ -5,18 +5,31 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.scripting.ide_services
|
package org.jetbrains.kotlin.scripting.ide_services
|
||||||
|
|
||||||
|
import com.intellij.mock.MockApplication
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
|
import com.intellij.util.indexing.FileContentImpl
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler
|
||||||
|
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
|
||||||
|
import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService
|
||||||
|
import org.jetbrains.kotlin.analysis.decompiler.stub.files.DummyFileAttributeService
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocationWithRange
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocationWithRange
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.KJvmCompiledModuleInMemoryImpl
|
||||||
import org.jetbrains.kotlin.scripting.ide_services.test_util.*
|
import org.jetbrains.kotlin.scripting.ide_services.test_util.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.io.path.*
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
|
import kotlin.io.path.createTempDirectory
|
||||||
|
import kotlin.io.path.invariantSeparatorsPathString
|
||||||
import kotlin.reflect.full.isSubclassOf
|
import kotlin.reflect.full.isSubclassOf
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledModuleInMemory
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvm.jvm
|
import kotlin.script.experimental.jvm.jvm
|
||||||
import kotlin.script.experimental.jvm.updateClasspath
|
import kotlin.script.experimental.jvm.updateClasspath
|
||||||
@@ -340,6 +353,28 @@ class JvmIdeServicesTest : TestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testReplScriptClassFileDecompilation() {
|
||||||
|
JvmTestRepl()
|
||||||
|
.use { repl ->
|
||||||
|
val compiledSnippet = checkCompile(repl, "10 + 10")
|
||||||
|
val snippetValue = compiledSnippet.get()!!
|
||||||
|
|
||||||
|
val compiledModule = snippetValue.getCompiledModule() as KJvmCompiledModuleInMemoryImpl
|
||||||
|
val folder = saveCompiledOutput("repl-script-decompilation", compiledModule)
|
||||||
|
|
||||||
|
val vFile = VirtualFileManager.getInstance().findFileByNioPath(folder.resolve("Line_0_simplescript.class").toPath())!!
|
||||||
|
val fileContent = FileContentImpl.createByFile(vFile)
|
||||||
|
|
||||||
|
val application = ApplicationManager.getApplication() as MockApplication
|
||||||
|
KotlinCoreEnvironment.underApplicationLock {
|
||||||
|
registerDecompilerServices(application)
|
||||||
|
}
|
||||||
|
|
||||||
|
val fileStub = KotlinClassFileDecompiler().stubBuilder.buildFileStub(fileContent)
|
||||||
|
assertNotNull(fileStub)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalPathApi::class)
|
@OptIn(ExperimentalPathApi::class)
|
||||||
companion object {
|
companion object {
|
||||||
private const val MODULE_PATH = "plugins/scripting/scripting-ide-services-test"
|
private const val MODULE_PATH = "plugins/scripting/scripting-ide-services-test"
|
||||||
@@ -366,6 +401,21 @@ class JvmIdeServicesTest : TestCase() {
|
|||||||
|
|
||||||
return CliCompilationResult(exitCode, jarPath)
|
return CliCompilationResult(exitCode, jarPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveCompiledOutput(subfolder: String, module: KJvmCompiledModuleInMemory): File {
|
||||||
|
val folder = outputJarDir.resolve(subfolder).toFile()
|
||||||
|
module.compilerOutputFiles.forEach { (name, contents) ->
|
||||||
|
val file = folder.resolve(name)
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
file.writeBytes(contents)
|
||||||
|
}
|
||||||
|
return folder
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerDecompilerServices(application: MockApplication) {
|
||||||
|
application.registerService(ClsKotlinBinaryClassCache::class.java)
|
||||||
|
application.registerService(FileAttributeService::class.java, DummyFileAttributeService)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user