[REPL] Fix syntax errors analysis and incompleteness detection
This commit is contained in:
+6
-10
@@ -92,7 +92,7 @@ open class KJvmReplCompilerBase<AnalyzerT : ReplCodeAnalyzerBase> protected cons
|
|||||||
snippet,
|
snippet,
|
||||||
messageCollector,
|
messageCollector,
|
||||||
compilationState,
|
compilationState,
|
||||||
checkSyntaxErrors = true
|
failOnSyntaxErrors = true
|
||||||
).valueOr { return@withMessageCollector it }
|
).valueOr { return@withMessageCollector it }
|
||||||
|
|
||||||
val (sourceFiles, sourceDependencies) = collectRefinedSourcesAndUpdateEnvironment(
|
val (sourceFiles, sourceDependencies) = collectRefinedSourcesAndUpdateEnvironment(
|
||||||
@@ -242,7 +242,7 @@ open class KJvmReplCompilerBase<AnalyzerT : ReplCodeAnalyzerBase> protected cons
|
|||||||
snippet: SourceCode,
|
snippet: SourceCode,
|
||||||
parentMessageCollector: MessageCollector,
|
parentMessageCollector: MessageCollector,
|
||||||
compilationState: JvmReplCompilerState.Compilation,
|
compilationState: JvmReplCompilerState.Compilation,
|
||||||
checkSyntaxErrors: Boolean
|
failOnSyntaxErrors: Boolean
|
||||||
): ResultWithDiagnostics<AnalyzePreparationResult> =
|
): ResultWithDiagnostics<AnalyzePreparationResult> =
|
||||||
withMessageCollector(
|
withMessageCollector(
|
||||||
snippet,
|
snippet,
|
||||||
@@ -269,15 +269,11 @@ open class KJvmReplCompilerBase<AnalyzerT : ReplCodeAnalyzerBase> protected cons
|
|||||||
)
|
)
|
||||||
.valueOr { return it }
|
.valueOr { return it }
|
||||||
|
|
||||||
if (checkSyntaxErrors) {
|
val syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(snippetKtFile, errorHolder)
|
||||||
val syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(snippetKtFile, errorHolder)
|
if (syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof) {
|
||||||
if (syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof) return failure(
|
messageCollector.report(ScriptDiagnostic(ScriptDiagnostic.incompleteCode, "Incomplete code"))
|
||||||
messageCollector, ScriptDiagnostic(ScriptDiagnostic.incompleteCode, "Incomplete code")
|
|
||||||
)
|
|
||||||
if (syntaxErrorReport.isHasErrors) return failure(
|
|
||||||
messageCollector
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
if (failOnSyntaxErrors && syntaxErrorReport.isHasErrors) return failure(messageCollector)
|
||||||
|
|
||||||
return AnalyzePreparationResult(
|
return AnalyzePreparationResult(
|
||||||
context,
|
context,
|
||||||
|
|||||||
+23
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.scripting.compiler.plugin.impl
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.Argument
|
import org.jetbrains.kotlin.cli.common.arguments.Argument
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
@@ -58,6 +59,28 @@ class ScriptDiagnosticsMessageCollector(private val parentMessageCollector: Mess
|
|||||||
}
|
}
|
||||||
parentMessageCollector?.report(severity, message, location)
|
parentMessageCollector?.report(severity, message, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun report(diagnostic: ScriptDiagnostic) {
|
||||||
|
_diagnostics.add(diagnostic)
|
||||||
|
|
||||||
|
if (parentMessageCollector == null) return
|
||||||
|
if (parentMessageCollector is ScriptDiagnosticsMessageCollector) {
|
||||||
|
parentMessageCollector.report(diagnostic)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val locationStart = diagnostic.location?.start
|
||||||
|
parentMessageCollector.report(
|
||||||
|
diagnostic.severity.toCompilerMessageSeverity(),
|
||||||
|
diagnostic.message,
|
||||||
|
CompilerMessageLocation.create(
|
||||||
|
null,
|
||||||
|
locationStart?.line ?: -1,
|
||||||
|
locationStart?.col ?: -1,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CompilerMessageSeverity.toScriptingSeverity(): ScriptDiagnostic.Severity? = when (this) {
|
private fun CompilerMessageSeverity.toScriptingSeverity(): ScriptDiagnostic.Severity? = when (this) {
|
||||||
|
|||||||
+14
@@ -198,6 +198,20 @@ class ReplCompletionAndErrorsAnalysisTest : TestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIncompleteCode() = test {
|
||||||
|
run {
|
||||||
|
doErrorCheck
|
||||||
|
|
||||||
|
code = "fun g(): Int { return 1"
|
||||||
|
|
||||||
|
expect {
|
||||||
|
addError(1, 24, 1, 24, "Expecting '}'", "ERROR")
|
||||||
|
errors.add(ScriptDiagnostic(ScriptDiagnostic.incompleteCode, "Incomplete code"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCompletionDuplication() = test {
|
fun testCompletionDuplication() = test {
|
||||||
for (i in 1..6) {
|
for (i in 1..6) {
|
||||||
|
|||||||
+1
-1
@@ -283,7 +283,7 @@ private suspend fun checkEvaluateInRepl(
|
|||||||
|
|
||||||
checkLists(index, "completions", expectedCompletions.list, completionsRes, expectedCompletions)
|
checkLists(index, "completions", expectedCompletions.list, completionsRes, expectedCompletions)
|
||||||
val expectedErrorsWithPath = expectedErrors.list.map {
|
val expectedErrorsWithPath = expectedErrors.list.map {
|
||||||
it.copy(sourcePath = errorsRes.firstOrNull()?.sourcePath)
|
if (it.location != null) it.copy(sourcePath = errorsRes.firstOrNull()?.sourcePath) else it
|
||||||
}
|
}
|
||||||
checkLists(index, "errors", expectedErrorsWithPath, errorsRes, expectedErrors)
|
checkLists(index, "errors", expectedErrorsWithPath, errorsRes, expectedErrors)
|
||||||
TestCase.assertEquals("Analysis result types are different", expectedResultType, resultType)
|
TestCase.assertEquals("Analysis result types are different", expectedResultType, resultType)
|
||||||
|
|||||||
+1
-1
@@ -111,7 +111,7 @@ class KJvmReplCompilerWithIdeServices(hostConfiguration: ScriptingHostConfigurat
|
|||||||
newSnippet,
|
newSnippet,
|
||||||
messageCollector,
|
messageCollector,
|
||||||
compilationState,
|
compilationState,
|
||||||
checkSyntaxErrors = false
|
failOnSyntaxErrors = false
|
||||||
).valueOr { return it }
|
).valueOr { return it }
|
||||||
|
|
||||||
val analysisResult =
|
val analysisResult =
|
||||||
|
|||||||
Reference in New Issue
Block a user