Skip to content

Commit a9b9b77

Browse files
committed
feat(devins-lang): add support for parsing and verifying SQL scripts before inserting them into the editor.
This commit introduces a new feature to the devins-lang extension that allows for the parsing and verification of SQL scripts before they are inserted into the editor. This is achieved by creating a temporary SQL file from the script text and using a custom visitor to check for syntax errors. If any errors are found, they are logged and the user is notified. This feature helps to ensure that only valid SQL scripts are entered into the editor, reducing the risk of runtime errors.
1 parent 6872c07 commit a9b9b77

File tree

2 files changed

+33
-23
lines changed

2 files changed

+33
-23
lines changed

exts/database/src/main/kotlin/cc/unitmesh/database/flow/AutoSqlBackgroundTask.kt

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import com.intellij.openapi.editor.Editor
99
import com.intellij.openapi.progress.ProgressIndicator
1010
import com.intellij.openapi.progress.Task
1111
import com.intellij.openapi.project.Project
12+
import com.intellij.psi.PsiElement
13+
import com.intellij.psi.PsiErrorElement
1214
import com.intellij.psi.PsiFileFactory
15+
import com.intellij.sql.psi.SqlFile
1316

1417
class AutoSqlBackgroundTask(
1518
private val project: Project,
@@ -44,9 +47,14 @@ class AutoSqlBackgroundTask(
4447
logger.info("SQL Script: $sqlScript")
4548
// verify sql script with parser
4649
try {
47-
val sqlDefine =
50+
val sqlFile =
4851
PsiFileFactory.getInstance(project).createFileFromText("temp.sql", language, sqlScript)
49-
// if there is no error, we can insert the code to editor
52+
as SqlFile
53+
54+
val errors = sqlFile.verifySqlElement()
55+
if (errors.isNotEmpty()) {
56+
logger.error("SQL Script parse error: ${errors[0]}")
57+
}
5058
} catch (e: Exception) {
5159
logger.error("SQL Script parse error: $e")
5260
}
@@ -59,4 +67,25 @@ class AutoSqlBackgroundTask(
5967

6068
indicator.fraction = 1.0
6169
}
70+
}
71+
72+
fun SqlFile.verifySqlElement(): MutableList<String> {
73+
val errors = mutableListOf<String>()
74+
val visitor = object : SqlSyntaxCheckingVisitor() {
75+
override fun visitElement(element: PsiElement) {
76+
if (element is PsiErrorElement) {
77+
errors.add("Syntax error at position ${element.textRange.startOffset}: ${element.errorDescription}")
78+
}
79+
super.visitElement(element)
80+
}
81+
}
82+
83+
this.accept(visitor)
84+
return errors
85+
}
86+
87+
abstract class SqlSyntaxCheckingVisitor : com.intellij.psi.PsiElementVisitor() {
88+
override fun visitElement(element: PsiElement) {
89+
element.children.forEach { it.accept(this) }
90+
}
6291
}
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package cc.unitmesh.database.flow;
22

3-
import com.intellij.psi.PsiElement
4-
import com.intellij.psi.PsiErrorElement
53
import com.intellij.psi.PsiFileFactory
64
import com.intellij.sql.psi.SqlFile
75
import com.intellij.sql.psi.SqlLanguage
@@ -20,27 +18,10 @@ class AutoSqlBackgroundTaskTest: LightPlatformTestCase() {
2018
PsiFileFactory.getInstance(project).createFileFromText("temp.sql", SqlLanguage.INSTANCE, code)
2119
as SqlFile
2220

23-
// verify sqlFile syntax correct
24-
// Verify
25-
val errors = mutableListOf<String>()
26-
val visitor = object : SqlSyntaxCheckingVisitor() {
27-
override fun visitElement(element: PsiElement) {
28-
if (element is PsiErrorElement) {
29-
errors.add("Syntax error at position ${element.textRange.startOffset}: ${element.errorDescription}")
30-
}
31-
super.visitElement(element)
32-
}
33-
}
34-
sqlFile.accept(visitor)
21+
val errors = sqlFile.verifySqlElement()
3522

36-
// err msg: SQL syntax contains errors: Syntax error at position 30: <expression>, ALL, ANY or SOME expected, got ';'
23+
// Then
3724
assertTrue(errors.isNotEmpty())
3825
assertEquals("Syntax error at position 30: <expression>, ALL, ANY or SOME expected, got ';'", errors[0])
3926
}
40-
41-
abstract class SqlSyntaxCheckingVisitor : com.intellij.psi.PsiElementVisitor() {
42-
override fun visitElement(element: PsiElement) {
43-
element.children.forEach { it.accept(this) }
44-
}
45-
}
4627
}

0 commit comments

Comments
 (0)