Evaluate expression: refactor error messages
This commit is contained in:
@@ -55,15 +55,18 @@ import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory
|
||||
import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.jet.OutputFileCollection
|
||||
import org.jetbrains.jet.lang.psi.JetExpressionCodeFragment
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getAnalysisResults
|
||||
import org.jetbrains.jet.lang.psi.JetCodeFragment
|
||||
import org.jetbrains.jet.lang.psi.JetImportList
|
||||
import org.jetbrains.jet.lang.psi.codeFragmentUtil.setSkipVisibilityCheck
|
||||
import org.jetbrains.jet.lang.psi.JetBlockCodeFragment
|
||||
import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import org.jetbrains.jet.codegen.CompilationErrorHandler
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage
|
||||
import org.jetbrains.jet.lang.diagnostics.Severity
|
||||
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages
|
||||
|
||||
object KotlinEvaluationBuilder: EvaluatorBuilder {
|
||||
override fun build(codeFragment: PsiElement, position: SourcePosition?): ExpressionEvaluator {
|
||||
@@ -91,14 +94,14 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment,
|
||||
try {
|
||||
val extractedFunction = getFunctionForExtractedFragment(codeFragment, sourcePosition.getFile(), sourcePosition.getLine())
|
||||
if (extractedFunction == null) {
|
||||
exception("This code fragment cannot be extracted to function")
|
||||
throw IllegalStateException("Code fragment cannot be extracted to function: ${sourcePosition.getFile().getText()}:${sourcePosition.getLine()},\ncodeFragment = ${codeFragment.getText()}")
|
||||
}
|
||||
|
||||
val classFileFactory = createClassFileFactory(extractedFunction)
|
||||
|
||||
// KT-4509
|
||||
val outputFiles = (classFileFactory : OutputFileCollection).asList().filter { it.relativePath != "$packageInternalName.class" }
|
||||
if (outputFiles.size() != 1) exception("More than one class file found. Note that lambdas, classes and objects are unsupported yet.\n${outputFiles.makeString("\n")}")
|
||||
if (outputFiles.size() != 1) exception("Expression compiles to more than one class file. Note that lambdas, classes and objects are unsupported yet. List of files: ${outputFiles.makeString(",")}")
|
||||
|
||||
val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine()
|
||||
|
||||
@@ -129,7 +132,9 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment,
|
||||
}
|
||||
}, 0)
|
||||
|
||||
if (resultValue == null) exception("Cannot evaluate expression")
|
||||
if (resultValue == null) {
|
||||
throw IllegalStateException("resultValue is null: cannot find method ${extractedFunction.getName()} in ${outputFiles.first().relativePath}")
|
||||
}
|
||||
|
||||
return resultValue!!.asJdiValue(virtualMachine, resultValue!!.asmType)
|
||||
}
|
||||
@@ -161,21 +166,19 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment,
|
||||
private fun EvaluationContextImpl.getArgumentsByNames(parameterNames: List<String>): List<Value> {
|
||||
val frames = getFrameProxy()?.getStackFrame()
|
||||
if (frames != null) {
|
||||
try {
|
||||
return parameterNames.map {
|
||||
name ->
|
||||
if (name == "this") {
|
||||
frames.thisObject().asValue()
|
||||
}
|
||||
else {
|
||||
frames.getValue(frames.visibleVariableByName(name)).asValue()
|
||||
fun getValue(name: String): Value {
|
||||
return try {
|
||||
when (name) {
|
||||
"this" -> frames.thisObject().asValue()
|
||||
else -> frames.getValue(frames.visibleVariableByName(name)).asValue()
|
||||
}
|
||||
}
|
||||
catch(e: Exception) {
|
||||
exception("Cannot get parameter value from local variables table: parameterName = ${name}. Note that captured parameters are unsupported yet.")
|
||||
}
|
||||
}
|
||||
catch(e: Throwable) {
|
||||
throw IllegalArgumentException(
|
||||
"Cannot get parameter values from VirtualMachine: ${e.javaClass}\nFunction parameters:\n${parameterNames.makeString("\n")}\nVisible variables:\n${frames.visibleVariables().makeString("\n")}")
|
||||
}
|
||||
|
||||
return parameterNames.map { getValue(it) }
|
||||
}
|
||||
return Collections.emptyList()
|
||||
}
|
||||
@@ -188,13 +191,16 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment,
|
||||
checkForSyntacticErrors(file)
|
||||
|
||||
val analyzeExhaust = file.getAnalysisResults()
|
||||
val bindingContext = analyzeExhaust.getBindingContext()
|
||||
try {
|
||||
analyzeExhaust.throwIfError()
|
||||
AnalyzingUtils.throwExceptionOnErrors(bindingContext)
|
||||
if (analyzeExhaust.isError()) {
|
||||
exception(analyzeExhaust.getError())
|
||||
}
|
||||
catch (e: IllegalStateException) {
|
||||
exception(e.getMessage() ?: "Exception from kotlin compiler")
|
||||
|
||||
val bindingContext = analyzeExhaust.getBindingContext()
|
||||
bindingContext.getDiagnostics().forEach {
|
||||
diagnostic ->
|
||||
if (diagnostic.getSeverity() == Severity.ERROR) {
|
||||
exception(DefaultErrorMessages.RENDERER.render(diagnostic))
|
||||
}
|
||||
}
|
||||
|
||||
val state = GenerationState(
|
||||
@@ -205,10 +211,7 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment,
|
||||
listOf(file)
|
||||
)
|
||||
|
||||
KotlinCodegenFacade.compileCorrectFiles(state) {
|
||||
e, msg ->
|
||||
exception("$msg\n${e?.getMessage() ?: ""}")
|
||||
}
|
||||
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION)
|
||||
|
||||
return state.getFactory()
|
||||
}
|
||||
@@ -217,6 +220,14 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment,
|
||||
}
|
||||
|
||||
private fun exception(msg: String) = throw EvaluateExceptionUtil.createEvaluateException(msg)
|
||||
|
||||
private fun exception(e: Throwable) {
|
||||
val message = e.getMessage()
|
||||
if (message != null) {
|
||||
exception(message)
|
||||
}
|
||||
throw EvaluateExceptionUtil.createEvaluateException(e)
|
||||
}
|
||||
}
|
||||
|
||||
private val template = """
|
||||
@@ -295,6 +306,26 @@ private fun getFunctionForExtractedFragment(
|
||||
breakpointFile: PsiFile,
|
||||
breakpointLine: Int
|
||||
): JetNamedFunction? {
|
||||
|
||||
fun getErrorMessageForExtractFunctionResult(analysisResult: AnalysisResult): String {
|
||||
return analysisResult.messages.map {
|
||||
errorMessage ->
|
||||
val message = when(errorMessage) {
|
||||
ErrorMessage.NO_EXPRESSION -> "Cannot perform an action without an expression"
|
||||
ErrorMessage.NO_CONTAINER -> "Cannot perform an action at this breakpoint ${breakpointFile.getName()}:${breakpointLine}"
|
||||
ErrorMessage.SUPER_CALL -> "Cannot perform an action for expression with super call"
|
||||
ErrorMessage.DENOTABLE_TYPES -> "Cannot perform an action because following types are unavailable from debugger scope"
|
||||
ErrorMessage.MULTIPLE_OUTPUT -> "Cannot perform an action because this code fragment changes more than one variable"
|
||||
ErrorMessage.NON_LOCAL_DECLARATION,
|
||||
ErrorMessage.DECLARATIONS_OUT_OF_SCOPE,
|
||||
ErrorMessage.OUTPUT_AND_EXIT_POINT,
|
||||
ErrorMessage.MULTIPLE_EXIT_POINTS,
|
||||
ErrorMessage.VARIABLES_ARE_USED_OUTSIDE -> "Cannot perform an action for this expression"
|
||||
}
|
||||
if (errorMessage.additionalInfo == null) message else "$message: ${errorMessage.additionalInfo?.makeString(", ")}"
|
||||
}.makeString(", ")
|
||||
}
|
||||
|
||||
return ApplicationManager.getApplication()?.runReadAction(object: Computable<JetNamedFunction> {
|
||||
override fun compute(): JetNamedFunction? {
|
||||
checkForSyntacticErrors(codeFragment)
|
||||
@@ -322,12 +353,12 @@ private fun getFunctionForExtractedFragment(
|
||||
|
||||
val analysisResult = ExtractionData(tmpFile, Collections.singletonList(newDebugExpression), nextSibling).performAnalysis()
|
||||
if (analysisResult.status != Status.SUCCESS) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(analysisResult.messages.makeString(", "))
|
||||
throw EvaluateExceptionUtil.createEvaluateException(getErrorMessageForExtractFunctionResult(analysisResult))
|
||||
}
|
||||
|
||||
val validationResult = analysisResult.descriptor!!.validate()
|
||||
if (!validationResult.conflicts.isEmpty()) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException("Some declarations are unavailable: ${validationResult.conflicts.keySet()?.map { it.getText() }?.makeString(",")}")
|
||||
throw EvaluateExceptionUtil.createEvaluateException("Following declarations are unavailable in debug scope: ${validationResult.conflicts.keySet()?.map { it.getText() }?.makeString(",")}")
|
||||
}
|
||||
|
||||
return validationResult.descriptor.generateFunction(true)
|
||||
|
||||
+2
-2
@@ -63,7 +63,7 @@ public class ExtractKotlinFunctionHandler : RefactoringActionHandler {
|
||||
val analysisResult = ExtractionData(file, elements, nextSibling).performAnalysis()
|
||||
|
||||
if (ApplicationManager.getApplication()!!.isUnitTestMode() && analysisResult.status != Status.SUCCESS) {
|
||||
throw ConflictsInTestsException(analysisResult.messages)
|
||||
throw ConflictsInTestsException(analysisResult.messages.map { it.renderMessage() })
|
||||
}
|
||||
|
||||
fun proceedWithExtraction() {
|
||||
@@ -84,7 +84,7 @@ public class ExtractKotlinFunctionHandler : RefactoringActionHandler {
|
||||
project.executeWriteCommand(EXTRACT_FUNCTION) { descriptor.generateFunction() }
|
||||
}
|
||||
|
||||
val message = analysisResult.messages.makeString("\n")
|
||||
val message = analysisResult.messages.map { it.renderMessage() }.makeString("\n")
|
||||
when (analysisResult.status) {
|
||||
Status.CRITICAL_ERROR -> {
|
||||
showErrorHint(project, editor, message)
|
||||
|
||||
+42
-1
@@ -33,6 +33,8 @@ import org.jetbrains.jet.lang.psi.JetTypeParameter
|
||||
import org.jetbrains.jet.lang.psi.JetTypeConstraint
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status
|
||||
import org.jetbrains.jet.plugin.refactoring.JetRefactoringBundle
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage
|
||||
|
||||
data class Parameter(
|
||||
val argumentText: String,
|
||||
@@ -137,13 +139,52 @@ data class ExtractionDescriptor(
|
||||
class AnalysisResult (
|
||||
val descriptor: ExtractionDescriptor?,
|
||||
val status: Status,
|
||||
val messages: List<String>
|
||||
val messages: List<ErrorMessage>
|
||||
) {
|
||||
enum class Status {
|
||||
SUCCESS
|
||||
NON_CRITICAL_ERROR
|
||||
CRITICAL_ERROR
|
||||
}
|
||||
|
||||
enum class ErrorMessage {
|
||||
NO_EXPRESSION
|
||||
NO_CONTAINER
|
||||
SUPER_CALL
|
||||
NON_LOCAL_DECLARATION
|
||||
DENOTABLE_TYPES
|
||||
MULTIPLE_OUTPUT
|
||||
OUTPUT_AND_EXIT_POINT
|
||||
MULTIPLE_EXIT_POINTS
|
||||
VARIABLES_ARE_USED_OUTSIDE
|
||||
DECLARATIONS_OUT_OF_SCOPE
|
||||
|
||||
var additionalInfo: List<String>? = null
|
||||
|
||||
fun addAdditionalInfo(info: List<String>): ErrorMessage {
|
||||
additionalInfo = info
|
||||
return this
|
||||
}
|
||||
|
||||
fun renderMessage(): String {
|
||||
val message = JetRefactoringBundle.message(when(this) {
|
||||
NO_EXPRESSION -> "cannot.refactor.no.expresson"
|
||||
NO_CONTAINER -> "cannot.refactor.no.container"
|
||||
SUPER_CALL -> "cannot.extract.super.call"
|
||||
NON_LOCAL_DECLARATION -> "cannot.extract.non.local.declaration.ref"
|
||||
DENOTABLE_TYPES -> "parameter.types.are.not.denotable"
|
||||
MULTIPLE_OUTPUT -> "selected.code.fragment.has.multiple.output.values"
|
||||
OUTPUT_AND_EXIT_POINT -> "selected.code.fragment.has.output.values.and.exit.points"
|
||||
MULTIPLE_EXIT_POINTS -> "selected.code.fragment.has.multiple.exit.points"
|
||||
VARIABLES_ARE_USED_OUTSIDE -> "variables.are.used.outside.of.selected.code.fragment"
|
||||
DECLARATIONS_OUT_OF_SCOPE -> "declarations.will.move.out.of.scope"
|
||||
})!!
|
||||
if (additionalInfo != null) {
|
||||
return "$message\n${additionalInfo?.makeString("\n")}"
|
||||
}
|
||||
return message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExtractionDescriptorWithConflicts(
|
||||
|
||||
+20
-20
@@ -100,6 +100,7 @@ import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Statu
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.psi.codeFragmentUtil.skipVisibilityCheck
|
||||
import org.jetbrains.jet.lang.psi.codeFragmentUtil.setSkipVisibilityCheck
|
||||
import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage
|
||||
|
||||
private val DEFAULT_FUNCTION_NAME = "myFun"
|
||||
private val DEFAULT_RETURN_TYPE = KotlinBuiltIns.getInstance().getUnitType()
|
||||
@@ -146,15 +147,14 @@ private fun List<Instruction>.analyzeControlFlow(
|
||||
bindingContext: BindingContext,
|
||||
parameters: Set<Parameter>,
|
||||
inferredType: JetType?
|
||||
): Pair<ControlFlow, String?> {
|
||||
): Pair<ControlFlow, ErrorMessage?> {
|
||||
val outParameters = parameters.filterTo(HashSet<Parameter>()) { it.mirrorVarName != null }
|
||||
|
||||
if (outParameters.size > 1) {
|
||||
val outValuesStr = outParameters.map { it.argumentText }.sort().makeString(separator = "\n")
|
||||
|
||||
val outValuesStr = outParameters.map { it.argumentText }.sort()
|
||||
return Pair(
|
||||
DefaultControlFlow,
|
||||
"${JetRefactoringBundle.message("selected.code.fragment.has.multiple.output.values")!!}\n$outValuesStr"
|
||||
ErrorMessage.MULTIPLE_OUTPUT.addAdditionalInfo(outValuesStr)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ private fun List<Instruction>.analyzeControlFlow(
|
||||
|
||||
if (outParameters.isNotEmpty()) {
|
||||
if (hasMeaningfulType || valuedReturnExits.isNotEmpty() || jumpExits.isNotEmpty()) {
|
||||
return Pair(DefaultControlFlow, JetRefactoringBundle.message("selected.code.fragment.has.output.values.and.exit.points")!!)
|
||||
return Pair(DefaultControlFlow, ErrorMessage.OUTPUT_AND_EXIT_POINT)
|
||||
}
|
||||
|
||||
return Pair(ParameterUpdate(outParameters.first()), null)
|
||||
@@ -198,7 +198,7 @@ private fun List<Instruction>.analyzeControlFlow(
|
||||
|
||||
val multipleExitsError = Pair(
|
||||
DefaultControlFlow,
|
||||
JetRefactoringBundle.message("selected.code.fragment.has.multiple.exit.points")!!
|
||||
ErrorMessage.MULTIPLE_EXIT_POINTS
|
||||
)
|
||||
|
||||
if (hasMeaningfulType) {
|
||||
@@ -310,7 +310,7 @@ private fun ExtractionData.inferParametersInfo(
|
||||
replacementMap: MutableMap<Int, Replacement>,
|
||||
parameters: MutableSet<Parameter>,
|
||||
typeParameters: MutableSet<TypeParameter>
|
||||
): String? {
|
||||
): ErrorMessage? {
|
||||
val varNameValidator = JetNameValidatorImpl(
|
||||
commonParent.getParentByType(javaClass<JetExpression>()),
|
||||
originalElements.first,
|
||||
@@ -328,7 +328,7 @@ private fun ExtractionData.inferParametersInfo(
|
||||
val selector = (ref.getParent() as? JetCallExpression) ?: ref
|
||||
val superExpr = (selector.getParent() as? JetQualifiedExpression)?.getReceiverExpression() as? JetSuperExpression
|
||||
if (superExpr != null) {
|
||||
return JetRefactoringBundle.message("cannot.extract.super.call")!!
|
||||
return ErrorMessage.SUPER_CALL
|
||||
}
|
||||
|
||||
val receiverArgument = resolvedCall?.getReceiverArgument()
|
||||
@@ -347,7 +347,7 @@ private fun ExtractionData.inferParametersInfo(
|
||||
|
||||
if (classObjectClassDescriptor != null) {
|
||||
if (!classObjectClassDescriptor.canBeReferencedViaImport()) {
|
||||
return JetRefactoringBundle.message("cannot.extract.non.local.declaration.ref")!!
|
||||
return ErrorMessage.NON_LOCAL_DECLARATION
|
||||
}
|
||||
|
||||
replacementMap[refInfo.offsetInBody] = FqNameReplacement(DescriptorUtils.getFqNameSafe(originalDescriptor))
|
||||
@@ -435,9 +435,9 @@ private fun ExtractionData.inferParametersInfo(
|
||||
if (nonDenotableTypes.isNotEmpty()) {
|
||||
val typeStr = nonDenotableTypes.map {
|
||||
DescriptorRenderer.HTML.renderType(it)
|
||||
}.sort().makeString(separator = "\n")
|
||||
}.sort()
|
||||
|
||||
return "${JetRefactoringBundle.message("parameter.types.are.not.denotable")!!}\n$typeStr"
|
||||
return ErrorMessage.DENOTABLE_TYPES.addAdditionalInfo(typeStr)
|
||||
}
|
||||
|
||||
parameters.addAll(extractedDescriptorToParameter.values())
|
||||
@@ -449,7 +449,7 @@ private fun ExtractionData.checkLocalDeclarationsWithNonLocalUsages(
|
||||
allInstructions: List<Instruction>,
|
||||
localInstructions: List<Instruction>,
|
||||
bindingContext: BindingContext
|
||||
): String? {
|
||||
): ErrorMessage? {
|
||||
// todo: non-locally used declaration can be turned into the output value
|
||||
|
||||
val declarations = ArrayList<JetNamedDeclaration>()
|
||||
@@ -465,14 +465,14 @@ private fun ExtractionData.checkLocalDeclarationsWithNonLocalUsages(
|
||||
}
|
||||
|
||||
if (declarations.isNotEmpty()) {
|
||||
val localVarStr = declarations.map { it.getName()!! }.sort().makeString(separator = "\n")
|
||||
return "${JetRefactoringBundle.message("variables.are.used.outside.of.selected.code.fragment")!!}\n$localVarStr"
|
||||
val localVarStr = declarations.map { it.getName()!! }.sort()
|
||||
return ErrorMessage.VARIABLES_ARE_USED_OUTSIDE.addAdditionalInfo(localVarStr)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun ExtractionData.checkDeclarationsMovingOutOfScope(controlFlow: ControlFlow): String? {
|
||||
private fun ExtractionData.checkDeclarationsMovingOutOfScope(controlFlow: ControlFlow): ErrorMessage? {
|
||||
val declarationsOutOfScope = HashSet<JetNamedDeclaration>()
|
||||
if (controlFlow is JumpBasedControlFlow) {
|
||||
controlFlow.elementToInsertAfterCall.accept(
|
||||
@@ -488,8 +488,8 @@ private fun ExtractionData.checkDeclarationsMovingOutOfScope(controlFlow: Contro
|
||||
}
|
||||
|
||||
if (declarationsOutOfScope.isNotEmpty()) {
|
||||
val declStr = declarationsOutOfScope.map { it.getName()!! }.sort().makeString(separator = "\n")
|
||||
return "${JetRefactoringBundle.message("declarations.will.move.out.of.scope")!!}\n$declStr"
|
||||
val declStr = declarationsOutOfScope.map { it.getName()!! }.sort()
|
||||
return ErrorMessage.DECLARATIONS_OUT_OF_SCOPE.addAdditionalInfo(declStr)
|
||||
}
|
||||
|
||||
return null
|
||||
@@ -497,14 +497,14 @@ private fun ExtractionData.checkDeclarationsMovingOutOfScope(controlFlow: Contro
|
||||
|
||||
fun ExtractionData.performAnalysis(): AnalysisResult {
|
||||
if (originalElements.empty) {
|
||||
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(JetRefactoringBundle.message("cannot.refactor.no.expresson")!!))
|
||||
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(ErrorMessage.NO_EXPRESSION))
|
||||
}
|
||||
|
||||
val commonParent = PsiTreeUtil.findCommonParent(originalElements)!!
|
||||
|
||||
val enclosingDeclaration = commonParent.getParentByType(javaClass<JetDeclarationWithBody>())
|
||||
if (enclosingDeclaration == null) {
|
||||
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(JetRefactoringBundle.message("cannot.refactor.no.container")!!))
|
||||
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(ErrorMessage.NO_CONTAINER))
|
||||
}
|
||||
|
||||
val resolveSession = originalFile.getLazyResolveSession()
|
||||
@@ -527,7 +527,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
||||
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(parameterError))
|
||||
}
|
||||
|
||||
val messages = ArrayList<String>()
|
||||
val messages = ArrayList<ErrorMessage>()
|
||||
|
||||
val (controlFlow, controlFlowMessage) = localInstructions.analyzeControlFlow(bindingContext, parameters, inferredResultType)
|
||||
controlFlowMessage?.let { messages.add(it) }
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
LineBreakpoint created at syntacticError.kt:5
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! syntacticError.SyntacticErrorPackage
|
||||
LineBreakpoint created at errors.kt:13
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! errors.ErrorsPackage
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
syntacticError.kt:4
|
||||
errors.kt:12
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
@@ -0,0 +1,28 @@
|
||||
package errors
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
MyClass().baseFun()
|
||||
}
|
||||
|
||||
class MyClass: Base() {
|
||||
override fun baseFun() {
|
||||
var prop = 1
|
||||
var prop2 = 2
|
||||
|
||||
//Breakpoint!
|
||||
prop.minus(prop2)
|
||||
}
|
||||
}
|
||||
|
||||
open class Base {
|
||||
open fun baseFun() {}
|
||||
}
|
||||
|
||||
// EXPRESSION: a
|
||||
// RESULT: Unresolved reference: a
|
||||
|
||||
// EXPRESSION: prop.
|
||||
// RESULT: Expecting an element; looking at ERROR_ELEMENT '(1,6) in /fragment.kt
|
||||
|
||||
// EXPRESSION: super.baseFun()
|
||||
// RESULT: Cannot perform an action for expression with super call
|
||||
@@ -0,0 +1,5 @@
|
||||
prop += 1
|
||||
prop2 +=2
|
||||
prop + prop2
|
||||
|
||||
// RESULT: Cannot perform an action because this code fragment changes more than one variable: prop, prop2
|
||||
@@ -0,0 +1,3 @@
|
||||
object {}
|
||||
|
||||
// RESULT: Cannot perform an action because following types are unavailable from debugger scope: errors.MyClass.baseFun.<no name provided>
|
||||
@@ -1,9 +0,0 @@
|
||||
package syntacticError
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
args.size
|
||||
}
|
||||
|
||||
// EXPRESSION: args.
|
||||
// RESULT: Expecting an element; looking at ERROR_ELEMENT '(1,6) in /fragment.kt
|
||||
+1
-1
@@ -45,7 +45,7 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC
|
||||
assert(expressions.size == expectedExpressionResults.size, "Sizes of test directives are different")
|
||||
|
||||
val blocks = findFilesWithBlocks(file).map { FileUtil.loadFile(it, true) }
|
||||
val expectedBlockResults = blocks.map { InTextDirectivesUtils.findStringWithPrefixes(it, "// RESULT: ") ?: throw AssertionError("Couldn't find expected result for block: $it") }
|
||||
val expectedBlockResults = blocks.map { InTextDirectivesUtils.findLinesWithPrefixesRemoved(it, "// RESULT: ").makeString("\n") }
|
||||
|
||||
createDebugProcess(path)
|
||||
|
||||
|
||||
+5
-5
@@ -71,6 +71,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
doTest("idea/testData/debugger/tinyApp/src/evaluate/enums.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("errors.kt")
|
||||
public void testErrors() throws Exception {
|
||||
doTest("idea/testData/debugger/tinyApp/src/evaluate/errors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extractLocalVariables.kt")
|
||||
public void testExtractLocalVariables() throws Exception {
|
||||
doTest("idea/testData/debugger/tinyApp/src/evaluate/extractLocalVariables.kt");
|
||||
@@ -116,11 +121,6 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
doTest("idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("syntacticError.kt")
|
||||
public void testSyntacticError() throws Exception {
|
||||
doTest("idea/testData/debugger/tinyApp/src/evaluate/syntacticError.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("vars.kt")
|
||||
public void testVars() throws Exception {
|
||||
doTest("idea/testData/debugger/tinyApp/src/evaluate/vars.kt");
|
||||
|
||||
Reference in New Issue
Block a user