From 5ec6d44b4ce578d7d717824273c87a03a6e8d992 Mon Sep 17 00:00:00 2001 From: Marius Andra Date: Tue, 18 Jun 2024 12:56:44 +0200 Subject: [PATCH] feat(hog): syntax highlighting for monaco (#23043) --- frontend/src/lib/components/CodeEditors.tsx | 42 +- frontend/src/lib/monaco/hog.ts | 245 +++++ frontend/src/lib/monaco/hogql.ts | 847 ++++++++++++++++++ .../nodes/HogQLQuery/HogQLQueryEditor.tsx | 2 +- frontend/src/scenes/debug/HogDebug.tsx | 2 +- .../PipelineHogFunctionConfiguration.tsx | 2 +- package.json | 4 +- pnpm-lock.yaml | 36 +- 8 files changed, 1153 insertions(+), 27 deletions(-) create mode 100644 frontend/src/lib/monaco/hog.ts create mode 100644 frontend/src/lib/monaco/hogql.ts diff --git a/frontend/src/lib/components/CodeEditors.tsx b/frontend/src/lib/components/CodeEditors.tsx index d66ef75f4d2..26f74b3f715 100644 --- a/frontend/src/lib/components/CodeEditors.tsx +++ b/frontend/src/lib/components/CodeEditors.tsx @@ -1,8 +1,10 @@ import './CodeEditor.scss' -import MonacoEditor, { type EditorProps } from '@monaco-editor/react' +import MonacoEditor, { type EditorProps, Monaco } from '@monaco-editor/react' import { useValues } from 'kea' import { Spinner } from 'lib/lemon-ui/Spinner' +import * as hog from 'lib/monaco/hog' +import * as hogQL from 'lib/monaco/hogql' import { inStorybookTestRunner } from 'lib/utils' import { useEffect, useRef, useState } from 'react' import AutoSizer from 'react-virtualized/dist/es/AutoSizer' @@ -11,9 +13,26 @@ import { themeLogic } from '~/layout/navigation-3000/themeLogic' export type CodeEditorProps = Omit -export function CodeEditor({ options, ...editorProps }: CodeEditorProps): JSX.Element { - const { isDarkModeOn } = useValues(themeLogic) +function registerHog(monaco: Monaco): void { + if (monaco.languages.getLanguages().some(({ id }) => id === 'hog')) { + return + } + monaco.languages.register({ id: 'hog', extensions: ['.hog'], mimetypes: ['application/hog'] }) + monaco.languages.setLanguageConfiguration('hog', hog.conf) + monaco.languages.setMonarchTokensProvider('hog', hog.language) +} +function registerHogQL(monaco: Monaco): void { + if (monaco.languages.getLanguages().some(({ id }) => id === 'hogql')) { + return + } + monaco.languages.register({ id: 'hogql', extensions: ['.sql', '.hogql'], mimetypes: ['application/hog+ql'] }) + monaco.languages.setLanguageConfiguration('hogql', hogQL.conf) + monaco.languages.setMonarchTokensProvider('hogql', hogQL.language) +} + +export function CodeEditor({ options, onMount, ...editorProps }: CodeEditorProps): JSX.Element { + const { isDarkModeOn } = useValues(themeLogic) const scrollbarRendering = !inStorybookTestRunner() ? 'auto' : 'hidden' return ( @@ -22,6 +41,12 @@ export function CodeEditor({ options, ...editorProps }: CodeEditorProps): JSX.El loading={} options={{ // :TRICKY: We need to declare all options here, as omitting something will carry its value from one to another. + minimap: { + enabled: false, + }, + scrollBeyondLastLine: false, + automaticLayout: true, + fixedOverflowWidgets: true, wordWrap: 'off', lineNumbers: 'on', ...options, @@ -33,6 +58,17 @@ export function CodeEditor({ options, ...editorProps }: CodeEditorProps): JSX.El }, }} {...editorProps} + onMount={(editor, monaco) => { + if (editorProps?.language === 'hog') { + registerHog(monaco) + } + if (editorProps?.language === 'hogql') { + registerHogQL(monaco) + } + if (onMount) { + onMount(editor, monaco) + } + }} /> ) } diff --git a/frontend/src/lib/monaco/hog.ts b/frontend/src/lib/monaco/hog.ts new file mode 100644 index 00000000000..b5325cb4dbb --- /dev/null +++ b/frontend/src/lib/monaco/hog.ts @@ -0,0 +1,245 @@ +// eslint-disable-next-line eslint-comments/disable-enable-pair +/* eslint-disable no-useless-escape */ + +// Adapted from: https://raw.githubusercontent.com/microsoft/monaco-editor/main/src/basic-languages/typescript/typescript.ts + +import { languages } from 'monaco-editor' +export const conf: languages.LanguageConfiguration = { + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + + comments: { + lineComment: '//', + blockComment: ['/*', '*/'], + }, + + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'], + ], + + onEnterRules: [ + { + // e.g. /** | */ + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { + indentAction: languages.IndentAction.IndentOutdent, + appendText: ' * ', + }, + }, + { + // e.g. /** ...| + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + action: { + indentAction: languages.IndentAction.None, + appendText: ' * ', + }, + }, + { + // e.g. * ...| + beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { + indentAction: languages.IndentAction.None, + appendText: '* ', + }, + }, + { + // e.g. */| + beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, + action: { + indentAction: languages.IndentAction.None, + removeText: 1, + }, + }, + ], + + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"', notIn: ['string'] }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '`', close: '`', notIn: ['string', 'comment'] }, + { open: '/**', close: ' */', notIn: ['string'] }, + ], + + folding: { + markers: { + start: new RegExp('^\\s*//\\s*#?region\\b'), + end: new RegExp('^\\s*//\\s*#?endregion\\b'), + }, + }, +} + +export const language: languages.IMonarchLanguage = { + // Set defaultToken to invalid to see what you do not tokenize yet + defaultToken: 'invalid', + tokenPostfix: '.hog', + + keywords: [ + 'fn', + 'let', + 'if', + 'else', + 'return', + 'true', + 'false', + 'null', + 'for', + 'while', + 'like', + 'ilike', + 'not', + 'and', + 'or', + 'in', + ], + operators: [ + '<=', + '>=', + '==', + '!=', + '=>', + '+', + '-', + '**', + '*', + '/', + '%', + '<<', + '>', + '>>>', + '&', + '|', + '^', + '!', + '~', + '||', + '??', + '?', + ':', + '=', + ':=', + '+=', + '-=', + '*=', + '*=~', + '!=', + '!=~', + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [/!(?=([^=]|$))/, 'delimiter'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '', + }, + }, + ], + + // numbers + [/(@digits)[eE]([\-+]?(@digits))?/, 'number.float'], + [/(@digits)\.(@digits)([eE][\-+]?(@digits))?/, 'number.float'], + [/(@digits)n?/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings that are actually fields, show as type.identifier to highlight + [/"([^"\\]|\\.)*$/, 'type.identifier.invalid'], // non-teminated type.identifier + [/'([^'\\]|\\.)*$/, 'type.identifier.invalid'], // non-teminated type.identifier + [/"/, 'type.identifier', '@string_double'], + [/`/, 'type.identifier', '@string_backtick'], + + // strings + [/f'/, 'string', '@string_format'], + [/'/, 'string', '@string_single'], + + // identifiers and keywords + [ + /#?[a-z_$][\w$]*/, + { + cases: { + '@keywords': 'keyword', + '@default': 'identifier', + }, + }, + ], + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@jsdoc'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'], + [/--.*$/, 'comment'], + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'], + ], + + jsdoc: [ + [/[^\/*]+/, 'comment.doc'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'], + ], + + string_double: [ + [/[^\\"]+/, 'type.identifier'], + [/@escapes/, 'type.identifier.escape'], + [/\\./, 'type.identifier.escape.invalid'], + [/"/, 'type.identifier', '@pop'], + ], + + string_backtick: [ + [/[^\\`]+/, 'type.identifier'], + [/@escapes/, 'type.identifier.escape'], + [/\\./, 'type.identifier.escape.invalid'], + [/`/, 'type.identifier', '@pop'], + ], + + string_single: [ + [/[^\\']+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/'/, 'string', '@pop'], + ], + + string_format: [ + [/\{/, { token: 'delimiter.bracket', next: '@bracketCounting' }], + [/[^\\'{]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/'/, 'string', '@pop'], + ], + + bracketCounting: [ + [/\{/, 'delimiter.bracket', '@bracketCounting'], + [/\}/, 'delimiter.bracket', '@pop'], + { include: 'common' }, + ], + }, +} diff --git a/frontend/src/lib/monaco/hogql.ts b/frontend/src/lib/monaco/hogql.ts new file mode 100644 index 00000000000..bd2feb6149a --- /dev/null +++ b/frontend/src/lib/monaco/hogql.ts @@ -0,0 +1,847 @@ +// Adapted from https://raw.githubusercontent.com/microsoft/monaco-editor/main/src/basic-languages/mysql/mysql.ts + +import { languages } from 'monaco-editor' + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '--', + blockComment: ['/*', '*/'], + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'], + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + ], +} + +export const language: languages.IMonarchLanguage = { + defaultToken: '', + tokenPostfix: '.sql', + ignoreCase: true, + + brackets: [ + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + ], + + keywords: [ + 'ALL', + 'ANTI', + 'ANY', + 'ARRAY', + 'AS', + 'ASCENDING', + 'ASOF', + 'BOTH', + 'BY', + 'CASE', + 'CAST', + 'COHORT', + 'COLLATE', + 'CROSS', + 'CUBE', + 'CURRENT', + 'DATE', + 'DAY', + 'DESC', + 'DESCENDING', + 'DISTINCT', + 'ELSE', + 'END', + 'EXTRACT', + 'FINAL', + 'FIRST', + 'FN', + 'FOLLOWING', + 'FOR', + 'FROM', + 'FULL', + 'GROUP', + 'HAVING', + 'HOUR', + 'ID', + 'IF', + 'INF', + 'INTERVAL', + 'KEY', + 'LAST', + 'LEADING', + 'LET', + 'LIMIT', + 'MINUTE', + 'MONTH', + 'NAN_SQL', + 'NULL_SQL', + 'NULLS', + 'OFFSET', + 'ON', + 'ORDER', + 'OVER', + 'PARTITION', + 'PRECEDING', + 'PREWHERE', + 'QUARTER', + 'RANGE', + 'RETURN', + 'ROLLUP', + 'ROW', + 'ROWS', + 'SAMPLE', + 'SECOND', + 'SELECT', + 'SEMI', + 'SETTINGS', + 'SUBSTRING', + 'THEN', + 'TIES', + 'TO', + 'TOP', + 'TOTALS', + 'TRAILING', + 'TRIM', + 'TRUNCATE', + 'UNBOUNDED', + 'USING', + 'WEEK', + 'WHEN', + 'WHERE', + 'WHILE', + 'WINDOW', + 'WITH', + 'YEAR', + ], + operators: [ + 'AND', + 'BETWEEN', + 'IN', + 'LIKE', + 'ILIKE', + 'NOT', + 'OR', + 'IS', + 'NULL', + 'UNION', + 'INNER', + 'JOIN', + 'LEFT', + 'OUTER', + 'RIGHT', + ], + builtinFunctions: [ + 'plus', + 'minus', + 'multiply', + 'divide', + 'intDiv', + 'intDivOrZero', + 'modulo', + 'moduloOrZero', + 'positiveModulo', + 'negate', + 'abs', + 'gcd', + 'lcm', + 'max2', + 'min2', + 'multiplyDecimal', + 'divideDecimal', + 'empty', + 'notEmpty', + 'length', + 'reverse', + 'array', + 'range', + 'arrayConcat', + 'arrayElement', + 'has', + 'hasAll', + 'hasAny', + 'hasSubstr', + 'indexOf', + 'arrayCount', + 'countEqual', + 'arrayEnumerate', + 'arrayEnumerateUniq', + 'arrayPopBack', + 'arrayPopFront', + 'arrayPushBack', + 'arrayPushFront', + 'arrayResize', + 'arraySlice', + 'arraySort', + 'arrayReverseSort', + 'arrayUniq', + 'arrayJoin', + 'arrayDifference', + 'arrayDistinct', + 'arrayEnumerateDense', + 'arrayIntersect', + 'arrayReverse', + 'arrayFilter', + 'arrayFlatten', + 'arrayCompact', + 'arrayZip', + 'arrayAUC', + 'arrayMap', + 'arrayFill', + 'arraySplit', + 'arrayReverseFill', + 'arrayReverseSplit', + 'arrayExists', + 'arrayAll', + 'arrayFirst', + 'arrayLast', + 'arrayFirstIndex', + 'arrayLastIndex', + 'arrayMin', + 'arrayMax', + 'arraySum', + 'arrayAvg', + 'arrayCumSum', + 'arrayCumSumNonNegative', + 'arrayProduct', + 'equals', + 'notEquals', + 'less', + 'greater', + 'lessOrEquals', + 'greaterOrEquals', + 'and', + 'or', + 'xor', + 'not', + 'hex', + 'unhex', + 'reinterpretAsUInt8', + 'reinterpretAsUInt16', + 'reinterpretAsUInt32', + 'reinterpretAsUInt64', + 'reinterpretAsUInt128', + 'reinterpretAsUInt256', + 'reinterpretAsInt8', + 'reinterpretAsInt16', + 'reinterpretAsInt32', + 'reinterpretAsInt64', + 'reinterpretAsInt128', + 'reinterpretAsInt256', + 'reinterpretAsFloat32', + 'reinterpretAsFloat64', + 'toInt', + '_toInt64', + 'toFloat', + 'toDecimal', + 'toDate', + 'toDateTime', + 'toUUID', + 'toString', + 'toJSONString', + 'parseDateTime', + 'parseDateTimeBestEffort', + 'toTypeName', + 'toTimeZone', + 'timeZoneOf', + 'timeZoneOffset', + 'toYear', + 'toQuarter', + 'toMonth', + 'toDayOfYear', + 'toDayOfMonth', + 'toDayOfWeek', + 'toHour', + 'toMinute', + 'toSecond', + 'toUnixTimestamp', + 'toUnixTimestamp64Milli', + 'toStartOfYear', + 'toStartOfISOYear', + 'toStartOfQuarter', + 'toStartOfMonth', + 'toLastDayOfMonth', + 'toMonday', + 'toStartOfWeek', + 'toStartOfDay', + 'toLastDayOfWeek', + 'toStartOfHour', + 'toStartOfMinute', + 'toStartOfSecond', + 'toStartOfFiveMinutes', + 'toStartOfTenMinutes', + 'toStartOfFifteenMinutes', + 'toTime', + 'toISOYear', + 'toISOWeek', + 'toWeek', + 'toYearWeek', + 'age', + 'dateDiff', + 'dateTrunc', + 'dateAdd', + 'dateSub', + 'timeStampAdd', + 'timeStampSub', + 'now', + 'nowInBlock', + 'rowNumberInAllBlocks', + 'today', + 'yesterday', + 'timeSlot', + 'toYYYYMM', + 'toYYYYMMDD', + 'toYYYYMMDDhhmmss', + 'addYears', + 'addMonths', + 'addWeeks', + 'addDays', + 'addHours', + 'addMinutes', + 'addSeconds', + 'addQuarters', + 'subtractYears', + 'subtractMonths', + 'subtractWeeks', + 'subtractDays', + 'subtractHours', + 'subtractMinutes', + 'subtractSeconds', + 'subtractQuarters', + 'timeSlots', + 'formatDateTime', + 'dateName', + 'monthName', + 'fromUnixTimestamp', + 'toModifiedJulianDay', + 'fromModifiedJulianDay', + 'toIntervalSecond', + 'toIntervalMinute', + 'toIntervalHour', + 'toIntervalDay', + 'toIntervalWeek', + 'toIntervalMonth', + 'toIntervalQuarter', + 'toIntervalYear', + 'left', + 'right', + 'lengthUTF8', + 'leftPad', + 'rightPad', + 'leftPadUTF8', + 'rightPadUTF8', + 'lower', + 'upper', + 'lowerUTF8', + 'upperUTF8', + 'isValidUTF8', + 'toValidUTF8', + 'repeat', + 'format', + 'reverseUTF8', + 'concat', + 'substring', + 'substringUTF8', + 'appendTrailingCharIfAbsent', + 'convertCharset', + 'base58Encode', + 'base58Decode', + 'tryBase58Decode', + 'base64Encode', + 'base64Decode', + 'tryBase64Decode', + 'endsWith', + 'startsWith', + 'trim', + 'trimLeft', + 'trimRight', + 'encodeXMLComponent', + 'decodeXMLComponent', + 'extractTextFromHTML', + 'ascii', + 'concatWithSeparator', + 'position', + 'positionCaseInsensitive', + 'positionUTF8', + 'positionCaseInsensitiveUTF8', + 'multiSearchAllPositions', + 'multiSearchAllPositionsUTF8', + 'multiSearchFirstPosition', + 'multiSearchFirstIndex', + 'multiSearchAny', + 'match', + 'multiMatchAny', + 'multiMatchAnyIndex', + 'multiMatchAllIndices', + 'multiFuzzyMatchAny', + 'multiFuzzyMatchAnyIndex', + 'multiFuzzyMatchAllIndices', + 'extract', + 'extractAll', + 'extractAllGroupsHorizontal', + 'extractAllGroupsVertical', + 'like', + 'ilike', + 'notLike', + 'notILike', + 'ngramDistance', + 'ngramSearch', + 'countSubstrings', + 'countSubstringsCaseInsensitive', + 'countSubstringsCaseInsensitiveUTF8', + 'countMatches', + 'regexpExtract', + 'replace', + 'replaceAll', + 'replaceOne', + 'replaceRegexpAll', + 'replaceRegexpOne', + 'regexpQuoteMeta', + 'translate', + 'translateUTF8', + 'if', + 'multiIf', + 'e', + 'pi', + 'exp', + 'log', + 'ln', + 'exp2', + 'log2', + 'exp10', + 'log10', + 'sqrt', + 'cbrt', + 'erf', + 'erfc', + 'lgamma', + 'tgamma', + 'sin', + 'cos', + 'tan', + 'asin', + 'acos', + 'atan', + 'pow', + 'power', + 'intExp2', + 'intExp10', + 'cosh', + 'acosh', + 'sinh', + 'asinh', + 'atanh', + 'atan2', + 'hypot', + 'log1p', + 'sign', + 'degrees', + 'radians', + 'factorial', + 'width_bucket', + 'floor', + 'ceil', + 'trunc', + 'round', + 'roundBankers', + 'roundToExp2', + 'roundDuration', + 'roundAge', + 'roundDown', + 'map', + 'mapFromArrays', + 'mapAdd', + 'mapSubtract', + 'mapPopulateSeries', + 'mapContains', + 'mapKeys', + 'mapValues', + 'mapContainsKeyLike', + 'mapExtractKeyLike', + 'mapApply', + 'mapFilter', + 'mapUpdate', + 'splitByChar', + 'splitByString', + 'splitByRegexp', + 'splitByWhitespace', + 'splitByNonAlpha', + 'arrayStringConcat', + 'alphaTokens', + 'extractAllGroups', + 'ngrams', + 'tokens', + 'bitAnd', + 'bitOr', + 'bitXor', + 'bitNot', + 'bitShiftLeft', + 'bitShiftRight', + 'bitRotateLeft', + 'bitRotateRight', + 'bitSlice', + 'bitTest', + 'bitTestAll', + 'bitTestAny', + 'bitCount', + 'bitHammingDistance', + 'bitmapBuild', + 'bitmapToArray', + 'bitmapSubsetInRange', + 'bitmapSubsetLimit', + 'subBitmap', + 'bitmapContains', + 'bitmapHasAny', + 'bitmapHasAll', + 'bitmapCardinality', + 'bitmapMin', + 'bitmapMax', + 'bitmapTransform', + 'bitmapAnd', + 'bitmapOr', + 'bitmapXor', + 'bitmapAndnot', + 'bitmapAndCardinality', + 'bitmapOrCardinality', + 'bitmapXorCardinality', + 'bitmapAndnotCardinality', + 'protocol', + 'domain', + 'domainWithoutWWW', + 'topLevelDomain', + 'firstSignificantSubdomain', + 'cutToFirstSignificantSubdomain', + 'cutToFirstSignificantSubdomainWithWWW', + 'port', + 'path', + 'pathFull', + 'queryString', + 'fragment', + 'queryStringAndFragment', + 'extractURLParameter', + 'extractURLParameters', + 'extractURLParameterNames', + 'URLHierarchy', + 'URLPathHierarchy', + 'encodeURLComponent', + 'decodeURLComponent', + 'encodeURLFormComponent', + 'decodeURLFormComponent', + 'netloc', + 'cutWWW', + 'cutQueryString', + 'cutFragment', + 'cutQueryStringAndFragment', + 'cutURLParameter', + 'isValidJSON', + 'JSONHas', + 'JSONLength', + 'JSONArrayLength', + 'JSONType', + 'JSONExtractUInt', + 'JSONExtractInt', + 'JSONExtractFloat', + 'JSONExtractBool', + 'JSONExtractString', + 'JSONExtractKey', + 'JSONExtractKeys', + 'JSONExtractRaw', + 'JSONExtractArrayRaw', + 'JSONExtractKeysAndValues', + 'JSONExtractKeysAndValuesRaw', + 'in', + 'notIn', + 'greatCircleDistance', + 'geoDistance', + 'greatCircleAngle', + 'pointInEllipses', + 'pointInPolygon', + 'geohashEncode', + 'geohashDecode', + 'geohashesInBox', + 'isnull', + 'isNotNull', + 'coalesce', + 'ifnull', + 'nullif', + 'assumeNotNull', + 'toNullable', + 'tuple', + 'tupleElement', + 'untuple', + 'tupleHammingDistance', + 'tupleToNameValuePairs', + 'tuplePlus', + 'tupleMinus', + 'tupleMultiply', + 'tupleDivide', + 'tupleNegate', + 'tupleMultiplyByNumber', + 'tupleDivideByNumber', + 'dotProduct', + 'isFinite', + 'isInfinite', + 'ifNotFinite', + 'isNaN', + 'bar', + 'transform', + 'formatReadableDecimalSize', + 'formatReadableSize', + 'formatReadableQuantity', + 'formatReadableTimeDelta', + 'least', + 'greatest', + 'tumble', + 'hop', + 'tumbleStart', + 'tumbleEnd', + 'hopStart', + 'hopEnd', + 'L1Norm', + 'L2Norm', + 'LinfNorm', + 'LpNorm', + 'L1Distance', + 'L2Distance', + 'LinfDistance', + 'LpDistance', + 'L1Normalize', + 'L2Normalize', + 'LinfNormalize', + 'LpNormalize', + 'cosineDistance', + 'rank', + 'dense_rank', + 'row_number', + 'first_value', + 'last_value', + 'nth_value', + 'lagInFrame', + 'leadInFrame', + 'equals', + 'notEquals', + 'less', + 'greater', + 'lessOrEquals', + 'greaterOrEquals', + 'like', + 'ilike', + 'notLike', + 'notILike', + 'in', + 'notIn', + 'count', + 'countIf', + 'countDistinctIf', + 'min', + 'minIf', + 'max', + 'maxIf', + 'sum', + 'sumIf', + 'avg', + 'avgIf', + 'any', + 'anyIf', + 'stddevPop', + 'stddevPopIf', + 'stddevSamp', + 'stddevSampIf', + 'varPop', + 'varPopIf', + 'varSamp', + 'varSampIf', + 'covarPop', + 'covarPopIf', + 'covarSamp', + 'covarSampIf', + 'corr', + 'anyHeavy', + 'anyHeavyIf', + 'anyLast', + 'anyLastIf', + 'argMin', + 'argMinIf', + 'argMax', + 'argMaxIf', + 'argMinMerge', + 'argMaxMerge', + 'avgState', + 'avgMerge', + 'avgWeighted', + 'avgWeightedIf', + 'avgArray', + 'groupArray', + 'groupUniqArray', + 'groupUniqArrayIf', + 'groupArrayInsertAt', + 'groupArrayInsertAtIf', + 'groupArrayMovingAvg', + 'groupArrayMovingAvgIf', + 'groupArrayMovingSum', + 'groupArrayMovingSumIf', + 'groupBitAnd', + 'groupBitAndIf', + 'groupBitOr', + 'groupBitOrIf', + 'groupBitXor', + 'groupBitXorIf', + 'groupBitmap', + 'groupBitmapIf', + 'groupBitmapAnd', + 'groupBitmapAndIf', + 'groupBitmapOr', + 'groupBitmapOrIf', + 'groupBitmapXor', + 'groupBitmapXorIf', + 'sumWithOverflow', + 'sumWithOverflowIf', + 'deltaSum', + 'deltaSumIf', + 'deltaSumTimestamp', + 'deltaSumTimestampIf', + 'sumMap', + 'sumMapIf', + 'sumMapMerge', + 'minMap', + 'minMapIf', + 'maxMap', + 'maxMapIf', + 'medianArray', + 'skewSamp', + 'skewSampIf', + 'skewPop', + 'skewPopIf', + 'kurtSamp', + 'kurtSampIf', + 'kurtPop', + 'kurtPopIf', + 'uniq', + 'uniqIf', + 'uniqExact', + 'uniqExactIf', + 'uniqHLL12', + 'uniqHLL12If', + 'uniqTheta', + 'uniqThetaIf', + 'median', + 'medianIf', + 'medianExact', + 'medianExactIf', + 'medianExactLow', + 'medianExactLowIf', + 'medianExactHigh', + 'medianExactHighIf', + 'medianExactWeighted', + 'medianExactWeightedIf', + 'medianTiming', + 'medianTimingIf', + 'medianTimingWeighted', + 'medianTimingWeightedIf', + 'medianDeterministic', + 'medianDeterministicIf', + 'medianTDigest', + 'medianTDigestIf', + 'medianTDigestWeighted', + 'medianTDigestWeightedIf', + 'medianBFloat16', + 'medianBFloat16If', + 'quantile', + 'quantileIf', + 'quantiles', + 'quantilesIf', + 'simpleLinearRegression', + 'simpleLinearRegressionIf', + 'contingency', + 'contingencyIf', + 'cramersV', + 'cramersVIf', + 'cramersVBiasCorrected', + 'cramersVBiasCorrectedIf', + 'theilsU', + 'theilsUIf', + 'maxIntersections', + 'maxIntersectionsIf', + 'maxIntersectionsPosition', + 'maxIntersectionsPositionIf', + ], + builtinVariables: [], + tokenizer: { + root: [ + { include: '@comments' }, + { include: '@whitespace' }, + { include: '@numbers' }, + { include: '@strings' }, + { include: '@complexIdentifiers' }, + { include: '@scopes' }, + [/[;,.]/, 'delimiter'], + [/[()]/, '@brackets'], + [ + /[\w@]+/, + { + cases: { + '@operators': 'operator', + '@builtinVariables': 'predefined', + '@builtinFunctions': 'predefined', + '@keywords': 'keyword', + '@default': 'identifier', + }, + }, + ], + [/[<>=!%&+\-*/|~^]/, 'operator'], + ], + whitespace: [[/\s+/, 'white']], + comments: [ + [/--+.*/, 'comment'], + [/#+.*/, 'comment'], + [/\/\*/, { token: 'comment.quote', next: '@comment' }], + ], + comment: [ + [/[^*/]+/, 'comment'], + // Not supporting nested comments, as nested comments seem to not be standard? + // i.e. http://stackoverflow.com/questions/728172/are-there-multiline-comment-delimiters-in-sql-that-are-vendor-agnostic + // [/\/\*/, { token: 'comment.quote', next: '@push' }], // nested comment not allowed :-( + [/\*\//, { token: 'comment.quote', next: '@pop' }], + [/./, 'comment'], + ], + numbers: [ + [/0[xX][0-9a-fA-F]*/, 'number'], + [/[$][+-]*\d*(\.\d*)?/, 'number'], + [/((\d+(\.\d*)?)|(\.\d+))([eE][-+]?\d+)?/, 'number'], + ], + strings: [ + [/'/, { token: 'string', next: '@string' }], + [/"/, { token: 'string.double', next: '@stringDouble' }], + ], + string: [ + [/\\'/, 'string'], + [/[^']+/, 'string'], + [/''/, 'string'], + [/'/, { token: 'string', next: '@pop' }], + ], + stringDouble: [ + [/[^"]+/, 'string.double'], + [/""/, 'string.double'], + [/"/, { token: 'string.double', next: '@pop' }], + ], + complexIdentifiers: [[/`/, { token: 'identifier.quote', next: '@quotedIdentifier' }]], + quotedIdentifier: [ + [/[^`]+/, 'identifier'], + [/``/, 'identifier'], + [/`/, { token: 'identifier.quote', next: '@pop' }], + ], + scopes: [ + // NOT SUPPORTED + ], + }, +} diff --git a/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx b/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx index a066925e6a9..2960f4c698f 100644 --- a/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx +++ b/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx @@ -223,7 +223,7 @@ export function HogQLQueryEditor(props: HogQLQueryEditorProps): JSX.Element {
setQueryInput(v ?? '')} height="100%" diff --git a/frontend/src/scenes/debug/HogDebug.tsx b/frontend/src/scenes/debug/HogDebug.tsx index 19a692c46a3..37d2e82c713 100644 --- a/frontend/src/scenes/debug/HogDebug.tsx +++ b/frontend/src/scenes/debug/HogDebug.tsx @@ -44,7 +44,7 @@ export function HogQueryEditor(props: HogQueryEditorProps): JSX.Element {
setQueryInput(v ?? '')} height="100%" diff --git a/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx b/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx index ec2e93abc99..68e50c49db0 100644 --- a/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx +++ b/frontend/src/scenes/pipeline/hogfunctions/PipelineHogFunctionConfiguration.tsx @@ -309,7 +309,7 @@ export function PipelineHogFunctionConfiguration({
onChange(v ?? '')} options={{ diff --git a/package.json b/package.json index 0c31a4fba5e..743d7a30ca4 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@lottiefiles/react-lottie-player": "^3.4.7", "@medv/finder": "^3.1.0", "@microlink/react-json-view": "^1.21.3", - "@monaco-editor/react": "4.4.6", + "@monaco-editor/react": "4.6.0", "@posthog/icons": "0.7.0", "@posthog/plugin-scaffold": "^1.4.4", "@react-hook/size": "^2.1.2", @@ -140,7 +140,7 @@ "kea-window-values": "^3.0.0", "maplibre-gl": "^3.5.1", "md5": "^2.3.0", - "monaco-editor": "^0.39.0", + "monaco-editor": "^0.49.0", "natural-orderby": "^3.0.2", "papaparse": "^5.4.1", "pmtiles": "^2.11.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 89bfe69c2ae..b88a38daaec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,8 +47,8 @@ dependencies: specifier: ^1.21.3 version: 1.22.2(@types/react@17.0.52)(react-dom@18.2.0)(react@18.2.0) '@monaco-editor/react': - specifier: 4.4.6 - version: 4.4.6(monaco-editor@0.39.0)(react-dom@18.2.0)(react@18.2.0) + specifier: 4.6.0 + version: 4.6.0(monaco-editor@0.49.0)(react-dom@18.2.0)(react@18.2.0) '@posthog/icons': specifier: 0.7.0 version: 0.7.0(react-dom@18.2.0)(react@18.2.0) @@ -242,8 +242,8 @@ dependencies: specifier: ^2.3.0 version: 2.3.0 monaco-editor: - specifier: ^0.39.0 - version: 0.39.0 + specifier: ^0.49.0 + version: 0.49.0 natural-orderby: specifier: ^3.0.2 version: 3.0.2 @@ -353,7 +353,7 @@ dependencies: optionalDependencies: fsevents: specifier: ^2.3.2 - version: 2.3.3 + version: 2.3.2 devDependencies: '@babel/core': @@ -634,7 +634,7 @@ devDependencies: version: 3.0.5 monaco-editor-webpack-plugin: specifier: ^7.0.1 - version: 7.0.1(monaco-editor@0.39.0)(webpack@5.88.2) + version: 7.0.1(monaco-editor@0.49.0)(webpack@5.88.2) msw: specifier: ^0.49.0 version: 0.49.0(typescript@4.9.5) @@ -5250,25 +5250,24 @@ packages: - encoding dev: false - /@monaco-editor/loader@1.3.3(monaco-editor@0.39.0): - resolution: {integrity: sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==} + /@monaco-editor/loader@1.4.0(monaco-editor@0.49.0): + resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==} peerDependencies: monaco-editor: '>= 0.21.0 < 1' dependencies: - monaco-editor: 0.39.0 + monaco-editor: 0.49.0 state-local: 1.0.7 dev: false - /@monaco-editor/react@4.4.6(monaco-editor@0.39.0)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==} + /@monaco-editor/react@4.6.0(monaco-editor@0.49.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==} peerDependencies: monaco-editor: '>= 0.25.0 < 1' react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@monaco-editor/loader': 1.3.3(monaco-editor@0.39.0) - monaco-editor: 0.39.0 - prop-types: 15.8.1 + '@monaco-editor/loader': 1.4.0(monaco-editor@0.49.0) + monaco-editor: 0.49.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -13079,7 +13078,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true /fsevents@2.3.3: @@ -16066,19 +16064,19 @@ packages: /moment@2.29.4: resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} - /monaco-editor-webpack-plugin@7.0.1(monaco-editor@0.39.0)(webpack@5.88.2): + /monaco-editor-webpack-plugin@7.0.1(monaco-editor@0.49.0)(webpack@5.88.2): resolution: {integrity: sha512-M8qIqizltrPlIbrb73cZdTWfU9sIsUVFvAZkL3KGjAHmVWEJ0hZKa/uad14JuOckc0GwnCaoGHvMoYtJjVyCzw==} peerDependencies: monaco-editor: '>= 0.31.0' webpack: ^4.5.0 || 5.x dependencies: loader-utils: 2.0.4 - monaco-editor: 0.39.0 + monaco-editor: 0.49.0 webpack: 5.88.2(@swc/core@1.3.93)(esbuild@0.19.8)(webpack-cli@5.1.4) dev: true - /monaco-editor@0.39.0: - resolution: {integrity: sha512-zhbZ2Nx93tLR8aJmL2zI1mhJpsl87HMebNBM6R8z4pLfs8pj604pIVIVwyF1TivcfNtIPpMXL+nb3DsBmE/x6Q==} + /monaco-editor@0.49.0: + resolution: {integrity: sha512-2I8/T3X/hLxB2oPHgqcNYUVdA/ZEFShT7IAujifIPMfKkNbLOqY8XCoyHCXrsdjb36dW9MwoTwBCFpXKMwNwaQ==} /moo-color@1.0.3: resolution: {integrity: sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==}