diff --git a/package.json b/package.json index 13d7e317b..f630a655d 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "3.4.0-rc1", "scripts": { "ng": "ng", + "generate-grammar": "lezer-generator --typeScript src/framework/codemirror-lang-typeql/typeql.grammar -o src/framework/codemirror-lang-typeql/generated/typeql.grammar.generated", "start": "ng serve", "build": "ng build", "watch": "ng build --watch --configuration development", @@ -23,9 +24,12 @@ "@angular/platform-browser-dynamic": "20.0.3", "@angular/router": "20.0.3", "@codemirror/lint": "6.8.5", + "@codemirror/autocomplete": "6.18.6", "@customerio/cdp-analytics-browser": "0.2.0", + "@codemirror/commands": "6.8.1", "@hhangular/resizable": "1.18.1", "@intercom/messenger-js-sdk": "0.0.14", + "@lezer/common": "^1.0.0", "@lezer/lr": "1.4.2", "@sigma/edge-curve": "3.1.0", "@sigma/node-square": "3.0.0", @@ -52,6 +56,7 @@ "@codemirror/language": "6.11.0", "@codemirror/state": "6.5.2", "@codemirror/view": "6.36.5", + "@lezer/generator": "1.7.3", "@lezer/highlight": "1.2.1", "@sanity/asset-utils": "1.3.0", "@sanity/icons": "3.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 63ac5472f..550b73c58 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,12 @@ importers: '@angular/router': specifier: 20.0.3 version: 20.0.3(@angular/common@20.0.3(@angular/core@20.0.3(@angular/compiler@20.0.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.0.3(@angular/compiler@20.0.3)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.0.3(@angular/animations@20.0.3(@angular/common@20.0.3(@angular/core@20.0.3(@angular/compiler@20.0.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.0.3(@angular/compiler@20.0.3)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@20.0.3(@angular/core@20.0.3(@angular/compiler@20.0.3)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.0.3(@angular/compiler@20.0.3)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@codemirror/autocomplete': + specifier: 6.18.6 + version: 6.18.6 + '@codemirror/commands': + specifier: 6.8.1 + version: 6.8.1 '@codemirror/lint': specifier: 6.8.5 version: 6.8.5 @@ -56,6 +62,9 @@ importers: '@intercom/messenger-js-sdk': specifier: 0.0.14 version: 0.0.14 + '@lezer/common': + specifier: ^1.0.0 + version: 1.2.3 '@lezer/lr': specifier: 1.4.2 version: 1.4.2 @@ -129,6 +138,9 @@ importers: '@codemirror/view': specifier: 6.36.5 version: 6.36.5 + '@lezer/generator': + specifier: 1.7.3 + version: 1.7.3 '@lezer/highlight': specifier: 1.2.1 version: 1.2.1 diff --git a/src/framework/codemirror-lang-typeql/complete.ts b/src/framework/codemirror-lang-typeql/complete.ts new file mode 100644 index 000000000..1606e3752 --- /dev/null +++ b/src/framework/codemirror-lang-typeql/complete.ts @@ -0,0 +1,176 @@ + +import { CompletionContext, Completion, CompletionResult } from "@codemirror/autocomplete"; +import { syntaxTree } from "@codemirror/language" +import { SyntaxNode, NodeType, Tree } from "@lezer/common" + +type TokenID = number; +export interface SuggestionMap { + [key: TokenID]: SuffixOfPrefixSuggestion[] +} + + +export type SuffixCandidate = TokenID[]; // A SuffixCandidate 's' "matches" a prefix if prefix[-s.length:] == s +export interface SuffixOfPrefixSuggestion { + suffixes: SuffixCandidate[], // If any of the suffix candidates match, the suggestions will be used. + suggestions: SuggestionFunction[] +} + +export type SuggestionFunction = (context: CompletionContext, tree: Tree, parseAt: SyntaxNode, climbedTo: SyntaxNode, prefix: NodeType[], state: STATE) => Completion[] | null; + +export function suggest(type: string, label: string, boost: number = 0): Completion { + // type (docs): used to pick an icon to show for the completion. Icons are styled with a CSS class created by appending the type name to "cm-completionIcon-". + return { + label: label, + type: type, + apply: label, + info: type, + boost: boost, + }; +} + +interface NodePrefixAutoCompleteState { + mayUpdateFromEditorState(context: CompletionContext, tree: Tree): void; +} + +// See: https://codemirror.net/examples/autocompletion/ and maybe the SQL / HTML Example there. +export class NodePrefixAutoComplete { + suggestionMap: SuggestionMap; + suggestorState: STATE; + + constructor(suggestionMap: SuggestionMap, suggestorState: STATE) { + // This is where we would set up the autocompletion, but we do it in the index.ts file. + // See: https://codemirror.net/docs/ref/#autocomplete.autocompletion + this.suggestionMap = suggestionMap; + this.suggestorState = suggestorState; + } + + getState(): STATE { + return this.suggestorState; + } + + autocomplete(context: CompletionContext): CompletionResult | null { + let tree: Tree = syntaxTree(context.state); + this.suggestorState.mayUpdateFromEditorState(context, tree); + let currentNode: SyntaxNode = tree.resolveInner(context.pos, -1); // https://lezer.codemirror.net/docs/ref/#common.SyntaxNode + let options = this.getSuggestions(context, tree, currentNode); + if (options != null) { + // And once we figure out, we have to create a list of completion objects + // It may be worth changing the grammar to be able to do this more easily, rather than replicate the original TypeQL grammar. + // https://codemirror.net/docs/ref/#autocomplete.Completion + let from = findStartOfCompletion(context) + 1; + return { + from: from, + options: options, + // Docs: "regular expression that tells the extension that, as long as the updated input (the range between the result's from property and the completion point) matches that value, it can continue to use the list of completions." + validFor: /^([\w\$]+)?$/ + } + } else { + return null; + } + } + + getSuggestions(context: CompletionContext, tree: Tree, parseAt: SyntaxNode): Completion[] | null { + return this.climbTillWeRecogniseSomething(context, tree, parseAt, parseAt, collectPrecedingChildrenOf(context, parseAt)); + } + + + climbTillWeRecogniseSomething(context: CompletionContext, tree: Tree, parseAt: SyntaxNode, climbedTo: SyntaxNode | null, prefix: NodeType[]): Completion[] | null { + if (climbedTo == null) { + // Uncomment this if you don't see suggestions + // this.logInterestingStuff(context, tree, parseAt, climbedTo, prefix); + return null; + } + let suggestionEither = this.suggestionMap[climbedTo.type.id]; + if (suggestionEither != null) { + for (let sops of (suggestionEither as SuffixOfPrefixSuggestion[])) { + if (prefixHasAnyOfSuffixes(prefix, sops.suffixes)) { + return this.combineSuggestions(context, tree, parseAt, climbedTo, prefix, sops.suggestions); + } + } + // None match? Fall through. + // console.log("Fell through!!!: ", climbedTo.type.name, "with prefix", prefix); + } + let newPrefix = collectSiblingsOf(climbedTo).concat(prefix); + return this.climbTillWeRecogniseSomething(context, tree, parseAt, climbedTo.parent, newPrefix); + } + + + combineSuggestions(context: CompletionContext, tree: Tree, parseAt: SyntaxNode, climbedTo: SyntaxNode, prefix: NodeType[], suggestionFunctions: SuggestionFunction[]): Completion[] { + let suggestions = suggestionFunctions.map((f) => { + return f(context, tree, parseAt, climbedTo, prefix, this.suggestorState); + }).reduce((acc, curr) => { + return (curr == null) ? acc : acc!.concat(curr); + }, []); + // console.log("Matched:", climbedTo.type.name, "with prefix", prefix, ". Suggestions:", suggestions); + return suggestions!; + } + + logInterestingStuff(context: CompletionContext, tree: Tree, parseAt: SyntaxNode, climbedTo: SyntaxNode | null, prefix: NodeType[]) { + console.log("Current Node:", parseAt.name); + console.log("ClimbedTo Node:", climbedTo?.name); + + let at: SyntaxNode | null = parseAt; + let climbThrough = []; + while (at != null && at.name != climbedTo?.name) { + climbThrough.push(at.name); + at = at.parent; + } + climbThrough.push(at?.name); + console.log("Climbed through", climbThrough); + console.log("Prefix:", prefix); + } +} + +function isPartOfWord(s: string): boolean { + let matches = s.match(/^[A-Za-z0-9_\-\$]+/); + return matches != null && matches.length > 0; +} + +function findStartOfCompletion(context: CompletionContext): number { + let str = context.state.doc.sliceString(0, context.pos); + let at = context.pos - 1; + while (at >= 0 && isPartOfWord(str.charAt(at))) { + at -= 1; + } + return at; +} + +function collectSiblingsOf(node: SyntaxNode): NodeType[] { + let siblings = []; + let prev: SyntaxNode | null = node; + while (null != (prev = prev.prevSibling)) { + siblings.push(prev.type); + } + return siblings.reverse(); +} + +function collectPrecedingChildrenOf(context: CompletionContext, node: SyntaxNode): NodeType[] { + let lastChild = node.childBefore(context.pos); + if (lastChild == null) { + return []; + } + let precedingChildren = collectSiblingsOf(lastChild); + precedingChildren.push(lastChild.type); + return precedingChildren; +} + +function prefixHasAnyOfSuffixes(prefix: NodeType[], suffixes: SuffixCandidate[]): boolean { + for (let i = 0; i < suffixes.length; i++) { + if (prefixHasSuffix(prefix, suffixes[i])) { + return true; + } + } + return false; +} + +function prefixHasSuffix(prefix: NodeType[], suffix: TokenID[]): boolean { + if (prefix.length < suffix.length) { + return false; + } + for (let i = 0; i < suffix.length; i++) { + if (prefix[prefix.length - suffix.length + i].id != suffix[i]) { + return false; + } + } + return true; +} diff --git a/src/framework/codemirror-lang-typeql/generated/typeql.grammar.generated.terms.ts b/src/framework/codemirror-lang-typeql/generated/typeql.grammar.generated.terms.ts new file mode 100644 index 000000000..fd7139195 --- /dev/null +++ b/src/framework/codemirror-lang-typeql/generated/typeql.grammar.generated.terms.ts @@ -0,0 +1,224 @@ +// This file was generated by lezer-generator. You probably shouldn't edit it. +export const + Query = 1, + QuerySchema = 2, + QueryDefine = 3, + DEFINE = 4, + Definables = 5, + Definable = 6, + DefinitionType = 7, + KIND = 8, + LABEL = 9, + COMMA = 10, + Annotations = 11, + Annotation = 12, + ANNOTATION_ABSTRACT = 13, + ANNOTATION_CASCADE = 14, + ANNOTATION_DISTINCT = 15, + ANNOTATION_INDEPENDENT = 16, + ANNOTATION_KEY = 17, + ANNOTATION_UNIQUE = 18, + ANNOTATION_CARD = 19, + PARENOPEN = 20, + Cardinality = 21, + INTEGERLITERAL = 22, + DOUBLE_DOT = 23, + PARENCLOSE = 24, + ANNOTATION_RANGE = 25, + Range = 26, + RangeBound = 27, + ValueLiteral = 28, + BOOLEANLITERAL = 29, + STRINGLITERAL = 30, + DOUBLELITERAL = 31, + ANNOTATION_REGEX = 32, + ANNOTATION_SUBKEY = 33, + IDENTIFIER = 34, + ANNOTATION_VALUES = 35, + TypeCapability = 36, + TypeCapabilityBase = 37, + SubDeclaration = 38, + SUB = 39, + ValueTypeDeclaration = 40, + VALUEKEYWORD = 41, + ValueType = 42, + BOOLEAN = 43, + INTEGER = 44, + DOUBLE = 45, + DECIMAL = 46, + DATETIMETZ = 47, + DATETIME = 48, + DATE = 49, + DURATION = 50, + STRING = 51, + OwnsDeclaration = 52, + OWNS = 53, + LabelList = 54, + SQBRACKETOPEN = 55, + SQBRACKETCLOSE = 56, + PlaysDeclaration = 57, + PLAYS = 58, + RelatesDeclaration = 59, + RELATES = 60, + AS = 61, + DefinitionFunction = 62, + FUN = 63, + FunctionSignature = 64, + FunctionArguments = 65, + FunctionArgument = 66, + VAR = 67, + COLON = 68, + NamedTypeAny = 69, + NamedTypeList = 70, + NamedType = 71, + ARROW = 72, + FunctionOutput = 73, + FunctionOutputStream = 74, + CURLYOPEN = 75, + CURLYCLOSE = 76, + FunctionOutputSingle = 77, + FunctionBlock = 78, + QueryStage = 79, + ClauseMatch = 80, + MATCH = 81, + Patterns = 82, + Pattern = 83, + Statement = 84, + StatementAssignment = 85, + LET = 86, + AssignmentLeft = 87, + VarsAssignment = 88, + VarAssignment = 89, + QUESTIONMARK = 90, + ASSIGN = 91, + IN = 92, + Expression = 93, + ExpressionValue = 94, + ExpressionParenthesis = 95, + FunctionCall = 96, + FunctionName = 97, + FunctionCallArguments = 98, + ExpressionOperator = 99, + POWER = 100, + TIMES = 101, + DIVIDE = 102, + MODULO = 103, + PLUS = 104, + MINUS = 105, + StatementType = 106, + TypeRef = 107, + TypeConstraint = 108, + TypeConstraintBase = 109, + SubConstraint = 110, + ValueTypeConstraint = 111, + LabelConstraint = 112, + LABELKEYWORD = 113, + OwnsConstraint = 114, + TypeRefList = 115, + RelatesConstraint = 116, + PlaysConstraint = 117, + StatementThing = 118, + ThingConstraintList = 119, + ThingConstraint = 120, + IsaConstraint = 121, + ISA = 122, + Comparison = 123, + ComparisonOperator = 124, + EQUAL = 125, + NOT_EQUAL = 126, + GREATER = 127, + GREATER_EQUAL = 128, + LESS = 129, + LESS_EQUAL = 130, + LIKE = 131, + CONTAINS = 132, + IidConstraint = 133, + IID = 134, + IID_VALUE = 135, + HasConstraint = 136, + HAS = 137, + LinksConstraint = 138, + LINKS = 139, + Relation = 140, + RolePlayer = 141, + PatternDisjunction = 142, + OR = 143, + PatternConjunction = 144, + PatternNegation = 145, + NOT = 146, + PatternTry = 147, + TRY = 148, + SEMICOLON = 149, + ClauseInsert = 150, + INSERT = 151, + ClausePut = 152, + PUT = 153, + ClauseUpdate = 154, + UPDATE = 155, + ClauseDelete = 156, + DELETE = 157, + StatementDeletable = 158, + OF = 159, + OperatorStream = 160, + OperatorSelect = 161, + SELECT = 162, + Vars = 163, + OperatorSort = 164, + SORT = 165, + VAROrder = 166, + ORDER = 167, + OperatorDistinct = 168, + DISTINCT = 169, + OperatorOffset = 170, + OFFSET = 171, + OperatorLimit = 172, + LIMIT = 173, + OperatorRequire = 174, + REQUIRE = 175, + OperatorReduce = 176, + REDUCE = 177, + ReduceAssign = 178, + Reducer = 179, + COUNT = 180, + MAX = 181, + MIN = 182, + MEAN = 183, + MEDIAN = 184, + STD = 185, + SUM = 186, + LIST = 187, + GROUPBY = 188, + ReturnStatement = 189, + RETURN = 190, + ReturnStream = 191, + ReturnSingle = 192, + ReturnSingleSelector = 193, + FIRST = 194, + LAST = 195, + ReturnReduce = 196, + DefinitionStruct = 197, + STRUCT = 198, + DefinitionStructFields = 199, + DefinitionStructField = 200, + StructFieldValueType = 201, + ValueTypeOptional = 202, + QueryUndefine = 203, + UNDEFINE = 204, + Undefinables = 205, + Undefinable = 206, + UndefineFrom = 207, + UndefineAnnotationFromCapability = 208, + AnnotationCategory = 209, + FROM = 210, + UndefineAnnotationFromType = 211, + UndefineCapability = 212, + UndefineSpecialise = 213, + UndefineStruct = 214, + QueryRedefine = 215, + REDEFINE = 216, + Redefinables = 217, + Redefinable = 218, + RedefinableType = 219, + QueryPipelinePreambled = 220, + Pipeline = 221, + END = 222 diff --git a/src/framework/codemirror-lang-typeql/generated/typeql.grammar.generated.ts b/src/framework/codemirror-lang-typeql/generated/typeql.grammar.generated.ts new file mode 100644 index 000000000..acf0573fa --- /dev/null +++ b/src/framework/codemirror-lang-typeql/generated/typeql.grammar.generated.ts @@ -0,0 +1,16 @@ +// This file was generated by lezer-generator. You probably shouldn't edit it. +import {LRParser} from "@lezer/lr" +export const parser = LRParser.deserialize({ + version: 14, + states: "!+`O!QQPOOO!_QQO'#EOO!vQPO'#FhO!vQPO'#FjO!vQPO'#FlO!{QPO'#FnO#ZQPO'#FsO#`QPO'#FvO#eQPO'#FzO#jQPO'#F|O#oQPO'#GOO#ZQPO'#GQO#tQPO'#GSOOQO'#Fr'#FrOOQO'#D}'#D}OOQO'#HZ'#HZO#yQPO'#HRO$TQQO'#C_O$cQPO'#GoO%pQQO'#G{OOQO'#C^'#C^OOQO'#HQ'#HQQOQPOOQ%{QPOOO&QQPO'#ETOOQO'#Ek'#EkO&hQPO'#EkO'gQPO'#EjO'nQQO'#EjOOQO'#ES'#ESO!_QQO'#FbO'vQPO'#FcO'{QPO'#FeOOQO'#ER'#ERO(QQPO'#H[O(VQQO'#EQOOQO,5:j,5:jO&VQPO'#EvO)]QPO'#HdO)bQPO,5O,5>OOOQO-E;b-E;bO7bQPO'#EkO7pQPO'#EsO7sQPO'#F_O7xQPO,5;xO8QQPO,5<[O8VQSO,5<[OOQO,5>P,5>POOQO-E;c-E;cO8[QPO,5PQQO,5=dO>UQPO,5=eOOQO,5=f,5=fOOQO,5=^,5=^OOQO,5>V,5>VOOQO-E;i-E;iO>ZQPO,5=kO>cQPO,5=kOOQO,5>W,5>WOOQO-E;j-E;jOOQO,5:s,5:sO>jQSO,5:rO>uQSO,5:rO?QQWO1G0ZO?iQWO,5;eOOQO,5;q,5;qO@]QPO,5;tO@tQPO,5;tOOQO,5;v,5;vOAVQPO,5;cOAhQPO,5;cOOQO1G0|1G0|OOQO,5;Y,5;YOOQO,5;Z,5;ZOOQO,5;[,5;[OApQPO,5;^OOQO,5;^,5;^OCiQPO,5;`OCsQPO,5;`OOQO,5;a,5;aOOQO,5;W,5;WOCzQPO1G0pODRQPO1G0pODRQPO1G0pODZQPO1G1hODcQPO1G1iODhQPO1G1kODmQPO,5;_ODrQPO,5;yODwQQO1G1dOESQPO1G1dOOQO1G1d1G1dOOQO1G1v1G1vOE[QPO1G1vOOQO,5>Q,5>QOEaQPO1G1{OOQO-E;d-E;dOOQO,5>R,5>ROOQO-E;e-E;eOOQO7+'h7+'hOElQPO'#GVOEzQPO'#GVOOQO1G2[1G2[OOQO,5>S,5>SOOQO-E;f-E;fOOQO7+'t7+'tO#ZQPO7+'tOFPQPO7+'tOFUQPO,59SOFZQPO,59SOFlQPO,59SO1jQQO,59SOFqQPO,59SOOQO-E;S-E;SOOQO,59l,59lOGPQPO1G.iOGeQPO1G.iOGeQPO1G.iOGmQPO1G.iOGtQPO,5:YOYQPO1G/rO1jQQO1G2oOG|QPO,5:OOHRQQO1G/oOHWQQO1G/oOH]QPO1G2}OOQO1G3O1G3OOHdQQO1G3POHiQPO1G3VOHpQPO1G3VOHpQPO1G3VOOQO,5=w,5=wOHxQSO1G0^OOQO-E;Z-E;ZOOQO'#Cx'#CxO?QQWO'#E_OOQO'#Ea'#EaOITQPO'#E`OOQO'#E^'#E^OInQQO'#E]OOQO7+%u7+%uOOQO'#E|'#E|O?QQWO'#E{OOQO1G1P1G1POOQO1G1`1G1`OOQO,5=|,5=|OI{QPO1G0}OOQO-E;`-E;`O'nQQO1G0zO'nQQO1G0zOOQO,5=z,5=zOJ^QPO7+&[OOQO-E;^-E;^OJeQPO7+&[OJmQPO'#HcOJrQPO7+'QOOQO7+'T7+'TOOQO7+'V7+'VOOQO1G0y1G0yOOQO1G1e1G1eOOQO,5={,5={OOQO7+'O7+'OOJzQQO7+'OOOQO-E;_-E;_OOQO7+'b7+'bPKVQPO'#HfOK[QPO,5U,5>UO!%qQQO1G2qOOQO-E;h-E;hO!%yQWO,5:|O!&QQPO,5:|OOQO7+&Q7+&QOOQO7+)T7+)TOOQOAN=`AN=`PFqQPO'#HVO!&YQPO,5:`PGwQPO'#HXO!&_QPO,5:dO!&gQQO,5:gO!&qQPO,5:gOOQOAN>fAN>fO!&yQPO,5<}OOQO,5=O,5=OO!'OQPO,5=SO!'VQPO,5=SOOQO,5=Y,5=YP1jQQO'#HjOOQO,5=x,5=xO!'_QWO1G0hOOQO-E;[-E;[OOQO1G/z1G/zO!'fQQO1G0OO!'pQPO1G0OOOQO1G0O1G0OOOQO,5=t,5=tO!'xQQO1G0ROOQO-E;W-E;WOOQO1G2i1G2iOOQO,5>T,5>TO!(SQPO1G2nOOQO-E;g-E;gP?QQWO'#H^OOQO7+%j7+%jO!(ZQQO7+%jP!!RQQO'#HYP8zQPO'#HiOOQO<T#V#WB[#W#XH}#X#Y!7Z#Y#Z!:|#Z#[!Cn#[#]!Gx#]#^!Ig#^#`5^#`#a#$u#a#b#1`#b#c#:k#c#d#<]#d#e#Bh#e#f5^#f#g#Fq#g#h$)t#h#i$7P#i#j$8w#j#k$@v#k#o5^#o#p$Cq#q#r$Cv~$pS&c~XY$kYZ$k]^$kpq$k~%PP!_!`%S~%XO#r~~%[VOr%Xrs%qs#O%X#O#P%v#P;'S%X;'S;=`&o<%lO%X~%vOn~~%yRO;'S%X;'S;=`&S;=`O%X~&VWOr%Xrs%qs#O%X#O#P%v#P;'S%X;'S;=`&o;=`<%l%X<%lO%X~&rP;=`<%l%X~&zS&d~OY&uZ;'S&u;'S;=`'W<%lO&u~'ZP;=`<%l&u~'aT}!O'p!Q!['p!c!}'p#R#S'p#T#o'p~'uT!e~}!O'p!Q!['p!c!}'p#R#S'p#T#o'p~(ZO#Z~~(`Od~~(eOh~~(jO#X~~(oO#[~~(tOY~Z(yQ#]Q!Q![)P!`!a)lX)WQoXfX!O!P)^!Q![)PX)aP!Q![)dX)iPoX!Q![)dP)qO!jP~)tP!O!P)w~)|Og~~*RO#Y~Z*YRoXfX!O!P)^!Q![)P#l#m*cQ*fR!Q![*o!c!i*o#T#Z*oQ*tR#{Q!Q![*o!c!i*o#T#Z*o~+SO!f~~+XO$Z~~+^P#u~!_!`+a~+fO#v~]+kP!}T!_!`+nW+sO#qW~+xP#s~!_!`+{~,QO#t~~,VO!|~~,YX#T#U,u#V#W-v#W#X/P#]#^0Q#_#`1e#f#g1v#g#h3P#i#j3t#j#k4i~,xP#U#V,{~-OP#g#h-R~-UP#h#i-X~-[P#f#g-_~-bP#T#U-e~-hP#V#W-k~-nP#h#i-q~-vO]~~-yP#T#U-|~.PQ#f#g.V#g#h.b~.YP#W#X.]~.bOc~~.eP#V#W.h~.kP#T#U.n~.qP#W#X.t~.wP#X#Y.z~/PO^~~/SP#]#^/V~/YP#g#h/]~/`P#h#i/c~/fP#]#^/i~/lP#b#c/o~/rP#V#W/u~/xP#h#i/{~0QO_~~0TP#b#c0W~0ZP#W#X0^~0aP#X#Y0d~0gP#d#e0j~0mP#X#Y0p~0sP#b#c0v~0yP#W#X0|~1PP#X#Y1S~1VP#b#c1Y~1]P#h#i1`~1eO`~~1hP#X#Y1k~1nP#m#n1q~1vOa~~1yQ#T#U2P#X#Y2h~2SP#b#c2V~2YP#Z#[2]~2`P#X#Y2c~2hOi~~2kP#Z#[2n~2qP#X#Y2t~2wP#l#m2z~3POp~~3SP#i#j3V~3YP#U#V3]~3`P#_#`3c~3fP#X#Y3i~3lP#m#n3o~3tOq~~3wP#b#c3z~3}P#]#^4Q~4TP#e#f4W~4ZP#i#j4^~4aP#X#Y4d~4iOb~~4lP#T#U4o~4rP#`#a4u~4xP#i#j4{~5OP#X#Y5R~5UP#g#h5X~5^Os~Y5aT}!O5p!Q![5p!c!}5p#R#S5p#T#o5pY5uUXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pY6[T}!O6k!Q![6k!c!}6k#R#S6k#T#o6kY6pTXY}!O6k!Q![6k!c!}6k#R#S6k#T#o6k~7UO!X~~7ZO!Y~~7`O#W~~7cW}!O5p!Q![5p!c!}5p#R#S5p#T#g5p#g#h7{#h#i9V#i#o5p_8SW!_PXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W8l#W#o5p^8sU$mSXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~9[WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i9t#i#o5p~9yWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g:c#g#o5p~:hWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^;Q#^#o5p~;VWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V;o#V#o5p~;tWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j<^#j#o5p~WV}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#d>m#d#o5p~>rWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d?[#d#o5p~?aWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a?y#a#o5p~@OWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y@h#Y#o5p~@mVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#UAS#U#o5p~AXWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cAq#c#o5p~AxU{~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~B_V}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#dBt#d#o5p~ByYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cCi#c#i5p#i#jGW#j#o5p~CnWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iDW#i#o5p~D]VXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#UDr#U#o5p~DwWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^Ea#^#o5p~EfWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cFO#c#o5p~FTWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#hFm#h#o5p~FtU#x~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZG]WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cGu#c#o5pZGzWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iHd#i#o5pZHkU$zPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~IQ^}!O5p!Q![5p!c!}5p#R#S5p#T#UI|#U#X5p#X#Y!!R#Y#]5p#]#^!+k#^#c5p#c#d!/z#d#i5p#i#j!2}#j#o5p~JRWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iJk#i#o5p~JpWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#YKY#Y#o5p~KaW!R~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iKy#i#o5p~LOWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^Lh#^#o5p~LmWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#bMV#b#o5p~M[WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#YMt#Y#o5p~M{U!Q~XY}!ON_!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~NdWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iN|#i#o5p~! RVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#n5p#n#o! h~! oU!P~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!!W^XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W!#S#W#Y5p#Y#Z!&S#Z#`5p#`#a!(h#a#g5p#g#h!*|#h#o5p~!#XWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!#q#^#o5p~!#vWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#b!$`#b#o5p~!$eVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U!$z#U#o5p~!%PWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!%i#a#o5p~!%pU!O~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!&XWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!&q#^#o5pZ!&vWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!'`#c#o5pZ!'eWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!'}#Y#o5pZ!(UUSPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!(mWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!)V#Y#o5p~!)[WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!)t#i#o5p~!)yWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!*c#Y#o5p~!*jU$c~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p^!+RWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W8l#W#o5p~!+pWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!,Y#h#o5p~!,_WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!,w#i#o5p~!,|WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!-f#^#o5p~!-kWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!.T#c#o5p~!.YWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W!.r#W#o5p~!.wWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!/a#i#o5p~!/hU$o~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!0PWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!0i#j#o5p~!0nWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V!1W#V#o5p~!1]WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!1u#a#o5p~!1zWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!2d#Y#o5p~!2kU}~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!3SWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!3l#g#o5p~!3qVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U!4W#U#o5p~!4]WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!4u#i#o5p~!4zWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!5d#^#o5p~!5iWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!6R#d#o5p~!6WWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!6p#c#o5p~!6wU!S~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!7^V}!O5p!Q![5p!c!}5p#R#S5p#T#b5p#b#c!7s#c#o5p~!7xYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X!8h#X#h5p#h#i!9R#i#o5p~!8oU%v~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!9WWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!9p#^#o5p~!9uWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!:_#i#o5p~!:dWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n=j#n#o5p~!;P[}!O5p!Q![5p!c!}5p#R#S5p#T#U!;u#U#]5p#]#^!>Z#^#f5p#f#g!@o#g#i5p#i#j!Bf#j#o5p~!;zWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!`WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!>x#g#o5pZ!>}WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!?g#h#o5pZ!?lWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!@U#i#o5pZ!@]U%YPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!@tWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!A^#d#o5pZ!AcWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#b!A{#b#o5pZ!BSU%jPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!BkWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!CT#c#o5p~!C[U!a~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!CqV}!O5p!Q![5p!c!}5p#R#S5p#T#f5p#f#g!DW#g#o5pZ!D]WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!Du#d#o5pZ!DzWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!Ed#j#o5pZ!EiWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#d5p#d#e!FR#e#o5pZ!FWWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V!Fp#V#o5pZ!FuWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n!G_#n#o5pZ!GfU%SPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!G{U}!O5p!Q![5p!c!}5p#R#S5p#T#U!H_#U#o5pZ!HdWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!H|#h#o5pZ!ITU#}PXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_!IjZ}!O5p!Q![5p!c!}5p#R#S5p#T#]5p#]#^!J]#^#b5p#b#c!Ke#c#g5p#g#h##p#h#o5pZ!JbWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X!Jz#X#o5pZ!KRU#zPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_!KlX#OSXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!LX#h#i!Nm#i#o5pZ!L^WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!Lv#Y#o5pZ!L{WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!Me#g#o5pZ!MjWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!NS#i#o5pZ!NZU$]RXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!NrWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y# [#Y#o5pZ# aWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Z5p#Z#[# y#[#o5pZ#!OWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#!h#Y#o5pZ#!mWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g##V#g#o5pZ##^U|RXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ##uVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#$[#U#o5pZ#$cU#nPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#$xY}!O5p!Q![5p!c!}5p#R#S5p#T#U#%h#U#X5p#X#Y#)[#Y#]5p#]#^#*d#^#o5pZ#%mYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V#&]#V#g5p#g#h#(S#h#o5pZ#&bWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#&z#Y#o5pZ#'PWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a#'i#a#o5pZ#'pU#ePXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#(XWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#(q#i#o5pZ#(xU%ZPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#)aWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#)y#i#o5p~#*QU!x~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#*i]XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#_5p#_#`#+b#`#a5p#a#b#,j#b#c#.a#c#g5p#g#h#0W#h#o5p~#+gWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#,P#Y#o5p~#,WU#w~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#,oWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#-X#^#o5p~#-^WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#-v#i#o5p~#-}U$s~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#.fWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#_5p#_#`#/O#`#o5pZ#/TWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#/m#h#o5pZ#/tU$PPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#0]WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#0u#i#o5pZ#0|U%RPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#1cY}!O5p!Q![5p!c!}5p#R#S5p#T#U#2R#U#X5p#X#Y#5W#Y#]5p#]#^#9c#^#o5p~#2WYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#2v#i#l5p#l#m#4m#m#o5p~#2{WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W#3e#W#o5p~#3jWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#[5p#[#]#4S#]#o5p~#4ZU!s~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#4tU${PXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#5]XXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#5x#U#W5p#W#X#7Q#X#o5pZ#5}WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#6g#c#o5pZ#6nU$}PXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#7VWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#7o#^#o5pZ#7tVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#8Z#U#o5pZ#8`WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#8x#c#o5pZ#9PU%OPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#9hWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#:Q#c#o5pZ#:XU$|PXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#:nV}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#d#;T#d#o5p~#;YWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#;r#i#o5p~#;yU$W~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_#<`Z}!O5p!Q![5p!c!}5p#R#S5p#T#Y5p#Y#Z#=R#Z#f5p#f#g#@W#g#k5p#k#l#@q#l#o5p_#=YW$eSXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z#=r#Z#o5pZ#=wWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#>a#h#o5pZ#>fWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#?O#Y#o5pZ#?TWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#?m#i#o5pZ#?tU$qRXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#@_U$TPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#@vWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#A`#c#o5pZ#AeWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#A}#h#o5pZ#BUU!VPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#BkX}!O5p!Q![5p!c!}5p#R#S5p#T#`5p#`#a#CW#a#i5p#i#j#Ei#j#o5pZ#C]VXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#Cr#U#o5pZ#CwWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n#Da#n#o5pZ#DfWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#EO#h#o5pZ#EVU![PXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#EnWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#FW#i#o5p~#F_U$_~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#FtV}!O5p!Q![5p!c!}5p#R#S5p#T#X5p#X#Y#GZ#Y#o5p~#G`^XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X#H[#X#`5p#`#a#My#a#e5p#e#f$$]#f#h5p#h#i$'`#i#o5p~#HaYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#IP#Y#i5p#i#j#LS#j#o5pZ#IUWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z#In#Z#o5pZ#IsWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#J]#^#o5pZ#JbWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#Jz#c#o5pZ#KPWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#Ki#Y#o5pZ#KpU%pPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#LXWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W#Lq#W#o5p~#LvWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#M`#Y#o5p~#MgU$w~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#NOVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#Ne#U#o5p~#NjWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$ S#i#o5p~$ XYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$ w#Y#]5p#]#^$#P#^#o5pZ$ |WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h$!f#h#o5pZ$!mU!^PXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$#UWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d$#n#d#o5p~$#sWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c=j#c#o5p~$$bWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$$z#j#o5p~$%PWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$%i#^#o5p~$%nWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$&W#g#o5p~$&]WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$&u#Y#o5p~$&|U$u~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$'eWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$'}#j#o5p~$(SWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$(l#g#o5p~$(qWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c$)Z#c#o5p~$)bU%U~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$)w[}!O5p!Q![5p!c!}5p#R#S5p#T#X5p#X#Y$*m#Y#c5p#c#d$-p#d#h5p#h#i$/g#i#j$5W#j#o5p~$*rWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a$+[#a#o5p~$+aWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$+y#Y#o5p~$,OWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W$,h#W#o5p~$,mWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$-V#i#o5p~$-^U$h~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$-uWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$._#g#o5p~$.dWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$.|#i#o5p~$/TU$k~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$/lYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X$0[#X#f5p#f#g$0u#g#o5pZ$0cU%PPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$0zYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$1j#^#i5p#i#j$3a#j#o5p~$1oWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c$2X#c#o5p~$2^WXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Z5p#Z#[$2v#[#o5p~$2}U!T~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$3fWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W$4O#W#o5p~$4TWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$4m#i#o5p~$4tU%^~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$5]YXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V$5{#V#a5p#a#b$6f#b#o5pZ$6SUwPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$6mU%QPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$7SV}!O5p!Q![5p!c!}5p#R#S5p#T#f5p#f#g$7i#g#o5p~$7nYXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!=R#j#m5p#m#n$8^#n#o5p~$8eU$Y~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$8zX}!O5p!Q![5p!c!}5p#R#S5p#T#b5p#b#c$9g#c#d5p#d#e$=v#e#o5pZ$9lWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X$:U#X#o5pZ$:ZWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$:s#Y#o5pZ$:xWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z$;b#Z#o5pZ$;gWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$e#X#o5p~$>jVXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U$?P#U#o5p~$?UWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$?n#i#o5p~$?sWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$@]#Y#o5p~$@dU$a~XY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$@yU}!O5p!Q![5p!c!}5p#R#S5p#T#U$A]#U#o5pZ$AbWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a$Az#a#o5pZ$BPWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$Bi#j#o5pZ$BnWXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$CW#Y#o5pZ$C_UyPXY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$CvO!m~~$C{O!n~", + tokenizers: [0, 1, 2, 3], + topRules: {"Query":[0,1]}, + tokenPrec: 2459 +}) diff --git a/src/framework/codemirror-lang-typeql/index.cjs b/src/framework/codemirror-lang-typeql/index.cjs deleted file mode 100644 index 42e809e4b..000000000 --- a/src/framework/codemirror-lang-typeql/index.cjs +++ /dev/null @@ -1,198 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -var lr = require('@lezer/lr'); -var language = require('@codemirror/language'); -var highlight = require('@lezer/highlight'); -var lint = require('@codemirror/lint'); - -// This file was generated by lezer-generator. You probably shouldn't edit it. -const parser = lr.LRParser.deserialize({ - version: 14, - states: "!+xOYQPOOO!ZQQO'#EPO!rQPO'#FiO!rQPO'#FkO!rQPO'#FmO!wQPO'#FoO#VQPO'#FtO#[QPO'#FwO#aQPO'#F{O#fQPO'#F}O#kQPO'#GPO#VQPO'#GRO#pQPO'#GTOOQO'#Fs'#FsOOQO'#EO'#EOOOQO'#H['#H[O$mQPO'#HSO$wQQO'#C`O%VQPO'#GpO&dQQO'#G|OOQO'#C_'#C_OOQO'#HR'#HROOQO'#C^'#C^Q&oQPOOO&tQPO'#EUOOQO'#El'#ElO'[QPO'#ElO(ZQPO'#EkO(bQQO'#EkOOQO'#ET'#ETO!ZQQO'#FcO(jQPO'#FdO(oQPO'#FfOOQO'#ES'#ESO(tQPO'#H]O(yQQO'#EROOQO,5:k,5:kO&yQPO'#EwO*PQPO'#HeO*UQPO,5P,5>POOQO-E;c-E;cO8_QPO'#ElO8mQPO'#EtO8pQPO'#F`O8uQPO,5;yO8}QPO,5<]O9SQSO,5<]OOQO,5>Q,5>QOOQO-E;d-E;dO9XQPO,5fQPO,5:UO>pQPO,5:UO>wQQO,5=dO>|QQO,5=eO?RQPO,5=fOOQO,5=g,5=gOOQO,5=_,5=_OOQO,5>W,5>WOOQO-E;j-E;jO?WQPO,5=lO?`QPO,5=lOOQO,5>X,5>XOOQO-E;k-E;kQYQPO,5>YOOQO-E;l-E;lOOQO,5:t,5:tO?gQSO,5:sO?rQSO,5:sO?}QWO1G0[O@fQWO,5;fOOQO,5;r,5;rOAYQPO,5;uOAqQPO,5;uOOQO,5;w,5;wOBSQPO,5;dOBeQPO,5;dOOQO1G0}1G0}OOQO,5;Z,5;ZOOQO,5;[,5;[OOQO,5;],5;]OBmQPO,5;_OOQO,5;_,5;_ODfQPO,5;aODpQPO,5;aOOQO,5;b,5;bOOQO,5;X,5;XODwQPO1G0qOEOQPO1G0qOEOQPO1G0qOEWQPO1G1iOE`QPO1G1jOEeQPO1G1lOEjQPO,5;`OEoQPO,5;zOEtQQO1G1eOFPQPO1G1eOOQO1G1e1G1eOOQO1G1w1G1wOFXQPO1G1wOOQO,5>R,5>ROF^QPO1G1|OOQO-E;e-E;eOOQO,5>S,5>SOOQO-E;f-E;fOOQO7+'i7+'iOFiQPO'#GWOFwQPO'#GWOOQO1G2]1G2]OOQO,5>T,5>TOOQO-E;g-E;gOOQO7+'u7+'uO#VQPO7+'uOF|QPO7+'uOGRQPO,59TOGWQPO,59TOGiQPO,59TO2^QQO,59TOGnQPO,59TOOQO-E;T-E;TOOQO,59m,59mOG|QPO1G.jOHbQPO1G.jOHbQPO1G.jOHjQPO1G.jOHqQPO,5:ZO#uQPO1G/sO2^QQO1G2pOHyQPO,5:POIOQQO1G/pOITQQO1G/pOIYQPO1G3OOOQO1G3P1G3POIaQQO1G3QOIfQPO1G3WOImQPO1G3WOImQPO1G3WOOQO1G3t1G3tOOQO,5=x,5=xOIuQSO1G0_OOQO-E;[-E;[OOQO'#Cy'#CyO?}QWO'#E`OOQO'#Eb'#EbOJQQPO'#EaOOQO'#E_'#E_OJkQQO'#E^OOQO7+%v7+%vOOQO'#E}'#E}O?}QWO'#E|OOQO1G1Q1G1QOOQO1G1a1G1aOOQO,5=},5=}OJxQPO1G1OOOQO-E;a-E;aO(bQQO1G0{O(bQQO1G0{OOQO,5={,5={OKZQPO7+&]OOQO-E;_-E;_OKbQPO7+&]OKjQPO'#HdOKoQPO7+'ROOQO7+'U7+'UOOQO7+'W7+'WOOQO1G0z1G0zOOQO1G1f1G1fOOQO,5=|,5=|OOQO7+'P7+'POKwQQO7+'POOQO-E;`-E;`OOQO7+'c7+'cPLSQPO'#HgOLXQPO,5OOOQO-E;b-E;bOOQO<V,5>VO!&nQQO1G2rOOQO-E;i-E;iO!&vQWO,5:}O!&}QPO,5:}OOQO7+&R7+&ROOQO7+)U7+)UOOQOAN=aAN=aPGnQPO'#HWO!'VQPO,5:aPHtQPO'#HYO!'[QPO,5:eO!'dQQO,5:hO!'nQPO,5:hOOQOAN>gAN>gO!'vQPO,5=OOOQO,5=P,5=PO!'{QPO,5=TO!(SQPO,5=TOOQO,5=Z,5=ZP2^QQO'#HkOOQO,5=y,5=yO!([QWO1G0iOOQO-E;]-E;]OOQO1G/{1G/{O!(cQQO1G0PO!(mQPO1G0POOQO1G0P1G0POOQO,5=u,5=uO!(uQQO1G0SOOQO-E;X-E;XOOQO1G2j1G2jOOQO,5>U,5>UO!)PQPO1G2oOOQO-E;h-E;hP?}QWO'#H_OOQO7+%k7+%kO!)WQQO7+%kP!#OQQO'#HZP9wQPO'#HjOOQO<T#V#WB[#W#XH}#X#Y!7Z#Y#Z!:|#Z#[!Cn#[#]!Gx#]#^!Ig#^#`5^#`#a#$u#a#b#1`#b#c#:k#c#d#<]#d#e#Bh#e#f5^#f#g#Fq#g#h$)t#h#i$7P#i#j$8w#j#k$@v#k#o5^#o#p$Cq#q#r$Cv~$pS&e~XY$kYZ$k]^$kpq$k~%PP!_!`%S~%XO#s~~%[VOr%Xrs%qs#O%X#O#P%v#P;'S%X;'S;=`&o<%lO%X~%vOo~~%yRO;'S%X;'S;=`&S;=`O%X~&VWOr%Xrs%qs#O%X#O#P%v#P;'S%X;'S;=`&o;=`<%l%X<%lO%X~&rP;=`<%l%X~&zS&f~OY&uZ;'S&u;'S;=`'W<%lO&u~'ZP;=`<%l&u~'aT}!O'p!Q!['p!c!}'p#R#S'p#T#o'p~'uT!f~}!O'p!Q!['p!c!}'p#R#S'p#T#o'p~(ZO#[~~(`Oe~~(eOi~~(jO#Y~~(oO#]~~(tOZ~Z(yQ#^Q!Q![)P!`!a)lX)WQpXgX!O!P)^!Q![)PX)aP!Q![)dX)iPpX!Q![)dP)qO!kP~)tP!O!P)w~)|Oh~~*RO#Z~Z*YRpXgX!O!P)^!Q![)P#l#m*cQ*fR!Q![*o!c!i*o#T#Z*oQ*tR#|Q!Q![*o!c!i*o#T#Z*o~+SO!g~~+XO$[~~+^P#v~!_!`+a~+fO#w~]+kP#OT!_!`+nW+sO#rW~+xP#t~!_!`+{~,QO#u~~,VO!}~~,YX#T#U,u#V#W-v#W#X/P#]#^0Q#_#`1e#f#g1v#g#h3P#i#j3t#j#k4i~,xP#U#V,{~-OP#g#h-R~-UP#h#i-X~-[P#f#g-_~-bP#T#U-e~-hP#V#W-k~-nP#h#i-q~-vO^~~-yP#T#U-|~.PQ#f#g.V#g#h.b~.YP#W#X.]~.bOd~~.eP#V#W.h~.kP#T#U.n~.qP#W#X.t~.wP#X#Y.z~/PO_~~/SP#]#^/V~/YP#g#h/]~/`P#h#i/c~/fP#]#^/i~/lP#b#c/o~/rP#V#W/u~/xP#h#i/{~0QO`~~0TP#b#c0W~0ZP#W#X0^~0aP#X#Y0d~0gP#d#e0j~0mP#X#Y0p~0sP#b#c0v~0yP#W#X0|~1PP#X#Y1S~1VP#b#c1Y~1]P#h#i1`~1eOa~~1hP#X#Y1k~1nP#m#n1q~1vOb~~1yQ#T#U2P#X#Y2h~2SP#b#c2V~2YP#Z#[2]~2`P#X#Y2c~2hOj~~2kP#Z#[2n~2qP#X#Y2t~2wP#l#m2z~3POq~~3SP#i#j3V~3YP#U#V3]~3`P#_#`3c~3fP#X#Y3i~3lP#m#n3o~3tOr~~3wP#b#c3z~3}P#]#^4Q~4TP#e#f4W~4ZP#i#j4^~4aP#X#Y4d~4iOc~~4lP#T#U4o~4rP#`#a4u~4xP#i#j4{~5OP#X#Y5R~5UP#g#h5X~5^Ot~Y5aT}!O5p!Q![5p!c!}5p#R#S5p#T#o5pY5uUYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pY6[T}!O6k!Q![6k!c!}6k#R#S6k#T#o6kY6pTYY}!O6k!Q![6k!c!}6k#R#S6k#T#o6k~7UO!Y~~7ZO!Z~~7`O#X~~7cW}!O5p!Q![5p!c!}5p#R#S5p#T#g5p#g#h7{#h#i9V#i#o5p_8SW!`PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W8l#W#o5p^8sU$nSYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~9[WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i9t#i#o5p~9yWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g:c#g#o5p~:hWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^;Q#^#o5p~;VWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V;o#V#o5p~;tWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j<^#j#o5p~WV}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#d>m#d#o5p~>rWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d?[#d#o5p~?aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a?y#a#o5p~@OWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y@h#Y#o5p~@mVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#UAS#U#o5p~AXWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cAq#c#o5p~AxU|~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~B_V}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#dBt#d#o5p~ByYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cCi#c#i5p#i#jGW#j#o5p~CnWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iDW#i#o5p~D]VYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#UDr#U#o5p~DwWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^Ea#^#o5p~EfWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cFO#c#o5p~FTWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#hFm#h#o5p~FtU#y~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZG]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cGu#c#o5pZGzWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iHd#i#o5pZHkU${PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~IQ^}!O5p!Q![5p!c!}5p#R#S5p#T#UI|#U#X5p#X#Y!!R#Y#]5p#]#^!+k#^#c5p#c#d!/z#d#i5p#i#j!2}#j#o5p~JRWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iJk#i#o5p~JpWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#YKY#Y#o5p~KaW!S~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iKy#i#o5p~LOWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^Lh#^#o5p~LmWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#bMV#b#o5p~M[WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#YMt#Y#o5p~M{U!R~YY}!ON_!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~NdWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iN|#i#o5p~! RVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#n5p#n#o! h~! oU!Q~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!!W^YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W!#S#W#Y5p#Y#Z!&S#Z#`5p#`#a!(h#a#g5p#g#h!*|#h#o5p~!#XWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!#q#^#o5p~!#vWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#b!$`#b#o5p~!$eVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U!$z#U#o5p~!%PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!%i#a#o5p~!%pU!P~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!&XWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!&q#^#o5pZ!&vWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!'`#c#o5pZ!'eWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!'}#Y#o5pZ!(UUTPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!(mWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!)V#Y#o5p~!)[WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!)t#i#o5p~!)yWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!*c#Y#o5p~!*jU$d~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p^!+RWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W8l#W#o5p~!+pWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!,Y#h#o5p~!,_WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!,w#i#o5p~!,|WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!-f#^#o5p~!-kWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!.T#c#o5p~!.YWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W!.r#W#o5p~!.wWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!/a#i#o5p~!/hU$p~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!0PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!0i#j#o5p~!0nWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V!1W#V#o5p~!1]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!1u#a#o5p~!1zWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!2d#Y#o5p~!2kU!O~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!3SWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!3l#g#o5p~!3qVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U!4W#U#o5p~!4]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!4u#i#o5p~!4zWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!5d#^#o5p~!5iWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!6R#d#o5p~!6WWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!6p#c#o5p~!6wU!T~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!7^V}!O5p!Q![5p!c!}5p#R#S5p#T#b5p#b#c!7s#c#o5p~!7xYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X!8h#X#h5p#h#i!9R#i#o5p~!8oU%w~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!9WWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!9p#^#o5p~!9uWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!:_#i#o5p~!:dWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n=j#n#o5p~!;P[}!O5p!Q![5p!c!}5p#R#S5p#T#U!;u#U#]5p#]#^!>Z#^#f5p#f#g!@o#g#i5p#i#j!Bf#j#o5p~!;zWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!`WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!>x#g#o5pZ!>}WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!?g#h#o5pZ!?lWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!@U#i#o5pZ!@]U%ZPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!@tWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!A^#d#o5pZ!AcWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#b!A{#b#o5pZ!BSU%kPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!BkWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!CT#c#o5p~!C[U!b~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!CqV}!O5p!Q![5p!c!}5p#R#S5p#T#f5p#f#g!DW#g#o5pZ!D]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!Du#d#o5pZ!DzWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!Ed#j#o5pZ!EiWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#d5p#d#e!FR#e#o5pZ!FWWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V!Fp#V#o5pZ!FuWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n!G_#n#o5pZ!GfU%TPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!G{U}!O5p!Q![5p!c!}5p#R#S5p#T#U!H_#U#o5pZ!HdWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!H|#h#o5pZ!ITU$OPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_!IjZ}!O5p!Q![5p!c!}5p#R#S5p#T#]5p#]#^!J]#^#b5p#b#c!Ke#c#g5p#g#h##p#h#o5pZ!JbWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X!Jz#X#o5pZ!KRU#{PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_!KlX#PSYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!LX#h#i!Nm#i#o5pZ!L^WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!Lv#Y#o5pZ!L{WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!Me#g#o5pZ!MjWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!NS#i#o5pZ!NZU$^RYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!NrWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y# [#Y#o5pZ# aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Z5p#Z#[# y#[#o5pZ#!OWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#!h#Y#o5pZ#!mWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g##V#g#o5pZ##^U}RYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ##uVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#$[#U#o5pZ#$cU#oPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#$xY}!O5p!Q![5p!c!}5p#R#S5p#T#U#%h#U#X5p#X#Y#)[#Y#]5p#]#^#*d#^#o5pZ#%mYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V#&]#V#g5p#g#h#(S#h#o5pZ#&bWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#&z#Y#o5pZ#'PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a#'i#a#o5pZ#'pU#fPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#(XWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#(q#i#o5pZ#(xU%[PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#)aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#)y#i#o5p~#*QU!y~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#*i]YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#_5p#_#`#+b#`#a5p#a#b#,j#b#c#.a#c#g5p#g#h#0W#h#o5p~#+gWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#,P#Y#o5p~#,WU#x~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#,oWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#-X#^#o5p~#-^WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#-v#i#o5p~#-}U$t~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#.fWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#_5p#_#`#/O#`#o5pZ#/TWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#/m#h#o5pZ#/tU$QPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#0]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#0u#i#o5pZ#0|U%SPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#1cY}!O5p!Q![5p!c!}5p#R#S5p#T#U#2R#U#X5p#X#Y#5W#Y#]5p#]#^#9c#^#o5p~#2WYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#2v#i#l5p#l#m#4m#m#o5p~#2{WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W#3e#W#o5p~#3jWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#[5p#[#]#4S#]#o5p~#4ZU!t~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#4tU$|PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#5]XYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#5x#U#W5p#W#X#7Q#X#o5pZ#5}WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#6g#c#o5pZ#6nU%OPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#7VWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#7o#^#o5pZ#7tVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#8Z#U#o5pZ#8`WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#8x#c#o5pZ#9PU%PPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#9hWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#:Q#c#o5pZ#:XU$}PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#:nV}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#d#;T#d#o5p~#;YWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#;r#i#o5p~#;yU$X~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_#<`Z}!O5p!Q![5p!c!}5p#R#S5p#T#Y5p#Y#Z#=R#Z#f5p#f#g#@W#g#k5p#k#l#@q#l#o5p_#=YW$fSYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z#=r#Z#o5pZ#=wWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#>a#h#o5pZ#>fWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#?O#Y#o5pZ#?TWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#?m#i#o5pZ#?tU$rRYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#@_U$UPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#@vWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#A`#c#o5pZ#AeWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#A}#h#o5pZ#BUU!WPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#BkX}!O5p!Q![5p!c!}5p#R#S5p#T#`5p#`#a#CW#a#i5p#i#j#Ei#j#o5pZ#C]VYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#Cr#U#o5pZ#CwWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n#Da#n#o5pZ#DfWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#EO#h#o5pZ#EVU!]PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#EnWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#FW#i#o5p~#F_U$`~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#FtV}!O5p!Q![5p!c!}5p#R#S5p#T#X5p#X#Y#GZ#Y#o5p~#G`^YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X#H[#X#`5p#`#a#My#a#e5p#e#f$$]#f#h5p#h#i$'`#i#o5p~#HaYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#IP#Y#i5p#i#j#LS#j#o5pZ#IUWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z#In#Z#o5pZ#IsWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#J]#^#o5pZ#JbWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#Jz#c#o5pZ#KPWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#Ki#Y#o5pZ#KpU%qPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#LXWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W#Lq#W#o5p~#LvWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#M`#Y#o5p~#MgU$x~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#NOVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#Ne#U#o5p~#NjWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$ S#i#o5p~$ XYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$ w#Y#]5p#]#^$#P#^#o5pZ$ |WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h$!f#h#o5pZ$!mU!_PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$#UWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d$#n#d#o5p~$#sWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c=j#c#o5p~$$bWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$$z#j#o5p~$%PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$%i#^#o5p~$%nWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$&W#g#o5p~$&]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$&u#Y#o5p~$&|U$v~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$'eWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$'}#j#o5p~$(SWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$(l#g#o5p~$(qWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c$)Z#c#o5p~$)bU%V~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$)w[}!O5p!Q![5p!c!}5p#R#S5p#T#X5p#X#Y$*m#Y#c5p#c#d$-p#d#h5p#h#i$/g#i#j$5W#j#o5p~$*rWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a$+[#a#o5p~$+aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$+y#Y#o5p~$,OWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W$,h#W#o5p~$,mWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$-V#i#o5p~$-^U$i~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$-uWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$._#g#o5p~$.dWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$.|#i#o5p~$/TU$l~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$/lYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X$0[#X#f5p#f#g$0u#g#o5pZ$0cU%QPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$0zYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$1j#^#i5p#i#j$3a#j#o5p~$1oWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c$2X#c#o5p~$2^WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Z5p#Z#[$2v#[#o5p~$2}U!U~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$3fWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W$4O#W#o5p~$4TWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$4m#i#o5p~$4tU%_~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$5]YYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V$5{#V#a5p#a#b$6f#b#o5pZ$6SUxPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$6mU%RPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$7SV}!O5p!Q![5p!c!}5p#R#S5p#T#f5p#f#g$7i#g#o5p~$7nYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!=R#j#m5p#m#n$8^#n#o5p~$8eU$Z~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$8zX}!O5p!Q![5p!c!}5p#R#S5p#T#b5p#b#c$9g#c#d5p#d#e$=v#e#o5pZ$9lWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X$:U#X#o5pZ$:ZWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$:s#Y#o5pZ$:xWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z$;b#Z#o5pZ$;gWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$e#X#o5p~$>jVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U$?P#U#o5p~$?UWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$?n#i#o5p~$?sWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$@]#Y#o5p~$@dU$b~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$@yU}!O5p!Q![5p!c!}5p#R#S5p#T#U$A]#U#o5pZ$AbWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a$Az#a#o5pZ$BPWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$Bi#j#o5pZ$BnWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$CW#Y#o5pZ$C_UzPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$CvO!n~~$C{O!o~", - tokenizers: [0, 1, 2, 3], - topRules: {"Query":[0,1]}, - tokenPrec: 2502 -}); - -// TODO: We could do better by climbing up the tree using `atNode.parentNode` to predict based on position as well. -// We could also refine the suggestions by creating datastructures based on the declarations in the schema, rather than blindly suggesting every label. -function suggestLabel(label) { - return { - label: label, - type: "label", - apply: label, - info: "label suggestion", - }; -} -function suggestVariable(varName) { - return { - label: varName, - type: "variable", - apply: varName, - info: "variable suggestion", - }; -} -function collectLabelSuggestions(context, tree, atNode) { - // This is a placeholder function. You will need to implement the logic to collect label suggestions. - // For now, we return an empty array. - var options = []; - tree.iterate({ - enter: (other) => { - if (other.name == "LABEL") { - let content = context.state.sliceDoc(other.from, other.to); - options.push(suggestLabel(content)); - } - } - }); - return options; -} -function collectVariableSuggestions(context, tree, atNode) { - var options = []; - tree.iterate({ - enter: (other) => { - if (other.name == "VAR") { - let content = context.state.sliceDoc(other.from, other.to); - options.push(suggestVariable(content)); - } - } - }); - return options; -} -// See: https://codemirror.net/examples/autocompletion/ and maybe the SQL / HTML Example there. -function autocompleteTypeQL(context) { - let tree = language.syntaxTree(context.state); - let currentNode = tree.resolveInner(context.pos, -1); // https://lezer.codemirror.net/docs/ref/#common.SyntaxNode - // We may have to walk the tree to find the most appropriate node to suggest things based on. - let options = null; - if (currentNode.name == "LABEL") { - options = collectLabelSuggestions(context, tree); - } - else if (currentNode.name == "VAR") { - options = collectVariableSuggestions(context, tree); - } - else ; - if (options != null) { - // And once we figure out, we have to create a list of completion objects - // It may be worth changing the grammar to be able to do this more easily, rather than replicate the original TypeQL grammar. - // https://codemirror.net/docs/ref/#autocomplete.Completion - return { - from: currentNode.from, - options: options, - // Docs: "regular expression that tells the extension that, as long as the updated input (the range between the result's from property and the completion point) matches that value, it can continue to use the list of completions." - validFor: /^(\w+)?$/ - }; - } - else { - return null; - } -} - -const TypeQLLanguage = language.LRLanguage.define({ - parser: parser.configure({ - props: [ - language.indentNodeProp.add({}), - language.foldNodeProp.add({ - QueryStage: language.foldInside - }), - highlight.styleTags({ - // See: https://lezer.codemirror.net/docs/ref/#highlight.tags - VAR: highlight.tags.variableName, - // Literals - STRINGLITERAL: highlight.tags.string, - INTEGERLITERAL: highlight.tags.number, - DOUBLELITERAL: highlight.tags.number, - BOOLEANLITERAL: highlight.tags.bool, - // Types - LABEL: highlight.tags.typeName, - BOOLEAN: highlight.tags.typeName, - INTEGER: highlight.tags.typeName, - DOUBLE: highlight.tags.typeName, - DECIMAL: highlight.tags.typeName, - DATETIMETZ: highlight.tags.typeName, - DATETIME: highlight.tags.typeName, - DATE: highlight.tags.typeName, - DURATION: highlight.tags.typeName, - STRING: highlight.tags.typeName, - // Keywords - ISA: highlight.tags.keyword, - HAS: highlight.tags.keyword, - LINKS: highlight.tags.keyword, - OWNS: highlight.tags.keyword, - RELATES: highlight.tags.keyword, - PLAYS: highlight.tags.keyword, - FUN: highlight.tags.keyword, - LET: highlight.tags.keyword, - FIRST: highlight.tags.keyword, - LAST: highlight.tags.keyword, - // Value type names? - // Stages - DEFINE: highlight.tags.heading1, - UNDEFINE: highlight.tags.heading1, - REDEFINE: highlight.tags.heading1, - MATCH: highlight.tags.heading1, - INSERT: highlight.tags.heading1, - DELETE: highlight.tags.heading1, - UPDATE: highlight.tags.heading1, - PUT: highlight.tags.heading1, - END: highlight.tags.heading1, - SELECT: highlight.tags.heading1, - REDUCE: highlight.tags.heading1, - SORT: highlight.tags.heading1, - OFFSET: highlight.tags.heading1, - LIMIT: highlight.tags.heading1, - REQUIRE: highlight.tags.heading1, - DISTINCT: highlight.tags.heading1, - GROUPBY: highlight.tags.heading1, - // SubPattern - OR: highlight.tags.controlOperator, - NOT: highlight.tags.controlOperator, - TRY: highlight.tags.controlOperator, - // Misc - Annotation: highlight.tags.meta, - LINECOMMENT: highlight.tags.lineComment, - }) - ] - }), - languageData: { - commentTokens: { line: "#" } - } -}); -function TypeQL() { - return new language.LanguageSupport(TypeQLLanguage, [ - TypeQLLanguage.data.of({ - autocomplete: autocompleteTypeQL - }), - ]); -} -// A Linter which flags syntax errors from: https://discuss.codemirror.net/t/showing-syntax-errors/3111/6 -function otherExampleLinter() { - return lint.linter((view) => { - const diagnostics = []; - language.syntaxTree(view.state).iterate({ - enter: n => { - if (n.type.isError) { - diagnostics.push({ - from: n.from, - to: n.to, - severity: "error", - message: "Syntax error.", - }); - } - }, - }); - return diagnostics; - }); -} - -exports.TypeQL = TypeQL; -exports.TypeQLLanguage = TypeQLLanguage; -exports.otherExampleLinter = otherExampleLinter; diff --git a/src/framework/codemirror-lang-typeql/index.d.cts b/src/framework/codemirror-lang-typeql/index.d.cts deleted file mode 100644 index 2bf6cd430..000000000 --- a/src/framework/codemirror-lang-typeql/index.d.cts +++ /dev/null @@ -1,5 +0,0 @@ -import { LRLanguage, LanguageSupport } from "@codemirror/language"; -declare const TypeQLLanguage: LRLanguage; -declare function TypeQL(): LanguageSupport; -declare function otherExampleLinter(): import("@codemirror/state").Extension; -export { TypeQLLanguage, TypeQL, otherExampleLinter }; diff --git a/src/framework/codemirror-lang-typeql/index.d.ts b/src/framework/codemirror-lang-typeql/index.d.ts deleted file mode 100644 index 2bf6cd430..000000000 --- a/src/framework/codemirror-lang-typeql/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { LRLanguage, LanguageSupport } from "@codemirror/language"; -declare const TypeQLLanguage: LRLanguage; -declare function TypeQL(): LanguageSupport; -declare function otherExampleLinter(): import("@codemirror/state").Extension; -export { TypeQLLanguage, TypeQL, otherExampleLinter }; diff --git a/src/framework/codemirror-lang-typeql/index.js b/src/framework/codemirror-lang-typeql/index.js deleted file mode 100644 index 54739ba37..000000000 --- a/src/framework/codemirror-lang-typeql/index.js +++ /dev/null @@ -1,192 +0,0 @@ -import { LRParser } from '@lezer/lr'; -import { syntaxTree, LRLanguage, indentNodeProp, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language'; -import { styleTags, tags } from '@lezer/highlight'; -import { linter } from '@codemirror/lint'; - -// This file was generated by lezer-generator. You probably shouldn't edit it. -const parser = LRParser.deserialize({ - version: 14, - states: "!+xOYQPOOO!ZQQO'#EPO!rQPO'#FiO!rQPO'#FkO!rQPO'#FmO!wQPO'#FoO#VQPO'#FtO#[QPO'#FwO#aQPO'#F{O#fQPO'#F}O#kQPO'#GPO#VQPO'#GRO#pQPO'#GTOOQO'#Fs'#FsOOQO'#EO'#EOOOQO'#H['#H[O$mQPO'#HSO$wQQO'#C`O%VQPO'#GpO&dQQO'#G|OOQO'#C_'#C_OOQO'#HR'#HROOQO'#C^'#C^Q&oQPOOO&tQPO'#EUOOQO'#El'#ElO'[QPO'#ElO(ZQPO'#EkO(bQQO'#EkOOQO'#ET'#ETO!ZQQO'#FcO(jQPO'#FdO(oQPO'#FfOOQO'#ES'#ESO(tQPO'#H]O(yQQO'#EROOQO,5:k,5:kO&yQPO'#EwO*PQPO'#HeO*UQPO,5P,5>POOQO-E;c-E;cO8_QPO'#ElO8mQPO'#EtO8pQPO'#F`O8uQPO,5;yO8}QPO,5<]O9SQSO,5<]OOQO,5>Q,5>QOOQO-E;d-E;dO9XQPO,5fQPO,5:UO>pQPO,5:UO>wQQO,5=dO>|QQO,5=eO?RQPO,5=fOOQO,5=g,5=gOOQO,5=_,5=_OOQO,5>W,5>WOOQO-E;j-E;jO?WQPO,5=lO?`QPO,5=lOOQO,5>X,5>XOOQO-E;k-E;kQYQPO,5>YOOQO-E;l-E;lOOQO,5:t,5:tO?gQSO,5:sO?rQSO,5:sO?}QWO1G0[O@fQWO,5;fOOQO,5;r,5;rOAYQPO,5;uOAqQPO,5;uOOQO,5;w,5;wOBSQPO,5;dOBeQPO,5;dOOQO1G0}1G0}OOQO,5;Z,5;ZOOQO,5;[,5;[OOQO,5;],5;]OBmQPO,5;_OOQO,5;_,5;_ODfQPO,5;aODpQPO,5;aOOQO,5;b,5;bOOQO,5;X,5;XODwQPO1G0qOEOQPO1G0qOEOQPO1G0qOEWQPO1G1iOE`QPO1G1jOEeQPO1G1lOEjQPO,5;`OEoQPO,5;zOEtQQO1G1eOFPQPO1G1eOOQO1G1e1G1eOOQO1G1w1G1wOFXQPO1G1wOOQO,5>R,5>ROF^QPO1G1|OOQO-E;e-E;eOOQO,5>S,5>SOOQO-E;f-E;fOOQO7+'i7+'iOFiQPO'#GWOFwQPO'#GWOOQO1G2]1G2]OOQO,5>T,5>TOOQO-E;g-E;gOOQO7+'u7+'uO#VQPO7+'uOF|QPO7+'uOGRQPO,59TOGWQPO,59TOGiQPO,59TO2^QQO,59TOGnQPO,59TOOQO-E;T-E;TOOQO,59m,59mOG|QPO1G.jOHbQPO1G.jOHbQPO1G.jOHjQPO1G.jOHqQPO,5:ZO#uQPO1G/sO2^QQO1G2pOHyQPO,5:POIOQQO1G/pOITQQO1G/pOIYQPO1G3OOOQO1G3P1G3POIaQQO1G3QOIfQPO1G3WOImQPO1G3WOImQPO1G3WOOQO1G3t1G3tOOQO,5=x,5=xOIuQSO1G0_OOQO-E;[-E;[OOQO'#Cy'#CyO?}QWO'#E`OOQO'#Eb'#EbOJQQPO'#EaOOQO'#E_'#E_OJkQQO'#E^OOQO7+%v7+%vOOQO'#E}'#E}O?}QWO'#E|OOQO1G1Q1G1QOOQO1G1a1G1aOOQO,5=},5=}OJxQPO1G1OOOQO-E;a-E;aO(bQQO1G0{O(bQQO1G0{OOQO,5={,5={OKZQPO7+&]OOQO-E;_-E;_OKbQPO7+&]OKjQPO'#HdOKoQPO7+'ROOQO7+'U7+'UOOQO7+'W7+'WOOQO1G0z1G0zOOQO1G1f1G1fOOQO,5=|,5=|OOQO7+'P7+'POKwQQO7+'POOQO-E;`-E;`OOQO7+'c7+'cPLSQPO'#HgOLXQPO,5OOOQO-E;b-E;bOOQO<V,5>VO!&nQQO1G2rOOQO-E;i-E;iO!&vQWO,5:}O!&}QPO,5:}OOQO7+&R7+&ROOQO7+)U7+)UOOQOAN=aAN=aPGnQPO'#HWO!'VQPO,5:aPHtQPO'#HYO!'[QPO,5:eO!'dQQO,5:hO!'nQPO,5:hOOQOAN>gAN>gO!'vQPO,5=OOOQO,5=P,5=PO!'{QPO,5=TO!(SQPO,5=TOOQO,5=Z,5=ZP2^QQO'#HkOOQO,5=y,5=yO!([QWO1G0iOOQO-E;]-E;]OOQO1G/{1G/{O!(cQQO1G0PO!(mQPO1G0POOQO1G0P1G0POOQO,5=u,5=uO!(uQQO1G0SOOQO-E;X-E;XOOQO1G2j1G2jOOQO,5>U,5>UO!)PQPO1G2oOOQO-E;h-E;hP?}QWO'#H_OOQO7+%k7+%kO!)WQQO7+%kP!#OQQO'#HZP9wQPO'#HjOOQO<T#V#WB[#W#XH}#X#Y!7Z#Y#Z!:|#Z#[!Cn#[#]!Gx#]#^!Ig#^#`5^#`#a#$u#a#b#1`#b#c#:k#c#d#<]#d#e#Bh#e#f5^#f#g#Fq#g#h$)t#h#i$7P#i#j$8w#j#k$@v#k#o5^#o#p$Cq#q#r$Cv~$pS&e~XY$kYZ$k]^$kpq$k~%PP!_!`%S~%XO#s~~%[VOr%Xrs%qs#O%X#O#P%v#P;'S%X;'S;=`&o<%lO%X~%vOo~~%yRO;'S%X;'S;=`&S;=`O%X~&VWOr%Xrs%qs#O%X#O#P%v#P;'S%X;'S;=`&o;=`<%l%X<%lO%X~&rP;=`<%l%X~&zS&f~OY&uZ;'S&u;'S;=`'W<%lO&u~'ZP;=`<%l&u~'aT}!O'p!Q!['p!c!}'p#R#S'p#T#o'p~'uT!f~}!O'p!Q!['p!c!}'p#R#S'p#T#o'p~(ZO#[~~(`Oe~~(eOi~~(jO#Y~~(oO#]~~(tOZ~Z(yQ#^Q!Q![)P!`!a)lX)WQpXgX!O!P)^!Q![)PX)aP!Q![)dX)iPpX!Q![)dP)qO!kP~)tP!O!P)w~)|Oh~~*RO#Z~Z*YRpXgX!O!P)^!Q![)P#l#m*cQ*fR!Q![*o!c!i*o#T#Z*oQ*tR#|Q!Q![*o!c!i*o#T#Z*o~+SO!g~~+XO$[~~+^P#v~!_!`+a~+fO#w~]+kP#OT!_!`+nW+sO#rW~+xP#t~!_!`+{~,QO#u~~,VO!}~~,YX#T#U,u#V#W-v#W#X/P#]#^0Q#_#`1e#f#g1v#g#h3P#i#j3t#j#k4i~,xP#U#V,{~-OP#g#h-R~-UP#h#i-X~-[P#f#g-_~-bP#T#U-e~-hP#V#W-k~-nP#h#i-q~-vO^~~-yP#T#U-|~.PQ#f#g.V#g#h.b~.YP#W#X.]~.bOd~~.eP#V#W.h~.kP#T#U.n~.qP#W#X.t~.wP#X#Y.z~/PO_~~/SP#]#^/V~/YP#g#h/]~/`P#h#i/c~/fP#]#^/i~/lP#b#c/o~/rP#V#W/u~/xP#h#i/{~0QO`~~0TP#b#c0W~0ZP#W#X0^~0aP#X#Y0d~0gP#d#e0j~0mP#X#Y0p~0sP#b#c0v~0yP#W#X0|~1PP#X#Y1S~1VP#b#c1Y~1]P#h#i1`~1eOa~~1hP#X#Y1k~1nP#m#n1q~1vOb~~1yQ#T#U2P#X#Y2h~2SP#b#c2V~2YP#Z#[2]~2`P#X#Y2c~2hOj~~2kP#Z#[2n~2qP#X#Y2t~2wP#l#m2z~3POq~~3SP#i#j3V~3YP#U#V3]~3`P#_#`3c~3fP#X#Y3i~3lP#m#n3o~3tOr~~3wP#b#c3z~3}P#]#^4Q~4TP#e#f4W~4ZP#i#j4^~4aP#X#Y4d~4iOc~~4lP#T#U4o~4rP#`#a4u~4xP#i#j4{~5OP#X#Y5R~5UP#g#h5X~5^Ot~Y5aT}!O5p!Q![5p!c!}5p#R#S5p#T#o5pY5uUYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pY6[T}!O6k!Q![6k!c!}6k#R#S6k#T#o6kY6pTYY}!O6k!Q![6k!c!}6k#R#S6k#T#o6k~7UO!Y~~7ZO!Z~~7`O#X~~7cW}!O5p!Q![5p!c!}5p#R#S5p#T#g5p#g#h7{#h#i9V#i#o5p_8SW!`PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W8l#W#o5p^8sU$nSYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~9[WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i9t#i#o5p~9yWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g:c#g#o5p~:hWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^;Q#^#o5p~;VWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V;o#V#o5p~;tWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j<^#j#o5p~WV}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#d>m#d#o5p~>rWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d?[#d#o5p~?aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a?y#a#o5p~@OWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y@h#Y#o5p~@mVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#UAS#U#o5p~AXWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cAq#c#o5p~AxU|~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~B_V}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#dBt#d#o5p~ByYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cCi#c#i5p#i#jGW#j#o5p~CnWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iDW#i#o5p~D]VYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#UDr#U#o5p~DwWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^Ea#^#o5p~EfWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cFO#c#o5p~FTWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#hFm#h#o5p~FtU#y~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZG]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#cGu#c#o5pZGzWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iHd#i#o5pZHkU${PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~IQ^}!O5p!Q![5p!c!}5p#R#S5p#T#UI|#U#X5p#X#Y!!R#Y#]5p#]#^!+k#^#c5p#c#d!/z#d#i5p#i#j!2}#j#o5p~JRWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iJk#i#o5p~JpWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#YKY#Y#o5p~KaW!S~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iKy#i#o5p~LOWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^Lh#^#o5p~LmWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#bMV#b#o5p~M[WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#YMt#Y#o5p~M{U!R~YY}!ON_!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~NdWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#iN|#i#o5p~! RVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#n5p#n#o! h~! oU!Q~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!!W^YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W!#S#W#Y5p#Y#Z!&S#Z#`5p#`#a!(h#a#g5p#g#h!*|#h#o5p~!#XWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!#q#^#o5p~!#vWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#b!$`#b#o5p~!$eVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U!$z#U#o5p~!%PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!%i#a#o5p~!%pU!P~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!&XWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!&q#^#o5pZ!&vWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!'`#c#o5pZ!'eWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!'}#Y#o5pZ!(UUTPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!(mWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!)V#Y#o5p~!)[WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!)t#i#o5p~!)yWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!*c#Y#o5p~!*jU$d~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p^!+RWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W8l#W#o5p~!+pWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!,Y#h#o5p~!,_WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!,w#i#o5p~!,|WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!-f#^#o5p~!-kWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!.T#c#o5p~!.YWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W!.r#W#o5p~!.wWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!/a#i#o5p~!/hU$p~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!0PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!0i#j#o5p~!0nWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V!1W#V#o5p~!1]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!1u#a#o5p~!1zWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!2d#Y#o5p~!2kU!O~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!3SWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!3l#g#o5p~!3qVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U!4W#U#o5p~!4]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!4u#i#o5p~!4zWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!5d#^#o5p~!5iWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!6R#d#o5p~!6WWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!6p#c#o5p~!6wU!T~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!7^V}!O5p!Q![5p!c!}5p#R#S5p#T#b5p#b#c!7s#c#o5p~!7xYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X!8h#X#h5p#h#i!9R#i#o5p~!8oU%w~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!9WWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^!9p#^#o5p~!9uWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!:_#i#o5p~!:dWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n=j#n#o5p~!;P[}!O5p!Q![5p!c!}5p#R#S5p#T#U!;u#U#]5p#]#^!>Z#^#f5p#f#g!@o#g#i5p#i#j!Bf#j#o5p~!;zWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a!`WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!>x#g#o5pZ!>}WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!?g#h#o5pZ!?lWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!@U#i#o5pZ!@]U%ZPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!@tWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!A^#d#o5pZ!AcWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#a5p#a#b!A{#b#o5pZ!BSU%kPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~!BkWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c!CT#c#o5p~!C[U!b~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!CqV}!O5p!Q![5p!c!}5p#R#S5p#T#f5p#f#g!DW#g#o5pZ!D]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d!Du#d#o5pZ!DzWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!Ed#j#o5pZ!EiWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#d5p#d#e!FR#e#o5pZ!FWWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V!Fp#V#o5pZ!FuWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n!G_#n#o5pZ!GfU%TPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!G{U}!O5p!Q![5p!c!}5p#R#S5p#T#U!H_#U#o5pZ!HdWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!H|#h#o5pZ!ITU$OPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_!IjZ}!O5p!Q![5p!c!}5p#R#S5p#T#]5p#]#^!J]#^#b5p#b#c!Ke#c#g5p#g#h##p#h#o5pZ!JbWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X!Jz#X#o5pZ!KRU#{PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_!KlX#PSYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h!LX#h#i!Nm#i#o5pZ!L^WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y!Lv#Y#o5pZ!L{WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g!Me#g#o5pZ!MjWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i!NS#i#o5pZ!NZU$^RYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ!NrWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y# [#Y#o5pZ# aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Z5p#Z#[# y#[#o5pZ#!OWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#!h#Y#o5pZ#!mWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g##V#g#o5pZ##^U}RYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ##uVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#$[#U#o5pZ#$cU#oPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#$xY}!O5p!Q![5p!c!}5p#R#S5p#T#U#%h#U#X5p#X#Y#)[#Y#]5p#]#^#*d#^#o5pZ#%mYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V#&]#V#g5p#g#h#(S#h#o5pZ#&bWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#&z#Y#o5pZ#'PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a#'i#a#o5pZ#'pU#fPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#(XWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#(q#i#o5pZ#(xU%[PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#)aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#)y#i#o5p~#*QU!y~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#*i]YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#_5p#_#`#+b#`#a5p#a#b#,j#b#c#.a#c#g5p#g#h#0W#h#o5p~#+gWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#,P#Y#o5p~#,WU#x~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#,oWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#-X#^#o5p~#-^WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#-v#i#o5p~#-}U$t~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#.fWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#_5p#_#`#/O#`#o5pZ#/TWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#/m#h#o5pZ#/tU$QPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#0]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#0u#i#o5pZ#0|U%SPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#1cY}!O5p!Q![5p!c!}5p#R#S5p#T#U#2R#U#X5p#X#Y#5W#Y#]5p#]#^#9c#^#o5p~#2WYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#2v#i#l5p#l#m#4m#m#o5p~#2{WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W#3e#W#o5p~#3jWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#[5p#[#]#4S#]#o5p~#4ZU!t~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#4tU$|PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#5]XYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#5x#U#W5p#W#X#7Q#X#o5pZ#5}WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#6g#c#o5pZ#6nU%OPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#7VWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#7o#^#o5pZ#7tVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#8Z#U#o5pZ#8`WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#8x#c#o5pZ#9PU%PPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#9hWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#:Q#c#o5pZ#:XU$}PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#:nV}!O5p!Q![5p!c!}5p#R#S5p#T#c5p#c#d#;T#d#o5p~#;YWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#;r#i#o5p~#;yU$X~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p_#<`Z}!O5p!Q![5p!c!}5p#R#S5p#T#Y5p#Y#Z#=R#Z#f5p#f#g#@W#g#k5p#k#l#@q#l#o5p_#=YW$fSYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z#=r#Z#o5pZ#=wWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#>a#h#o5pZ#>fWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#?O#Y#o5pZ#?TWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#?m#i#o5pZ#?tU$rRYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#@_U$UPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ#@vWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#A`#c#o5pZ#AeWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#A}#h#o5pZ#BUU!WPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#BkX}!O5p!Q![5p!c!}5p#R#S5p#T#`5p#`#a#CW#a#i5p#i#j#Ei#j#o5pZ#C]VYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#Cr#U#o5pZ#CwWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#m5p#m#n#Da#n#o5pZ#DfWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h#EO#h#o5pZ#EVU!]PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#EnWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i#FW#i#o5p~#F_U$`~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#FtV}!O5p!Q![5p!c!}5p#R#S5p#T#X5p#X#Y#GZ#Y#o5p~#G`^YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X#H[#X#`5p#`#a#My#a#e5p#e#f$$]#f#h5p#h#i$'`#i#o5p~#HaYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#IP#Y#i5p#i#j#LS#j#o5pZ#IUWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z#In#Z#o5pZ#IsWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^#J]#^#o5pZ#JbWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c#Jz#c#o5pZ#KPWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#Ki#Y#o5pZ#KpU%qPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#LXWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W#Lq#W#o5p~#LvWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y#M`#Y#o5p~#MgU$x~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~#NOVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U#Ne#U#o5p~#NjWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$ S#i#o5p~$ XYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$ w#Y#]5p#]#^$#P#^#o5pZ$ |WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#g5p#g#h$!f#h#o5pZ$!mU!_PYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$#UWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#c5p#c#d$#n#d#o5p~$#sWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c=j#c#o5p~$$bWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$$z#j#o5p~$%PWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$%i#^#o5p~$%nWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$&W#g#o5p~$&]WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$&u#Y#o5p~$&|U$v~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$'eWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$'}#j#o5p~$(SWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$(l#g#o5p~$(qWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c$)Z#c#o5p~$)bU%V~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$)w[}!O5p!Q![5p!c!}5p#R#S5p#T#X5p#X#Y$*m#Y#c5p#c#d$-p#d#h5p#h#i$/g#i#j$5W#j#o5p~$*rWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a$+[#a#o5p~$+aWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$+y#Y#o5p~$,OWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W$,h#W#o5p~$,mWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$-V#i#o5p~$-^U$i~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$-uWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#f5p#f#g$._#g#o5p~$.dWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$.|#i#o5p~$/TU$l~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$/lYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X$0[#X#f5p#f#g$0u#g#o5pZ$0cU%QPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$0zYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$1j#^#i5p#i#j$3a#j#o5p~$1oWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#b5p#b#c$2X#c#o5p~$2^WYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Z5p#Z#[$2v#[#o5p~$2}U!U~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$3fWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#V5p#V#W$4O#W#o5p~$4TWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$4m#i#o5p~$4tU%_~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$5]YYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U5p#U#V$5{#V#a5p#a#b$6f#b#o5pZ$6SUxPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$6mU%RPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$7SV}!O5p!Q![5p!c!}5p#R#S5p#T#f5p#f#g$7i#g#o5p~$7nYYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j!=R#j#m5p#m#n$8^#n#o5p~$8eU$Z~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$8zX}!O5p!Q![5p!c!}5p#R#S5p#T#b5p#b#c$9g#c#d5p#d#e$=v#e#o5pZ$9lWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#W5p#W#X$:U#X#o5pZ$:ZWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$:s#Y#o5pZ$:xWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#Y5p#Y#Z$;b#Z#o5pZ$;gWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#]5p#]#^$e#X#o5p~$>jVYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#U$?P#U#o5p~$?UWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#h5p#h#i$?n#i#o5p~$?sWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$@]#Y#o5p~$@dU$b~YY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5pZ$@yU}!O5p!Q![5p!c!}5p#R#S5p#T#U$A]#U#o5pZ$AbWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#`5p#`#a$Az#a#o5pZ$BPWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#i5p#i#j$Bi#j#o5pZ$BnWYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#X5p#X#Y$CW#Y#o5pZ$C_UzPYY}!O5p!Q![5p![!]6X!c!}5p#R#S5p#T#o5p~$CvO!n~~$C{O!o~", - tokenizers: [0, 1, 2, 3], - topRules: {"Query":[0,1]}, - tokenPrec: 2502 -}); - -// TODO: We could do better by climbing up the tree using `atNode.parentNode` to predict based on position as well. -// We could also refine the suggestions by creating datastructures based on the declarations in the schema, rather than blindly suggesting every label. -function suggestLabel(label) { - return { - label: label, - type: "label", - apply: label, - info: "label suggestion", - }; -} -function suggestVariable(varName) { - return { - label: varName, - type: "variable", - apply: varName, - info: "variable suggestion", - }; -} -function collectLabelSuggestions(context, tree, atNode) { - // This is a placeholder function. You will need to implement the logic to collect label suggestions. - // For now, we return an empty array. - var options = []; - tree.iterate({ - enter: (other) => { - if (other.name == "LABEL") { - let content = context.state.sliceDoc(other.from, other.to); - options.push(suggestLabel(content)); - } - } - }); - return options; -} -function collectVariableSuggestions(context, tree, atNode) { - var options = []; - tree.iterate({ - enter: (other) => { - if (other.name == "VAR") { - let content = context.state.sliceDoc(other.from, other.to); - options.push(suggestVariable(content)); - } - } - }); - return options; -} -// See: https://codemirror.net/examples/autocompletion/ and maybe the SQL / HTML Example there. -function autocompleteTypeQL(context) { - let tree = syntaxTree(context.state); - let currentNode = tree.resolveInner(context.pos, -1); // https://lezer.codemirror.net/docs/ref/#common.SyntaxNode - // We may have to walk the tree to find the most appropriate node to suggest things based on. - let options = null; - if (currentNode.name == "LABEL") { - options = collectLabelSuggestions(context, tree); - } - else if (currentNode.name == "VAR") { - options = collectVariableSuggestions(context, tree); - } - else ; - if (options != null) { - // And once we figure out, we have to create a list of completion objects - // It may be worth changing the grammar to be able to do this more easily, rather than replicate the original TypeQL grammar. - // https://codemirror.net/docs/ref/#autocomplete.Completion - return { - from: currentNode.from, - options: options, - // Docs: "regular expression that tells the extension that, as long as the updated input (the range between the result's from property and the completion point) matches that value, it can continue to use the list of completions." - validFor: /^(\w+)?$/ - }; - } - else { - return null; - } -} - -const TypeQLLanguage = LRLanguage.define({ - parser: parser.configure({ - props: [ - indentNodeProp.add({}), - foldNodeProp.add({ - QueryStage: foldInside - }), - styleTags({ - // See: https://lezer.codemirror.net/docs/ref/#highlight.tags - VAR: tags.variableName, - // Literals - STRINGLITERAL: tags.string, - INTEGERLITERAL: tags.number, - DOUBLELITERAL: tags.number, - BOOLEANLITERAL: tags.bool, - // Types - LABEL: tags.typeName, - BOOLEAN: tags.typeName, - INTEGER: tags.typeName, - DOUBLE: tags.typeName, - DECIMAL: tags.typeName, - DATETIMETZ: tags.typeName, - DATETIME: tags.typeName, - DATE: tags.typeName, - DURATION: tags.typeName, - STRING: tags.typeName, - // Keywords - ISA: tags.keyword, - HAS: tags.keyword, - LINKS: tags.keyword, - OWNS: tags.keyword, - RELATES: tags.keyword, - PLAYS: tags.keyword, - FUN: tags.keyword, - LET: tags.keyword, - FIRST: tags.keyword, - LAST: tags.keyword, - // Value type names? - // Stages - DEFINE: tags.heading1, - UNDEFINE: tags.heading1, - REDEFINE: tags.heading1, - MATCH: tags.heading1, - INSERT: tags.heading1, - DELETE: tags.heading1, - UPDATE: tags.heading1, - PUT: tags.heading1, - END: tags.heading1, - SELECT: tags.heading1, - REDUCE: tags.heading1, - SORT: tags.heading1, - OFFSET: tags.heading1, - LIMIT: tags.heading1, - REQUIRE: tags.heading1, - DISTINCT: tags.heading1, - GROUPBY: tags.heading1, - // SubPattern - OR: tags.controlOperator, - NOT: tags.controlOperator, - TRY: tags.controlOperator, - // Misc - Annotation: tags.meta, - LINECOMMENT: tags.lineComment, - }) - ] - }), - languageData: { - commentTokens: { line: "#" } - } -}); -function TypeQL() { - return new LanguageSupport(TypeQLLanguage, [ - TypeQLLanguage.data.of({ - autocomplete: autocompleteTypeQL - }), - ]); -} -// A Linter which flags syntax errors from: https://discuss.codemirror.net/t/showing-syntax-errors/3111/6 -function otherExampleLinter() { - return linter((view) => { - const diagnostics = []; - syntaxTree(view.state).iterate({ - enter: n => { - if (n.type.isError) { - diagnostics.push({ - from: n.from, - to: n.to, - severity: "error", - message: "Syntax error.", - }); - } - }, - }); - return diagnostics; - }); -} - -export { TypeQL, TypeQLLanguage, otherExampleLinter }; diff --git a/src/framework/codemirror-lang-typeql/index.ts b/src/framework/codemirror-lang-typeql/index.ts new file mode 100644 index 000000000..bf8d31da6 --- /dev/null +++ b/src/framework/codemirror-lang-typeql/index.ts @@ -0,0 +1,143 @@ + +import { parser } from "./generated/typeql.grammar.generated" +import { LRLanguage, LanguageSupport, indentNodeProp, foldNodeProp, foldInside, syntaxTree } from "@codemirror/language" +import { styleTags, tags as t } from "@lezer/highlight" +import { Diagnostic } from "@codemirror/lint"; +import { EditorView } from "@codemirror/view"; +import { linter } from '@codemirror/lint' +import { autocompletion, CompletionContext } from "@codemirror/autocomplete"; +import { NodePrefixAutoComplete } from "./complete" +import {TypeQLAutocompleteSchema} from "./typeQLAutocompleteSchema"; +import { SUGGESTION_MAP } from "./typeql_suggestions"; +import {Schema} from "../../service/schema-state.service"; + +export const TypeQLLanguage = LRLanguage.define({ + parser: parser.configure({ + props: [ + indentNodeProp.add({ + + }), + foldNodeProp.add({ + QueryStage: foldInside + }), + styleTags({ + // See: https://lezer.codemirror.net/docs/ref/#highlight.tags + + VAR: t.variableName, + + // Literals + STRINGLITERAL: t.string, + INTEGERLITERAL: t.number, + DOUBLELITERAL: t.number, + BOOLEANLITERAL: t.bool, + + // Types + LABEL: t.typeName, + + BOOLEAN: t.typeName, + INTEGER: t.typeName, + DOUBLE: t.typeName, + DECIMAL: t.typeName, + DATETIMETZ: t.typeName, + DATETIME: t.typeName, + DATE: t.typeName, + DURATION: t.typeName, + STRING: t.typeName, + + + // Keywords + ISA: t.keyword, + HAS: t.keyword, + LINKS: t.keyword, + OWNS: t.keyword, + RELATES: t.keyword, + PLAYS: t.keyword, + + FUN: t.keyword, + LET: t.keyword, + FIRST: t.keyword, + LAST: t.keyword, + + // Value type names? + + // Stages + DEFINE: t.heading1, + UNDEFINE: t.heading1, + REDEFINE: t.heading1, + + MATCH: t.heading1, + INSERT: t.heading1, + DELETE: t.heading1, + UPDATE: t.heading1, + PUT: t.heading1, + END: t.heading1, + + SELECT: t.heading1, + REDUCE: t.heading1, + SORT: t.heading1, + OFFSET: t.heading1, + LIMIT: t.heading1, + REQUIRE: t.heading1, + DISTINCT: t.heading1, + GROUPBY: t.heading1, + + // SubPattern + OR: t.controlOperator, + NOT: t.controlOperator, + TRY: t.controlOperator, + + // Misc + Annotation: t.meta, + LINECOMMENT: t.lineComment, + }) + ] + }), + languageData: { + commentTokens: { line: "#" } + } +}) + + +export function TypeQL() { + return new LanguageSupport(TypeQLLanguage, []) +} + +// A Linter which flags syntax errors from: https://discuss.codemirror.net/t/showing-syntax-errors/3111/6 +export function otherExampleLinter() { + return linter((view: EditorView) => { + const diagnostics: Diagnostic[] = []; + syntaxTree(view.state).iterate({ + enter: n => { + if (n.type.isError) { + diagnostics.push({ + from: n.from, + to: n.to, + severity: "error", + message: "Syntax error.", + }); + } + }, + }); + return diagnostics; + }); +} + +// Autocomplete +let typeqlAutocomplete = new NodePrefixAutoComplete( + SUGGESTION_MAP, + new TypeQLAutocompleteSchema({entities: {}, relations: {}, attributes: {}}, {entities: {}, relations: {}, attributes: {}}) +); + +function wrappedAutocomplete(context: CompletionContext) { + return typeqlAutocomplete.autocomplete(context); +} +export function typeqlAutocompleteExtension() { + return autocompletion({ override: [wrappedAutocomplete] }); +} + +export function updateAutocomleteSchemaFromDB(schema: Schema) { + typeqlAutocomplete.getState().updateFromDB(schema); +} + +// (window as any)._updateSchemaFromDB = updateSchemaFromDB; +(window as any)._typeqlAutoComplete = typeqlAutocomplete; diff --git a/src/framework/codemirror-lang-typeql/navigation.ts b/src/framework/codemirror-lang-typeql/navigation.ts new file mode 100644 index 000000000..f723fd6dd --- /dev/null +++ b/src/framework/codemirror-lang-typeql/navigation.ts @@ -0,0 +1,24 @@ +import {SyntaxNode} from "@lezer/common"; + +// path should be token ids +type TokenID = number; +export function nodesWithPath(root: SyntaxNode, path: TokenID[]) : SyntaxNode[] { + return nodesWithPathImpl([root], path, 0); +} + +function nodesWithPathImpl(from: SyntaxNode[], path: TokenID[], index: number) : SyntaxNode[] { + if (index >= path.length) { + return from; + } else { + let next = from.flatMap((node) => node.getChildren(path[index])); + return nodesWithPathImpl(next, path, index + 1) + } +} + +export function climbTill(from: SyntaxNode, till: TokenID): SyntaxNode | null { + let at: SyntaxNode | null = from; + while (at != null && at.type.id != till) { + at = at.parent; + } + return at; +} diff --git a/src/framework/codemirror-lang-typeql/typeQLAutocompleteSchema.ts b/src/framework/codemirror-lang-typeql/typeQLAutocompleteSchema.ts new file mode 100644 index 000000000..0db4eba84 --- /dev/null +++ b/src/framework/codemirror-lang-typeql/typeQLAutocompleteSchema.ts @@ -0,0 +1,213 @@ +import { Tree } from "@lezer/common"; +import { CompletionContext } from "@codemirror/autocomplete"; +import * as tokens from "./generated/typeql.grammar.generated.terms"; +import {nodesWithPath} from "./navigation"; +import { + Schema, + SchemaAttribute, + SchemaRole, + SchemaEntity, + SchemaRelation +} from "../../service/schema-state.service"; +type SchemaObject = SchemaEntity | SchemaRelation; + +type TypeLabel = string; + +function extractText(text: string, from: number, to: number): string { + return text.slice(from, to); +} + +export class TypeQLAutocompleteSchema { + fromDB: Schema; + fromEditor: Schema; // Partial because we don't care about subtypes, supertype or valueType + + constructor(fromDB: Schema, fromEditor: Schema) { + this.fromDB = fromDB; + this.fromEditor = fromEditor; + } + + updateFromDB(fromDB: Schema): void { + this.fromDB = fromDB; + } + + mayUpdateFromEditorState(context: CompletionContext, tree: Tree): void { + this.fromEditor = buildSchemafromTypeQL(context.state.sliceDoc(), tree); + } + + attributeTypes(): SchemaAttribute[] { + return record_values(this.fromDB.attributes).concat(record_values(this.fromEditor.attributes)); + } + + objectTypes(): SchemaObject[] { + return (this.entityTypes() as SchemaObject[]).concat(this.relationTypes() as SchemaObject[]); + } + + entityTypes(): SchemaEntity[] { + return record_values(this.fromDB.entities) + .concat(record_values(this.fromEditor.entities)); + } + + relationTypes(): SchemaRelation[] { + return record_values(this.fromDB.relations).concat(record_values(this.fromEditor.relations)); + } + + attributeType(type: TypeLabel): SchemaAttribute { + return this.fromDB.attributes[type] ?? + this.fromEditor.attributes[type]; + } + + objectType(type: TypeLabel): SchemaObject | null { + return this.entityType(type) ?? this.relationType(type); + } + + entityType(type: TypeLabel): SchemaEntity | null { + return this.fromDB.entities[type] ?? this.fromEditor.entities[type]; + } + + relationType(type: TypeLabel): SchemaRelation { + return this.fromDB.relations[type] ?? this.fromEditor.relations[type]; + } + + getOwns(label: TypeLabel): SchemaAttribute[] { + const objectType = this.objectType(label); + return objectType ? objectType.ownedAttributes : []; + } + + getPlays(label: TypeLabel): SchemaRole[] { + const objectType = this.objectType(label); + return objectType ? objectType.playedRoles : []; + } + getRelates(label: TypeLabel): SchemaRole[] { + const objectType = this.objectType(label); + return objectType ? objectType.playedRoles : []; + } +} + +export class SchemaBuilder { + schema: Schema; + constructor() { + this.schema = { entities: {}, relations:{}, attributes: {} }; + } + + entityType(label: TypeLabel): SchemaEntity { + if (!this.schema.entities[label]) { + this.schema.entities[label] = { + kind: "entityType", label, ownedAttributes: [], playedRoles: [], + subtypes: [], + }; + } + return this.schema.entities[label]; + } + + relationType(label: TypeLabel): SchemaRelation { + if (!this.schema.relations[label]) { + this.schema.relations[label] = { + kind: "relationType", label, ownedAttributes: [], playedRoles: [], relatedRoles: [], + subtypes: [], + }; + } + return this.schema.relations[label]; + } + + attributeType(label: TypeLabel): SchemaAttribute { + if (!this.schema.attributes[label]) { + this.schema.attributes[label] = { + kind: "attributeType", label, valueType: "string", + subtypes: [], + }; + } + return this.schema.attributes[label]; + } + + getObjectType(label: TypeLabel): SchemaObject | null{ + return this.schema.entities[label] ?? this.schema.relations[label]; + } + + recordOwns(type: TypeLabel, ownedType: TypeLabel): void { + const objectType = this.getObjectType(type)!; + const attributeType = this.attributeType(ownedType); + if (!objectType.ownedAttributes.includes(attributeType)) { + objectType.ownedAttributes.push(attributeType); + } + } + recordPlays(type: TypeLabel, playedType: TypeLabel): void { + const objectType = this.getObjectType(type)!; + let roleType: SchemaRole = { kind: "roleType", label: playedType }; + if (!objectType.playedRoles.includes(roleType)) { + objectType.playedRoles.push(roleType); + } + } + + recordRelates(type: TypeLabel, relatedType: TypeLabel): void { + const objectType = this.relationType(type); + let roleType: SchemaRole = { kind: "roleType", label: relatedType }; + if (!objectType.relatedRoles.includes(roleType)) { + objectType.relatedRoles.push(roleType); + } + } + + build(): Schema { + return this.schema; + } +} + + + +function buildSchemafromTypeQL(text: string, tree: Tree) : Schema { + let builder = new SchemaBuilder(); + // Extract all type declarations from the tree + let root = tree.topNode; + let definitionTypes = nodesWithPath(root, [tokens.QuerySchema, tokens.QueryDefine, tokens.Definables, tokens.Definable, tokens.DefinitionType]) + definitionTypes.forEach(node => { + let kindNode = node.getChild(tokens.KIND); + let labelNode = node.getChild(tokens.LABEL); + if (kindNode != null && labelNode != null) { + let kind = extractText(text, kindNode.from, kindNode.to); + let label = extractText(text, labelNode.from, labelNode.to); + switch (kind) { + case "entity": { + builder.entityType(label); + break; + } + case "relation": { + builder.relationType(label); + break; + } + case "attribute": { + builder.attributeType(label); + break; + } + } + } + }) + + + // Extract owns/relates/plays. Idk what to do with sub or annotations. + definitionTypes.forEach(node => { + let labelNode = node.getChild(tokens.LABEL); + if (labelNode == null) return; + let label = extractText(text, labelNode.from, labelNode.to); + nodesWithPath(node, [tokens.TypeCapability, tokens.TypeCapabilityBase]) + .map(typeCapabilityBaseNode => typeCapabilityBaseNode.firstChild) + .forEach(actualCapabilityNode => { + switch (actualCapabilityNode?.type.id) { + // We actually only want type-declarations for now. + case tokens.RelatesDeclaration: { + let roleTypeNode = actualCapabilityNode.firstChild!.nextSibling!; + let roleType = extractText(text, roleTypeNode.from, roleTypeNode.to); + builder.recordRelates(label, `${label}:${roleType}`); + break; + } + default: { + // Ignore other capabilities for now + break; + } + } + }); + }); + return builder.build(); +} + +function record_values(records: Record): Y[] { + return Object.entries(records).map(([_, value]) => value); +} diff --git a/src/framework/codemirror-lang-typeql/typeql.grammar b/src/framework/codemirror-lang-typeql/typeql.grammar new file mode 100644 index 000000000..3dc8c9a83 --- /dev/null +++ b/src/framework/codemirror-lang-typeql/typeql.grammar @@ -0,0 +1,778 @@ +// TypeQL grammar for lezer. run `pnpm run generate-grammar` to generate the parser and propagate these changes to typescript. + +// TODO: This is a direct translation of the original pest grammar (which is PEG iirc) +// It may be better to rewrite as much as possible so that it's better suited to the LR parser. +@top Query { QuerySchema | QueryPipelinePreambled (END SEMICOLON)? } +@skip { whitespace | linecomment } + +// Schema +QuerySchema { + QueryDefine | + QueryUndefine | + QueryRedefine +} + +QueryDefine { + DEFINE Definables +} + +QueryUndefine { + UNDEFINE Undefinables +} + +QueryRedefine { + REDEFINE Redefinables +} + +Definables { + (Definable SEMICOLON)+ +} + +Definable { + DefinitionType | + DefinitionFunction | + DefinitionStruct +} + +Undefinables { + (Undefinable SEMICOLON)+ +} + +Undefinable { + UndefineFrom | + // UndefineFunction | + UndefineStruct | + KIND LABEL +} + +Redefinables { + (Redefinable SEMICOLON)+ +} + +Redefinable { + RedefinableType | DefinitionFunction +} + +RedefinableType { + KIND? LABEL ((Annotations | TypeCapability) (COMMA TypeCapability)* COMMA?)? +} + +DefinitionType { + KIND? LABEL COMMA? ((Annotations | TypeCapability) (COMMA TypeCapability)* COMMA?)? +} + +TypeCapability { + TypeCapabilityBase Annotations? +} + +TypeCapabilityBase { + SubDeclaration | + ValueTypeDeclaration | + // AliasDeclaration | + OwnsDeclaration | + PlaysDeclaration | + RelatesDeclaration +} + +SubDeclaration { + SUB LABEL +} + +ValueTypeDeclaration { + VALUEKEYWORD ValueType +} + +// AliasDeclaration { +// ALIAS LABEL +// } + +OwnsDeclaration { + OWNS LABEL | + OWNS LabelList +} + +PlaysDeclaration { + PLAYS LABEL // | PLAYS LabelScoped +} + +RelatesDeclaration { + RELATES LABEL (AS LABEL)? | + RELATES LabelList (AS LabelList)? +} + + +DefinitionStruct { + STRUCT IDENTIFIER COLON DefinitionStructFields +} + +DefinitionStructFields { + DefinitionStructField (COMMA DefinitionStructField)* COMMA? +} + +DefinitionStructField { + IDENTIFIER VALUEKEYWORD StructFieldValueType +} + +StructFieldValueType { + ValueTypeOptional | ValueType +} + +ValueTypeOptional { + ValueType QUESTIONMARK +} + + +UndefineFrom { + UndefineAnnotationFromCapability | + UndefineAnnotationFromType | + UndefineCapability | + UndefineSpecialise +} + +UndefineAnnotationFromCapability { + AnnotationCategory FROM LABEL TypeCapabilityBase +} + +UndefineAnnotationFromType { + AnnotationCategory FROM LABEL +} + +UndefineCapability { + TypeCapabilityBase FROM LABEL +} + +UndefineSpecialise { + AS LABEL FROM LABEL RelatesDeclaration +} + +// UndefineFunction { +// FUN IDENTIFIER +// } + +UndefineStruct { + STRUCT IDENTIFIER +} + +LabelList { LABEL SQBRACKETOPEN SQBRACKETCLOSE } +NamedTypeAny { NamedTypeList | NamedType } +NamedTypeList { NamedType SQBRACKETOPEN SQBRACKETCLOSE } +NamedType { LABEL | ValueType } + +// Annotations +AnnotationCategory { + ANNOTATION_ABSTRACT + | ANNOTATION_CARD + | ANNOTATION_CASCADE + | ANNOTATION_DISTINCT + | ANNOTATION_INDEPENDENT + | ANNOTATION_KEY + | ANNOTATION_RANGE + | ANNOTATION_REGEX + | ANNOTATION_SUBKEY + | ANNOTATION_UNIQUE + | ANNOTATION_VALUES +} + + +Annotations { + Annotation+ +} + +Annotation { + ANNOTATION_ABSTRACT | + ANNOTATION_CASCADE | + ANNOTATION_DISTINCT | + ANNOTATION_INDEPENDENT | + ANNOTATION_KEY | + ANNOTATION_UNIQUE | + ANNOTATION_CARD PARENOPEN Cardinality PARENCLOSE | + ANNOTATION_RANGE PARENOPEN Range PARENCLOSE | + ANNOTATION_REGEX PARENOPEN STRINGLITERAL PARENCLOSE | + ANNOTATION_SUBKEY PARENOPEN IDENTIFIER PARENCLOSE | + ANNOTATION_VALUES PARENOPEN ValueLiteral (COMMA ValueLiteral)* COMMA? PARENCLOSE +} + +Cardinality { + INTEGERLITERAL DOUBLE_DOT INTEGERLITERAL? | + INTEGERLITERAL +} + +Range { + RangeBound DOUBLE_DOT RangeBound | + RangeBound DOUBLE_DOT | + DOUBLE_DOT RangeBound +} + +RangeBound { + ValueLiteral +} + + +// Pipelines +QueryPipelinePreambled { + Pipeline +// Preamble* Pipeline +} + +//Pipeline { +// QueryStage+ QueryStageTerminal? +//} + + +//Preamble { +// WITH DefinitionFunction +//} + +Pipeline { + QueryStage+ +} +QueryStage { + ClauseMatch | + ClauseInsert | + ClausePut | + ClauseUpdate | + ClauseDelete | + OperatorStream +} + +//QueryStageTerminal { +// ClauseFetch SEMICOLON +//} + + +// +// Stages +ClauseMatch { + MATCH Patterns +} + + +ClauseInsert { + INSERT (StatementThing SEMICOLON)+ +// INSERT (StatementThing SEMICOLON | StatementAssignment SEMICOLON)+ +} + +ClausePut { + PUT (StatementThing SEMICOLON)+ +} + +ClauseUpdate { + UPDATE (StatementThing SEMICOLON)+ +} + +ClauseDelete { + DELETE (StatementDeletable SEMICOLON)+ +} + +OperatorStream { + OperatorSelect | + OperatorSort | + OperatorDistinct | + OperatorOffset | + OperatorLimit | + OperatorRequire | + OperatorReduce +} + +OperatorSelect { + SELECT Vars SEMICOLON +} + +OperatorSort { + SORT VAROrder (COMMA VAROrder)* SEMICOLON +} + +OperatorOffset { + OFFSET INTEGERLITERAL SEMICOLON +} + +OperatorLimit { + LIMIT INTEGERLITERAL SEMICOLON +} + +OperatorRequire { + REQUIRE Vars SEMICOLON +} + +OperatorDistinct { + DISTINCT SEMICOLON +} + +OperatorReduce { + REDUCE ReduceAssign (COMMA ReduceAssign)* (GROUPBY Vars)? SEMICOLON +} + +// Stage arguments +Vars { + VAR (COMMA VAR)* COMMA? +} + +VAROrder { + VAR ORDER? +} + +ReduceAssign { + (VAR ASSIGN Reducer) +} + +Reducer { + COUNT (PARENOPEN VAR PARENCLOSE)? | + MAX PARENOPEN VAR PARENCLOSE | + MIN PARENOPEN VAR PARENCLOSE | + MEAN PARENOPEN VAR PARENCLOSE | + MEDIAN PARENOPEN VAR PARENCLOSE | + STD PARENOPEN VAR PARENCLOSE | + SUM PARENOPEN VAR PARENCLOSE | + LIST PARENOPEN VAR PARENCLOSE +} + +// Patterns +Patterns { + (Pattern SEMICOLON)+ +} + +Pattern { + Statement | + PatternDisjunction | + PatternConjunction | + PatternNegation | + PatternTry +} + +PatternConjunction { + CURLYOPEN Patterns CURLYCLOSE +} + +PatternDisjunction { + CURLYOPEN Patterns CURLYCLOSE (OR CURLYOPEN Patterns CURLYCLOSE)+ +} + +PatternNegation { + NOT CURLYOPEN Patterns CURLYCLOSE +} + +PatternTry { + TRY CURLYOPEN Patterns CURLYCLOSE +} + +StatementDeletable { + HAS? VAR OF VAR | + LINKS? Relation OF VAR | + VAR +} + +StatementType { + KIND? TypeRef (TypeConstraint (COMMA TypeConstraint)* COMMA?)? +} + +TypeConstraint { + TypeConstraintBase Annotations? +} + +TypeConstraintBase { + SubConstraint | + ValueTypeConstraint | + LabelConstraint | + OwnsConstraint | + RelatesConstraint | + PlaysConstraint +} + +SubConstraint { + SUB TypeRef +} + +ValueTypeConstraint { + VALUEKEYWORD ValueType +} + +LabelConstraint { + LABELKEYWORD LABEL // (LabelScoped | LABEL) +} + + +OwnsConstraint { + OWNS TypeRef | + OWNS TypeRefList +} + +RelatesConstraint { + RELATES TypeRef (AS TypeRef)? | + RELATES TypeRefList (AS TypeRefList)? +} + +PlaysConstraint { + PLAYS TypeRef +} + +Statement { + StatementAssignment | + // StatementSingle | + StatementType | + StatementThing +} + + +StatementThing { + VAR COMMA? ThingConstraintList + // ThingRelationAnonymous (COMMA? ThingConstraintList)? +} + +// ThingRelationAnonymous { +// TypeRef? Relation +// } + +ThingConstraintList { + ThingConstraint (COMMA ThingConstraint)* COMMA? +} + +ThingConstraint { + IsaConstraint | + IidConstraint | + HasConstraint | + LinksConstraint +} + +IsaConstraint { + ISA TypeRef (Expression | Comparison)? // | ExpressionStruct // | ValueLiteral is subsumed by Expression // | Relation is ambiguous with paranthesis expressions +} + +IidConstraint { + IID IID_VALUE +} + +HasConstraint { + HAS TypeRef VAR | + HAS TypeRef ValueLiteral | + HAS VAR +} + +LinksConstraint { + LINKS Relation +} + +Relation { + PARENOPEN RolePlayer (COMMA RolePlayer)* COMMA? PARENCLOSE +} + +RolePlayer { + TypeRefList COLON VAR | + TypeRef COLON VAR | + VAR +} + +TypeRefList { + TypeRef SQBRACKETOPEN SQBRACKETCLOSE +} + +TypeRef { + // LabelScoped | + LABEL | + VAR +} + +// LabelScoped { +// LABEL COLON LABEL +// } + + +ValueLiteral { + BOOLEANLITERAL | + STRINGLITERAL | + INTEGERLITERAL | + DOUBLELITERAL + // TODO +} + +ValueType { + BOOLEAN | + INTEGER | + DOUBLE | + DECIMAL | + DATETIMETZ | + DATETIME | + DATE | + DURATION | + STRING +} + +Comparison { + ComparisonOperator Expression +} + +ComparisonOperator { + EQUAL | NOT_EQUAL | GREATER | GREATER_EQUAL | LESS | LESS_EQUAL | LIKE | CONTAINS +} + +// Function +IDENTIFIER { LABEL } // hack + +DefinitionFunction { + FUN FunctionSignature COLON FunctionBlock +} + +FunctionSignature { + IDENTIFIER PARENOPEN FunctionArguments? PARENCLOSE ARROW FunctionOutput +} + + +FunctionArguments { + FunctionArgument (COMMA FunctionArgument)* COMMA? +} + +FunctionArgument { + VAR COLON NamedTypeAny +} + +FunctionOutput { + FunctionOutputStream | + FunctionOutputSingle +} + +FunctionOutputStream { + CURLYOPEN NamedTypeAny (COMMA NamedTypeAny)* COMMA? CURLYCLOSE +} + +FunctionOutputSingle { + NamedTypeAny (COMMA NamedTypeAny)* COMMA? +} + +FunctionBlock { + QueryStage+ ReturnStatement +} + +ReturnStatement { + RETURN (ReturnStream | ReturnSingle | ReturnReduce) +} + +ReturnStream { + CURLYOPEN Vars CURLYCLOSE +} + +ReturnSingle { + ReturnSingleSelector Vars +} + +ReturnSingleSelector { + FIRST | LAST +} + +ReturnReduce { + Reducer (COMMA Reducer)* COMMA? +} + +// Assignment +StatementAssignment { + LET AssignmentLeft (ASSIGN | IN) Expression +} + +AssignmentLeft { + VarsAssignment // | StructDestructor +} + +VarsAssignment { + VarAssignment (COMMA VarAssignment)* COMMA? +} + +VarAssignment { + VAR QUESTIONMARK? +} + +// StructDestructor { +// CURLYOPEN StructKey COLON StructDestructorValue CURLYCLOSE +// } + +// // StructDestructorValue { +// // VAR | StructDestructor +// // } + +// Expression +Expression { + ExpressionValue (ExpressionOperator ExpressionValue)* +} + +ExpressionValue { + // ExpressionListIndex | + ExpressionParenthesis | + FunctionCall | + ValueLiteral | + VAR +} + +FunctionCall { + FunctionName PARENOPEN FunctionCallArguments? PARENCLOSE +} + +FunctionName { + IDENTIFIER +} + +FunctionCallArguments { + Expression (COMMA Expression)* COMMA? +} +ExpressionOperator { + POWER | TIMES | DIVIDE | MODULO | PLUS | MINUS +} + +ExpressionParenthesis { + PARENOPEN Expression PARENCLOSE +} + +// ExpressionListIndex { +// VAR SQBRACKETOPEN Expression SQBRACKETCLOSE +// } + + +@tokens { + VAR { DOLLAR $[a-zA-Z_\-0-9]+ } + // IDENTIFIER { $[a-zA-Z_\-0-9]+ } // Consider splitting this into Label and LabelScoped + LABEL { $[a-zA-Z] $[a-zA-Z_\-0-9]+ (':' $[a-zA-Z_\-0-9]+)? } // Consider splitting this into Label and LabelScoped + DOLLAR { "$" } + + DISTINCT { "distinct" } + // + DEFINE { "define" } + UNDEFINE { "undefine" } + REDEFINE { "redefine" } + + ANNOTATION_ABSTRACT { "@abstract" } + ANNOTATION_CASCADE { "@cascade" } + ANNOTATION_DISTINCT { "@distinct" } + ANNOTATION_INDEPENDENT { "@independent" } + ANNOTATION_KEY { "@key" } + ANNOTATION_UNIQUE { "@unique" } + ANNOTATION_CARD { "@card" } + ANNOTATION_RANGE { "@range" } + ANNOTATION_REGEX { "@regex" } + ANNOTATION_SUBKEY { "@subkey" } + ANNOTATION_VALUES { "@values" } + + + // WITH { "with" } + MATCH { "match" } + INSERT { "insert" } + PUT { "put" } + UPDATE { "update" } + DELETE { "delete" } + SELECT { "select" } + SORT { "sort" } + OFFSET { "offset" } + LIMIT { "limit" } + REQUIRE { "require" } + // DISTINCT is already covered + REDUCE { "reduce" } + GROUPBY { "groupby" } + + END { "end" } + + COUNT { "count" } + MAX { "max" } + MIN { "min" } + MEAN { "mean" } + MEDIAN { "median" } + STD { "std" } + SUM { "sum" } + LIST { "list" } + ORDER { ASCENDINGORDER | DESCENDINGORDER } + ASCENDINGORDER { "asc" } + DESCENDINGORDER { "desc" } + + + // Patterns + OR { "or" } + NOT { "not" } + TRY { "try" } + + // Statements + HAS { "has" } + ISA { "isa" } + LINKS { "links" } + IID { "iid" } + + SUB { "sub" } + VALUEKEYWORD { "value" } + LABELKEYWORD { "label" } + OWNS { "owns" } + RELATES { "relates" } + PLAYS { "plays" } + + KIND { "entity" | "relation" | "attribute" } + + OF { "of" } + AS { "as" } + FROM { "from" } + + // ValueTypes + BOOLEAN { "boolean" } + INTEGER { "integer" } + DOUBLE { "double" } + DECIMAL { "decimal" } + DATETIMETZ { "datetime-tz" } + DATETIME { "datetime" } + DATE { "date" } + DURATION { "duration" } + STRING { "string" } + + // Functions & structs + FUN { "fun" } + ARROW { "->" } + STRUCT { "struct" } + RETURN { "return" } + + FIRST { "first" } + LAST { "last" } + + // Punctuation + SEMICOLON { ";" } + COMMA { "," } + COLON { ":" } + PARENOPEN { "(" } + PARENCLOSE { ")" } + CURLYOPEN { "{" } + CURLYCLOSE { "}" } + SQBRACKETOPEN { "[" } + SQBRACKETCLOSE { "]" } + DOUBLE_DOT { ".." } + QUESTIONMARK { "?" } + + // Expression operators + LET { "let" } + ASSIGN { "=" } + IN { "in" } + POWER { "^" } + TIMES { "*" } + DIVIDE { "/" } + MODULO { "%" } + PLUS { "+" } + MINUS { "-" } + + // Comparison operators + EQUAL { "==" } + NOT_EQUAL { "!=" } + GREATER { ">" } + GREATER_EQUAL { ">=" } + LESS { "<" } + LESS_EQUAL { "<=" } + LIKE { "like" } + CONTAINS { "contains" } + + //@precedence { ASCENDINGORDER, DESCENDINGORDER } + @precedence { + END, KIND, STRUCT, LET, FUN, RETURN, + BOOLEAN, INTEGER, STRING, DURATION, DOUBLE, DECIMAL, DATETIME, DATETIMETZ, DATE, + BOOLEANLITERAL, LIKE, CONTAINS, + NOT, TRY, DELETE, DISTINCT, MATCH, INSERT, PUT, UPDATE, SELECT, SORT, OFFSET, LIMIT, REQUIRE, REDUCE, + LABEL } // This causes some weird parses sometimes. + + // Literals + IID_VALUE { "0x" $[0-9a-fA-F]+ } + + BOOLEANLITERAL { "false" | "true" } + STRINGLITERAL { '"' (!["\\] | "\\" _)* '"' } + INTEGERLITERAL { "-"? $[0-9]+ } + DOUBLELITERAL { "-"? $[0-9]+('.' $[0-9]+)? } + @precedence { DOUBLELITERAL, INTEGERLITERAL } + + linecomment { "#" ![\n]* } + whitespace { $[ \t\n\r]+ } +} diff --git a/src/framework/codemirror-lang-typeql/typeql.grammar.d.ts b/src/framework/codemirror-lang-typeql/typeql.grammar.d.ts new file mode 100644 index 000000000..38f49b476 --- /dev/null +++ b/src/framework/codemirror-lang-typeql/typeql.grammar.d.ts @@ -0,0 +1,3 @@ +import {LRParser} from "@lezer/lr" + +export declare const parser: LRParser diff --git a/src/framework/codemirror-lang-typeql/typeql_suggestions.ts b/src/framework/codemirror-lang-typeql/typeql_suggestions.ts new file mode 100644 index 000000000..021d4ffd6 --- /dev/null +++ b/src/framework/codemirror-lang-typeql/typeql_suggestions.ts @@ -0,0 +1,184 @@ +import * as tokens from "./generated/typeql.grammar.generated.terms"; +import { CompletionContext, Completion } from "@codemirror/autocomplete"; +import {SyntaxNode, NodeType, Tree} from "@lezer/common" +import { SuggestionMap, SuffixOfPrefixSuggestion, suggest } from "./complete"; +import { TypeQLAutocompleteSchema } from "./typeQLAutocompleteSchema"; +import {climbTill, nodesWithPath} from "./navigation"; + +function findIsaConstraintLabelsForVar(context: CompletionContext, parseAt: SyntaxNode): string[] { + let parentStatementThing = climbTill(parseAt, tokens.StatementThing)!; + let varNode = parentStatementThing.getChild(tokens.VAR)!; + let varName = context.state.sliceDoc(varNode.from, varNode.to); + let pipelineNode = climbTill(parentStatementThing, tokens.Pipeline)!; + // TODO: Maybe consider disjunctions? + let statements = nodesWithPath(pipelineNode, [tokens.QueryStage, tokens.ClauseMatch, tokens.Patterns, tokens.Pattern, tokens.Statement, tokens.StatementThing]); + let relevantStatementThings = statements + .filter(n => { + let otherVarNode = n.getChild(tokens.VAR)!; + return context.state.sliceDoc(otherVarNode.from, otherVarNode.to) == varName; + }); + let possibleLabels = relevantStatementThings + .flatMap(n => nodesWithPath(n, [tokens.ThingConstraintList, tokens.ThingConstraint, tokens.IsaConstraint, tokens.TypeRef])) + .map(n => context.state.sliceDoc(n.from, n.to)); + // console.log(parentStatementThing, varNode, varName, pipelineNode, statements, relevantStatementThings, possibleLabels); + return possibleLabels; +} + +function suggestAttributeTypeForHas(context: CompletionContext, tree: Tree, parseAt: SyntaxNode, climbedTo: SyntaxNode, prefix: NodeType[], schema: TypeQLAutocompleteSchema): Completion[] { + let possibleLabels = findIsaConstraintLabelsForVar(context, parseAt); + if (possibleLabels.length > 0) { + return possibleLabels.flatMap(owner => schema.getOwns(owner)) + .map((attributeType) => suggest("AttributeType", attributeType.label)) + } else { + return suggestAttributeTypeLabels(context, tree, parseAt, climbedTo, prefix, schema); + } +} + +function suggestRoleTypeForLinks(context: CompletionContext, tree: Tree, parseAt: SyntaxNode, climbedTo: SyntaxNode, prefix: NodeType[], schema: TypeQLAutocompleteSchema): Completion[] { + let possibleLabels = findIsaConstraintLabelsForVar(context, parseAt); + if (possibleLabels.length > 0) { + return possibleLabels.flatMap(relationType => schema.getRelates(relationType)) + .map((roleType) => suggest("RoleType", roleType.label.split(":")[1])) + } else { + return suggestRelatedRoleTypeLabelsUnscoped(context, tree, parseAt, climbedTo, prefix, schema); + } +} + +function suggestAttributeTypeLabels(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], schema: TypeQLAutocompleteSchema): Completion[] { + return schema.attributeTypes().map((attributeType) => { return suggest("AttributeType", attributeType.label); }); +} + +function suggestObjectTypeLabels(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], schema: TypeQLAutocompleteSchema): Completion[] { + return schema.objectTypes().map((objectType) => suggest("ObjectType", objectType.label)); +} + +function suggestRoleTypesUnscopedForPlaysDeclaration(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], schema: TypeQLAutocompleteSchema): Completion[] { + return schema.objectTypes() + .flatMap((objectType) => objectType.playedRoles) + .map((role) => suggest("RoleType", role.label)); +} + +function suggestRelatedRoleTypeLabelsUnscoped(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], schema: TypeQLAutocompleteSchema): Completion[] { + return schema.relationTypes() + .flatMap((relation) => relation.relatedRoles) + .map((role) => suggest("RoleType", role.label.split(":")[1])); +} + +function suggestThingTypeLabels(context: CompletionContext, tree: Tree, parseAt: SyntaxNode, climbedTo: SyntaxNode, prefix: NodeType[], schema: TypeQLAutocompleteSchema): Completion[] { + return suggestAttributeTypeLabels(context, tree, parseAt, climbedTo, prefix, schema).concat( + suggestObjectTypeLabels(context, tree, parseAt, climbedTo, prefix, schema) + ); +} + +function suggestVariables(context: CompletionContext, tree: Tree, boost= 0): Completion[] { + let options: Completion[] = []; + tree.iterate({ + enter: (other: SyntaxNode) => { + if (other.type.id == tokens.VAR) { + let varName = context.state.sliceDoc(other.from, other.to); + options.push(suggest("variable", varName, boost)); + } + } + }); + return options; +} + +function suggestVariablesAt10(context: CompletionContext, tree: Tree): Completion[] { + return suggestVariables(context, tree, 10); +} + +function suggestVariablesAtMinus10(context: CompletionContext, tree: Tree): Completion[] { + return suggestVariables(context, tree, -10); +} + +function suggestThingConstraintKeywords(): Completion[] { + return ["isa", "has", "links"].map((constraintName) => { + return { + label: constraintName, + type: "thingConstraint", + apply: constraintName, + info: "Thing constraint keyword", + }; + }); +} +function suggestTypeConstraintKeywords(): Completion[] { + return ["sub", "owns", "relates", "plays"].map((constraintName) => { + return { + label: constraintName, + type: "typeConstraint", + apply: constraintName, + info: "Type constraint keyword", + }; + }); +} + +function suggestDefinedKeywords(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], _schema: TypeQLAutocompleteSchema): Completion[] { + return ["define", "redefine", "undefine"].map((keyword) => suggest("keyword", keyword, 1)); +} + +function suggestPipelineStages(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], _schema: TypeQLAutocompleteSchema): Completion[] { + return ["match", "insert", "delete", "update", "put", "select", "reduce", "sort", "limit", "offset", "end"].map((keyword) => suggest("keyword", keyword, 1)) +} + +function suggestKinds(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], _schema: TypeQLAutocompleteSchema): Completion[] { + return ["entity", "attribute", "relation"].map((keyword) => suggest("kind", keyword, 2)); +} + +function suggestNestedPatterns(_context: CompletionContext, _tree: Tree, _parseAt: SyntaxNode, _climbedTo: SyntaxNode, _prefix: NodeType[], _schema: TypeQLAutocompleteSchema): Completion[] { + return ["not {};", "{} or {};", "try {};"].map((keyword) => suggest("method", keyword, 2)); +} + +const SUFFIX_VAR_OR_COMMA = [[tokens.COMMA], [tokens.VAR]]; + + +// Will pick the first matching suffix. If you want to handle things manually, use an empty suffix. +const SUGGESTION_GROUP_FOR_THING_STATEMENTS: SuffixOfPrefixSuggestion[] = [ + { suffixes: SUFFIX_VAR_OR_COMMA, suggestions: [suggestThingConstraintKeywords] }, + { suffixes: [[tokens.HAS]], suggestions: [suggestAttributeTypeForHas, suggestVariablesAtMinus10] }, + { suffixes: [[tokens.ISA]], suggestions: [suggestThingTypeLabels, suggestVariablesAtMinus10] }, + { suffixes: [[tokens.HAS, tokens.TypeRef], [tokens.ISA, tokens.TypeRef]], suggestions: [suggestVariablesAtMinus10] }, +]; + +export const SUGGESTION_MAP: SuggestionMap = { + [tokens.LABEL]: [{ suffixes: [[]], suggestions: [suggestThingTypeLabels] }], + [tokens.VAR]: [{ suffixes: [[]], suggestions: [suggestVariablesAt10] }], + [tokens.Relation]: [ + {suffixes: [[tokens.PARENOPEN], [tokens.COMMA]], suggestions: [suggestRoleTypeForLinks, suggestVariablesAtMinus10]}, + {suffixes: [[tokens.COLON]], suggestions: [suggestVariablesAt10]}, + ], + [tokens.Statement]: [ + { suffixes: SUFFIX_VAR_OR_COMMA, suggestions: [suggestThingConstraintKeywords, suggestTypeConstraintKeywords] }, + { suffixes: [[tokens.HAS]], suggestions: [suggestAttributeTypeForHas, suggestVariablesAtMinus10] }, + { suffixes: [[tokens.ISA]], suggestions: [suggestThingTypeLabels, suggestVariablesAtMinus10] }, + { suffixes: [[tokens.HAS, tokens.TypeRef], [tokens.ISA, tokens.TypeRef]], suggestions: [suggestVariablesAtMinus10] }, + { suffixes: [[tokens.SEMICOLON, tokens.TypeRef]], suggestions: [suggestTypeConstraintKeywords] }, + { suffixes: [[tokens.OWNS]], suggestions: [suggestAttributeTypeLabels, suggestVariablesAtMinus10] }, + { suffixes: [[tokens.SUB]], suggestions: [suggestThingTypeLabels, suggestVariablesAtMinus10] }, + { suffixes: [[tokens.RELATES]], suggestions: [suggestRelatedRoleTypeLabelsUnscoped] }, + { suffixes: [[tokens.PLAYS]], suggestions: [suggestRoleTypesUnscopedForPlaysDeclaration] }, + ], + [tokens.ClauseMatch]: [ + { suffixes: [[tokens.MATCH, tokens.TypeRef]], suggestions: [suggestTypeConstraintKeywords] }, + { suffixes: [[tokens.MATCH]], suggestions: [suggestNestedPatterns, suggestVariablesAt10, suggestThingTypeLabels ] }, + ], + [tokens.ClauseInsert]: SUGGESTION_GROUP_FOR_THING_STATEMENTS, + [tokens.Query]: [ + { suffixes: [[tokens.QuerySchema]], suggestions: [suggestThingTypeLabels, suggestKinds] }, + { suffixes: [[tokens.QueryPipelinePreambled]], suggestions: [suggestNestedPatterns, suggestVariablesAt10, suggestPipelineStages ] }, + ], + + // Now some for define statements + [tokens.QuerySchema]: [ + { suffixes: [[tokens.DEFINE]], suggestions: [ suggestThingTypeLabels, suggestKinds] }, + { suffixes: [[tokens.DEFINE, tokens.LABEL]], suggestions: [ suggestTypeConstraintKeywords] }, + { suffixes: [[tokens.SEMICOLON, tokens.LABEL]], suggestions: [ suggestTypeConstraintKeywords] }, + ], + [tokens.Definable]: [ + { suffixes: [[tokens.COMMA], [tokens.KIND, tokens.LABEL]], suggestions: [ suggestTypeConstraintKeywords ] }, + { suffixes: [[tokens.OWNS]], suggestions: [suggestAttributeTypeLabels] }, + { suffixes: [[tokens.SUB]], suggestions: [suggestThingTypeLabels] }, + { suffixes: [ [tokens.PLAYS] ], suggestions: [ suggestRoleTypesUnscopedForPlaysDeclaration ] }, + { suffixes: [ [tokens.RELATES] ], suggestions: [ suggestRelatedRoleTypeLabelsUnscoped ] }, + ], + // TODO: Add any cases krishnan didn't think of. +}; diff --git a/src/framework/graph-visualiser/index.ts b/src/framework/graph-visualiser/index.ts index bcd6dcfc8..041a52928 100644 --- a/src/framework/graph-visualiser/index.ts +++ b/src/framework/graph-visualiser/index.ts @@ -47,8 +47,8 @@ export class GraphVisualiser { handleQueryResult(res: ApiResponse) { if (isApiErrorResponse(res)) return; - if (res.ok.answerType == "conceptRows" && res.ok.query != null) { + (window as any)._lastQueryAnswers = res.ok.answers; // TODO: Remove once schema based autocomplete is stable. let converter = new StudioConverter(this.graph, res.ok.query, false, this.structureParameters, this.styleParameters); let logicalGraph = constructGraphFromRowsResult(res.ok); // In memory, not visualised convertLogicalGraphWith(logicalGraph, converter); diff --git a/src/framework/typedb-driver/response.ts b/src/framework/typedb-driver/response.ts index a287e78fd..725b47062 100644 --- a/src/framework/typedb-driver/response.ts +++ b/src/framework/typedb-driver/response.ts @@ -36,6 +36,7 @@ export interface ConceptRow { } export interface ConceptRowAnswer { + involvedBlocks: number[]; data: ConceptRow; } @@ -56,10 +57,7 @@ export interface OkQueryResponse extends QueryResponseBase { export interface ConceptRowsQueryResponse extends QueryResponseBase { answerType: "conceptRows"; - answers: { - involvedBlocks: number[]; - data: ConceptRow - }[]; + answers: ConceptRowAnswer[]; } export interface ConceptDocumentsQueryResponse extends QueryResponseBase { diff --git a/src/module/query/query-tool.component.html b/src/module/query/query-tool.component.html index 81a487d15..feb2bcd8d 100644 --- a/src/module/query/query-tool.component.html +++ b/src/module/query/query-tool.component.html @@ -42,7 +42,7 @@

Query

@if (!codeEditorHidden) { - + }
diff --git a/src/module/query/query-tool.component.ts b/src/module/query/query-tool.component.ts index 307f8eae7..02884cbaa 100644 --- a/src/module/query/query-tool.component.ts +++ b/src/module/query/query-tool.component.ts @@ -21,7 +21,7 @@ import { MatTooltipModule } from "@angular/material/tooltip"; import { RouterLink } from "@angular/router"; import { ResizableDirective } from "@hhangular/resizable"; import { distinctUntilChanged, filter, first, map, startWith } from "rxjs"; -import { otherExampleLinter, TypeQL } from "../../framework/codemirror-lang-typeql"; +import { otherExampleLinter, TypeQL, typeqlAutocompleteExtension } from "../../framework/codemirror-lang-typeql"; import { DriverAction, TransactionOperationAction, isQueryRun, isTransactionOperation } from "../../concept/action"; import { basicDark } from "../../framework/code-editor/theme"; import { DetectScrollDirective } from "../../framework/scroll-container/detect-scroll.directive"; @@ -33,6 +33,9 @@ import { QueryToolState } from "../../service/query-tool-state.service"; import { SnackbarService } from "../../service/snackbar.service"; import { PageScaffoldComponent } from "../scaffold/page/page-scaffold.component"; import { SchemaTreeNodeComponent } from "./schema-tree-node/schema-tree-node.component"; +import {keymap} from "@codemirror/view"; +import {defaultKeymap} from "@codemirror/commands"; +import {startCompletion, completionKeymap} from "@codemirror/autocomplete"; @Component({ selector: "ts-query-tool", @@ -134,4 +137,6 @@ export class QueryToolComponent implements OnInit, AfterViewInit, OnDestroy { readonly JSON = JSON; readonly TypeQL = TypeQL; readonly linter = otherExampleLinter; + readonly typeqlAutocompleteExtension = typeqlAutocompleteExtension; + readonly codeEditorKeymap = keymap.of([...defaultKeymap, {key: "Alt-Space", run: startCompletion, preventDefault: true}]); } diff --git a/src/service/schema-state.service.ts b/src/service/schema-state.service.ts index ad17e5b40..4e84499fe 100644 --- a/src/service/schema-state.service.ts +++ b/src/service/schema-state.service.ts @@ -16,6 +16,7 @@ import { AttributeType, EntityType, RelationType, RoleType, Type } from "../fram import { ApiOkResponse, ApiResponse, ConceptRowsQueryResponse, isApiErrorResponse, QueryResponse } from "../framework/typedb-driver/response"; import { DriverState } from "./driver-state.service"; import { SnackbarService } from "./snackbar.service"; +import {updateAutocomleteSchemaFromDB} from "../framework/codemirror-lang-typeql"; const NO_SERVER_CONNECTED = `No server connected`; const NO_DATABASE_SELECTED = `No database selected`; @@ -30,14 +31,14 @@ const schemaQueriesList = Object.values(schemaQueries); type VisualiserStatus = "ok" | "running" | "noAnswers" | "error"; -interface SchemaEntity extends EntityType { +export interface SchemaEntity extends EntityType { supertype?: SchemaEntity; subtypes: SchemaEntity[]; ownedAttributes: SchemaAttribute[]; playedRoles: SchemaRole[]; } -interface SchemaRelation extends RelationType { +export interface SchemaRelation extends RelationType { supertype?: SchemaRelation; subtypes: SchemaRelation[]; ownedAttributes: SchemaAttribute[]; @@ -86,6 +87,11 @@ export class SchemaState { this.queryResponses$.subscribe(data => { this.push(data); }); + this.value$.subscribe(schema => { + if (schema != null) { + updateAutocomleteSchemaFromDB(schema) + } + }) } refresh() {