[scripting] Move earlierScripts to the frontend descriptor

^KT-20488 fixed
This commit is contained in:
Ilya Muradyan
2021-11-13 00:28:06 +03:00
parent 4149b91c0d
commit 6917ff7d2a
15 changed files with 94 additions and 65 deletions
@@ -17,4 +17,8 @@ public class ScriptPriorities {
Integer priority = script.getUserData(PRIORITY_KEY);
return priority == null ? 0 : priority;
}
public static boolean isReplScript(@NotNull KtScript script) {
return script.getUserData(PRIORITY_KEY) != null;
}
}
@@ -40,10 +40,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
import org.jetbrains.kotlin.resolve.scopes.utils.addImportingScope
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
import org.jetbrains.kotlin.scripting.definitions.findScriptCompilationConfiguration
import org.jetbrains.kotlin.scripting.definitions.*
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit
@@ -120,6 +117,7 @@ class LazyScriptDescriptor(
override fun getSource() = sourceElement
private val priority: Int = ScriptPriorities.getScriptPriority(scriptInfo.script)
private val isReplScript: Boolean = ScriptPriorities.isReplScript(scriptInfo.script)
override fun getPriority() = priority
@@ -290,6 +288,7 @@ class LazyScriptDescriptor(
internal class ConstructorWithParams(
val constructor: ClassConstructorDescriptorImpl,
val earlierScriptsParameter: ValueParameterDescriptor?,
val baseClassConstructorParameters: List<ValueParameterDescriptor>,
val implicitReceiversParameters: List<ValueParameterDescriptor>,
val scriptProvidedPropertiesParameters: List<ValueParameterDescriptor>
@@ -305,46 +304,60 @@ class LazyScriptDescriptor(
val receiverName =
if (receiver is ScriptDescriptor) "${LazyScriptClassMemberScope.IMPORTED_SCRIPT_PARAM_NAME_PREFIX}${receiver.name}"
else "${LazyScriptClassMemberScope.IMPLICIT_RECEIVER_PARAM_NAME_PREFIX}$idx"
receiverName to receiver.defaultType
Name.identifier(receiverName) to receiver.defaultType
}
val providedPropertiesParamTypes =
scriptProvidedProperties().map {
it.name.identifier to it.type
it.name to it.type
}
val constructorDescriptor = ClassConstructorDescriptorImpl.create(this, inheritedAnnotations, true, source)
var paramsIndexBase = baseExplicitParameters.lastIndex + 1
var paramsIndexBase = 0
fun createValueParameter(param: Pair<String, org.jetbrains.kotlin.types.KotlinType>) =
fun createValueParameter(param: Pair<Name, org.jetbrains.kotlin.types.KotlinType>) =
ValueParameterDescriptorImpl(
constructorDescriptor,
null,
paramsIndexBase++,
Annotations.EMPTY,
Name.identifier(param.first),
param.first,
param.second,
declaresDefaultValue = false, isCrossinline = false, isNoinline = false, varargElementType = null,
source = SourceElement.NO_SOURCE
)
val explicitParameters = baseExplicitParameters.map { it.copy(constructorDescriptor, it.name, it.index) }
val earlierScriptsParameter = if (isReplScript) {
createValueParameter(Name.special("<earlierScripts>") to builtIns.array.defaultType)
} else null
val explicitParameters = baseExplicitParameters.map { it.copy(constructorDescriptor, it.name, paramsIndexBase++) }
val implicitReceiversParameters = implicitReceiversParamTypes.map(::createValueParameter)
val providedPropertiesParameters = providedPropertiesParamTypes.map(::createValueParameter)
constructorDescriptor.initialize(
explicitParameters + implicitReceiversParameters + providedPropertiesParameters, DescriptorVisibilities.PUBLIC
buildList {
earlierScriptsParameter?.let { add(it) }
addAll(explicitParameters)
addAll(implicitReceiversParameters)
addAll(providedPropertiesParameters)
},
DescriptorVisibilities.PUBLIC
)
constructorDescriptor.returnType = defaultType()
ConstructorWithParams(
constructorDescriptor,
earlierScriptsParameter = earlierScriptsParameter,
baseClassConstructorParameters = explicitParameters,
implicitReceiversParameters = implicitReceiversParameters,
scriptProvidedPropertiesParameters = providedPropertiesParameters
)
}
override fun getEarlierScriptsConstructorParameter(): ValueParameterDescriptor? =
scriptPrimaryConstructorWithParams().earlierScriptsParameter
override fun getExplicitConstructorParameters(): List<ValueParameterDescriptor> =
scriptPrimaryConstructorWithParams().baseClassConstructorParameters
@@ -384,4 +397,8 @@ class LazyScriptDescriptor(
override val annotations: Annotations
get() = scriptClassAnnotations()
override fun isReplScript(): Boolean {
return isReplScript
}
}
@@ -100,12 +100,20 @@ open class ReplCodeAnalyzerBase(
fun reset(): List<SourceCodeByReplLine> = replState.reset()
fun analyzeReplLine(psiFile: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult {
protected fun prepareForAnalyze(
psiFile: KtFile,
priority: Int
) {
topDownAnalysisContext.scripts.clear()
trace.clearDiagnostics()
psiFile.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, codeLine.no)
val script = psiFile.script!!
script.putUserData(ScriptPriorities.PRIORITY_KEY, priority)
}
fun analyzeReplLine(psiFile: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult {
prepareForAnalyze(psiFile, codeLine.no)
return doAnalyze(psiFile, emptyList(), codeLine.toSourceCode())
}
@@ -115,11 +123,7 @@ open class ReplCodeAnalyzerBase(
codeLine: SourceCode,
priority: Int
): ReplLineAnalysisResult {
topDownAnalysisContext.scripts.clear()
trace.clearDiagnostics()
psiFile.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, priority)
prepareForAnalyze(psiFile, priority)
return doAnalyze(psiFile, importedScripts, codeLine.addNo(priority))
}
@@ -28,6 +28,7 @@ dependencies {
testImplementation(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core"))
testImplementation(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core-jvm"))
testImplementation(project(":kotlin-reflect"))
testRuntimeOnly(project(":kotlin-compiler"))
testRuntimeOnly(commonDep("org.jetbrains.intellij.deps", "trove4j"))
testRuntimeOnly(project(":kotlin-scripting-ide-common")) { isTransitive = false }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.scripting.ide_services.test_util.*
import java.io.File
import kotlin.io.path.*
import kotlin.reflect.full.isSubclassOf
import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
import kotlin.script.experimental.jvm.jvm
@@ -325,6 +326,20 @@ class JvmIdeServicesTest : TestCase() {
}
}
fun testAnonymousObjectReflection() {
JvmTestRepl()
.use { repl ->
assertEvalResult(repl, "42", 42)
assertEvalUnit(repl, "val sim = object : ArrayList<String>() {}")
val compiledSnippet = checkCompile(repl, "sim")
val evalResult = repl.eval(compiledSnippet!!)
val a = (evalResult.valueOrThrow().get().result as ResultValue.Value).value!!
assertTrue(a::class.isSubclassOf(List::class))
}
}
@OptIn(ExperimentalPathApi::class)
companion object {
private const val MODULE_PATH = "plugins/scripting/scripting-ide-services-test"
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.resolve.calls.tower.ImplicitsExtensionsResolutionFil
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.scripting.compiler.plugin.repl.ReplCodeAnalyzerBase
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
class IdeLikeReplCodeAnalyzer(
private val environment: KotlinCoreEnvironment,
@@ -44,11 +43,7 @@ class IdeLikeReplCodeAnalyzer(
importedScripts: List<KtFile>,
priority: Int
): ReplLineAnalysisResultWithStateless {
topDownAnalysisContext.scripts.clear()
trace.clearDiagnostics()
psiFile.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, priority)
prepareForAnalyze(psiFile, priority)
return doStatelessAnalyze(psiFile, importedScripts)
}