@witchcraft/expressit 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/dist/Lexer.js +2 -2
- package/dist/Parser.d.ts +14 -29
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +120 -135
- package/dist/ast/builders/array.d.ts +1 -3
- package/dist/ast/builders/array.d.ts.map +1 -1
- package/dist/ast/builders/array.js +3 -5
- package/dist/ast/builders/condition.d.ts +5 -11
- package/dist/ast/builders/condition.d.ts.map +1 -1
- package/dist/ast/builders/condition.js +2 -3
- package/dist/ast/builders/delim.d.ts +1 -1
- package/dist/ast/builders/error.d.ts +3 -4
- package/dist/ast/builders/error.d.ts.map +1 -1
- package/dist/ast/builders/error.js +6 -2
- package/dist/ast/builders/expression.d.ts +3 -7
- package/dist/ast/builders/expression.d.ts.map +1 -1
- package/dist/ast/builders/expression.js +3 -5
- package/dist/ast/builders/group.d.ts +3 -8
- package/dist/ast/builders/group.d.ts.map +1 -1
- package/dist/ast/builders/group.js +3 -3
- package/dist/ast/builders/pos.d.ts +1 -2
- package/dist/ast/builders/pos.d.ts.map +1 -1
- package/dist/ast/builders/token.d.ts +3 -5
- package/dist/ast/builders/token.d.ts.map +1 -1
- package/dist/ast/builders/token.js +3 -4
- package/dist/ast/builders/type.d.ts +1 -1
- package/dist/ast/builders/variable.d.ts +3 -5
- package/dist/ast/builders/variable.d.ts.map +1 -1
- package/dist/ast/builders/variable.js +2 -3
- package/dist/ast/createArrayNode.d.ts +3 -0
- package/dist/ast/createArrayNode.d.ts.map +1 -0
- package/dist/ast/createArrayNode.js +12 -0
- package/dist/ast/createConditionNode.d.ts +11 -0
- package/dist/ast/createConditionNode.d.ts.map +1 -0
- package/dist/ast/createConditionNode.js +18 -0
- package/dist/ast/createExpressionNode.d.ts +3 -0
- package/dist/ast/createExpressionNode.d.ts.map +1 -0
- package/dist/ast/createExpressionNode.js +14 -0
- package/dist/ast/createGroupNode.d.ts +5 -0
- package/dist/ast/createGroupNode.d.ts.map +1 -0
- package/dist/ast/createGroupNode.js +14 -0
- package/dist/ast/createNormalizedCondition.d.ts +3 -0
- package/dist/ast/createNormalizedCondition.d.ts.map +1 -0
- package/dist/ast/createNormalizedCondition.js +10 -0
- package/dist/ast/createNormalizedExpression.d.ts +3 -0
- package/dist/ast/createNormalizedExpression.d.ts.map +1 -0
- package/dist/ast/createNormalizedExpression.js +10 -0
- package/dist/ast/createToken.d.ts +6 -0
- package/dist/ast/createToken.d.ts.map +1 -0
- package/dist/ast/createToken.js +15 -0
- package/dist/ast/createVariableNode.d.ts +3 -0
- package/dist/ast/createVariableNode.d.ts.map +1 -0
- package/dist/ast/createVariableNode.js +12 -0
- package/dist/ast/error.d.ts +3 -0
- package/dist/ast/error.d.ts.map +1 -0
- package/dist/ast/error.js +9 -0
- package/dist/ast/handlers.d.ts +5 -12
- package/dist/ast/handlers.d.ts.map +1 -1
- package/dist/ast/handlers.js +21 -29
- package/dist/ast/index.d.ts +9 -1
- package/dist/ast/index.d.ts.map +1 -1
- package/dist/ast/index.js +18 -2
- package/dist/defaults/defaultConditionNormalizer.d.ts +3 -0
- package/dist/defaults/defaultConditionNormalizer.d.ts.map +1 -0
- package/dist/defaults/defaultKeyParser.d.ts +3 -0
- package/dist/defaults/defaultKeyParser.d.ts.map +1 -0
- package/dist/defaults/defaultPrefixApplier.d.ts +3 -0
- package/dist/defaults/defaultPrefixApplier.d.ts.map +1 -0
- package/dist/defaults/defaultValueComparer.d.ts +3 -0
- package/dist/defaults/defaultValueComparer.d.ts.map +1 -0
- package/dist/{helpers/general → defaults}/index.d.ts +0 -2
- package/dist/defaults/index.d.ts.map +1 -0
- package/dist/{helpers/general → defaults}/index.js +0 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/{helpers/errors.d.ts → internal/ExpressitError.d.ts} +3 -2
- package/dist/internal/ExpressitError.d.ts.map +1 -0
- package/dist/{helpers/errors.js → internal/ExpressitError.js} +2 -2
- package/dist/internal/applyBoolean.d.ts.map +1 -0
- package/dist/{helpers/general → internal}/applyPrefix.d.ts +1 -1
- package/dist/internal/applyPrefix.d.ts.map +1 -0
- package/dist/{helpers/parser → internal}/checkParserOpts.d.ts +2 -1
- package/dist/internal/checkParserOpts.d.ts.map +1 -0
- package/dist/{helpers/parser → internal}/checkParserOpts.js +14 -14
- package/dist/internal/escapeVariableOrPrefix.d.ts +2 -0
- package/dist/internal/escapeVariableOrPrefix.d.ts.map +1 -0
- package/dist/internal/escapeVariableOrPrefix.js +38 -0
- package/dist/internal/extractPosition.d.ts +5 -0
- package/dist/internal/extractPosition.d.ts.map +1 -0
- package/dist/internal/getUnclosedRightParenCount.d.ts +4 -0
- package/dist/internal/getUnclosedRightParenCount.d.ts.map +1 -0
- package/dist/{helpers/parser → internal}/getUnclosedRightParenCount.js +1 -1
- package/dist/{helpers/parser → internal}/parseParserOptions.d.ts +1 -1
- package/dist/internal/parseParserOptions.d.ts.map +1 -0
- package/dist/{helpers/parser → internal}/parseParserOptions.js +4 -4
- package/dist/internal/unescape.d.ts.map +1 -0
- package/dist/package.json.js +7 -7
- package/dist/types/ast.d.ts +195 -6
- package/dist/types/ast.d.ts.map +1 -1
- package/dist/types/ast.js +2 -0
- package/dist/types/autocomplete.d.ts +5 -6
- package/dist/types/autocomplete.d.ts.map +1 -1
- package/dist/types/parser.d.ts +17 -22
- package/dist/types/parser.d.ts.map +1 -1
- package/dist/utils/extractTokens.d.ts +2 -4
- package/dist/utils/extractTokens.d.ts.map +1 -1
- package/dist/utils/extractTokens.js +14 -18
- package/dist/utils/generateParentsMap.d.ts +10 -0
- package/dist/utils/generateParentsMap.d.ts.map +1 -0
- package/dist/utils/generateParentsMap.js +73 -0
- package/dist/utils/getCursorInfo.d.ts +1 -1
- package/dist/utils/getCursorInfo.d.ts.map +1 -1
- package/dist/utils/getCursorInfo.js +3 -5
- package/dist/utils/getOppositeDelimiter.d.ts +2 -1
- package/dist/utils/getOppositeDelimiter.d.ts.map +1 -1
- package/dist/utils/getOppositeDelimiter.js +6 -5
- package/dist/utils/getParent.d.ts +5 -0
- package/dist/utils/getParent.d.ts.map +1 -0
- package/dist/utils/getParent.js +6 -0
- package/dist/utils/getSurroundingErrors.d.ts +3 -4
- package/dist/utils/getSurroundingErrors.d.ts.map +1 -1
- package/dist/utils/getSurroundingErrors.js +3 -3
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +8 -0
- package/dist/utils/isNode.d.ts +10 -0
- package/dist/utils/isNode.d.ts.map +1 -0
- package/dist/utils/isNode.js +6 -0
- package/dist/utils/isToken.d.ts +8 -0
- package/dist/utils/isToken.d.ts.map +1 -0
- package/dist/utils/isToken.js +6 -0
- package/dist/utils/prettyAst.d.ts +1 -2
- package/dist/utils/prettyAst.d.ts.map +1 -1
- package/dist/utils/prettyAst.js +19 -26
- package/package.json +7 -7
- package/src/Lexer.ts +2 -2
- package/src/Parser.ts +158 -165
- package/src/ast/builders/array.ts +4 -9
- package/src/ast/builders/condition.ts +10 -15
- package/src/ast/builders/delim.ts +1 -1
- package/src/ast/builders/error.ts +10 -6
- package/src/ast/builders/expression.ts +17 -23
- package/src/ast/builders/group.ts +7 -11
- package/src/ast/builders/pos.ts +2 -3
- package/src/ast/builders/token.ts +6 -7
- package/src/ast/builders/type.ts +1 -1
- package/src/ast/builders/variable.ts +6 -8
- package/src/ast/createArrayNode.ts +17 -0
- package/src/ast/createConditionNode.ts +58 -0
- package/src/ast/createExpressionNode.ts +21 -0
- package/src/ast/createGroupNode.ts +46 -0
- package/src/ast/createNormalizedCondition.ts +12 -0
- package/src/ast/createNormalizedExpression.ts +9 -0
- package/src/ast/createToken.ts +26 -0
- package/src/ast/createVariableNode.ts +18 -0
- package/src/ast/error.ts +9 -0
- package/src/ast/handlers.ts +26 -37
- package/src/ast/index.ts +9 -1
- package/src/{helpers/general → defaults}/defaultConditionNormalizer.ts +1 -1
- package/src/{helpers/general → defaults}/defaultKeyParser.ts +1 -1
- package/src/{helpers/general → defaults}/defaultPrefixApplier.ts +1 -1
- package/src/{helpers/general → defaults}/defaultValueComparer.ts +1 -1
- package/src/{helpers/general → defaults}/index.ts +0 -2
- package/src/index.ts +2 -1
- package/src/{helpers/errors.ts → internal/ExpressitError.ts} +2 -2
- package/src/{helpers/general → internal}/applyPrefix.ts +1 -1
- package/src/{helpers/parser → internal}/checkParserOpts.ts +16 -15
- package/src/internal/escapeVariableOrPrefix.ts +36 -0
- package/src/{helpers/parser → internal}/extractPosition.ts +2 -2
- package/src/{helpers/parser → internal}/getUnclosedRightParenCount.ts +1 -2
- package/src/{helpers/parser → internal}/parseParserOptions.ts +5 -5
- package/src/types/ast.ts +292 -7
- package/src/types/autocomplete.ts +5 -7
- package/src/types/parser.ts +17 -22
- package/src/utils/extractTokens.ts +16 -20
- package/src/utils/generateParentsMap.ts +60 -0
- package/src/utils/getCursorInfo.ts +4 -6
- package/src/utils/getOppositeDelimiter.ts +11 -10
- package/src/utils/getParent.ts +16 -0
- package/src/utils/getSurroundingErrors.ts +10 -9
- package/src/utils/index.ts +4 -0
- package/src/utils/isNode.ts +12 -0
- package/src/utils/isToken.ts +10 -0
- package/src/utils/prettyAst.ts +20 -17
- package/dist/ast/classes/ArrayNode.d.ts +0 -18
- package/dist/ast/classes/ArrayNode.d.ts.map +0 -1
- package/dist/ast/classes/ArrayNode.js +0 -55
- package/dist/ast/classes/Condition.d.ts +0 -13
- package/dist/ast/classes/Condition.d.ts.map +0 -1
- package/dist/ast/classes/Condition.js +0 -21
- package/dist/ast/classes/ConditionNode.d.ts +0 -73
- package/dist/ast/classes/ConditionNode.d.ts.map +0 -1
- package/dist/ast/classes/ConditionNode.js +0 -101
- package/dist/ast/classes/ErrorToken.d.ts +0 -27
- package/dist/ast/classes/ErrorToken.d.ts.map +0 -1
- package/dist/ast/classes/ErrorToken.js +0 -47
- package/dist/ast/classes/Expression.d.ts +0 -13
- package/dist/ast/classes/Expression.d.ts.map +0 -1
- package/dist/ast/classes/Expression.js +0 -19
- package/dist/ast/classes/ExpressionNode.d.ts +0 -21
- package/dist/ast/classes/ExpressionNode.d.ts.map +0 -1
- package/dist/ast/classes/ExpressionNode.js +0 -57
- package/dist/ast/classes/GroupNode.d.ts +0 -64
- package/dist/ast/classes/GroupNode.d.ts.map +0 -1
- package/dist/ast/classes/GroupNode.js +0 -69
- package/dist/ast/classes/Node.d.ts +0 -22
- package/dist/ast/classes/Node.d.ts.map +0 -1
- package/dist/ast/classes/Node.js +0 -28
- package/dist/ast/classes/Token.d.ts +0 -27
- package/dist/ast/classes/Token.d.ts.map +0 -1
- package/dist/ast/classes/Token.js +0 -28
- package/dist/ast/classes/ValidToken.d.ts +0 -26
- package/dist/ast/classes/ValidToken.d.ts.map +0 -1
- package/dist/ast/classes/ValidToken.js +0 -49
- package/dist/ast/classes/VariableNode.d.ts +0 -33
- package/dist/ast/classes/VariableNode.d.ts.map +0 -1
- package/dist/ast/classes/VariableNode.js +0 -58
- package/dist/ast/classes/index.d.ts +0 -12
- package/dist/ast/classes/index.d.ts.map +0 -1
- package/dist/ast/classes/index.js +0 -24
- package/dist/helpers/errors.d.ts.map +0 -1
- package/dist/helpers/general/applyBoolean.d.ts.map +0 -1
- package/dist/helpers/general/applyPrefix.d.ts.map +0 -1
- package/dist/helpers/general/defaultConditionNormalizer.d.ts +0 -3
- package/dist/helpers/general/defaultConditionNormalizer.d.ts.map +0 -1
- package/dist/helpers/general/defaultKeyParser.d.ts +0 -3
- package/dist/helpers/general/defaultKeyParser.d.ts.map +0 -1
- package/dist/helpers/general/defaultPrefixApplier.d.ts +0 -3
- package/dist/helpers/general/defaultPrefixApplier.d.ts.map +0 -1
- package/dist/helpers/general/defaultValueComparer.d.ts +0 -3
- package/dist/helpers/general/defaultValueComparer.d.ts.map +0 -1
- package/dist/helpers/general/index.d.ts.map +0 -1
- package/dist/helpers/index.d.ts +0 -4
- package/dist/helpers/index.d.ts.map +0 -1
- package/dist/helpers/index.js +0 -8
- package/dist/helpers/parser/assignParents.d.ts +0 -4
- package/dist/helpers/parser/assignParents.d.ts.map +0 -1
- package/dist/helpers/parser/assignParents.js +0 -71
- package/dist/helpers/parser/checkParserOpts.d.ts.map +0 -1
- package/dist/helpers/parser/extractPosition.d.ts +0 -5
- package/dist/helpers/parser/extractPosition.d.ts.map +0 -1
- package/dist/helpers/parser/getUnclosedRightParenCount.d.ts +0 -4
- package/dist/helpers/parser/getUnclosedRightParenCount.d.ts.map +0 -1
- package/dist/helpers/parser/index.d.ts +0 -9
- package/dist/helpers/parser/index.d.ts.map +0 -1
- package/dist/helpers/parser/index.js +0 -18
- package/dist/helpers/parser/parseParserOptions.d.ts.map +0 -1
- package/dist/helpers/parser/seal.d.ts +0 -8
- package/dist/helpers/parser/seal.d.ts.map +0 -1
- package/dist/helpers/parser/seal.js +0 -10
- package/dist/helpers/parser/setParent.d.ts +0 -6
- package/dist/helpers/parser/setParent.d.ts.map +0 -1
- package/dist/helpers/parser/setParent.js +0 -4
- package/dist/helpers/parser/unescape.d.ts.map +0 -1
- package/src/ast/classes/ArrayNode.ts +0 -46
- package/src/ast/classes/Condition.ts +0 -22
- package/src/ast/classes/ConditionNode.ts +0 -141
- package/src/ast/classes/ErrorToken.ts +0 -49
- package/src/ast/classes/Expression.ts +0 -26
- package/src/ast/classes/ExpressionNode.ts +0 -62
- package/src/ast/classes/GroupNode.ts +0 -127
- package/src/ast/classes/Node.ts +0 -47
- package/src/ast/classes/Token.ts +0 -59
- package/src/ast/classes/ValidToken.ts +0 -56
- package/src/ast/classes/VariableNode.ts +0 -67
- package/src/ast/classes/index.ts +0 -13
- package/src/helpers/index.ts +0 -6
- package/src/helpers/parser/assignParents.ts +0 -51
- package/src/helpers/parser/index.ts +0 -10
- package/src/helpers/parser/seal.ts +0 -14
- package/src/helpers/parser/setParent.ts +0 -5
- /package/dist/{helpers/general → defaults}/defaultConditionNormalizer.js +0 -0
- /package/dist/{helpers/general → defaults}/defaultKeyParser.js +0 -0
- /package/dist/{helpers/general → defaults}/defaultPrefixApplier.js +0 -0
- /package/dist/{helpers/general → defaults}/defaultValueComparer.js +0 -0
- /package/dist/{helpers/general → internal}/applyBoolean.d.ts +0 -0
- /package/dist/{helpers/general → internal}/applyBoolean.js +0 -0
- /package/dist/{helpers/general → internal}/applyPrefix.js +0 -0
- /package/dist/{helpers/parser → internal}/extractPosition.js +0 -0
- /package/dist/{helpers/parser → internal}/unescape.d.ts +0 -0
- /package/dist/{helpers/parser → internal}/unescape.js +0 -0
- /package/src/{helpers/general → internal}/applyBoolean.ts +0 -0
- /package/src/{helpers/parser → internal}/unescape.ts +0 -0
package/src/Parser.ts
CHANGED
|
@@ -8,34 +8,34 @@ import type { AddParameters , DeepPartial } from "@alanscodelog/utils/types"
|
|
|
8
8
|
import { unreachable } from "@alanscodelog/utils/unreachable.js"
|
|
9
9
|
|
|
10
10
|
import { pos } from "./ast/builders/pos.js"
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { ErrorToken } from "./ast/classes/ErrorToken.js"
|
|
14
|
-
import { ExpressionNode } from "./ast/classes/ExpressionNode.js"
|
|
15
|
-
import { GroupNode } from "./ast/classes/GroupNode.js"
|
|
16
|
-
import { Condition, Expression } from "./ast/classes/index.js"
|
|
17
|
-
import { ValidToken } from "./ast/classes/ValidToken.js"
|
|
18
|
-
import { VariableNode } from "./ast/classes/VariableNode.js"
|
|
11
|
+
import { createCondition } from "./ast/createNormalizedCondition.js"
|
|
12
|
+
import { createExpression } from "./ast/createNormalizedExpression.js"
|
|
19
13
|
import * as handle from "./ast/handlers.js"
|
|
20
|
-
import { applyBoolean } from "./
|
|
21
|
-
import { applyPrefix } from "./
|
|
22
|
-
import { checkParserOpts } from "./
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
14
|
+
import { applyBoolean } from "./internal/applyBoolean.js"
|
|
15
|
+
import { applyPrefix } from "./internal/applyPrefix.js"
|
|
16
|
+
import { checkParserOpts } from "./internal/checkParserOpts.js"
|
|
17
|
+
import { escapeVariableOrPrefix } from "./internal/escapeVariableOrPrefix.js"
|
|
18
|
+
import { extractPosition } from "./internal/extractPosition.js"
|
|
19
|
+
import { getUnclosedRightParenCount } from "./internal/getUnclosedRightParenCount.js"
|
|
20
|
+
import { parseParserOptions } from "./internal/parseParserOptions.js"
|
|
21
|
+
import { unescape } from "./internal/unescape.js"
|
|
27
22
|
import { $C, $T, Lexer,type RealTokenType, type Token, type TokenCategoryType, type TokenType } from "./Lexer.js"
|
|
28
|
-
import type { ParserResults, TokenBooleanTypes } from "./types/ast.js"
|
|
29
|
-
import { type AnyToken, type Completion, type Position, type Suggestion,SUGGESTION_TYPE, TOKEN_TYPE } from "./types/index.js"
|
|
23
|
+
import type { ArrayNode, ConditionNode, GroupNode, NormalizedCondition, NormalizedExpression, ParserResults, TokenBooleanTypes, ValidToken, VariableNode, } from "./types/ast.js"
|
|
24
|
+
import { type AnyToken, AST_TYPE,type Completion, type Position, type Suggestion,SUGGESTION_TYPE, TOKEN_TYPE } from "./types/index.js"
|
|
30
25
|
import type { FullParserOptions, KeywordEntry, ParserOptions, ValidationQuery, ValueQuery } from "./types/parser.js"
|
|
31
26
|
import { extractTokens } from "./utils/extractTokens.js"
|
|
27
|
+
import { generateParentsMap } from "./utils/generateParentsMap.js"
|
|
32
28
|
import { getCursorInfo } from "./utils/getCursorInfo.js"
|
|
29
|
+
import { getParent } from "./utils/getParent.js"
|
|
33
30
|
import { getSurroundingErrors } from "./utils/getSurroundingErrors.js"
|
|
31
|
+
import { isNode } from "./utils/isNode.js"
|
|
32
|
+
import { isToken } from "./utils/isToken.js"
|
|
34
33
|
|
|
35
34
|
const OPPOSITE = {
|
|
36
35
|
[TOKEN_TYPE.AND]: TOKEN_TYPE.OR,
|
|
37
36
|
[TOKEN_TYPE.OR]: TOKEN_TYPE.AND,
|
|
38
37
|
}
|
|
38
|
+
|
|
39
39
|
function isEqualSet(setA: Set<any>, setB: Set<any>): boolean {
|
|
40
40
|
if (setA.size !== setB.size) return false
|
|
41
41
|
for (const key of setA) {
|
|
@@ -59,11 +59,11 @@ const createDefaultRequires = (partial: DeepPartial<Suggestion["requires"]> = {}
|
|
|
59
59
|
})
|
|
60
60
|
|
|
61
61
|
/** Returns if valid token requires whitespace if none between cursor and token. */
|
|
62
|
-
const tokenRequiresWhitespace = (
|
|
63
|
-
if (whitespace ||
|
|
64
|
-
return
|
|
65
|
-
([TOKEN_TYPE.AND, TOKEN_TYPE.OR, TOKEN_TYPE.NOT].includes(
|
|
66
|
-
wordOps.find(_ => _.value ===
|
|
62
|
+
const tokenRequiresWhitespace = (valid: ValidToken | undefined, whitespace: boolean, wordOps: KeywordEntry[]): boolean => {
|
|
63
|
+
if (whitespace || valid === undefined) return false
|
|
64
|
+
return valid.type === TOKEN_TYPE.VALUE ||
|
|
65
|
+
([TOKEN_TYPE.AND, TOKEN_TYPE.OR, TOKEN_TYPE.NOT].includes(valid.type) &&
|
|
66
|
+
wordOps.find(_ => _.value === valid.value) !== undefined)
|
|
67
67
|
}
|
|
68
68
|
const tokenVariable = [TOKEN_TYPE.BACKTICK, TOKEN_TYPE.DOUBLEQUOTE, TOKEN_TYPE.SINGLEQUOTE, TOKEN_TYPE.VALUE, TOKEN_TYPE.REGEX]
|
|
69
69
|
|
|
@@ -173,8 +173,6 @@ export class Parser<T extends {} = {}> {
|
|
|
173
173
|
rawInput: string
|
|
174
174
|
},
|
|
175
175
|
): ParserResults {
|
|
176
|
-
// eslint-disable-next-line prefer-rest-params
|
|
177
|
-
const doSeal = arguments[1]?.seal ?? true
|
|
178
176
|
if (typeof input === "string" && isWhitespace(input)) {
|
|
179
177
|
return handle.token.value(undefined, { start: 0, end: 0 }) as any
|
|
180
178
|
}
|
|
@@ -187,9 +185,6 @@ export class Parser<T extends {} = {}> {
|
|
|
187
185
|
lexedTokens,
|
|
188
186
|
}
|
|
189
187
|
const res = this.ruleMain()
|
|
190
|
-
if (doSeal) {
|
|
191
|
-
seal(res)
|
|
192
|
-
}
|
|
193
188
|
this.state = {
|
|
194
189
|
rawInput: "",
|
|
195
190
|
shift: 0,
|
|
@@ -199,14 +194,9 @@ export class Parser<T extends {} = {}> {
|
|
|
199
194
|
return res
|
|
200
195
|
}
|
|
201
196
|
|
|
202
|
-
subParserOne?: Parser<T>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
subParserTwo?: Parser<T> & {
|
|
207
|
-
parse: AddParameters<Parser<T>["parse"], [{ seal: boolean }]>
|
|
208
|
-
}
|
|
209
|
-
|
|
197
|
+
subParserOne?: Parser<T>
|
|
198
|
+
|
|
199
|
+
subParserTwo?: Parser<T>
|
|
210
200
|
|
|
211
201
|
createSubParserIfNotExists(opts: ParserOptions<T>, which: "One" | "Two" = "One"): Parser["subParserOne"] {
|
|
212
202
|
if (this[`subParser${which}`] === undefined) {
|
|
@@ -444,13 +434,13 @@ export class Parser<T extends {} = {}> {
|
|
|
444
434
|
const property = this.ruleConditionProperty()
|
|
445
435
|
const propVal = property?.prop?.value === undefined
|
|
446
436
|
? undefined
|
|
447
|
-
: property.prop.value
|
|
437
|
+
: !property.prop.value.valid
|
|
448
438
|
? ""
|
|
449
439
|
: property.prop.value.value
|
|
450
440
|
|
|
451
441
|
const propOpVal = property?.rest?.propertyOperator === undefined
|
|
452
442
|
? undefined
|
|
453
|
-
: property.rest.propertyOperator
|
|
443
|
+
: !property.rest.propertyOperator?.valid
|
|
454
444
|
? ""
|
|
455
445
|
: property.rest.propertyOperator?.value
|
|
456
446
|
|
|
@@ -466,7 +456,9 @@ export class Parser<T extends {} = {}> {
|
|
|
466
456
|
let value = this.ruleConditionValue(property, { convertRegexValues, convertArrayValues })
|
|
467
457
|
|
|
468
458
|
let group
|
|
469
|
-
if (
|
|
459
|
+
if (
|
|
460
|
+
isNode(value)
|
|
461
|
+
&& !(value.type === AST_TYPE.ARRAY)
|
|
470
462
|
&& !isArray(value)
|
|
471
463
|
&& (!value || this.options.prefixableGroups)
|
|
472
464
|
&& this.isType(this.peek(1), $T.PAREN_L) // is not already plain group
|
|
@@ -478,7 +470,11 @@ export class Parser<T extends {} = {}> {
|
|
|
478
470
|
group = value
|
|
479
471
|
value = undefined
|
|
480
472
|
}
|
|
481
|
-
if (
|
|
473
|
+
if (
|
|
474
|
+
convertRegexValues && isNode(value)
|
|
475
|
+
&& value.type === AST_TYPE.VARIABLE
|
|
476
|
+
&& value.quote?.left.type === TOKEN_TYPE.REGEX
|
|
477
|
+
) {
|
|
482
478
|
value = handle.variable(undefined, undefined, handle.token.value(
|
|
483
479
|
(value.quote?.left?.value ?? "") + (value.value.value ?? "") + (value.quote?.right?.value ?? ""),
|
|
484
480
|
pos(value),
|
|
@@ -607,7 +603,7 @@ export class Parser<T extends {} = {}> {
|
|
|
607
603
|
regexValues: convertRegexValues,
|
|
608
604
|
arrayValues: convertArrayValues,
|
|
609
605
|
}, "One")
|
|
610
|
-
const parsed = this.subParserOne!.parse(" ".repeat(start) + subInput
|
|
606
|
+
const parsed = this.subParserOne!.parse(" ".repeat(start) + subInput)
|
|
611
607
|
return [parenL, parsed, parenR]
|
|
612
608
|
}
|
|
613
609
|
return [parenL, condition, parenR]
|
|
@@ -655,14 +651,16 @@ export class Parser<T extends {} = {}> {
|
|
|
655
651
|
expandedPropertySeparator: undefined,
|
|
656
652
|
arrayValues: false,
|
|
657
653
|
}, "Two")
|
|
658
|
-
const parsed = this.subParserTwo!.parse(" ".repeat(start) + subInput
|
|
659
|
-
if (parsed
|
|
654
|
+
const parsed = this.subParserTwo!.parse(" ".repeat(start) + subInput)
|
|
655
|
+
if ("type" in parsed && parsed.type === AST_TYPE.CONDITION) {
|
|
660
656
|
return parsed.value as ArrayNode
|
|
661
657
|
}
|
|
662
|
-
if (
|
|
658
|
+
if (("valid" in parsed && !parsed.valid)
|
|
659
|
+
|| ("type" in parsed && (parsed.type === AST_TYPE.EXPRESSION || parsed.type === AST_TYPE.GROUP))
|
|
660
|
+
) {
|
|
663
661
|
unreachable("parsed.value should not be an ErrorToken, ExpressionNode, or GroupNode.")
|
|
664
662
|
}
|
|
665
|
-
return parsed
|
|
663
|
+
return parsed as any as VariableNode
|
|
666
664
|
}
|
|
667
665
|
|
|
668
666
|
ruleConditionProperty(): {
|
|
@@ -961,15 +959,16 @@ export class Parser<T extends {} = {}> {
|
|
|
961
959
|
}
|
|
962
960
|
|
|
963
961
|
/**
|
|
964
|
-
* Given a list of @
|
|
962
|
+
* Given the ast, a list of {@link Suggestion} entries, the parser options, and a list of variables, prefixes, operators, etc, and the preferred quote type, returns a list of {@link Completion} entries.
|
|
965
963
|
*
|
|
966
964
|
* It takes care of suggesting the correct delimiters for fixes, quoting variables/prefixes if it would not be possible to parse them unquoted, and separating symbol from non-symbol (word) operators.
|
|
967
965
|
*
|
|
968
|
-
* Does not add whitespace or group requirements. The suggestion information is still in the completion if you wish to show these. But they should not be added to the completion value if using @
|
|
966
|
+
* Does not add whitespace or group requirements. The suggestion information is still in the completion if you wish to show these. But they should not be added to the completion value if using {@link autoreplace} which will take care of it.
|
|
969
967
|
*
|
|
970
|
-
* Is not aware of existing values. You will have to use @
|
|
968
|
+
* Is not aware of existing values. You will have to use {@link getCursorInfo} to understand the context in which the suggestion was made, so that, for example, you could filter out used regex flags.
|
|
971
969
|
*/
|
|
972
970
|
autocomplete(
|
|
971
|
+
ast: ParserResults,
|
|
973
972
|
suggestions: Suggestion[],
|
|
974
973
|
{
|
|
975
974
|
values = [], arrayValues = [], variables = [], prefixes = [], properties = [], expandedPropertyOperators = [], customPropertyOperators = (this as any as Parser<T>).options.customPropertyOperators ?? [], keywords = (this as any as Parser<T>).options.keywords, regexFlags = ["i", "m", "u"], quote = "\"",
|
|
@@ -986,6 +985,7 @@ export class Parser<T extends {} = {}> {
|
|
|
986
985
|
keywords?: FullParserOptions<T>["keywords"]
|
|
987
986
|
} = {},
|
|
988
987
|
): Completion[] {
|
|
988
|
+
const parentMap = generateParentsMap(ast)
|
|
989
989
|
const self = (this as any as Parser<T>)
|
|
990
990
|
return suggestions.map(suggestion => {
|
|
991
991
|
const type = suggestion.type
|
|
@@ -1007,11 +1007,11 @@ export class Parser<T extends {} = {}> {
|
|
|
1007
1007
|
if (suggestion.type !== SUGGESTION_TYPE.REGEX_FLAGS) {return true}
|
|
1008
1008
|
|
|
1009
1009
|
const token = suggestion.cursorInfo
|
|
1010
|
-
const flags = token.at && (token.at
|
|
1010
|
+
const flags = token.at && (getParent(token.at, parentMap) as VariableNode)?.quote?.flags === suggestion.cursorInfo.at
|
|
1011
1011
|
? token.at
|
|
1012
|
-
: token.next && (token.next
|
|
1012
|
+
: token.next && (getParent(token.next, parentMap) as VariableNode)?.quote?.flags === suggestion.cursorInfo.next
|
|
1013
1013
|
? token.next
|
|
1014
|
-
: token.prev && (token.prev
|
|
1014
|
+
: token.prev && (getParent(token.prev, parentMap) as VariableNode)?.quote?.flags === suggestion.cursorInfo.prev
|
|
1015
1015
|
? token.prev
|
|
1016
1016
|
: undefined
|
|
1017
1017
|
|
|
@@ -1050,38 +1050,17 @@ export class Parser<T extends {} = {}> {
|
|
|
1050
1050
|
: type === SUGGESTION_TYPE.VALUE
|
|
1051
1051
|
? values
|
|
1052
1052
|
: unreachable()
|
|
1053
|
-
return arr.map(variable => {
|
|
1054
|
-
// we don't need to alter options since we can just check there are no quotes (also tells us no prefixes are used) and no operators are defined
|
|
1055
|
-
const res = self.parse(variable)
|
|
1056
|
-
if (res instanceof ConditionNode &&
|
|
1057
|
-
res.operator === undefined &&
|
|
1058
|
-
res.value instanceof VariableNode &&
|
|
1059
|
-
res.value.quote === undefined) {
|
|
1060
|
-
return { suggestion, value: res.value.value.value }
|
|
1061
|
-
} else {
|
|
1062
|
-
return { suggestion, value: quote + variable.replace(new RegExp(quote, "g"), `\\${quote}`) + quote }
|
|
1063
|
-
}
|
|
1064
|
-
})
|
|
1053
|
+
return arr.map(variable => ({ suggestion, value: escapeVariableOrPrefix(variable, quote) }))
|
|
1065
1054
|
}
|
|
1066
|
-
case SUGGESTION_TYPE.PREFIX: return prefixes.map(prefix => {
|
|
1067
|
-
const res = self.parse(prefix)
|
|
1068
|
-
if (res instanceof ConditionNode &&
|
|
1069
|
-
res.operator === undefined &&
|
|
1070
|
-
res.value instanceof VariableNode &&
|
|
1071
|
-
res.value.quote === undefined) {
|
|
1072
|
-
return { suggestion, value: res.value.value.value }
|
|
1073
|
-
} else {
|
|
1074
|
-
return { suggestion, value: quote + prefix.replace(new RegExp(quote, "g"), `\\${quote}`) + quote }
|
|
1075
|
-
}
|
|
1076
|
-
})
|
|
1055
|
+
case SUGGESTION_TYPE.PREFIX: return prefixes.map(prefix => ({ suggestion, value: escapeVariableOrPrefix(prefix, quote) }))
|
|
1077
1056
|
}
|
|
1078
1057
|
}).flat()
|
|
1079
1058
|
}
|
|
1080
1059
|
|
|
1081
1060
|
/**
|
|
1082
|
-
* Given the input string and a @
|
|
1061
|
+
* Given the input string and a {@link Completion} consisting of the value of the replacement and a {@link Suggestion} entry, returns the replacement string and the new position of the cursor.
|
|
1083
1062
|
*
|
|
1084
|
-
* The value passed should be escaped if it's needed (or quoted). @
|
|
1063
|
+
* The value passed should be escaped if it's needed (or quoted). {@link autocomplete} already takes care of quoting variables if you're using it.
|
|
1085
1064
|
*/
|
|
1086
1065
|
autoreplace(
|
|
1087
1066
|
input: string,
|
|
@@ -1119,9 +1098,9 @@ export class Parser<T extends {} = {}> {
|
|
|
1119
1098
|
}
|
|
1120
1099
|
|
|
1121
1100
|
/**
|
|
1122
|
-
* Returns a list of suggestions ( @
|
|
1101
|
+
* Returns a list of suggestions ( {@link Suggestion} ). These are not a list of autocomplete entries (with values), but more a list of entries describing possible suggestions. This list can then be passed to {@link Parser}["autocomplete"] to build a list to show users, from which you can then pick an entry to pass to {@link Parser}["autoreplace"] .
|
|
1123
1102
|
*
|
|
1124
|
-
* The list returned is "unsorted", but there is still some logic to the order. Fixes for errors are suggested first, in the order returned by @
|
|
1103
|
+
* The list returned is "unsorted", but there is still some logic to the order. Fixes for errors are suggested first, in the order returned by {@link getSurroundingErrors}. Regular suggestions come after in the following order: prefixes if enabled, variables, boolean symbol operators, then boolean word operators.
|
|
1125
1104
|
*
|
|
1126
1105
|
* When the cursor is between two tokens that have possible suggestions, only suggestion types for the token before are returned. For example:
|
|
1127
1106
|
*
|
|
@@ -1141,6 +1120,7 @@ export class Parser<T extends {} = {}> {
|
|
|
1141
1120
|
* ```
|
|
1142
1121
|
*/
|
|
1143
1122
|
autosuggest(input: string, ast: ParserResults, index: number): Suggestion[] {
|
|
1123
|
+
const parentMap = generateParentsMap(ast)
|
|
1144
1124
|
// wrapped like this because the function is HUGE
|
|
1145
1125
|
const opts = (this as any as Parser<T>).options
|
|
1146
1126
|
const tokens = extractTokens(ast)
|
|
@@ -1171,7 +1151,7 @@ export class Parser<T extends {} = {}> {
|
|
|
1171
1151
|
: requiresWhitespaceNext
|
|
1172
1152
|
|
|
1173
1153
|
const suggestions: Suggestion[] = []
|
|
1174
|
-
if (ast
|
|
1154
|
+
if (isToken(ast) && !ast.valid) {
|
|
1175
1155
|
suggestions.push({
|
|
1176
1156
|
type: SUGGESTION_TYPE.PREFIX,
|
|
1177
1157
|
requires: createDefaultRequires({ group: true }),
|
|
@@ -1207,8 +1187,9 @@ export class Parser<T extends {} = {}> {
|
|
|
1207
1187
|
case TOKEN_TYPE.DOUBLEQUOTE:
|
|
1208
1188
|
case TOKEN_TYPE.SINGLEQUOTE:
|
|
1209
1189
|
case TOKEN_TYPE.BACKTICK: {
|
|
1210
|
-
const
|
|
1211
|
-
const
|
|
1190
|
+
const errorParent = getParent(error, parentMap)
|
|
1191
|
+
const isLeft = (errorParent as VariableNode).quote!.left === error
|
|
1192
|
+
const isRight = (errorParent as VariableNode).quote!.right === error
|
|
1212
1193
|
suggestions.push({
|
|
1213
1194
|
...errorSuggestion,
|
|
1214
1195
|
type: type as any as SUGGESTION_TYPE,
|
|
@@ -1254,10 +1235,13 @@ export class Parser<T extends {} = {}> {
|
|
|
1254
1235
|
})
|
|
1255
1236
|
break
|
|
1256
1237
|
case TOKEN_TYPE.VALUE: {
|
|
1257
|
-
const
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
|
|
1238
|
+
const errorParent = getParent(error, parentMap)
|
|
1239
|
+
const prefixedValue = errorParent?.type === AST_TYPE.VARIABLE
|
|
1240
|
+
? (getParent(error, parentMap) as VariableNode)?.prefix?.value
|
|
1241
|
+
: false
|
|
1242
|
+
const isRegexValue = errorParent?.type === AST_TYPE.VARIABLE && (
|
|
1243
|
+
errorParent.quote?.left.type === TOKEN_TYPE.REGEX ||
|
|
1244
|
+
errorParent.quote?.right.type === TOKEN_TYPE.REGEX
|
|
1261
1245
|
)
|
|
1262
1246
|
if (!isRegexValue) {
|
|
1263
1247
|
// both are always suggested since missing value tokens only happen for variables
|
|
@@ -1322,22 +1306,23 @@ export class Parser<T extends {} = {}> {
|
|
|
1322
1306
|
}
|
|
1323
1307
|
}
|
|
1324
1308
|
}
|
|
1309
|
+
|
|
1325
1310
|
|
|
1326
1311
|
/** The quotes are checked because of situations like `prefix|"var"`.*/
|
|
1327
|
-
const prevVar = token.valid.prev
|
|
1328
|
-
const nextVar = token.valid.next
|
|
1329
|
-
const prevCondition = prevVar
|
|
1330
|
-
const nextCondition = nextVar
|
|
1331
|
-
const atVar = token.at
|
|
1332
|
-
const atCondition = atVar
|
|
1312
|
+
const prevVar = getParent(token.valid.prev, parentMap)
|
|
1313
|
+
const nextVar = getParent(token.valid.next, parentMap)
|
|
1314
|
+
const prevCondition = getParent(prevVar, parentMap)
|
|
1315
|
+
const nextCondition = getParent(nextVar, parentMap)
|
|
1316
|
+
const atVar = getParent(token.at, parentMap)
|
|
1317
|
+
const atCondition = getParent(atVar, parentMap)
|
|
1333
1318
|
|
|
1334
1319
|
const isVarPrev =
|
|
1335
1320
|
!token.whitespace.prev &&
|
|
1336
1321
|
token.valid.prev?.type !== TOKEN_TYPE.REGEX &&
|
|
1337
|
-
prevVar
|
|
1322
|
+
prevVar?.type === AST_TYPE.VARIABLE &&
|
|
1338
1323
|
(
|
|
1339
1324
|
(
|
|
1340
|
-
prevCondition
|
|
1325
|
+
prevCondition?.type === AST_TYPE.CONDITION &&
|
|
1341
1326
|
prevCondition.value === prevVar &&
|
|
1342
1327
|
(
|
|
1343
1328
|
prevVar.quote?.right === token.valid.prev ||
|
|
@@ -1345,17 +1330,17 @@ export class Parser<T extends {} = {}> {
|
|
|
1345
1330
|
)
|
|
1346
1331
|
) ||
|
|
1347
1332
|
(
|
|
1348
|
-
prevCondition
|
|
1333
|
+
prevCondition?.type === AST_TYPE.ARRAY
|
|
1349
1334
|
)
|
|
1350
1335
|
)
|
|
1351
1336
|
|
|
1352
1337
|
const isVarNext =
|
|
1353
1338
|
!token.whitespace.next &&
|
|
1354
1339
|
token.valid.next?.type !== TOKEN_TYPE.REGEX &&
|
|
1355
|
-
nextVar
|
|
1356
|
-
(
|
|
1340
|
+
nextVar?.type === AST_TYPE.VARIABLE
|
|
1341
|
+
&& (
|
|
1357
1342
|
(
|
|
1358
|
-
nextCondition
|
|
1343
|
+
nextCondition?.type === AST_TYPE.CONDITION &&
|
|
1359
1344
|
nextCondition.value === nextVar &&
|
|
1360
1345
|
(
|
|
1361
1346
|
nextVar.quote?.left === token.valid.next ||
|
|
@@ -1363,41 +1348,44 @@ export class Parser<T extends {} = {}> {
|
|
|
1363
1348
|
)
|
|
1364
1349
|
) ||
|
|
1365
1350
|
(
|
|
1366
|
-
nextCondition
|
|
1351
|
+
nextCondition?.type === AST_TYPE.ARRAY
|
|
1367
1352
|
)
|
|
1368
1353
|
)
|
|
1369
1354
|
|
|
1370
1355
|
const isVarAt = (
|
|
1371
1356
|
(
|
|
1372
|
-
atVar
|
|
1373
|
-
atCondition
|
|
1357
|
+
atVar?.type === AST_TYPE.VARIABLE &&
|
|
1358
|
+
atCondition?.type === AST_TYPE.CONDITION
|
|
1374
1359
|
) ||
|
|
1375
1360
|
(
|
|
1376
|
-
prevVar
|
|
1361
|
+
prevVar?.type === AST_TYPE.VARIABLE &&
|
|
1377
1362
|
token.valid.prev === prevVar?.quote?.left) ||
|
|
1378
1363
|
|
|
1379
1364
|
(
|
|
1380
|
-
nextVar
|
|
1365
|
+
nextVar?.type === AST_TYPE.VARIABLE &&
|
|
1381
1366
|
token.valid.next === nextVar?.quote?.right
|
|
1382
1367
|
)
|
|
1383
1368
|
)
|
|
1384
1369
|
|
|
1385
1370
|
const isPropertyPrev =
|
|
1386
|
-
prevCondition
|
|
1371
|
+
prevCondition?.type === AST_TYPE.CONDITION &&
|
|
1387
1372
|
prevVar !== undefined &&
|
|
1388
1373
|
prevVar === prevCondition?.property
|
|
1389
1374
|
const isPropertyNext =
|
|
1390
|
-
nextCondition
|
|
1375
|
+
nextCondition?.type === AST_TYPE.CONDITION &&
|
|
1391
1376
|
nextVar !== undefined &&
|
|
1392
1377
|
nextVar === nextCondition?.property
|
|
1393
1378
|
const isPropertyAt =
|
|
1394
|
-
atCondition
|
|
1379
|
+
atCondition?.type === AST_TYPE.CONDITION &&
|
|
1395
1380
|
atVar !== undefined &&
|
|
1396
1381
|
atVar === atCondition?.property
|
|
1397
1382
|
|
|
1398
|
-
const isPropertyOperatorPrev = prevVar
|
|
1399
|
-
|
|
1400
|
-
const
|
|
1383
|
+
const isPropertyOperatorPrev = prevVar?.type === AST_TYPE.CONDITION
|
|
1384
|
+
&& token.valid.prev === prevVar?.propertyOperator
|
|
1385
|
+
const isPropertyOperatorNext = nextVar?.type === AST_TYPE.CONDITION
|
|
1386
|
+
&& token.valid.next === nextVar?.propertyOperator
|
|
1387
|
+
const isPropertyOperatorAt = atVar?.type === AST_TYPE.CONDITION
|
|
1388
|
+
&& token.at === atVar?.propertyOperator
|
|
1401
1389
|
|
|
1402
1390
|
/** Situations like `[|]` and `[|` */
|
|
1403
1391
|
const noArrayValuesTarget = token.valid.prev?.type === TOKEN_TYPE.BRACKETL &&
|
|
@@ -1434,24 +1422,26 @@ export class Parser<T extends {} = {}> {
|
|
|
1434
1422
|
|
|
1435
1423
|
|
|
1436
1424
|
if (target) {
|
|
1437
|
-
const parent = target
|
|
1438
|
-
if (parent
|
|
1425
|
+
const parent = getParent(target, parentMap)
|
|
1426
|
+
if (parent && parent.type === AST_TYPE.VARIABLE) {
|
|
1439
1427
|
const range = pos(parent)
|
|
1440
|
-
const
|
|
1428
|
+
const parentParent = getParent(parent, parentMap)
|
|
1429
|
+
const condition = parentParent as ConditionNode
|
|
1441
1430
|
const isValue = condition.propertyOperator !== undefined && condition.value === parent
|
|
1442
|
-
const maybeGroup =
|
|
1443
|
-
const isPrefix = maybeGroup
|
|
1431
|
+
const maybeGroup = getParent(parentParent, parentMap)
|
|
1432
|
+
const isPrefix = maybeGroup?.type === AST_TYPE.GROUP
|
|
1433
|
+
&& maybeGroup.prefix === condition
|
|
1444
1434
|
|
|
1445
1435
|
// look at whitespace before/after the entire variable
|
|
1446
1436
|
const varStart = getCursorInfo(input, ast, parent.start)
|
|
1447
1437
|
const varEnd = getCursorInfo(input, ast, parent.end)
|
|
1448
1438
|
const targetRequiresWhitespacePrev = tokenRequiresWhitespace(varStart.valid.prev, varStart.whitespace.prev, wordOps)
|
|
1449
1439
|
const targetRequiresWhitespaceNext = tokenRequiresWhitespace(varEnd.valid.next, varEnd.whitespace.next, wordOps)
|
|
1450
|
-
const prefixedValue =
|
|
1440
|
+
const prefixedValue = parent.type === AST_TYPE.VARIABLE ? parent?.prefix?.value : false
|
|
1451
1441
|
|
|
1452
1442
|
// most of these require additional handling below
|
|
1453
1443
|
const isSepPrev = token.prev?.type === TOKEN_TYPE.OP_EXPANDED_SEP
|
|
1454
|
-
const arrayValue =
|
|
1444
|
+
const arrayValue = parentParent?.type === AST_TYPE.ARRAY
|
|
1455
1445
|
const isRegexFlag = target === parent.quote?.flags
|
|
1456
1446
|
|
|
1457
1447
|
if (!isRegexFlag && !isSepPrev && !isValue && !arrayValue && !prefixedValue && opts.prefixableGroups) {
|
|
@@ -1508,9 +1498,10 @@ export class Parser<T extends {} = {}> {
|
|
|
1508
1498
|
})
|
|
1509
1499
|
}
|
|
1510
1500
|
if (propOpTarget) {
|
|
1501
|
+
const propOpTargetParent = getParent(propOpTarget, parentMap)
|
|
1511
1502
|
suggestions.push({
|
|
1512
1503
|
...baseSuggestion,
|
|
1513
|
-
type: (
|
|
1504
|
+
type: (propOpTargetParent as ConditionNode).sep
|
|
1514
1505
|
? SUGGESTION_TYPE.EXPANDED_PROPERTY_OPERATOR
|
|
1515
1506
|
: SUGGESTION_TYPE.CUSTOM_PROPERTY_OPERATOR
|
|
1516
1507
|
,
|
|
@@ -1540,7 +1531,7 @@ export class Parser<T extends {} = {}> {
|
|
|
1540
1531
|
)
|
|
1541
1532
|
|
|
1542
1533
|
if (canSuggestValue) {
|
|
1543
|
-
const inArrayNode = [nextCondition, prevCondition, nextVar, prevVar].find(_ => _
|
|
1534
|
+
const inArrayNode = [nextCondition, prevCondition, nextVar, prevVar].find(_ => _?.type === AST_TYPE.ARRAY) !== undefined
|
|
1544
1535
|
const opsNotNeeded = ["and", "or"].includes(opts.onMissingBooleanOperator)
|
|
1545
1536
|
|
|
1546
1537
|
|
|
@@ -1564,24 +1555,26 @@ export class Parser<T extends {} = {}> {
|
|
|
1564
1555
|
})
|
|
1565
1556
|
}
|
|
1566
1557
|
}
|
|
1567
|
-
|
|
1558
|
+
const tokenAtParent = getParent(token.at, parentMap)
|
|
1559
|
+
const tokenValidPrevParent = getParent(token.valid.prev, parentMap)
|
|
1560
|
+
const tokenValidNextParent = getParent(token.valid.next, parentMap)
|
|
1568
1561
|
const canSuggestRegexFlags =
|
|
1569
1562
|
// has existing flags before/after
|
|
1570
1563
|
(
|
|
1571
1564
|
token.at &&
|
|
1572
|
-
token.at === (
|
|
1565
|
+
token.at === (tokenAtParent as VariableNode)?.quote?.flags
|
|
1573
1566
|
) ||
|
|
1574
1567
|
(
|
|
1575
1568
|
token.valid.prev &&
|
|
1576
|
-
token.valid.prev === (
|
|
1569
|
+
token.valid.prev === (tokenValidPrevParent as VariableNode)?.quote?.flags
|
|
1577
1570
|
) ||
|
|
1578
1571
|
(
|
|
1579
1572
|
token.valid.next &&
|
|
1580
|
-
token.valid.next === (
|
|
1573
|
+
token.valid.next === (tokenValidNextParent as VariableNode)?.quote?.flags
|
|
1581
1574
|
) ||
|
|
1582
1575
|
( // no flags
|
|
1583
1576
|
token.valid.prev?.type === TOKEN_TYPE.REGEX &&
|
|
1584
|
-
token.valid.prev === (
|
|
1577
|
+
token.valid.prev === (tokenValidPrevParent as VariableNode).quote?.right
|
|
1585
1578
|
)
|
|
1586
1579
|
|
|
1587
1580
|
if (canSuggestRegexFlags) {
|
|
@@ -1622,16 +1615,16 @@ export class Parser<T extends {} = {}> {
|
|
|
1622
1615
|
*
|
|
1623
1616
|
* How the ast is evaluated for different operators can be controlled by the {@link ParserOptions.valueComparer valueComparer} option.
|
|
1624
1617
|
*/
|
|
1625
|
-
evaluate(ast:
|
|
1618
|
+
evaluate(ast: NormalizedExpression<any, any> | NormalizedCondition<any, any>, context: Record<string, any>): boolean {
|
|
1626
1619
|
this._checkEvaluationOptions()
|
|
1627
1620
|
const opts = (this as any as Parser<T>).options
|
|
1628
1621
|
|
|
1629
|
-
if (ast
|
|
1622
|
+
if (ast.type === AST_TYPE.NORMALIZED_CONDITION) {
|
|
1630
1623
|
const contextValue = get(context, ast.property)
|
|
1631
|
-
const res = opts.valueComparer(
|
|
1624
|
+
const res = opts.valueComparer(ast, contextValue, context)
|
|
1632
1625
|
return ast.negate ? !res : res
|
|
1633
1626
|
}
|
|
1634
|
-
if (ast
|
|
1627
|
+
if (ast.type === AST_TYPE.NORMALIZED_EXPRESSION) {
|
|
1635
1628
|
const left = this.evaluate(ast.left, context)
|
|
1636
1629
|
const right = this.evaluate(ast.right, context)
|
|
1637
1630
|
|
|
@@ -1705,11 +1698,11 @@ export class Parser<T extends {} = {}> {
|
|
|
1705
1698
|
*
|
|
1706
1699
|
* Queries like `(a || b) && (a || c)` would require all the variables to be indexed `[Set(a), Set(b), Set(c)]`.
|
|
1707
1700
|
*/
|
|
1708
|
-
getIndexes(ast:
|
|
1709
|
-
if (ast
|
|
1701
|
+
getIndexes(ast: NormalizedCondition | NormalizedExpression): Set<string>[] {
|
|
1702
|
+
if (ast.type === AST_TYPE.NORMALIZED_CONDITION) {
|
|
1710
1703
|
return [new Set(ast.property.join("."))]
|
|
1711
1704
|
}
|
|
1712
|
-
if (ast
|
|
1705
|
+
if (ast.type === AST_TYPE.NORMALIZED_EXPRESSION) {
|
|
1713
1706
|
const left = this.getIndexes(ast.left)
|
|
1714
1707
|
const right = this.getIndexes(ast.right)
|
|
1715
1708
|
|
|
@@ -1779,10 +1772,10 @@ export class Parser<T extends {} = {}> {
|
|
|
1779
1772
|
/**
|
|
1780
1773
|
* Normalizes the ast by applying {@link GroupNode GroupNodes} and converting {@link ConditionNode ConditionNodes} to {@link NormalizedConditionNode NormalizedConditionNodes}.
|
|
1781
1774
|
*/
|
|
1782
|
-
normalize<TType extends string, TValue>(ast: ParserResults):
|
|
1775
|
+
normalize<TType extends string, TValue>(ast: ParserResults): NormalizedCondition<TType, TValue> | NormalizedExpression<TType, TValue> {
|
|
1783
1776
|
this._checkEvaluationOptions()
|
|
1784
1777
|
const opts = (this as any as Parser<T>).options
|
|
1785
|
-
if (
|
|
1778
|
+
if (!ast.valid) {
|
|
1786
1779
|
throw new Error("AST node must be valid.")
|
|
1787
1780
|
}
|
|
1788
1781
|
// eslint-disable-next-line prefer-rest-params
|
|
@@ -1794,16 +1787,16 @@ export class Parser<T extends {} = {}> {
|
|
|
1794
1787
|
|
|
1795
1788
|
const self_ = this as any as Parser & { normalize: AddParameters<Parser["normalize"], [typeof prefix, typeof groupValue, typeof operator]> }
|
|
1796
1789
|
|
|
1797
|
-
if (ast
|
|
1798
|
-
if (!(ast.value
|
|
1799
|
-
const isValue = ast.value
|
|
1800
|
-
let name = ast.property
|
|
1790
|
+
if (ast.type === AST_TYPE.CONDITION) {
|
|
1791
|
+
if (!(ast.value.type === AST_TYPE.GROUP)) {
|
|
1792
|
+
const isValue = ast.value.type === AST_TYPE.ARRAY || (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
|
|
1793
|
+
let name = ast.property?.value?.value
|
|
1801
1794
|
? unescape(ast.property.value.value)
|
|
1802
1795
|
: isValue
|
|
1803
1796
|
// the property might be missing, whether this is valid or not is up to the user
|
|
1804
1797
|
// e.g. if prefix is defined this would make some sense
|
|
1805
1798
|
? undefined
|
|
1806
|
-
: unescape((ast.value as VariableNode)
|
|
1799
|
+
: unescape((ast.value as VariableNode)!.value!.value!)
|
|
1807
1800
|
// some ancestor node went through the else block because it was a group node (e.g. prop:op(val))
|
|
1808
1801
|
// so the "prefix" we passed is actually the name of the property (e.g. prop) and the value is the name we're getting here (e.g. val)
|
|
1809
1802
|
const isNested = operator !== undefined
|
|
@@ -1815,18 +1808,18 @@ export class Parser<T extends {} = {}> {
|
|
|
1815
1808
|
value = name ?? true
|
|
1816
1809
|
name = prefix
|
|
1817
1810
|
} else {
|
|
1818
|
-
value = ast.value
|
|
1819
|
-
? ast.value.values.map(val => unescape(val.value.value))
|
|
1811
|
+
value = ast.value.type === AST_TYPE.ARRAY
|
|
1812
|
+
? ast.value.values.map(val => unescape(val.value.value!))
|
|
1820
1813
|
: (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
|
|
1821
|
-
? ast.value.value
|
|
1822
|
-
: ast.property && ast.value
|
|
1823
|
-
? unescape(ast.value.value.value)
|
|
1814
|
+
? ast.value.value?.value
|
|
1815
|
+
: ast.property && ast.value.type === AST_TYPE.VARIABLE
|
|
1816
|
+
? unescape(ast.value.value.value!)
|
|
1824
1817
|
: true
|
|
1825
1818
|
}
|
|
1826
1819
|
const propertyKeys = name ? opts.keyParser(name) : []
|
|
1827
1820
|
|
|
1828
1821
|
const boolValue = applyBoolean(groupValue, ast.operator === undefined)
|
|
1829
|
-
const valuePrefix = ast.value
|
|
1822
|
+
const valuePrefix = ast.value.type === AST_TYPE.VARIABLE && ast.value.prefix
|
|
1830
1823
|
? unescape(ast.value.prefix.value)
|
|
1831
1824
|
: undefined
|
|
1832
1825
|
// one or the other might be defined, but never both since nested properties (e.g. `prop:op(prop:op(...))`) are not allowed
|
|
@@ -1848,9 +1841,9 @@ export class Parser<T extends {} = {}> {
|
|
|
1848
1841
|
condition: ast,
|
|
1849
1842
|
}
|
|
1850
1843
|
const res = opts.conditionNormalizer(query)
|
|
1851
|
-
return
|
|
1844
|
+
return createCondition({ property: propertyKeys, ...res })
|
|
1852
1845
|
} else {
|
|
1853
|
-
let name = unescape((ast.property as VariableNode).value.value) // this is always a variable node
|
|
1846
|
+
let name = unescape((ast.property as VariableNode).value.value!) // this is always a variable node
|
|
1854
1847
|
if (prefix !== undefined) {
|
|
1855
1848
|
name = applyPrefix(prefix, name, opts.prefixApplier)
|
|
1856
1849
|
}
|
|
@@ -1863,26 +1856,26 @@ export class Parser<T extends {} = {}> {
|
|
|
1863
1856
|
}
|
|
1864
1857
|
}
|
|
1865
1858
|
|
|
1866
|
-
if (ast
|
|
1867
|
-
const _prefix = ast.prefix
|
|
1868
|
-
? unescape(ast.prefix.value.value.value)
|
|
1859
|
+
if (ast.type === AST_TYPE.GROUP) {
|
|
1860
|
+
const _prefix = ast.prefix?.type === AST_TYPE.CONDITION && ast.prefix?.value.type === AST_TYPE.VARIABLE
|
|
1861
|
+
? unescape(ast.prefix.value.value.value!)
|
|
1869
1862
|
: undefined // we do not want to apply not tokens
|
|
1870
|
-
const _groupValue = ast.prefix
|
|
1863
|
+
const _groupValue = ast.prefix?.type === AST_TYPE.CONDITION
|
|
1871
1864
|
? ast.prefix.operator === undefined
|
|
1872
|
-
: !(ast.prefix
|
|
1865
|
+
: !(ast.prefix?.valid === true)
|
|
1873
1866
|
|
|
1874
1867
|
const applied = applyPrefix(prefix, _prefix ?? "", opts.prefixApplier)
|
|
1875
1868
|
|
|
1876
1869
|
return self_.normalize(ast.expression as any, applied, applyBoolean(groupValue, _groupValue), operator) as any
|
|
1877
1870
|
}
|
|
1878
|
-
if (ast
|
|
1871
|
+
if (ast.type === AST_TYPE.EXPRESSION) {
|
|
1879
1872
|
const left = self_.normalize(ast.left, prefix, groupValue, operator)
|
|
1880
1873
|
const right = self_.normalize(ast.right, prefix, groupValue, operator)
|
|
1881
1874
|
|
|
1882
1875
|
// apply De Morgan's laws if group prefix was negative
|
|
1883
1876
|
// the values are already flipped, we just have to flip the operator
|
|
1884
|
-
const type: TokenBooleanTypes = (groupValue === false ? OPPOSITE[ast.operator
|
|
1885
|
-
return
|
|
1877
|
+
const type: TokenBooleanTypes = (groupValue === false ? OPPOSITE[ast.operator!.type!] : ast.operator.type) as TokenBooleanTypes
|
|
1878
|
+
return createExpression<TType, TValue>({ operator: type, left: left as any, right: right as any })
|
|
1886
1879
|
}
|
|
1887
1880
|
return unreachable()
|
|
1888
1881
|
}
|
|
@@ -1898,7 +1891,7 @@ export class Parser<T extends {} = {}> {
|
|
|
1898
1891
|
self._checkValidationOptions()
|
|
1899
1892
|
const opts = self.options
|
|
1900
1893
|
// see evaluate function, this method is practically identical, except we don't keep track of the real value (since we are not evaluating) and the actual nodes/tokens are passed to the valueValidator, not just the string values.
|
|
1901
|
-
if (
|
|
1894
|
+
if (!ast.valid) {
|
|
1902
1895
|
throw new Error("AST node must be valid.")
|
|
1903
1896
|
}
|
|
1904
1897
|
/** Handle hidden recursive version of the function. */
|
|
@@ -1915,16 +1908,16 @@ export class Parser<T extends {} = {}> {
|
|
|
1915
1908
|
|
|
1916
1909
|
const self_ = this as any as Parser & { validate: AddParameters<Parser["validate"], [typeof prefix, typeof groupValue, typeof results, typeof prefixes, typeof operator]> }
|
|
1917
1910
|
|
|
1918
|
-
if (ast
|
|
1919
|
-
if (!(ast.value
|
|
1920
|
-
const isValue = ast.value
|
|
1911
|
+
if (ast.type === AST_TYPE.CONDITION) {
|
|
1912
|
+
if (!(ast.value.type === AST_TYPE.GROUP)) {
|
|
1913
|
+
const isValue = ast.value.type === AST_TYPE.ARRAY || (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
|
|
1921
1914
|
const nameNode = ast.property
|
|
1922
1915
|
? ast.property as VariableNode
|
|
1923
1916
|
: isValue
|
|
1924
1917
|
? undefined
|
|
1925
1918
|
: ast.value as VariableNode
|
|
1926
1919
|
|
|
1927
|
-
let name = nameNode ? unescape(nameNode.value.value) : undefined
|
|
1920
|
+
let name = nameNode ? unescape(nameNode.value.value!) : undefined
|
|
1928
1921
|
const isNested = operator !== undefined
|
|
1929
1922
|
if (prefix !== undefined && !isNested) {
|
|
1930
1923
|
name = name ? applyPrefix(prefix, name, opts.prefixApplier) : prefix
|
|
@@ -1938,11 +1931,11 @@ export class Parser<T extends {} = {}> {
|
|
|
1938
1931
|
propertyNodes = [...prefixes]
|
|
1939
1932
|
} else {
|
|
1940
1933
|
propertyNodes = [...prefixes, ...(nameNode ? [nameNode] : [])]
|
|
1941
|
-
value = ast.value
|
|
1934
|
+
value = ast.value.type === AST_TYPE.ARRAY
|
|
1942
1935
|
? ast.value.values
|
|
1943
1936
|
: (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX
|
|
1944
1937
|
? ast.value
|
|
1945
|
-
: ast.property && ast.value
|
|
1938
|
+
: ast.property && ast.value.type === AST_TYPE.VARIABLE
|
|
1946
1939
|
? ast.value
|
|
1947
1940
|
: true
|
|
1948
1941
|
}
|
|
@@ -1950,7 +1943,7 @@ export class Parser<T extends {} = {}> {
|
|
|
1950
1943
|
const contextValue = context !== undefined ? get(context, propertyKeys) : undefined
|
|
1951
1944
|
|
|
1952
1945
|
const boolValue = applyBoolean(groupValue, ast.operator === undefined)
|
|
1953
|
-
const valuePrefix = ast.value
|
|
1946
|
+
const valuePrefix = ast.value.type === AST_TYPE.VARIABLE && ast.value.prefix
|
|
1954
1947
|
? ast.value.prefix
|
|
1955
1948
|
: undefined
|
|
1956
1949
|
operator ??= ast.propertyOperator as ValidToken<TOKEN_TYPE.VALUE | TOKEN_TYPE.OP_CUSTOM>
|
|
@@ -1977,7 +1970,7 @@ export class Parser<T extends {} = {}> {
|
|
|
1977
1970
|
if (res && !isArray(res)) throw new Error("The valueValidator must return an array or nothing/undefined")
|
|
1978
1971
|
if (res) { for (const entry of res) results.push(entry) }
|
|
1979
1972
|
} else {
|
|
1980
|
-
let name = unescape((ast.property as VariableNode).value.value) // this is always a variable node
|
|
1973
|
+
let name = unescape((ast.property as VariableNode).value.value!) // this is always a variable node
|
|
1981
1974
|
if (prefix !== undefined) {
|
|
1982
1975
|
name = applyPrefix(prefix, name, opts.prefixApplier)
|
|
1983
1976
|
}
|
|
@@ -1991,19 +1984,19 @@ export class Parser<T extends {} = {}> {
|
|
|
1991
1984
|
}
|
|
1992
1985
|
}
|
|
1993
1986
|
|
|
1994
|
-
if (ast
|
|
1995
|
-
const _prefix = ast.prefix
|
|
1987
|
+
if (ast.type === AST_TYPE.GROUP) {
|
|
1988
|
+
const _prefix = ast.prefix?.type === AST_TYPE.CONDITION && ast.prefix.value.type === AST_TYPE.VARIABLE
|
|
1996
1989
|
? ast.prefix.value
|
|
1997
1990
|
: undefined // we do not want to apply not tokens
|
|
1998
1991
|
if (_prefix) prefixes.push(_prefix)
|
|
1999
1992
|
|
|
2000
|
-
const _groupValue = ast.prefix
|
|
1993
|
+
const _groupValue = ast.prefix?.type === AST_TYPE.CONDITION
|
|
2001
1994
|
? ast.prefix.operator === undefined
|
|
2002
|
-
: !(ast.prefix
|
|
1995
|
+
: !(ast.prefix?.valid === true)
|
|
2003
1996
|
|
|
2004
1997
|
self_.validate(ast.expression as any, context, applyPrefix(prefix, _prefix?.value.value ?? "", opts.prefixApplier), applyBoolean(groupValue, _groupValue), results, prefixes, operator)
|
|
2005
1998
|
}
|
|
2006
|
-
if (ast
|
|
1999
|
+
if (ast.type === AST_TYPE.EXPRESSION) {
|
|
2007
2000
|
// prefixes must be spread because we don't want the left branch (if it goes deeper) to affect the right
|
|
2008
2001
|
self_.validate(ast.left, context, prefix, groupValue, results, [...prefixes], operator)
|
|
2009
2002
|
self_.validate(ast.right, context, prefix, groupValue, results, [...prefixes], operator)
|