REPL: improve "are all errors at EOF" detection

Also ignore whitespaces and comments that appear after the last error in
a REPL line

 #KT-15172 Fixed
This commit is contained in:
Alexander Udalov
2017-06-06 17:55:53 +03:00
parent 2326b5faf3
commit 6f22baa0f6
3 changed files with 36 additions and 7 deletions
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.cli.common.messages
import com.intellij.openapi.util.io.FileUtil.toSystemDependentName import com.intellij.openapi.util.io.FileUtil.toSystemDependentName
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement import com.intellij.psi.*
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiModifierListOwner
import com.intellij.psi.util.PsiFormatUtil import com.intellij.psi.util.PsiFormatUtil
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
@@ -170,9 +168,7 @@ class AnalyzerWithCompilerReport(private val messageCollector: MessageCollector)
return hasErrors return hasErrors
} }
fun reportSyntaxErrors( fun reportSyntaxErrors(file: PsiElement, reporter: DiagnosticMessageReporter): SyntaxErrorReport {
file: PsiElement,
reporter: DiagnosticMessageReporter): SyntaxErrorReport {
class ErrorReportingVisitor : AnalyzingUtils.PsiErrorElementVisitor() { class ErrorReportingVisitor : AnalyzingUtils.PsiErrorElementVisitor() {
var hasErrors = false var hasErrors = false
var allErrorsAtEof = true var allErrorsAtEof = true
@@ -180,12 +176,20 @@ class AnalyzerWithCompilerReport(private val messageCollector: MessageCollector)
private fun <E : PsiElement> reportDiagnostic(element: E, factory: DiagnosticFactory0<E>, message: String) { private fun <E : PsiElement> reportDiagnostic(element: E, factory: DiagnosticFactory0<E>, message: String) {
val diagnostic = MyDiagnostic(element, factory, message) val diagnostic = MyDiagnostic(element, factory, message)
AnalyzerWithCompilerReport.reportDiagnostic(diagnostic, reporter) AnalyzerWithCompilerReport.reportDiagnostic(diagnostic, reporter)
if (element.textRange.startOffset != file.textRange.endOffset) { if (allErrorsAtEof && !element.isAtEof()) {
allErrorsAtEof = false allErrorsAtEof = false
} }
hasErrors = true hasErrors = true
} }
private fun PsiElement.isAtEof(): Boolean {
var element = this
while (true) {
element = element.nextSibling ?: return true
if (element !is PsiWhiteSpace || element !is PsiComment) return false
}
}
override fun visitErrorElement(element: PsiErrorElement) { override fun visitErrorElement(element: PsiErrorElement) {
val description = element.errorDescription val description = element.errorDescription
reportDiagnostic(element, SYNTAX_ERROR_FACTORY, reportDiagnostic(element, SYNTAX_ERROR_FACTORY,
@@ -0,0 +1,19 @@
>>> fun f1(): String {
...
... return "1"
... }
>>> fun f2(): String { // comment
... return "2" // comment
... } // comment
>>> fun f3(): String {
... /* comment */
...
... // comment
... return "3"
... }
>>> fun f4(): String {
... return "4"
... }
>>>
>>> f1() + f2() + f3() + f4()
1234
@@ -281,6 +281,12 @@ public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/repl/multiline"), Pattern.compile("^(.+)\\.repl$"), TargetBackend.ANY, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/repl/multiline"), Pattern.compile("^(.+)\\.repl$"), TargetBackend.ANY, true);
} }
@TestMetadata("blankLinesAndComments.repl")
public void testBlankLinesAndComments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/multiline/blankLinesAndComments.repl");
doTest(fileName);
}
@TestMetadata("functionOnSeveralLines.repl") @TestMetadata("functionOnSeveralLines.repl")
public void testFunctionOnSeveralLines() throws Exception { public void testFunctionOnSeveralLines() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/multiline/functionOnSeveralLines.repl"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/multiline/functionOnSeveralLines.repl");