From 830c7cef07c721aeb38dc250f465c9921aa8d172 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 18 Feb 2020 21:26:49 +0900 Subject: [PATCH] i18n: Add bundle for JVM debugger (evaluation) --- .../kotlin/idea/KotlinBundle.properties | 1 - .../KotlinDebuggerEvaluationBundle.properties | 23 ++++++++++++++++++ .../evaluate/KotlinCodeFragmentFactory.kt | 2 +- .../KotlinDebuggerEvaluationBundle.kt | 24 +++++++++++++++++++ .../evaluate/KotlinEvaluatorBuilder.kt | 22 ++++++++--------- .../OrdinaryClassLoadingAdapter.kt | 7 +++--- .../CodeFragmentParameterAnalyzer.kt | 16 ++++++++----- .../KotlinRuntimeTypeCastSurrounder.kt | 4 ++-- 8 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 idea/jvm-debugger/jvm-debugger-evaluation/resources/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.properties create mode 100644 idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.kt diff --git a/idea/idea-analysis/resources/org/jetbrains/kotlin/idea/KotlinBundle.properties b/idea/idea-analysis/resources/org/jetbrains/kotlin/idea/KotlinBundle.properties index 235b910b807..218d0a87c09 100644 --- a/idea/idea-analysis/resources/org/jetbrains/kotlin/idea/KotlinBundle.properties +++ b/idea/idea-analysis/resources/org/jetbrains/kotlin/idea/KotlinBundle.properties @@ -120,7 +120,6 @@ create.local.variable.from.usage=Create local variable ''{0}'' create.parameter.from.usage=Create parameter ''{0}'' surround.with.string.template="${expr}" surround.with.when.template=when (expr) {} -surround.with.runtime.type.cast.template=(expr as RuntimeType) surround.with.function.template={ } kotlin.code.transformations=Kotlin Code Transformations fold.if.to.call=Replace 'if' expression with method call diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/resources/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.properties b/idea/jvm-debugger/jvm-debugger-evaluation/resources/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.properties new file mode 100644 index 00000000000..bc81fc62b88 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-evaluation/resources/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.properties @@ -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 \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt index c3cc9e50c95..548d404fc05 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinCodeFragmentFactory.kt @@ -239,7 +239,7 @@ class KotlinCodeFragmentFactory : CodeFragmentFactory() { if (javaExpression != null && !PsiTreeUtil.hasErrorElements(javaExpression)) { var convertedFragment: KtExpressionCodeFragment? = null - project.executeWriteCommand("Convert java expression to kotlin in Evaluate Expression") { + project.executeWriteCommand(KotlinDebuggerEvaluationBundle.message("j2k.expression")) { try { val (elementResults, _, conversionContext) = javaExpression.convertToKotlin() ?: return@executeWriteCommand val newText = elementResults.singleOrNull()?.text diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.kt new file mode 100644 index 00000000000..190e5b3814d --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinDebuggerEvaluationBundle.kt @@ -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) + } +} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt index 0f3cfb9226e..a6befdcb478 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt @@ -83,7 +83,7 @@ object KotlinEvaluatorBuilder : EvaluatorBuilder { if (file != null && file !is KtFile) { 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)) @@ -124,7 +124,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi runReadAction { if (DumbService.getInstance(codeFragment.project).isDumb) { 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 { status.error(EvaluationError.ThreadNotAvailable) - evaluationException("Cannot evaluate a code fragment: thread is not available") + evaluationException(KotlinDebuggerEvaluationBundle.message("error.thread.unavailable")) } if (!operatingThread.isSuspended) { status.error(EvaluationError.ThreadNotSuspended) - evaluationException("Evaluation is available only for the suspended threads") + evaluationException(KotlinDebuggerEvaluationBundle.message("error.thread.not.suspended")) } try { @@ -174,10 +174,10 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi } 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 "" - 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) { status.error(EvaluationError.CoroutineContextUnavailable) - evaluationException("'coroutineContext' is not available") + evaluationException(KotlinDebuggerEvaluationBundle.message("error.coroutine.context.unavailable")) } else if (parameter in compiledData.crossingBounds) { status.error(EvaluationError.ParameterNotCaptured) - evaluationException("'$name' is not captured") + evaluationException(KotlinDebuggerEvaluationBundle.message("error.not.captured", name)) } else if (parameter.kind == CodeFragmentParameter.Kind.FIELD_VAR) { 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()) { status.error(EvaluationError.InsideDefaultMethod) - evaluationException("Parameter evaluation is not supported for '\$default' methods") + evaluationException(KotlinDebuggerEvaluationBundle.message("error.parameter.evaluation.default.methods")) } else { status.error(EvaluationError.CannotFindVariable) - evaluationException("Cannot find local variable '$name' with type " + asmType.className) + evaluationException(KotlinDebuggerEvaluationBundle.message("error.cant.find.variable", name, asmType.className)) } } diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/OrdinaryClassLoadingAdapter.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/OrdinaryClassLoadingAdapter.kt index 990a910aef5..183bb50343d 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/OrdinaryClassLoadingAdapter.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/classLoading/OrdinaryClassLoadingAdapter.kt @@ -22,6 +22,7 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion import com.sun.jdi.ClassLoaderReference import com.sun.jdi.ClassType 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.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter @@ -101,13 +102,13 @@ class OrdinaryClassLoadingAdapter : ClassLoadingAdapter { val classLoader = try { ClassLoadingUtils.getClassLoader(context.evaluationContext, process) } catch (e: Exception) { - throw EvaluateException("Error creating evaluation class loader: $e", e) + throw EvaluateException(KotlinDebuggerEvaluationBundle.message("error.creating.class.loader", e.toString()), e) } try { defineClasses(classes, context, classLoader) } catch (e: Exception) { - throw EvaluateException("Error during classes definition $e", e) + throw EvaluateException(KotlinDebuggerEvaluationBundle.message("error.class.definition", e.toString()), e) } return classLoader @@ -157,7 +158,7 @@ class OrdinaryClassLoadingAdapter : ClassLoadingAdapter { private class ClassBytes(val name: String) { val bytes: ByteArray by lazy { 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 { it.readBytes() diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt index bdacebf390c..586c7e0b883 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt @@ -13,10 +13,8 @@ import org.jetbrains.kotlin.codegen.getCallLabelForLambdaArgument import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor 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.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.compilation.CodeFragmentParameter.* import org.jetbrains.kotlin.idea.debugger.safeLocation @@ -195,10 +193,14 @@ class CodeFragmentParameterAnalyzer( val descriptor = resolvedCall.resultingDescriptor if (descriptor is FunctionDescriptor && descriptor.isSuspend) { 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)) { - 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? { if (target is ValueParameterDescriptor && target.isCrossinline) { 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 diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/surroundWith/KotlinRuntimeTypeCastSurrounder.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/surroundWith/KotlinRuntimeTypeCastSurrounder.kt index 7c0a870dc68..96b7f78cc85 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/surroundWith/KotlinRuntimeTypeCastSurrounder.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/surroundWith/KotlinRuntimeTypeCastSurrounder.kt @@ -18,10 +18,10 @@ import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.util.ProgressWindow import com.intellij.openapi.project.Project 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.core.ShortenReferences 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.psi.* import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -57,7 +57,7 @@ class KotlinRuntimeTypeCastSurrounder : KotlinExpressionSurrounder() { } 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(