i18n: Add bundle for JVM debugger (evaluation)

This commit is contained in:
Yan Zhulanow
2020-02-18 21:26:49 +09:00
committed by Dmitry Gridin
parent 7f80fb8b98
commit 830c7cef07
8 changed files with 75 additions and 24 deletions
@@ -120,7 +120,6 @@ create.local.variable.from.usage=Create local variable ''{0}''
create.parameter.from.usage=Create parameter ''{0}'' create.parameter.from.usage=Create parameter ''{0}''
surround.with.string.template="${expr}" surround.with.string.template="${expr}"
surround.with.when.template=when (expr) {} surround.with.when.template=when (expr) {}
surround.with.runtime.type.cast.template=(expr as RuntimeType)
surround.with.function.template={ } surround.with.function.template={ }
kotlin.code.transformations=Kotlin Code Transformations kotlin.code.transformations=Kotlin Code Transformations
fold.if.to.call=Replace 'if' expression with method call fold.if.to.call=Replace 'if' expression with method call
@@ -0,0 +1,23 @@
surround.with.runtime.type.cast.template=(expr as RuntimeType)
j2k.expression=Convert Java expression to Kotlin in Evaluate Expression
error.suspend.calls.not.supported=Evaluation of 'suspend' calls is not supported
error.nothing.initialization='Nothing' can't be instantiated
error.crossinline.lambda.evaluation=Evaluation of 'crossinline' lambdas is not supported
error.cant.evaluate=Can not evaluate the expression
error.bad.context=Couldn't evaluate Kotlin expression in this context
error.dumb.mode=Code fragment evaluation is not available in the dumb mode
error.thread.unavailable=Cannot evaluate a code fragment: thread is not available
error.thread.not.suspended=Evaluation is available only for the suspended threads
error.creating.class.loader=Error creating evaluation class loader: {0}
error.class.definition=Error during classes definition: {0}
error.exception.occurred=An exception occurred
error.coroutine.context.unavailable='coroutineContext' is not available
error.not.captured=''{0}'' is not captured
error.cant.find.backing.field=Cannot find the backing field ''{0}''
error.parameter.evaluation.default.methods=Parameter evaluation is not supported for '$default' methods
error.cant.find.variable=Can not find local variable ''{0}'' with type {1}
error.cant.find.class=Can not find class ''{0}'' in the current ClassLoader
@@ -239,7 +239,7 @@ class KotlinCodeFragmentFactory : CodeFragmentFactory() {
if (javaExpression != null && !PsiTreeUtil.hasErrorElements(javaExpression)) { if (javaExpression != null && !PsiTreeUtil.hasErrorElements(javaExpression)) {
var convertedFragment: KtExpressionCodeFragment? = null var convertedFragment: KtExpressionCodeFragment? = null
project.executeWriteCommand("Convert java expression to kotlin in Evaluate Expression") { project.executeWriteCommand(KotlinDebuggerEvaluationBundle.message("j2k.expression")) {
try { try {
val (elementResults, _, conversionContext) = javaExpression.convertToKotlin() ?: return@executeWriteCommand val (elementResults, _, conversionContext) = javaExpression.convertToKotlin() ?: return@executeWriteCommand
val newText = elementResults.singleOrNull()?.text val newText = elementResults.singleOrNull()?.text
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2020 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.idea.debugger.evaluate
import com.intellij.CommonBundle
import org.jetbrains.annotations.NonNls
import org.jetbrains.annotations.PropertyKey
import org.jetbrains.kotlin.idea.core.util.KotlinBundleBase
import java.util.*
object KotlinDebuggerEvaluationBundle : KotlinBundleBase() {
@NonNls
private const val BUNDLE = "org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerEvaluationBundle"
override fun createBundle(): ResourceBundle = ResourceBundle.getBundle(BUNDLE)
@JvmStatic
fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any?): String {
return CommonBundle.message(bundle, key, *params)
}
}
@@ -83,7 +83,7 @@ object KotlinEvaluatorBuilder : EvaluatorBuilder {
if (file != null && file !is KtFile) { if (file != null && file !is KtFile) {
reportError(codeFragment, position, "Unknown context${codeFragment.context?.javaClass}") reportError(codeFragment, position, "Unknown context${codeFragment.context?.javaClass}")
evaluationException("Couldn't evaluate Kotlin expression in this context") evaluationException(KotlinDebuggerEvaluationBundle.message("error.bad.context"))
} }
return ExpressionEvaluatorImpl(KotlinEvaluator(codeFragment, position)) return ExpressionEvaluatorImpl(KotlinEvaluator(codeFragment, position))
@@ -124,7 +124,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi
runReadAction { runReadAction {
if (DumbService.getInstance(codeFragment.project).isDumb) { if (DumbService.getInstance(codeFragment.project).isDumb) {
status.error(EvaluationError.DumbMode) status.error(EvaluationError.DumbMode)
evaluationException("Code fragment evaluation is not available in the dumb mode") evaluationException(KotlinDebuggerEvaluationBundle.message("error.dumb.mode"))
} }
} }
@@ -140,12 +140,12 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi
val operatingThread = context.suspendContext.thread ?: run { val operatingThread = context.suspendContext.thread ?: run {
status.error(EvaluationError.ThreadNotAvailable) status.error(EvaluationError.ThreadNotAvailable)
evaluationException("Cannot evaluate a code fragment: thread is not available") evaluationException(KotlinDebuggerEvaluationBundle.message("error.thread.unavailable"))
} }
if (!operatingThread.isSuspended) { if (!operatingThread.isSuspended) {
status.error(EvaluationError.ThreadNotSuspended) status.error(EvaluationError.ThreadNotSuspended)
evaluationException("Evaluation is available only for the suspended threads") evaluationException(KotlinDebuggerEvaluationBundle.message("error.thread.not.suspended"))
} }
try { try {
@@ -174,10 +174,10 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi
} }
status.error(EvaluationError.GenericException) status.error(EvaluationError.GenericException)
reportError(codeFragment, sourcePosition, e.message ?: "An exception occurred", e) reportError(codeFragment, sourcePosition, e.message ?: KotlinDebuggerEvaluationBundle.message("error.exception.occurred"), e)
val cause = if (e.message != null) ": ${e.message}" else "" val cause = if (e.message != null) ": ${e.message}" else ""
evaluationException("Cannot evaluate the expression: $cause") evaluationException(KotlinDebuggerEvaluationBundle.message("error.cant.evaluate") + cause)
} }
} }
@@ -422,19 +422,19 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi
if (parameter.kind == CodeFragmentParameter.Kind.COROUTINE_CONTEXT) { if (parameter.kind == CodeFragmentParameter.Kind.COROUTINE_CONTEXT) {
status.error(EvaluationError.CoroutineContextUnavailable) status.error(EvaluationError.CoroutineContextUnavailable)
evaluationException("'coroutineContext' is not available") evaluationException(KotlinDebuggerEvaluationBundle.message("error.coroutine.context.unavailable"))
} else if (parameter in compiledData.crossingBounds) { } else if (parameter in compiledData.crossingBounds) {
status.error(EvaluationError.ParameterNotCaptured) status.error(EvaluationError.ParameterNotCaptured)
evaluationException("'$name' is not captured") evaluationException(KotlinDebuggerEvaluationBundle.message("error.not.captured", name))
} else if (parameter.kind == CodeFragmentParameter.Kind.FIELD_VAR) { } else if (parameter.kind == CodeFragmentParameter.Kind.FIELD_VAR) {
status.error(EvaluationError.BackingFieldNotFound) status.error(EvaluationError.BackingFieldNotFound)
evaluationException("Cannot find the backing field '${parameter.name}'") evaluationException(KotlinDebuggerEvaluationBundle.message("error.cant.find.backing.field", parameter.name))
} else if (parameter.kind == CodeFragmentParameter.Kind.ORDINARY && isInsideDefaultInterfaceMethod()) { } else if (parameter.kind == CodeFragmentParameter.Kind.ORDINARY && isInsideDefaultInterfaceMethod()) {
status.error(EvaluationError.InsideDefaultMethod) status.error(EvaluationError.InsideDefaultMethod)
evaluationException("Parameter evaluation is not supported for '\$default' methods") evaluationException(KotlinDebuggerEvaluationBundle.message("error.parameter.evaluation.default.methods"))
} else { } else {
status.error(EvaluationError.CannotFindVariable) status.error(EvaluationError.CannotFindVariable)
evaluationException("Cannot find local variable '$name' with type " + asmType.className) evaluationException(KotlinDebuggerEvaluationBundle.message("error.cant.find.variable", name, asmType.className))
} }
} }
@@ -22,6 +22,7 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion
import com.sun.jdi.ClassLoaderReference import com.sun.jdi.ClassLoaderReference
import com.sun.jdi.ClassType import com.sun.jdi.ClassType
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerEvaluationBundle
import org.jetbrains.kotlin.idea.debugger.isDexDebug import org.jetbrains.kotlin.idea.debugger.isDexDebug
import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -101,13 +102,13 @@ class OrdinaryClassLoadingAdapter : ClassLoadingAdapter {
val classLoader = try { val classLoader = try {
ClassLoadingUtils.getClassLoader(context.evaluationContext, process) ClassLoadingUtils.getClassLoader(context.evaluationContext, process)
} catch (e: Exception) { } catch (e: Exception) {
throw EvaluateException("Error creating evaluation class loader: $e", e) throw EvaluateException(KotlinDebuggerEvaluationBundle.message("error.creating.class.loader", e.toString()), e)
} }
try { try {
defineClasses(classes, context, classLoader) defineClasses(classes, context, classLoader)
} catch (e: Exception) { } catch (e: Exception) {
throw EvaluateException("Error during classes definition $e", e) throw EvaluateException(KotlinDebuggerEvaluationBundle.message("error.class.definition", e.toString()), e)
} }
return classLoader return classLoader
@@ -157,7 +158,7 @@ class OrdinaryClassLoadingAdapter : ClassLoadingAdapter {
private class ClassBytes(val name: String) { private class ClassBytes(val name: String) {
val bytes: ByteArray by lazy { val bytes: ByteArray by lazy {
val inputStream = this::class.java.classLoader.getResourceAsStream(name.replace('.', '/') + ".class") val inputStream = this::class.java.classLoader.getResourceAsStream(name.replace('.', '/') + ".class")
?: throw EvaluateException("Couldn't find $name class in current class loader") ?: throw EvaluateException(KotlinDebuggerEvaluationBundle.message("error.cant.find.class", name))
inputStream.use { inputStream.use {
it.readBytes() it.readBytes()
@@ -13,10 +13,8 @@ import org.jetbrains.kotlin.codegen.getCallLabelForLambdaArgument
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
import org.jetbrains.kotlin.idea.debugger.evaluate.*
import org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldPropertyDescriptor import org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldPropertyDescriptor
import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationError
import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationStatus
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory.Companion.FAKE_JAVA_CONTEXT_FUNCTION_NAME import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory.Companion.FAKE_JAVA_CONTEXT_FUNCTION_NAME
import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.CodeFragmentParameter.* import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.CodeFragmentParameter.*
import org.jetbrains.kotlin.idea.debugger.safeLocation import org.jetbrains.kotlin.idea.debugger.safeLocation
@@ -195,10 +193,14 @@ class CodeFragmentParameterAnalyzer(
val descriptor = resolvedCall.resultingDescriptor val descriptor = resolvedCall.resultingDescriptor
if (descriptor is FunctionDescriptor && descriptor.isSuspend) { if (descriptor is FunctionDescriptor && descriptor.isSuspend) {
evaluationStatus.error(EvaluationError.SuspendCall) evaluationStatus.error(EvaluationError.SuspendCall)
throw EvaluateExceptionUtil.createEvaluateException("Evaluation of 'suspend' calls is not supported") throw EvaluateExceptionUtil.createEvaluateException(
KotlinDebuggerEvaluationBundle.message("error.suspend.calls.not.supported")
)
} }
if (descriptor is ConstructorDescriptor && KotlinBuiltIns.isNothing(descriptor.returnType)) { if (descriptor is ConstructorDescriptor && KotlinBuiltIns.isNothing(descriptor.returnType)) {
throw EvaluateExceptionUtil.createEvaluateException("'Nothing' can't be instantiated") throw EvaluateExceptionUtil.createEvaluateException(
KotlinDebuggerEvaluationBundle.message("error.nothing.initialization")
)
} }
} }
@@ -284,7 +286,9 @@ class CodeFragmentParameterAnalyzer(
private fun processSimpleNameExpression(target: DeclarationDescriptor, expression: KtSimpleNameExpression): Smart? { private fun processSimpleNameExpression(target: DeclarationDescriptor, expression: KtSimpleNameExpression): Smart? {
if (target is ValueParameterDescriptor && target.isCrossinline) { if (target is ValueParameterDescriptor && target.isCrossinline) {
evaluationStatus.error(EvaluationError.CrossInlineLambda) evaluationStatus.error(EvaluationError.CrossInlineLambda)
throw EvaluateExceptionUtil.createEvaluateException("Evaluation of 'crossinline' lambdas is not supported") throw EvaluateExceptionUtil.createEvaluateException(
KotlinDebuggerEvaluationBundle.message("error.crossinline.lambda.evaluation")
)
} }
val isLocalTarget = (target as? DeclarationDescriptorWithVisibility)?.visibility == Visibilities.LOCAL val isLocalTarget = (target as? DeclarationDescriptorWithVisibility)?.visibility == Visibilities.LOCAL
@@ -18,10 +18,10 @@ import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.util.ProgressWindow import com.intellij.openapi.progress.util.ProgressWindow
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.surroundWith.KotlinExpressionSurrounder import org.jetbrains.kotlin.idea.core.surroundWith.KotlinExpressionSurrounder
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerEvaluationBundle
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinRuntimeTypeEvaluator import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinRuntimeTypeEvaluator
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -57,7 +57,7 @@ class KotlinRuntimeTypeCastSurrounder : KotlinExpressionSurrounder() {
} }
override fun getTemplateDescription(): String { override fun getTemplateDescription(): String {
return KotlinBundle.message("surround.with.runtime.type.cast.template") return KotlinDebuggerEvaluationBundle.message("surround.with.runtime.type.cast.template")
} }
private inner class SurroundWithCastWorker( private inner class SurroundWithCastWorker(