From 1a67593b46111696b24fcf91986189190c5cecfb Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Tue, 2 Apr 2024 11:45:16 +0800 Subject: [PATCH] fix(kotlin-provider): add PsiErrorElement handling and collect syntax errors This commit fixes an issue where PsiErrorElements were not being handled properly, leading to incorrect behavior when parsing Kotlin files. The commit adds a new method to the RunService interface, `PsiFile.collectPsiError()`, which collects all syntax errors from a PsiErrorElement. This method is used to ensure that only valid Kotlin files are tested. Additionally, the `JavaAutoTestService` now checks for syntax errors before creating a configuration, ensuring that only valid Java files are tested. --- .../idea/service/JavaAutoTestService.kt | 7 +++++ .../kotlin/provider/KotlinAutoTestService.kt | 3 +++ .../cc/unitmesh/devti/provider/RunService.kt | 26 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/java/src/main/kotlin/cc/unitmesh/idea/service/JavaAutoTestService.kt b/java/src/main/kotlin/cc/unitmesh/idea/service/JavaAutoTestService.kt index f2c230fdb4..62bec90d6c 100644 --- a/java/src/main/kotlin/cc/unitmesh/idea/service/JavaAutoTestService.kt +++ b/java/src/main/kotlin/cc/unitmesh/idea/service/JavaAutoTestService.kt @@ -30,6 +30,12 @@ class JavaAutoTestService : AutoTestService() { override fun isApplicable(element: PsiElement): Boolean = element.language is JavaLanguage override fun createConfiguration(project: Project, virtualFile: VirtualFile): RunConfiguration? { + val psiFile = PsiManager.getInstance(project).findFile(virtualFile) as? PsiJavaFile ?: return null + + if(psiFile.collectPsiError().isNotEmpty()) { + return null + } + return createConfigForGradle(virtualFile, project) } @@ -148,6 +154,7 @@ class JavaAutoTestService : AutoTestService() { val document = FileDocumentManager.getInstance().getDocument(testFile) document?.setText(testFileContent) + // OptimizeImportsFix testFile } } diff --git a/kotlin/src/main/kotlin/cc/unitmesh/kotlin/provider/KotlinAutoTestService.kt b/kotlin/src/main/kotlin/cc/unitmesh/kotlin/provider/KotlinAutoTestService.kt index a98fed4ff5..649c504f77 100644 --- a/kotlin/src/main/kotlin/cc/unitmesh/kotlin/provider/KotlinAutoTestService.kt +++ b/kotlin/src/main/kotlin/cc/unitmesh/kotlin/provider/KotlinAutoTestService.kt @@ -219,6 +219,9 @@ class KotlinAutoTestService : AutoTestService() { val document = FileDocumentManager.getInstance().getDocument(testFile) document?.setText(testFileContent) + // TODO: fix import + // org.jetbrains.kotlin.idea.quickfix.ImportFix + testFile } } diff --git a/src/main/kotlin/cc/unitmesh/devti/provider/RunService.kt b/src/main/kotlin/cc/unitmesh/devti/provider/RunService.kt index 6d89e9f850..30f32ea393 100644 --- a/src/main/kotlin/cc/unitmesh/devti/provider/RunService.kt +++ b/src/main/kotlin/cc/unitmesh/devti/provider/RunService.kt @@ -6,12 +6,15 @@ import com.intellij.execution.RunnerAndConfigurationSettings import com.intellij.execution.actions.ConfigurationContext import com.intellij.execution.configurations.RunConfiguration import com.intellij.execution.configurations.RunProfile +import com.intellij.openapi.application.runReadAction import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElement +import com.intellij.psi.PsiErrorElement +import com.intellij.psi.PsiFile interface RunService { private val logger: Logger get() = logger() @@ -88,6 +91,29 @@ interface RunService { return settings } + fun PsiFile.collectPsiError(): MutableList { + val errors = mutableListOf() + val visitor = object : JavaSyntaxCheckingVisitor() { + override fun visitElement(element: PsiElement) { + if (element is PsiErrorElement) { + errors.add("Syntax error at position ${element.textRange.startOffset}: ${element.errorDescription}") + } + super.visitElement(element) + } + } + + this.accept(visitor) + return errors + } + + abstract class JavaSyntaxCheckingVisitor : com.intellij.psi.PsiElementVisitor() { + override fun visitElement(element: PsiElement) { + runReadAction { + element.children.forEach { it.accept(this) } + } + } + } + private fun createDefaultTestConfigurations(project: Project, element: PsiElement): RunnerAndConfigurationSettings? { return ConfigurationContext(element).configurationsFromContext?.firstOrNull()?.configurationSettings }