From bed5a3c8f3a3ea584db7eb73e36bfe5eebe2234a Mon Sep 17 00:00:00 2001 From: Natalia Selezneva Date: Thu, 15 Mar 2018 09:41:24 +0300 Subject: [PATCH] Scratch: find correct line to report error at ^KT-23480 Fixed EA-117936 Fixed --- .../scratch/compile/KtCompilingExecutor.kt | 43 +++++++++++++------ .../scratch/unresolvedMultiline.comp.after | 3 ++ idea/testData/scratch/unresolvedMultiline.kts | 3 ++ .../scratch/unresolvedMultiline.repl.after | 3 ++ .../ScratchRunActionTestGenerated.java | 10 +++++ 5 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 idea/testData/scratch/unresolvedMultiline.comp.after create mode 100644 idea/testData/scratch/unresolvedMultiline.kts create mode 100644 idea/testData/scratch/unresolvedMultiline.repl.after diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt index 4eafe0b994d..d13f311fcfc 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtCompilingExecutor.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtScript +import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.resolve.AnalyzingUtils import java.io.File @@ -180,8 +181,12 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { if (psiFile == scratchPsiFile) { if (diagnostic.psiElement.containingFile == psiFile) { val scratchExpression = file.findExpression(diagnostic.psiElement) - handlers.forEach { - it.handle(file, scratchExpression, ScratchOutput(errorText, ScratchOutputType.ERROR)) + if (scratchExpression == null) { + LOG.error("Couldn't find expression to report error: ${diagnostic.psiElement.getElementTextWithContext()}") + handlers.forEach { it.error(file, errorText) } + + } else { + handlers.forEach { it.handle(file, scratchExpression, ScratchOutput(errorText, ScratchOutputType.ERROR)) } } } else { handlers.forEach { it.error(file, errorText) } @@ -201,12 +206,14 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { handlers.forEach { it.onFinish(file) } } - private fun ScratchFile.findExpression(psiElement: PsiElement): ScratchExpression { - return findExpression(psiElement.getLineNumber(true), psiElement.getLineNumber(false)) + private fun ScratchFile.findExpression(psiElement: PsiElement): ScratchExpression? { + val lineStart = psiElement.getLineNumber(true) + val lineEnd = psiElement.getLineNumber(false) + return getExpressions().firstOrNull { it.lineStart == lineStart || it.lineEnd == lineEnd } } - private fun ScratchFile.findExpression(lineStart: Int, lineEnd: Int): ScratchExpression { - return getExpressions().first { it.lineStart == lineStart && it.lineEnd == lineEnd } + private fun ScratchFile.findExpression(lineStart: Int, lineEnd: Int): ScratchExpression? { + return getExpressions().firstOrNull { it.lineStart == lineStart && it.lineEnd == lineEnd } } private inner class ProcessOutputParser { @@ -234,18 +241,26 @@ class KtCompilingExecutor(file: ScratchFile) : ScratchExecutor(file) { if (isGeneratedOutput(line)) { val lineWoPrefix = line.removePrefix(KtScratchSourceFileProcessor.GENERATED_OUTPUT_PREFIX) if (isResultEnd(lineWoPrefix)) { - val (startLine, endLine) = extractLineInfoFrom(lineWoPrefix) + val extractedLineInfo = extractLineInfoFrom(lineWoPrefix) ?: return error("Couldn't extract line info from line: $lineWoPrefix") + val (startLine, endLine) = extractedLineInfo val scratchExpression = file.findExpression(startLine, endLine) - userOutput.forEach { output -> - handlers.forEach { - it.handle(file, scratchExpression, ScratchOutput(output, ScratchOutputType.OUTPUT)) + if (scratchExpression == null) { + LOG.error( + "Couldn't find expression with start line = $startLine, end line = $endLine.\n" + + file.getExpressions().joinToString("\n") + ) + } else { + userOutput.forEach { output -> + handlers.forEach { + it.handle(file, scratchExpression, ScratchOutput(output, ScratchOutputType.OUTPUT)) + } } - } - results.forEach { result -> - handlers.forEach { - it.handle(file, scratchExpression, ScratchOutput(result, ScratchOutputType.RESULT)) + results.forEach { result -> + handlers.forEach { + it.handle(file, scratchExpression, ScratchOutput(result, ScratchOutputType.RESULT)) + } } } diff --git a/idea/testData/scratch/unresolvedMultiline.comp.after b/idea/testData/scratch/unresolvedMultiline.comp.after new file mode 100644 index 00000000000..2dac17a1d44 --- /dev/null +++ b/idea/testData/scratch/unresolvedMultiline.comp.after @@ -0,0 +1,3 @@ +foo.forEach { // ERROR: Unresolved reference: foo; Cannot choose among the following candidates without completing type inference: + 1 + 1 +} \ No newline at end of file diff --git a/idea/testData/scratch/unresolvedMultiline.kts b/idea/testData/scratch/unresolvedMultiline.kts new file mode 100644 index 00000000000..b3da33ca920 --- /dev/null +++ b/idea/testData/scratch/unresolvedMultiline.kts @@ -0,0 +1,3 @@ +foo.forEach { + 1 + 1 +} \ No newline at end of file diff --git a/idea/testData/scratch/unresolvedMultiline.repl.after b/idea/testData/scratch/unresolvedMultiline.repl.after new file mode 100644 index 00000000000..ef7666a5543 --- /dev/null +++ b/idea/testData/scratch/unresolvedMultiline.repl.after @@ -0,0 +1,3 @@ +foo.forEach { // ERROR: error: unresolved reference: foo + 1 + 1 +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java index 1e2dd1c9ca5..93c1917d50a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java @@ -66,6 +66,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest runTest("idea/testData/scratch/unresolved.kts"); } + @TestMetadata("unresolvedMultiline.kts") + public void testUnresolvedMultiline() throws Exception { + runTest("idea/testData/scratch/unresolvedMultiline.kts"); + } + @TestMetadata("userOutput.kts") public void testUserOutput() throws Exception { runTest("idea/testData/scratch/userOutput.kts"); @@ -129,6 +134,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest runTest("idea/testData/scratch/unresolved.kts"); } + @TestMetadata("unresolvedMultiline.kts") + public void testUnresolvedMultiline() throws Exception { + runTest("idea/testData/scratch/unresolvedMultiline.kts"); + } + @TestMetadata("userOutput.kts") public void testUserOutput() throws Exception { runTest("idea/testData/scratch/userOutput.kts");