-
Notifications
You must be signed in to change notification settings - Fork 83
feat(webui): Highlight Presto SQL syntax errors for guided UI inputs with ANTLR. #1533
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 11 commits
bf8af6a
33f4afe
1b326fd
2b9a0ea
6f83b4d
63d3d45
57edfd4
e26809e
76248cd
cb77dad
8799f54
ec83aef
528f9b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,41 @@ | ||
| // Reference: https://github.com/vikyd/vue-monaco-singleline | ||
| import {useCallback} from "react"; | ||
| import { | ||
| useCallback, | ||
| useEffect, | ||
| useRef, | ||
| } from "react"; | ||
|
|
||
| import { Nullable } from "@webui/common/utility-types"; | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; | ||
|
|
||
| import {ValidationError} from "../../sql-parser"; | ||
| import SqlEditor, { | ||
| SqlEditorProps, | ||
| SqlEditorType, | ||
| } from "../SqlEditor"; | ||
|
|
||
|
|
||
| type SqlInputProps = SqlEditorProps & { | ||
| /** | ||
| * Validation function to check SQL syntax and return errors. | ||
| */ | ||
| validateFn?: (sqlString: string) => ValidationError[]; | ||
| }; | ||
|
|
||
| /** | ||
| * Single-line SQL input. | ||
| * | ||
| * @param props | ||
| * @return | ||
| */ | ||
| const SqlInput = (props: SqlEditorProps) => { | ||
| const SqlInput = (props: SqlInputProps) => { | ||
| const {validateFn, ...editorProps} = props; | ||
| const editorRef = useRef<Nullable<SqlEditorType>>(null); | ||
|
|
||
| const handleEditorReady = useCallback((editor: SqlEditorType) => { | ||
| editorRef.current = editor; | ||
|
|
||
| // Prevent multi-line input by repositioning cursor and replacing newlines with empty | ||
| // string. | ||
| editor.onDidChangeCursorPosition((e) => { | ||
|
|
@@ -42,6 +61,41 @@ const SqlInput = (props: SqlEditorProps) => { | |
| }); | ||
| }, []); | ||
|
|
||
| // Validate SQL and update markers whenever value changes | ||
| useEffect(() => { | ||
| const editor = editorRef.current; | ||
| if (null === editor) { | ||
| return; | ||
| } | ||
|
|
||
| const model = editor.getModel(); | ||
| if (null === model) { | ||
| return; | ||
| } | ||
|
|
||
| const value = editorProps.value ?? ""; | ||
|
|
||
| // Clear markers if no validation function or empty/whitespace-only input | ||
| if ("undefined" === typeof validateFn || "" === value.trim()) { | ||
| monaco.editor.setModelMarkers(model, "sql-parser", []); | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| const errors = validateFn(value); | ||
| const markers: monaco.editor.IMarkerData[] = errors.map((error) => ({ | ||
| endColumn: error.endColumn, | ||
| endLineNumber: error.line, | ||
| message: error.message, | ||
| severity: monaco.MarkerSeverity.Error, | ||
| startColumn: error.startColumn, | ||
| startLineNumber: error.line, | ||
| })); | ||
|
|
||
| monaco.editor.setModelMarkers(model, "sql-parser", markers); | ||
| }, [editorProps.value, | ||
| validateFn]); | ||
|
Comment on lines
+63
to
+96
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial LGTM with optional error-handling suggestion. The validation logic correctly applies Monaco markers and follows the coding guidelines with explicit comparisons. The useEffect dependencies are accurate. Optionally, consider wrapping the validator call in a try-catch to handle unexpected parse errors gracefully: const errors = validateFn(value);
+ try {
+ errors = validateFn(value);
+ } catch (e) {
+ console.error("Validation failed:", e);
+ return;
+ }
const markers: monaco.editor.IMarkerData[] = errors.map((error) => ({This would prevent the component from crashing if the validator throws an unexpected error.
🤖 Prompt for AI Agents |
||
|
|
||
| return ( | ||
| <SqlEditor | ||
| options={{ | ||
|
|
@@ -76,8 +130,9 @@ const SqlInput = (props: SqlEditorProps) => { | |
| wordWrap: "off", | ||
| }} | ||
| onEditorReady={handleEditorReady} | ||
| {...props}/> | ||
| {...editorProps}/> | ||
| ); | ||
| }; | ||
|
|
||
| export default SqlInput; | ||
| export type {SqlInputProps}; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix import sorting to resolve pipeline failure.
The pipeline reports an import sorting violation that must be resolved before merge.
Run the autofix command to sort the imports:
Or manually reorder if needed.
🧰 Tools
🪛 GitHub Actions: clp-lint
[warning] 2-2: Run autofix to sort these imports! simple-import-sort/imports
🤖 Prompt for AI Agents