@xano/xanoscript-language-server 11.8.3 → 11.8.5
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/.claude/settings.local.json +2 -1
- package/cache/documentCache.js +58 -10
- package/lexer/db.js +9 -1
- package/lexer/security.js +16 -0
- package/onCompletion/onCompletion.js +61 -1
- package/onDefinition/onDefinition.js +150 -0
- package/onDefinition/onDefinition.spec.js +313 -0
- package/onDidChangeContent/onDidChangeContent.js +52 -5
- package/onHover/functions.md +28 -0
- package/package.json +1 -1
- package/parser/base_parser.js +61 -3
- package/parser/clauses/middlewareClause.js +16 -0
- package/parser/definitions/columnDefinition.js +5 -0
- package/parser/functions/api/apiCallFn.js +5 -3
- package/parser/functions/controls/functionCallFn.js +5 -3
- package/parser/functions/controls/functionRunFn.js +61 -5
- package/parser/functions/controls/taskCallFn.js +5 -3
- package/parser/functions/db/captureFieldName.js +63 -0
- package/parser/functions/db/dbAddFn.js +5 -3
- package/parser/functions/db/dbAddOrEditFn.js +13 -3
- package/parser/functions/db/dbBulkAddFn.js +5 -3
- package/parser/functions/db/dbBulkDeleteFn.js +5 -3
- package/parser/functions/db/dbBulkPatchFn.js +5 -3
- package/parser/functions/db/dbBulkUpdateFn.js +5 -3
- package/parser/functions/db/dbDelFn.js +10 -3
- package/parser/functions/db/dbEditFn.js +13 -3
- package/parser/functions/db/dbGetFn.js +10 -3
- package/parser/functions/db/dbHasFn.js +9 -3
- package/parser/functions/db/dbPatchFn.js +10 -3
- package/parser/functions/db/dbQueryFn.js +29 -3
- package/parser/functions/db/dbSchemaFn.js +5 -3
- package/parser/functions/db/dbTruncateFn.js +5 -3
- package/parser/functions/middlewareCallFn.js +3 -1
- package/parser/functions/security/register.js +19 -9
- package/parser/functions/security/securityCreateAuthTokenFn.js +22 -0
- package/parser/functions/security/securityJweDecodeLegacyFn.js +24 -0
- package/parser/functions/security/securityJweDecodeLegacyFn.spec.js +26 -0
- package/parser/functions/security/securityJweEncodeLegacyFn.js +24 -0
- package/parser/functions/security/securityJweEncodeLegacyFn.spec.js +25 -0
- package/parser/functions/securityFn.js +2 -0
- package/parser/functions/varFn.js +1 -1
- package/parser/generic/asVariable.js +2 -0
- package/parser/generic/assignableVariableAs.js +1 -0
- package/parser/generic/assignableVariableProperty.js +5 -2
- package/parser/table_trigger_parser.js +21 -0
- package/parser/table_trigger_parser.spec.js +29 -0
- package/parser/tests/variable_test/coverage_check.xs +293 -0
- package/parser/variableScanner.js +64 -0
- package/parser/variableValidator.js +44 -0
- package/parser/variableValidator.spec.js +179 -0
- package/server.js +164 -10
- package/utils.js +32 -0
- package/utils.spec.js +93 -1
- package/workspace/crossFileValidator.js +166 -0
- package/workspace/crossFileValidator.spec.js +654 -0
- package/workspace/referenceTracking.spec.js +420 -0
- package/workspace/workspaceIndex.js +149 -0
- package/workspace/workspaceIndex.spec.js +189 -0
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { FunctionToken, RunToken } from "../../../lexer/function.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
FloatLiteral,
|
|
4
|
+
IntegerLiteral,
|
|
5
|
+
SingleQuotedStringLiteral,
|
|
6
|
+
StringLiteral,
|
|
7
|
+
} from "../../../lexer/literal.js";
|
|
8
|
+
import { DotToken, FalseToken, Identifier, TrueToken } from "../../../lexer/tokens.js";
|
|
9
|
+
import { getVarName } from "../../generic/utils.js";
|
|
10
|
+
|
|
11
|
+
const literalTypeMap = new Map([
|
|
12
|
+
[IntegerLiteral.name, "int"],
|
|
13
|
+
[FloatLiteral.name, "decimal"],
|
|
14
|
+
[StringLiteral.name, "text"],
|
|
15
|
+
[SingleQuotedStringLiteral.name, "text"],
|
|
16
|
+
[TrueToken.name, "bool"],
|
|
17
|
+
[FalseToken.name, "bool"],
|
|
18
|
+
]);
|
|
4
19
|
|
|
5
20
|
/**
|
|
6
21
|
*
|
|
@@ -14,11 +29,13 @@ export function functionRunFn($) {
|
|
|
14
29
|
$.CONSUME(DotToken); // "."
|
|
15
30
|
const fnToken = $.CONSUME(RunToken); // "run"
|
|
16
31
|
|
|
17
|
-
$.OR([
|
|
18
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
19
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
32
|
+
const nameToken = $.OR([
|
|
33
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
34
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
20
35
|
]);
|
|
36
|
+
$.addReference("function", getVarName(nameToken), nameToken);
|
|
21
37
|
|
|
38
|
+
const captured = {};
|
|
22
39
|
$.OPTION(() => {
|
|
23
40
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
24
41
|
ARGS: [
|
|
@@ -30,10 +47,49 @@ export function functionRunFn($) {
|
|
|
30
47
|
"runtime_mode?": ["async-shared", "async-dedicated"],
|
|
31
48
|
"mock?": { "![string]": "[expression]" },
|
|
32
49
|
},
|
|
50
|
+
captured,
|
|
33
51
|
],
|
|
34
52
|
});
|
|
35
53
|
});
|
|
36
54
|
|
|
55
|
+
$.ACTION(() => {
|
|
56
|
+
if (captured.input) {
|
|
57
|
+
const args = {};
|
|
58
|
+
const tokens = $.input;
|
|
59
|
+
for (const [k, v] of Object.entries(captured.input)) {
|
|
60
|
+
if (k === "key" || k === "value") continue;
|
|
61
|
+
const keyOffset = v?.key?.startOffset;
|
|
62
|
+
|
|
63
|
+
// Find value token: scan from key token, skip colon, grab next token
|
|
64
|
+
let type = null;
|
|
65
|
+
let value = v?.value?.image ?? null;
|
|
66
|
+
if (keyOffset != null) {
|
|
67
|
+
for (let i = 0; i < tokens.length - 2; i++) {
|
|
68
|
+
if (tokens[i].startOffset === keyOffset) {
|
|
69
|
+
// tokens[i] = key, tokens[i+1] = colon, tokens[i+2] = value
|
|
70
|
+
const valueToken = tokens[i + 2];
|
|
71
|
+
if (valueToken) {
|
|
72
|
+
type = literalTypeMap.get(valueToken.tokenType.name) ?? null;
|
|
73
|
+
if (type && !value) value = valueToken.image;
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
args[k] = {
|
|
81
|
+
value,
|
|
82
|
+
type,
|
|
83
|
+
startOffset: v?.key?.startOffset ?? null,
|
|
84
|
+
endOffset: v?.key?.endOffset ?? null,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (Object.keys(args).length > 0) {
|
|
88
|
+
$.setReferenceArgs(args);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
37
93
|
$.SUBRULE($.asVariable, { ARGS: [fnToken] });
|
|
38
94
|
$.sectionStack.pop();
|
|
39
95
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
2
2
|
import { CallToken, TaskToken } from "../../../lexer/task.js";
|
|
3
3
|
import { DotToken, Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
@@ -17,10 +18,11 @@ export function taskCallFn($) {
|
|
|
17
18
|
$.CONSUME(DotToken); // "."
|
|
18
19
|
const fnToken = $.CONSUME(CallToken); // "call"
|
|
19
20
|
|
|
20
|
-
$.OR([
|
|
21
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
22
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
21
|
+
const nameToken = $.OR([
|
|
22
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
23
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
23
24
|
]);
|
|
25
|
+
$.addReference("task", getVarName(nameToken), nameToken);
|
|
24
26
|
|
|
25
27
|
$.SUBRULE($.functionAttrReq, {
|
|
26
28
|
ARGS: [fnToken, requiredAttrs, optionalAttrs],
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { SingleQuotedStringLiteral,StringLiteral } from "../../../lexer/literal.js";
|
|
2
|
+
import { Identifier } from "../../../lexer/tokens.js";
|
|
3
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
|
+
|
|
5
|
+
const identifierLikeTokens = new Set([
|
|
6
|
+
Identifier.name,
|
|
7
|
+
StringLiteral.name,
|
|
8
|
+
SingleQuotedStringLiteral.name,
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Extract data object keys from captured schema and attach to last reference.
|
|
13
|
+
* @param {import('../../base_parser.js').XanoBaseParser} $
|
|
14
|
+
* @param {Object} captured
|
|
15
|
+
*/
|
|
16
|
+
export function captureDataKeys($, captured) {
|
|
17
|
+
if (!captured.data) return;
|
|
18
|
+
|
|
19
|
+
const dataKeys = [];
|
|
20
|
+
for (const [k, v] of Object.entries(captured.data)) {
|
|
21
|
+
if (k === "key" || k === "value") continue;
|
|
22
|
+
const keyToken = v?.key;
|
|
23
|
+
if (keyToken) {
|
|
24
|
+
dataKeys.push({
|
|
25
|
+
name: k,
|
|
26
|
+
startOffset: keyToken.startOffset,
|
|
27
|
+
endOffset: keyToken.endOffset,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (dataKeys.length > 0) {
|
|
32
|
+
$.setReferenceDataKeys(dataKeys);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Extract field_name value from captured schema object and attach to last reference.
|
|
38
|
+
* Only captures when the value is an identifier or string literal (not a variable expression).
|
|
39
|
+
* @param {import('../../base_parser.js').XanoBaseParser} $
|
|
40
|
+
* @param {Object} captured
|
|
41
|
+
*/
|
|
42
|
+
export function captureFieldName($, captured) {
|
|
43
|
+
if (!captured.field_name) return;
|
|
44
|
+
|
|
45
|
+
const keyOffset = captured.field_name.key?.startOffset;
|
|
46
|
+
if (keyOffset == null) return;
|
|
47
|
+
|
|
48
|
+
const tokens = $.input;
|
|
49
|
+
for (let i = 0; i < tokens.length - 2; i++) {
|
|
50
|
+
if (tokens[i].startOffset === keyOffset) {
|
|
51
|
+
// tokens[i] = "field_name" key, tokens[i+1] = "=", tokens[i+2] = value
|
|
52
|
+
const valueToken = tokens[i + 2];
|
|
53
|
+
if (valueToken && identifierLikeTokens.has(valueToken.tokenType.name)) {
|
|
54
|
+
$.setReferenceFieldName(
|
|
55
|
+
getVarName(valueToken),
|
|
56
|
+
valueToken.startOffset,
|
|
57
|
+
valueToken.endOffset
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AddToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
import { addonSchema } from "./schema.js";
|
|
5
6
|
/**
|
|
6
7
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -10,13 +11,14 @@ export function dbAddFn($) {
|
|
|
10
11
|
$.sectionStack.push("dbAddFn");
|
|
11
12
|
const fnToken = $.CONSUME(AddToken); // "add"
|
|
12
13
|
|
|
13
|
-
$.OR({
|
|
14
|
+
const nameToken = $.OR({
|
|
14
15
|
DEF: [
|
|
15
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
17
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
18
|
],
|
|
18
19
|
ERR_MSG: "Expected a table name",
|
|
19
20
|
});
|
|
21
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
20
22
|
|
|
21
23
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
22
24
|
ARGS: [
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { AddOrEditToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
5
|
+
import { captureDataKeys,captureFieldName } from "./captureFieldName.js";
|
|
4
6
|
import { addonSchema } from "./schema.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -10,14 +12,16 @@ export function dbAddOrEditFn($) {
|
|
|
10
12
|
return () => {
|
|
11
13
|
$.sectionStack.push("dbAddOrEditFn");
|
|
12
14
|
const fnToken = $.CONSUME(AddOrEditToken); // "edit"
|
|
13
|
-
$.OR({
|
|
15
|
+
const nameToken = $.OR({
|
|
14
16
|
DEF: [
|
|
15
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
18
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
19
|
],
|
|
18
20
|
ERR_MSG: "Expected a table name",
|
|
19
21
|
});
|
|
22
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
20
23
|
|
|
24
|
+
const captured = {};
|
|
21
25
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
22
26
|
ARGS: [
|
|
23
27
|
fnToken,
|
|
@@ -30,9 +34,15 @@ export function dbAddOrEditFn($) {
|
|
|
30
34
|
"addon?": [addonSchema],
|
|
31
35
|
"mock?": { "![string]": "[expression]" },
|
|
32
36
|
},
|
|
37
|
+
captured,
|
|
33
38
|
],
|
|
34
39
|
});
|
|
35
40
|
|
|
41
|
+
$.ACTION(() => {
|
|
42
|
+
captureFieldName($, captured);
|
|
43
|
+
captureDataKeys($, captured);
|
|
44
|
+
});
|
|
45
|
+
|
|
36
46
|
$.SUBRULE($.asVariable, { ARGS: [fnToken] });
|
|
37
47
|
$.sectionStack.pop();
|
|
38
48
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AddToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -9,13 +10,14 @@ export function dbBulkAddFn($) {
|
|
|
9
10
|
return () => {
|
|
10
11
|
$.sectionStack.push("dbBulkAddFn");
|
|
11
12
|
const fnToken = $.CONSUME(AddToken); // "add"
|
|
12
|
-
$.OR({
|
|
13
|
+
const nameToken = $.OR({
|
|
13
14
|
DEF: [
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
15
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
17
|
],
|
|
17
18
|
ERR_MSG: "Expected a table name",
|
|
18
19
|
});
|
|
20
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
19
21
|
const defined = {};
|
|
20
22
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
21
23
|
ARGS: [
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DeleteToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -9,13 +10,14 @@ export function dbBulkDeleteFn($) {
|
|
|
9
10
|
return () => {
|
|
10
11
|
$.sectionStack.push("dbBulkDeleteFn");
|
|
11
12
|
const fnToken = $.CONSUME(DeleteToken); // "delete"
|
|
12
|
-
$.OR({
|
|
13
|
+
const nameToken = $.OR({
|
|
13
14
|
DEF: [
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
15
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
17
|
],
|
|
17
18
|
ERR_MSG: "Expected a table name",
|
|
18
19
|
});
|
|
20
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
19
21
|
|
|
20
22
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
21
23
|
ARGS: [
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PatchToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -9,13 +10,14 @@ export function dbBulkPatchFn($) {
|
|
|
9
10
|
return () => {
|
|
10
11
|
$.sectionStack.push("dbBulkPatchFn");
|
|
11
12
|
const fnToken = $.CONSUME(PatchToken); // "patch"
|
|
12
|
-
$.OR({
|
|
13
|
+
const nameToken = $.OR({
|
|
13
14
|
DEF: [
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
15
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
17
|
],
|
|
17
18
|
ERR_MSG: "Expected a table name",
|
|
18
19
|
});
|
|
20
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
19
21
|
|
|
20
22
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
21
23
|
ARGS: [
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { UpdateToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -9,13 +10,14 @@ export function dbBulkUpdateFn($) {
|
|
|
9
10
|
return () => {
|
|
10
11
|
$.sectionStack.push("dbBulkUpdateFn");
|
|
11
12
|
const fnToken = $.CONSUME(UpdateToken); // "update"
|
|
12
|
-
$.OR({
|
|
13
|
+
const nameToken = $.OR({
|
|
13
14
|
DEF: [
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
15
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
17
|
],
|
|
17
18
|
ERR_MSG: "Expected a table name",
|
|
18
19
|
});
|
|
20
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
19
21
|
|
|
20
22
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
21
23
|
ARGS: [
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DelToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
5
|
+
import { captureFieldName } from "./captureFieldName.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -9,14 +11,16 @@ export function dbDelFn($) {
|
|
|
9
11
|
return () => {
|
|
10
12
|
$.sectionStack.push("dbDelFn");
|
|
11
13
|
const fnToken = $.CONSUME(DelToken); // "delete"
|
|
12
|
-
$.OR({
|
|
14
|
+
const nameToken = $.OR({
|
|
13
15
|
DEF: [
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
17
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
18
|
],
|
|
17
19
|
ERR_MSG: "Expected a table name",
|
|
18
20
|
});
|
|
21
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
19
22
|
|
|
23
|
+
const captured = {};
|
|
20
24
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
21
25
|
ARGS: [
|
|
22
26
|
fnToken,
|
|
@@ -26,9 +30,12 @@ export function dbDelFn($) {
|
|
|
26
30
|
"description?": "[string]",
|
|
27
31
|
"disabled?": "[boolean]",
|
|
28
32
|
},
|
|
33
|
+
captured,
|
|
29
34
|
],
|
|
30
35
|
});
|
|
31
36
|
|
|
37
|
+
$.ACTION(() => captureFieldName($, captured));
|
|
38
|
+
|
|
32
39
|
$.sectionStack.pop();
|
|
33
40
|
};
|
|
34
41
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { EditToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
5
|
+
import { captureDataKeys,captureFieldName } from "./captureFieldName.js";
|
|
4
6
|
import { addonSchema } from "./schema.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -10,14 +12,16 @@ export function dbEditFn($) {
|
|
|
10
12
|
return () => {
|
|
11
13
|
$.sectionStack.push("dbEditFn");
|
|
12
14
|
const fnToken = $.CONSUME(EditToken); // "edit"
|
|
13
|
-
$.OR({
|
|
15
|
+
const nameToken = $.OR({
|
|
14
16
|
DEF: [
|
|
15
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
18
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
19
|
],
|
|
18
20
|
ERR_MSG: "Expected a table name",
|
|
19
21
|
});
|
|
22
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
20
23
|
|
|
24
|
+
const captured = {};
|
|
21
25
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
22
26
|
ARGS: [
|
|
23
27
|
fnToken,
|
|
@@ -31,9 +35,15 @@ export function dbEditFn($) {
|
|
|
31
35
|
"addon?": [addonSchema],
|
|
32
36
|
"mock?": { "![string]": "[expression]" },
|
|
33
37
|
},
|
|
38
|
+
captured,
|
|
34
39
|
],
|
|
35
40
|
});
|
|
36
41
|
|
|
42
|
+
$.ACTION(() => {
|
|
43
|
+
captureFieldName($, captured);
|
|
44
|
+
captureDataKeys($, captured);
|
|
45
|
+
});
|
|
46
|
+
|
|
37
47
|
$.SUBRULE($.asVariable, { ARGS: [fnToken] });
|
|
38
48
|
$.sectionStack.pop();
|
|
39
49
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { GetToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
5
|
+
import { captureFieldName } from "./captureFieldName.js";
|
|
4
6
|
import { addonSchema } from "./schema.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -10,14 +12,16 @@ export function dbGetFn($) {
|
|
|
10
12
|
return () => {
|
|
11
13
|
$.sectionStack.push("dbGetFn");
|
|
12
14
|
const fnToken = $.CONSUME(GetToken); // "get"
|
|
13
|
-
$.OR({
|
|
15
|
+
const nameToken = $.OR({
|
|
14
16
|
DEF: [
|
|
15
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
18
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
19
|
],
|
|
18
20
|
ERR_MSG: "Expected a table name",
|
|
19
21
|
});
|
|
22
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
20
23
|
|
|
24
|
+
const captured = {};
|
|
21
25
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
22
26
|
ARGS: [
|
|
23
27
|
fnToken,
|
|
@@ -31,9 +35,12 @@ export function dbGetFn($) {
|
|
|
31
35
|
"addon?": [addonSchema],
|
|
32
36
|
"mock?": { "![string]": "[expression]" },
|
|
33
37
|
},
|
|
38
|
+
captured,
|
|
34
39
|
],
|
|
35
40
|
});
|
|
36
41
|
|
|
42
|
+
$.ACTION(() => captureFieldName($, captured));
|
|
43
|
+
|
|
37
44
|
$.SUBRULE($.asVariable, { ARGS: [fnToken] });
|
|
38
45
|
$.sectionStack.pop();
|
|
39
46
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { HasToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
5
|
+
import { captureFieldName } from "./captureFieldName.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -9,13 +11,15 @@ export function dbHasFn($) {
|
|
|
9
11
|
return () => {
|
|
10
12
|
$.sectionStack.push("dbHasFn");
|
|
11
13
|
const fnToken = $.CONSUME(HasToken); // "has"
|
|
12
|
-
$.OR({
|
|
14
|
+
const nameToken = $.OR({
|
|
13
15
|
DEF: [
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
17
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
18
|
],
|
|
17
19
|
ERR_MSG: "Expected a table name",
|
|
18
20
|
});
|
|
21
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
22
|
+
const captured = {};
|
|
19
23
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
20
24
|
ARGS: [
|
|
21
25
|
fnToken,
|
|
@@ -26,8 +30,10 @@ export function dbHasFn($) {
|
|
|
26
30
|
"disabled?": "[boolean]",
|
|
27
31
|
"mock?": { "![string]": "[expression]" },
|
|
28
32
|
},
|
|
33
|
+
captured,
|
|
29
34
|
],
|
|
30
35
|
});
|
|
36
|
+
$.ACTION(() => captureFieldName($, captured));
|
|
31
37
|
$.SUBRULE($.asVariable, { ARGS: [fnToken] });
|
|
32
38
|
$.sectionStack.pop();
|
|
33
39
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { PatchToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
5
|
+
import { captureFieldName } from "./captureFieldName.js";
|
|
4
6
|
import { addonSchema } from "./schema.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -10,14 +12,16 @@ export function dbPatchFn($) {
|
|
|
10
12
|
return () => {
|
|
11
13
|
$.sectionStack.push("dbPatchFn");
|
|
12
14
|
const fnToken = $.CONSUME(PatchToken); // "patch"
|
|
13
|
-
$.OR({
|
|
15
|
+
const nameToken = $.OR({
|
|
14
16
|
DEF: [
|
|
15
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
18
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
17
19
|
],
|
|
18
20
|
ERR_MSG: "Expected a table name",
|
|
19
21
|
});
|
|
22
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
20
23
|
|
|
24
|
+
const captured = {};
|
|
21
25
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
22
26
|
ARGS: [
|
|
23
27
|
fnToken,
|
|
@@ -30,9 +34,12 @@ export function dbPatchFn($) {
|
|
|
30
34
|
"addon?": [addonSchema],
|
|
31
35
|
"mock?": { "![string]": "[expression]" },
|
|
32
36
|
},
|
|
37
|
+
captured,
|
|
33
38
|
],
|
|
34
39
|
});
|
|
35
40
|
|
|
41
|
+
$.ACTION(() => captureFieldName($, captured));
|
|
42
|
+
|
|
36
43
|
$.SUBRULE($.asVariable, { ARGS: [fnToken] });
|
|
37
44
|
$.sectionStack.pop();
|
|
38
45
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { QueryToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
import { addonSchema } from "./schema.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -10,11 +11,13 @@ export function dbQueryFn($) {
|
|
|
10
11
|
return () => {
|
|
11
12
|
$.sectionStack.push("dbQueryFn");
|
|
12
13
|
const fnToken = $.CONSUME(QueryToken); // "query"
|
|
13
|
-
$.OR([
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
14
|
+
const nameToken = $.OR([
|
|
15
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
17
|
]);
|
|
18
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
17
19
|
|
|
20
|
+
const captured = {};
|
|
18
21
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
19
22
|
ARGS: [
|
|
20
23
|
fnToken,
|
|
@@ -51,9 +54,32 @@ export function dbQueryFn($) {
|
|
|
51
54
|
"where?": "[query]",
|
|
52
55
|
"additional_where?": "[query]",
|
|
53
56
|
},
|
|
57
|
+
captured,
|
|
54
58
|
],
|
|
55
59
|
});
|
|
56
60
|
|
|
61
|
+
$.ACTION(() => {
|
|
62
|
+
// Extract join table references
|
|
63
|
+
if (captured.join) {
|
|
64
|
+
for (const [k, v] of Object.entries(captured.join)) {
|
|
65
|
+
if (k === "key" || k === "value") continue;
|
|
66
|
+
const tableEntry = v?.table;
|
|
67
|
+
if (tableEntry?.value) {
|
|
68
|
+
$.addReference("table", getVarName(tableEntry.value), tableEntry.value);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Extract addon name references
|
|
73
|
+
if (captured.addon?.value && Array.isArray(captured.addon.value)) {
|
|
74
|
+
for (const item of captured.addon.value) {
|
|
75
|
+
const nameEntry = item.name;
|
|
76
|
+
if (nameEntry?.value) {
|
|
77
|
+
$.addReference("function", getVarName(nameEntry.value), nameEntry.value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
57
83
|
// db.query rule is used within an addon declaration, but
|
|
58
84
|
// in this context we don't allow "as" variable assignment
|
|
59
85
|
const isAddonContext = $.sectionStack.includes("addonDeclaration");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SchemaToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -12,10 +13,11 @@ export function dbSchemaFn($) {
|
|
|
12
13
|
|
|
13
14
|
$.sectionStack.push("dbSchemaFn");
|
|
14
15
|
const fnToken = $.CONSUME(SchemaToken); // "schema"
|
|
15
|
-
$.OR([
|
|
16
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
17
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
|
+
const nameToken = $.OR([
|
|
17
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
18
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
18
19
|
]);
|
|
20
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
19
21
|
$.SUBRULE($.functionAttrReq, {
|
|
20
22
|
ARGS: [fnToken, requiredAttrs, optionalAttrs],
|
|
21
23
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TruncateToken } from "../../../lexer/db.js";
|
|
2
2
|
import { StringLiteral } from "../../../lexer/literal.js";
|
|
3
3
|
import { Identifier } from "../../../lexer/tokens.js";
|
|
4
|
+
import { getVarName } from "../../generic/utils.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {import('../base_parser.js').XanoBaseParser} $
|
|
@@ -9,13 +10,14 @@ export function dbTruncateFn($) {
|
|
|
9
10
|
return () => {
|
|
10
11
|
$.sectionStack.push("dbTruncateFn");
|
|
11
12
|
const fnToken = $.CONSUME(TruncateToken); // "truncate"
|
|
12
|
-
$.OR({
|
|
13
|
+
const nameToken = $.OR({
|
|
13
14
|
DEF: [
|
|
14
|
-
{ ALT: () => $.CONSUME(Identifier) },
|
|
15
|
-
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
15
|
+
{ ALT: () => $.CONSUME(Identifier) },
|
|
16
|
+
{ ALT: () => $.CONSUME1(StringLiteral) },
|
|
16
17
|
],
|
|
17
18
|
ERR_MSG: "Expected a table name",
|
|
18
19
|
});
|
|
20
|
+
$.addReference("table", getVarName(nameToken), nameToken);
|
|
19
21
|
|
|
20
22
|
$.SUBRULE($.schemaParseAttributeFn, {
|
|
21
23
|
ARGS: [
|