From 3cf0cc1577b1444e21d9d65bde050520f4005237 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Thu, 16 Jan 2025 11:26:16 +0300 Subject: [PATCH 1/3] feat(QueryEditor): add error highlighting --- .../Tenant/Query/QueryEditor/QueryEditor.tsx | 2 + .../Tenant/Query/QueryEditor/helpers.ts | 1 + src/utils/monaco/highlightErrors.ts | 54 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/utils/monaco/highlightErrors.ts diff --git a/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx b/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx index 29cd198ad..a5c6a289c 100644 --- a/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx +++ b/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx @@ -42,6 +42,7 @@ import { import {useChangedQuerySettings} from '../../../../utils/hooks/useChangedQuerySettings'; import {useLastQueryExecutionSettings} from '../../../../utils/hooks/useLastQueryExecutionSettings'; import {YQL_LANGUAGE_ID} from '../../../../utils/monaco/constats'; +import {updateErrorsHighlighting} from '../../../../utils/monaco/highlightErrors'; import {QUERY_ACTIONS} from '../../../../utils/query'; import type {InitialPaneState} from '../../utils/paneVisibilityToggleHelpers'; import { @@ -294,6 +295,7 @@ export default function QueryEditor(props: QueryEditorProps) { }; const onChange = (newValue: string) => { + updateErrorsHighlighting(); changeUserInput({input: newValue}); }; diff --git a/src/containers/Tenant/Query/QueryEditor/helpers.ts b/src/containers/Tenant/Query/QueryEditor/helpers.ts index d1207d33c..990ded87b 100644 --- a/src/containers/Tenant/Query/QueryEditor/helpers.ts +++ b/src/containers/Tenant/Query/QueryEditor/helpers.ts @@ -13,6 +13,7 @@ const EDITOR_OPTIONS: EditorOptions = { minimap: { enabled: false, }, + fixedOverflowWidgets: true, }; export function useEditorOptions() { diff --git a/src/utils/monaco/highlightErrors.ts b/src/utils/monaco/highlightErrors.ts new file mode 100644 index 000000000..e4a521382 --- /dev/null +++ b/src/utils/monaco/highlightErrors.ts @@ -0,0 +1,54 @@ +import {parseYqlQueryWithoutCursor} from '@gravity-ui/websql-autocomplete/yql'; +import {MarkerSeverity, editor} from 'monaco-editor'; + +const owner = 'ydb'; + +let errorsHighlightingTimeoutId: ReturnType; + +export function disableErrorsHighlighting(): void { + unHighlightErrors(); +} + +export function updateErrorsHighlighting(): void { + disableErrorsHighlighting(); + + clearTimeout(errorsHighlightingTimeoutId); + errorsHighlightingTimeoutId = setTimeout(() => highlightErrors(), 500); +} + +function highlightErrors(): void { + const model = window.ydbEditor?.getModel(); + if (!model) { + console.error('unable to retrieve model when highlighting errors'); + return; + } + + const errors = parseYqlQueryWithoutCursor(model.getValue()).errors; + if (!errors.length) { + unHighlightErrors(); + return; + } + + const markers = errors.map( + (error): editor.IMarkerData => ({ + message: 'Syntax error', + source: error.message, + severity: MarkerSeverity.Error, + startLineNumber: error.startLine, + startColumn: convertAutocompleteErrorLocationIndexToMonacoIndex(error.startColumn), + endLineNumber: error.endLine, + endColumn: convertAutocompleteErrorLocationIndexToMonacoIndex(error.endColumn), + }), + ); + editor.setModelMarkers(model, owner, markers); +} + +function unHighlightErrors(): void { + editor.removeAllMarkers(owner); +} + +function convertAutocompleteErrorLocationIndexToMonacoIndex( + autocompleteLocationIndex: number, +): number { + return autocompleteLocationIndex + 1; +} From 3f22c2f36f9e78dd96333b5b0c908d9661e8f168 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Fri, 17 Jan 2025 15:49:28 +0300 Subject: [PATCH 2/3] fix: review --- src/utils/monaco/highlightErrors.ts | 31 +++++++++++------------------ src/utils/monaco/i18n/en.json | 3 +++ src/utils/monaco/i18n/index.ts | 7 +++++++ 3 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 src/utils/monaco/i18n/en.json create mode 100644 src/utils/monaco/i18n/index.ts diff --git a/src/utils/monaco/highlightErrors.ts b/src/utils/monaco/highlightErrors.ts index e4a521382..04a483a8d 100644 --- a/src/utils/monaco/highlightErrors.ts +++ b/src/utils/monaco/highlightErrors.ts @@ -1,22 +1,20 @@ import {parseYqlQueryWithoutCursor} from '@gravity-ui/websql-autocomplete/yql'; import {MarkerSeverity, editor} from 'monaco-editor'; +import i18n from './i18n'; + const owner = 'ydb'; let errorsHighlightingTimeoutId: ReturnType; -export function disableErrorsHighlighting(): void { +export function updateErrorsHighlighting() { unHighlightErrors(); -} - -export function updateErrorsHighlighting(): void { - disableErrorsHighlighting(); clearTimeout(errorsHighlightingTimeoutId); errorsHighlightingTimeoutId = setTimeout(() => highlightErrors(), 500); } -function highlightErrors(): void { +function highlightErrors() { const model = window.ydbEditor?.getModel(); if (!model) { console.error('unable to retrieve model when highlighting errors'); @@ -29,26 +27,21 @@ function highlightErrors(): void { return; } - const markers = errors.map( - (error): editor.IMarkerData => ({ - message: 'Syntax error', + const markers = errors.map((error): editor.IMarkerData => { + const markerColumn = error.startColumn + 1; + return { + message: i18n('context_syntax-error'), source: error.message, severity: MarkerSeverity.Error, startLineNumber: error.startLine, - startColumn: convertAutocompleteErrorLocationIndexToMonacoIndex(error.startColumn), + startColumn: markerColumn, endLineNumber: error.endLine, - endColumn: convertAutocompleteErrorLocationIndexToMonacoIndex(error.endColumn), - }), - ); + endColumn: markerColumn, + }; + }); editor.setModelMarkers(model, owner, markers); } function unHighlightErrors(): void { editor.removeAllMarkers(owner); } - -function convertAutocompleteErrorLocationIndexToMonacoIndex( - autocompleteLocationIndex: number, -): number { - return autocompleteLocationIndex + 1; -} diff --git a/src/utils/monaco/i18n/en.json b/src/utils/monaco/i18n/en.json new file mode 100644 index 000000000..d4b173c36 --- /dev/null +++ b/src/utils/monaco/i18n/en.json @@ -0,0 +1,3 @@ +{ + "context_syntax-error": "Syntax error" +} diff --git a/src/utils/monaco/i18n/index.ts b/src/utils/monaco/i18n/index.ts new file mode 100644 index 000000000..0061fd670 --- /dev/null +++ b/src/utils/monaco/i18n/index.ts @@ -0,0 +1,7 @@ +import {registerKeysets} from '../../i18n'; + +import en from './en.json'; + +const COMPONENT = 'ydb-monaco'; + +export default registerKeysets(COMPONENT, {en}); From f303d3825b7c11d5b9fd1e624428b9f41425fcd7 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Fri, 17 Jan 2025 16:22:51 +0300 Subject: [PATCH 3/3] fix: review --- src/utils/monaco/highlightErrors.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/utils/monaco/highlightErrors.ts b/src/utils/monaco/highlightErrors.ts index 04a483a8d..d5eace811 100644 --- a/src/utils/monaco/highlightErrors.ts +++ b/src/utils/monaco/highlightErrors.ts @@ -27,18 +27,17 @@ function highlightErrors() { return; } - const markers = errors.map((error): editor.IMarkerData => { - const markerColumn = error.startColumn + 1; - return { + const markers = errors.map( + (error): editor.IMarkerData => ({ message: i18n('context_syntax-error'), source: error.message, severity: MarkerSeverity.Error, startLineNumber: error.startLine, - startColumn: markerColumn, + startColumn: error.startColumn + 1, endLineNumber: error.endLine, - endColumn: markerColumn, - }; - }); + endColumn: error.endColumn + 1, + }), + ); editor.setModelMarkers(model, owner, markers); }