jsxpression 0.1.41 → 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/lib/analyze/analysis-error.d.ts.map +1 -1
- package/lib/analyze/analysis-error.js +2 -7
- package/lib/analyze/analysis-error.js.map +1 -1
- package/lib/analyze/analysis-report.d.ts +13 -13
- package/lib/analyze/analysis-report.d.ts.map +1 -1
- package/lib/analyze/analysis-report.js +48 -45
- package/lib/analyze/analysis-report.js.map +1 -1
- package/lib/analyze/analyze.d.ts +1 -1
- package/lib/analyze/analyze.d.ts.map +1 -1
- package/lib/analyze/analyze.js +4 -4
- package/lib/analyze/analyze.js.map +1 -1
- package/lib/analyze/data/analyze.d.ts +1 -1
- package/lib/analyze/data/analyze.d.ts.map +1 -1
- package/lib/analyze/data/analyze.js +5 -5
- package/lib/analyze/data/analyze.js.map +1 -1
- package/lib/analyze/data/data-access.d.ts +1 -1
- package/lib/analyze/data/data-access.d.ts.map +1 -1
- package/lib/analyze/data/data-access.js +19 -15
- package/lib/analyze/data/data-access.js.map +1 -1
- package/lib/analyze/data/method-calls.d.ts +1 -1
- package/lib/analyze/data/method-calls.d.ts.map +1 -1
- package/lib/analyze/data/method-calls.js +5 -5
- package/lib/analyze/data/method-calls.js.map +1 -1
- package/lib/analyze/data/utils.d.ts +3 -3
- package/lib/analyze/data/utils.d.ts.map +1 -1
- package/lib/analyze/data/utils.js +6 -5
- package/lib/analyze/data/utils.js.map +1 -1
- package/lib/analyze/index.d.ts +1 -1
- package/lib/analyze/index.d.ts.map +1 -1
- package/lib/analyze/index.js +1 -1
- package/lib/analyze/index.js.map +1 -1
- package/lib/analyze/jsx/analyze.d.ts +1 -1
- package/lib/analyze/jsx/analyze.d.ts.map +1 -1
- package/lib/analyze/jsx/analyze.js +4 -4
- package/lib/analyze/jsx/analyze.js.map +1 -1
- package/lib/analyze/jsx/element-attributes.d.ts +1 -1
- package/lib/analyze/jsx/element-attributes.d.ts.map +1 -1
- package/lib/analyze/jsx/element-attributes.js +3 -3
- package/lib/analyze/jsx/element-attributes.js.map +1 -1
- package/lib/analyze/jsx/element-children.d.ts +1 -1
- package/lib/analyze/jsx/element-children.d.ts.map +1 -1
- package/lib/analyze/jsx/element-children.js +3 -3
- package/lib/analyze/jsx/element-children.js.map +1 -1
- package/lib/analyze/jsx/element-tags.d.ts +1 -1
- package/lib/analyze/jsx/element-tags.d.ts.map +1 -1
- package/lib/analyze/jsx/element-tags.js +2 -2
- package/lib/analyze/jsx/element-tags.js.map +1 -1
- package/lib/analyze/security/analyze.d.ts +1 -1
- package/lib/analyze/security/analyze.d.ts.map +1 -1
- package/lib/analyze/security/analyze.js +4 -4
- package/lib/analyze/security/analyze.js.map +1 -1
- package/lib/analyze/security/call-expressions.d.ts +1 -1
- package/lib/analyze/security/call-expressions.d.ts.map +1 -1
- package/lib/analyze/security/call-expressions.js +3 -5
- package/lib/analyze/security/call-expressions.js.map +1 -1
- package/lib/analyze/security/declarations.d.ts +1 -1
- package/lib/analyze/security/declarations.d.ts.map +1 -1
- package/lib/analyze/security/declarations.js +6 -6
- package/lib/analyze/security/declarations.js.map +1 -1
- package/lib/analyze/security/expressions.d.ts +1 -1
- package/lib/analyze/security/expressions.d.ts.map +1 -1
- package/lib/analyze/security/expressions.js +3 -6
- package/lib/analyze/security/expressions.js.map +1 -1
- package/lib/analyze/security/identifiers.d.ts +1 -1
- package/lib/analyze/security/identifiers.d.ts.map +1 -1
- package/lib/analyze/security/identifiers.js +19 -22
- package/lib/analyze/security/identifiers.js.map +1 -1
- package/lib/analyze/utils.d.ts +4 -4
- package/lib/analyze/utils.d.ts.map +1 -1
- package/lib/analyze/utils.js +5 -3
- package/lib/analyze/utils.js.map +1 -1
- package/lib/analyze/validation-context.d.ts +8 -8
- package/lib/analyze/validation-context.d.ts.map +1 -1
- package/lib/analyze/validation-context.js +23 -21
- package/lib/analyze/validation-context.js.map +1 -1
- package/lib/builtins.d.ts +6 -6
- package/lib/builtins.d.ts.map +1 -1
- package/lib/builtins.js +9 -8
- package/lib/builtins.js.map +1 -1
- package/lib/codegen/builtins/builtin-types.d.ts.map +1 -1
- package/lib/codegen/builtins/builtin-types.js +9 -13
- package/lib/codegen/builtins/builtin-types.js.map +1 -1
- package/lib/codegen/generate-typescript-definitions.d.ts +18 -17
- package/lib/codegen/generate-typescript-definitions.d.ts.map +1 -1
- package/lib/codegen/generate-typescript-definitions.js +19 -23
- package/lib/codegen/generate-typescript-definitions.js.map +1 -1
- package/lib/codegen/schema/component-types.d.ts.map +1 -1
- package/lib/codegen/schema/component-types.js +7 -4
- package/lib/codegen/schema/component-types.js.map +1 -1
- package/lib/codegen/schema/data-types.d.ts.map +1 -1
- package/lib/codegen/schema/data-types.js +1 -1
- package/lib/codegen/schema/data-types.js.map +1 -1
- package/lib/codegen/schema/function-types.d.ts.map +1 -1
- package/lib/codegen/schema/function-types.js +1 -3
- package/lib/codegen/schema/function-types.js.map +1 -1
- package/lib/codegen/schema/utils.d.ts +4 -3
- package/lib/codegen/schema/utils.d.ts.map +1 -1
- package/lib/codegen/schema/utils.js +12 -8
- package/lib/codegen/schema/utils.js.map +1 -1
- package/lib/compile/compilation-error.d.ts +1 -1
- package/lib/compile/compilation-error.d.ts.map +1 -1
- package/lib/compile/compilation-error.js +3 -1
- package/lib/compile/compilation-error.js.map +1 -1
- package/lib/compile/compile.d.ts.map +1 -1
- package/lib/compile/compile.js +5 -11
- package/lib/compile/compile.js.map +1 -1
- package/lib/evaluate/evaluate.d.ts +6 -6
- package/lib/evaluate/evaluate.d.ts.map +1 -1
- package/lib/evaluate/evaluate.js +1 -1
- package/lib/evaluate/evaluate.js.map +1 -1
- package/lib/evaluate/evaluation-error.d.ts.map +1 -1
- package/lib/evaluate/evaluation-error.js +1 -0
- package/lib/evaluate/evaluation-error.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/jsx.d.ts +3 -3
- package/lib/jsx.d.ts.map +1 -1
- package/lib/jsx.js.map +1 -1
- package/lib/parse/parse-error.d.ts.map +1 -1
- package/lib/parse/parse-error.js +1 -0
- package/lib/parse/parse-error.js.map +1 -1
- package/lib/render.d.ts +25 -33
- package/lib/render.d.ts.map +1 -1
- package/lib/render.js +21 -26
- package/lib/render.js.map +1 -1
- package/lib/schema.d.ts +9 -9
- package/lib/schema.d.ts.map +1 -1
- package/lib/schema.js +1 -1
- package/lib/schema.js.map +1 -1
- package/lib/traverse.d.ts.map +1 -1
- package/lib/traverse.js.map +1 -1
- package/lib/validate.d.ts +14 -17
- package/lib/validate.d.ts.map +1 -1
- package/lib/validate.js +13 -14
- package/lib/validate.js.map +1 -1
- package/package.json +14 -14
- package/src/analyze/analysis-error.ts +2 -6
- package/src/analyze/analysis-report.ts +73 -62
- package/src/analyze/analyze.test.ts +14 -18
- package/src/analyze/analyze.ts +4 -4
- package/src/analyze/data/analyze.ts +5 -8
- package/src/analyze/data/data-access.ts +49 -46
- package/src/analyze/data/method-calls.ts +9 -18
- package/src/analyze/data/utils.ts +15 -19
- package/src/analyze/index.ts +1 -1
- package/src/analyze/jsx/analyze.ts +4 -4
- package/src/analyze/jsx/element-attributes.ts +5 -18
- package/src/analyze/jsx/element-children.ts +4 -8
- package/src/analyze/jsx/element-tags.ts +2 -2
- package/src/analyze/security/analyze.ts +4 -4
- package/src/analyze/security/call-expressions.ts +5 -18
- package/src/analyze/security/declarations.ts +14 -43
- package/src/analyze/security/expressions.ts +12 -49
- package/src/analyze/security/identifiers.ts +37 -39
- package/src/analyze/utils.ts +25 -19
- package/src/analyze/validation-context.ts +32 -23
- package/src/builtins.ts +27 -38
- package/src/codegen/builtins/builtin-types.ts +13 -20
- package/src/codegen/generate-typescript-definitions.test.ts +6 -6
- package/src/codegen/generate-typescript-definitions.ts +19 -23
- package/src/codegen/schema/component-types.ts +22 -12
- package/src/codegen/schema/data-types.ts +6 -6
- package/src/codegen/schema/function-types.ts +1 -3
- package/src/codegen/schema/utils.ts +24 -23
- package/src/compile/compilation-error.ts +5 -1
- package/src/compile/compile.test.ts +7 -21
- package/src/compile/compile.ts +18 -30
- package/src/evaluate/evaluate.test.ts +76 -92
- package/src/evaluate/evaluate.ts +15 -20
- package/src/evaluate/evaluation-error.ts +1 -0
- package/src/index.ts +1 -7
- package/src/jsx.ts +4 -6
- package/src/parse/parse-error.ts +1 -0
- package/src/parse/parse.test.ts +1 -1
- package/src/render.test.ts +4 -4
- package/src/render.ts +26 -38
- package/src/schema.ts +11 -11
- package/src/traverse.test.ts +6 -6
- package/src/traverse.ts +3 -3
- package/src/validate.ts +14 -17
- package/CHANGELOG.md +0 -8
|
@@ -1,57 +1,28 @@
|
|
|
1
1
|
import type { Program, Expression, Super } from "acorn";
|
|
2
|
-
import { traverse } from "../../traverse.js";
|
|
3
2
|
import type { Schema } from "../../schema.js";
|
|
4
|
-
import
|
|
5
|
-
import { AnalysisReport } from "../analysis-report.js";
|
|
3
|
+
import { traverse } from "../../traverse.js";
|
|
4
|
+
import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
|
|
6
5
|
import { getNodeRange } from "../utils.js";
|
|
6
|
+
import type { ValidationContext } from "../validation-context.js";
|
|
7
7
|
|
|
8
|
-
export function analyzeExpressions(
|
|
9
|
-
|
|
10
|
-
_schema: Schema,
|
|
11
|
-
validationContext: ValidationContext
|
|
12
|
-
): AnalysisReport {
|
|
13
|
-
const analysisReport = new AnalysisReport();
|
|
8
|
+
export function analyzeExpressions(ast: Program, _schema: Schema, validationContext: ValidationContext): AnalysisReport {
|
|
9
|
+
const analysisReport = createAnalysisReport();
|
|
14
10
|
|
|
15
11
|
traverse(ast, {
|
|
16
12
|
NewExpression(node) {
|
|
17
|
-
analysisReport.addIssue(
|
|
18
|
-
"NEW_NOT_ALLOWED",
|
|
19
|
-
"new not allowed",
|
|
20
|
-
getNodeRange(node),
|
|
21
|
-
validationContext.getSnapshot()
|
|
22
|
-
);
|
|
13
|
+
analysisReport.addIssue("NEW_NOT_ALLOWED", "new not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
23
14
|
},
|
|
24
15
|
ThisExpression(node) {
|
|
25
|
-
analysisReport.addIssue(
|
|
26
|
-
"THIS_NOT_ALLOWED",
|
|
27
|
-
"this not allowed",
|
|
28
|
-
getNodeRange(node),
|
|
29
|
-
validationContext.getSnapshot()
|
|
30
|
-
);
|
|
16
|
+
analysisReport.addIssue("THIS_NOT_ALLOWED", "this not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
31
17
|
},
|
|
32
18
|
WithStatement(node) {
|
|
33
|
-
analysisReport.addIssue(
|
|
34
|
-
"WITH_NOT_ALLOWED",
|
|
35
|
-
"with not allowed",
|
|
36
|
-
getNodeRange(node),
|
|
37
|
-
validationContext.getSnapshot()
|
|
38
|
-
);
|
|
19
|
+
analysisReport.addIssue("WITH_NOT_ALLOWED", "with not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
39
20
|
},
|
|
40
21
|
AwaitExpression(node) {
|
|
41
|
-
analysisReport.addIssue(
|
|
42
|
-
"AWAIT_NOT_ALLOWED",
|
|
43
|
-
"await not allowed",
|
|
44
|
-
getNodeRange(node),
|
|
45
|
-
validationContext.getSnapshot()
|
|
46
|
-
);
|
|
22
|
+
analysisReport.addIssue("AWAIT_NOT_ALLOWED", "await not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
47
23
|
},
|
|
48
24
|
YieldExpression(node) {
|
|
49
|
-
analysisReport.addIssue(
|
|
50
|
-
"YIELD_NOT_ALLOWED",
|
|
51
|
-
"yield not allowed",
|
|
52
|
-
getNodeRange(node),
|
|
53
|
-
validationContext.getSnapshot()
|
|
54
|
-
);
|
|
25
|
+
analysisReport.addIssue("YIELD_NOT_ALLOWED", "yield not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
55
26
|
},
|
|
56
27
|
ArrowFunctionExpression(node) {
|
|
57
28
|
if (node.body.type === "BlockStatement") {
|
|
@@ -83,12 +54,7 @@ export function analyzeExpressions(
|
|
|
83
54
|
currentNode = currentNode.object;
|
|
84
55
|
}
|
|
85
56
|
if (depth > 5) {
|
|
86
|
-
analysisReport.addIssue(
|
|
87
|
-
"MEMBER_CHAIN_TOO_DEEP",
|
|
88
|
-
"member chain too deep",
|
|
89
|
-
getNodeRange(node),
|
|
90
|
-
validationContext.getSnapshot()
|
|
91
|
-
);
|
|
57
|
+
analysisReport.addIssue("MEMBER_CHAIN_TOO_DEEP", "member chain too deep", getNodeRange(node), validationContext.getSnapshot());
|
|
92
58
|
}
|
|
93
59
|
|
|
94
60
|
if (node.computed) {
|
|
@@ -101,10 +67,7 @@ export function analyzeExpressions(
|
|
|
101
67
|
"computed member access not allowed",
|
|
102
68
|
getNodeRange(node),
|
|
103
69
|
validationContext.getSnapshot(),
|
|
104
|
-
[
|
|
105
|
-
"Use dot notation: obj.prop instead of obj[prop]",
|
|
106
|
-
"For arrays, use numeric indices: array[0] instead of array[variable]",
|
|
107
|
-
]
|
|
70
|
+
["Use dot notation: obj.prop instead of obj[prop]", "For arrays, use numeric indices: array[0] instead of array[variable]"]
|
|
108
71
|
);
|
|
109
72
|
}
|
|
110
73
|
},
|
|
@@ -2,12 +2,12 @@ import type { AnyNode, ArrowFunctionExpression, FunctionDeclaration, Identifier,
|
|
|
2
2
|
import { getBuiltinGlobals } from "../../builtins.js";
|
|
3
3
|
import type { Schema } from "../../schema.js";
|
|
4
4
|
import { traverse } from "../../traverse.js";
|
|
5
|
-
import { AnalysisReport } from "../analysis-report.js";
|
|
5
|
+
import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
|
|
6
6
|
import { getNodeRange } from "../utils.js";
|
|
7
7
|
import type { ValidationContext } from "../validation-context.js";
|
|
8
8
|
|
|
9
9
|
export function analyzeIdentifiers(ast: Program, schema: Schema, validationContext: ValidationContext): AnalysisReport {
|
|
10
|
-
const analysisReport =
|
|
10
|
+
const analysisReport = createAnalysisReport();
|
|
11
11
|
const arrowParamScopes = getArrowParamScopes(ast);
|
|
12
12
|
const functionParamScopes = getFunctionParamScopes(ast);
|
|
13
13
|
const functionLocalConsts = getFunctionLocalConsts(ast);
|
|
@@ -36,14 +36,7 @@ export function analyzeIdentifiers(ast: Program, schema: Schema, validationConte
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const dataKeys = Object.keys(schema.data ?? {});
|
|
39
|
-
const allowedRoots = [
|
|
40
|
-
"props",
|
|
41
|
-
...dataKeys,
|
|
42
|
-
...getBuiltinGlobals(),
|
|
43
|
-
...constNames,
|
|
44
|
-
...functionNames,
|
|
45
|
-
...schemaFunctionNames,
|
|
46
|
-
];
|
|
39
|
+
const allowedRoots = ["props", ...dataKeys, ...getBuiltinGlobals(), ...constNames, ...functionNames, ...schemaFunctionNames];
|
|
47
40
|
|
|
48
41
|
if (allowedRoots.includes(name)) {
|
|
49
42
|
return;
|
|
@@ -52,10 +45,7 @@ export function analyzeIdentifiers(ast: Program, schema: Schema, validationConte
|
|
|
52
45
|
const scopeParent = findScopeParent(node, ast);
|
|
53
46
|
|
|
54
47
|
if (scopeParent) {
|
|
55
|
-
const params =
|
|
56
|
-
scopeParent.type === "ArrowFunctionExpression"
|
|
57
|
-
? arrowParamScopes.get(scopeParent)
|
|
58
|
-
: functionParamScopes.get(scopeParent);
|
|
48
|
+
const params = scopeParent.type === "ArrowFunctionExpression" ? arrowParamScopes.get(scopeParent) : functionParamScopes.get(scopeParent);
|
|
59
49
|
if (params?.has(name)) {
|
|
60
50
|
return;
|
|
61
51
|
}
|
|
@@ -141,7 +131,7 @@ function collectParamNames(param: AnyNode, names: Set<string>): void {
|
|
|
141
131
|
names.add(param.name);
|
|
142
132
|
break;
|
|
143
133
|
case "ObjectPattern":
|
|
144
|
-
for (const prop of
|
|
134
|
+
for (const prop of param.properties) {
|
|
145
135
|
if (prop.type === "RestElement") {
|
|
146
136
|
collectParamNames(prop.argument, names);
|
|
147
137
|
} else {
|
|
@@ -150,21 +140,25 @@ function collectParamNames(param: AnyNode, names: Set<string>): void {
|
|
|
150
140
|
}
|
|
151
141
|
break;
|
|
152
142
|
case "ArrayPattern":
|
|
153
|
-
for (const el of
|
|
154
|
-
if (el)
|
|
143
|
+
for (const el of param.elements) {
|
|
144
|
+
if (el) {
|
|
145
|
+
collectParamNames(el, names);
|
|
146
|
+
}
|
|
155
147
|
}
|
|
156
148
|
break;
|
|
157
149
|
case "AssignmentPattern":
|
|
158
|
-
collectParamNames(
|
|
150
|
+
collectParamNames(param.left, names);
|
|
159
151
|
break;
|
|
160
152
|
case "RestElement":
|
|
161
|
-
collectParamNames(
|
|
153
|
+
collectParamNames(param.argument, names);
|
|
154
|
+
break;
|
|
155
|
+
default:
|
|
162
156
|
break;
|
|
163
157
|
}
|
|
164
158
|
}
|
|
165
159
|
|
|
166
|
-
function getTopLevelConstNames(ast: Program): string
|
|
167
|
-
const names: string
|
|
160
|
+
function getTopLevelConstNames(ast: Program): Array<string> {
|
|
161
|
+
const names: Array<string> = [];
|
|
168
162
|
for (const stmt of ast.body) {
|
|
169
163
|
if (stmt.type === "VariableDeclaration" && stmt.kind === "const") {
|
|
170
164
|
for (const decl of stmt.declarations) {
|
|
@@ -177,8 +171,8 @@ function getTopLevelConstNames(ast: Program): string[] {
|
|
|
177
171
|
return names;
|
|
178
172
|
}
|
|
179
173
|
|
|
180
|
-
function getTopLevelFunctionNames(ast: Program): string
|
|
181
|
-
const names: string
|
|
174
|
+
function getTopLevelFunctionNames(ast: Program): Array<string> {
|
|
175
|
+
const names: Array<string> = [];
|
|
182
176
|
for (const stmt of ast.body) {
|
|
183
177
|
if (stmt.type === "FunctionDeclaration" && stmt.id) {
|
|
184
178
|
names.push(stmt.id.name);
|
|
@@ -201,17 +195,18 @@ function findScopeParent(targetNode: AnyNode, rootNode: AnyNode): ArrowFunctionE
|
|
|
201
195
|
found = node as ArrowFunctionExpression | FunctionDeclaration;
|
|
202
196
|
}
|
|
203
197
|
|
|
204
|
-
|
|
205
|
-
|
|
198
|
+
const record = node as unknown as Record<string, unknown>;
|
|
199
|
+
for (const key of Object.keys(record)) {
|
|
200
|
+
const value = record[key];
|
|
206
201
|
|
|
207
202
|
if (value && typeof value === "object") {
|
|
208
203
|
if (Array.isArray(value)) {
|
|
209
204
|
for (const item of value) {
|
|
210
|
-
if (item && typeof item === "object" && walk(item)) {
|
|
205
|
+
if (item && typeof item === "object" && walk(item as AnyNode)) {
|
|
211
206
|
return true;
|
|
212
207
|
}
|
|
213
208
|
}
|
|
214
|
-
} else if (walk(value)) {
|
|
209
|
+
} else if (walk(value as AnyNode)) {
|
|
215
210
|
return true;
|
|
216
211
|
}
|
|
217
212
|
}
|
|
@@ -228,25 +223,28 @@ function findScopeParent(targetNode: AnyNode, rootNode: AnyNode): ArrowFunctionE
|
|
|
228
223
|
return found;
|
|
229
224
|
}
|
|
230
225
|
|
|
231
|
-
function buildParentMap(ast: Program): Map<
|
|
232
|
-
const parentMap = new Map<
|
|
226
|
+
function buildParentMap(ast: Program): Map<AnyNode, AnyNode | null> {
|
|
227
|
+
const parentMap = new Map<AnyNode, AnyNode | null>();
|
|
233
228
|
|
|
234
|
-
function visit(node:
|
|
235
|
-
if (!node || typeof node !== "object")
|
|
236
|
-
|
|
237
|
-
|
|
229
|
+
function visit(node: unknown, parent: AnyNode | null): void {
|
|
230
|
+
if (!node || typeof node !== "object") {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const record = node as Record<string, unknown>;
|
|
234
|
+
if (record["type"]) {
|
|
235
|
+
parentMap.set(node as AnyNode, parent);
|
|
238
236
|
}
|
|
239
|
-
for (const key of Object.keys(
|
|
240
|
-
const value =
|
|
237
|
+
for (const key of Object.keys(record)) {
|
|
238
|
+
const value = record[key];
|
|
241
239
|
if (value && typeof value === "object") {
|
|
242
240
|
if (Array.isArray(value)) {
|
|
243
241
|
for (const child of value) {
|
|
244
|
-
if (child && typeof child === "object" && child
|
|
245
|
-
visit(child, node);
|
|
242
|
+
if (child && typeof child === "object" && (child as Record<string, unknown>)["type"]) {
|
|
243
|
+
visit(child, node as AnyNode);
|
|
246
244
|
}
|
|
247
245
|
}
|
|
248
|
-
} else if (value
|
|
249
|
-
visit(value, node);
|
|
246
|
+
} else if ((value as Record<string, unknown>)["type"]) {
|
|
247
|
+
visit(value, node as AnyNode);
|
|
250
248
|
}
|
|
251
249
|
}
|
|
252
250
|
}
|
package/src/analyze/utils.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Node } from "acorn";
|
|
2
|
+
|
|
1
3
|
export interface RangePosition {
|
|
2
4
|
line: number;
|
|
3
5
|
column: number;
|
|
@@ -8,7 +10,8 @@ export interface Range {
|
|
|
8
10
|
end: RangePosition;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
export function getNodeRange(
|
|
13
|
+
export function getNodeRange(nodeParam: unknown): Range {
|
|
14
|
+
const node = nodeParam as Node;
|
|
12
15
|
if (node.loc) {
|
|
13
16
|
return {
|
|
14
17
|
start: {
|
|
@@ -34,15 +37,15 @@ export function getNodeRange(node: any): Range {
|
|
|
34
37
|
};
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
export function getElementSimilarityMatchers(invalid: string, available: string
|
|
40
|
+
export function getElementSimilarityMatchers(invalid: string, available: Array<string>): Array<SimilarityMatcher> {
|
|
38
41
|
return getSimilarityMatchers(invalid, available, "element");
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
export function getAttributeSimilarityMatchers(invalid: string, available: string
|
|
44
|
+
export function getAttributeSimilarityMatchers(invalid: string, available: Array<string>): Array<SimilarityMatcher> {
|
|
42
45
|
return getSimilarityMatchers(invalid, available, "attribute");
|
|
43
46
|
}
|
|
44
47
|
|
|
45
|
-
export function getBestSimilarityMatcherSuggestion(invalid: string, available: string
|
|
48
|
+
export function getBestSimilarityMatcherSuggestion(invalid: string, available: Array<string>): string | null {
|
|
46
49
|
const similarityMatchers = getElementSimilarityMatchers(invalid, available);
|
|
47
50
|
|
|
48
51
|
if (similarityMatchers.length === 0) {
|
|
@@ -66,24 +69,27 @@ interface SimilarityMatcher {
|
|
|
66
69
|
type: SimilarityMatcherType;
|
|
67
70
|
}
|
|
68
71
|
|
|
69
|
-
function getSimilarityMatchers(invalid: string, available: string
|
|
72
|
+
function getSimilarityMatchers(invalid: string, available: Array<string>, type: SimilarityMatcherType): Array<SimilarityMatcher> {
|
|
70
73
|
if (available.length === 0) {
|
|
71
74
|
return [];
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
suggestion
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
return (
|
|
78
|
+
available
|
|
79
|
+
.map((suggestion) => ({
|
|
80
|
+
suggestion,
|
|
81
|
+
distance: levenshteinDistance(invalid.toLowerCase(), suggestion.toLowerCase()),
|
|
82
|
+
type,
|
|
83
|
+
}))
|
|
84
|
+
.filter((similarityMatcher) => similarityMatcher.distance <= Math.max(2, Math.floor(invalid.length * 0.4)))
|
|
85
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
86
|
+
.sort((a, b) => a.distance - b.distance)
|
|
87
|
+
.slice(0, 3)
|
|
88
|
+
.map((similarityMatcher) => ({
|
|
89
|
+
...similarityMatcher,
|
|
90
|
+
confidence: 1 - similarityMatcher.distance / Math.max(invalid.length, similarityMatcher.suggestion.length),
|
|
91
|
+
}))
|
|
92
|
+
);
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
function levenshteinDistance(x: string, y: string): number {
|
|
@@ -94,7 +100,7 @@ function levenshteinDistance(x: string, y: string): number {
|
|
|
94
100
|
return x.length;
|
|
95
101
|
}
|
|
96
102
|
|
|
97
|
-
const matrix: number
|
|
103
|
+
const matrix: Array<Array<number>> = [];
|
|
98
104
|
|
|
99
105
|
for (let i = 0; i <= y.length; i++) {
|
|
100
106
|
matrix[i] = [i];
|
|
@@ -1,32 +1,41 @@
|
|
|
1
1
|
export interface ValidationContextSnapshot {
|
|
2
|
-
elements: string
|
|
2
|
+
elements: Array<string>;
|
|
3
3
|
currentElement?: string;
|
|
4
|
-
parentElements: string
|
|
4
|
+
parentElements: Array<string>;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
|
|
7
|
+
export interface ValidationContext {
|
|
8
|
+
readonly currentPath: string;
|
|
9
|
+
enterElement: (element: string) => void;
|
|
10
|
+
exitElement: () => void;
|
|
11
|
+
getSnapshot: () => ValidationContextSnapshot;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createValidationContext(): ValidationContext {
|
|
15
|
+
const elements: Array<string> = [];
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
return {
|
|
18
|
+
get currentPath(): string {
|
|
19
|
+
if (elements.length > 0) {
|
|
20
|
+
return elements.join(" > ");
|
|
21
|
+
}
|
|
22
|
+
return "";
|
|
23
|
+
},
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
enterElement(element: string): void {
|
|
26
|
+
elements.push(element);
|
|
27
|
+
},
|
|
20
28
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
exitElement(): void {
|
|
30
|
+
elements.pop();
|
|
31
|
+
},
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
getSnapshot(): ValidationContextSnapshot {
|
|
34
|
+
return {
|
|
35
|
+
elements: elements.slice(),
|
|
36
|
+
currentElement: elements[elements.length - 1],
|
|
37
|
+
parentElements: elements.slice(0, -1),
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
};
|
|
32
41
|
}
|
package/src/builtins.ts
CHANGED
|
@@ -13,13 +13,13 @@ interface BuiltinParamBaseSchema {
|
|
|
13
13
|
|
|
14
14
|
export interface BuiltinPrimitiveParamSchema extends BuiltinParamBaseSchema {
|
|
15
15
|
kind: "primitive";
|
|
16
|
-
types: string
|
|
16
|
+
types: Array<string>;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface BuiltinFunctionParamSchema extends BuiltinParamBaseSchema {
|
|
20
20
|
kind: "function";
|
|
21
21
|
signature: {
|
|
22
|
-
params: BuiltinCallbackParamSchema
|
|
22
|
+
params: Array<BuiltinCallbackParamSchema>;
|
|
23
23
|
returnType: string;
|
|
24
24
|
};
|
|
25
25
|
}
|
|
@@ -27,7 +27,7 @@ export interface BuiltinFunctionParamSchema extends BuiltinParamBaseSchema {
|
|
|
27
27
|
export type BuiltinParamSchema = BuiltinPrimitiveParamSchema | BuiltinFunctionParamSchema;
|
|
28
28
|
|
|
29
29
|
export interface BuiltinMethodSchema {
|
|
30
|
-
params: BuiltinParamSchema
|
|
30
|
+
params: Array<BuiltinParamSchema>;
|
|
31
31
|
returnType: string;
|
|
32
32
|
description?: string;
|
|
33
33
|
}
|
|
@@ -383,8 +383,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
383
383
|
generic: "<T>",
|
|
384
384
|
methods: {
|
|
385
385
|
map: {
|
|
386
|
-
description:
|
|
387
|
-
"Calls a defined callback function on each element of an array, and returns an array that contains the results",
|
|
386
|
+
description: "Calls a defined callback function on each element of an array, and returns an array that contains the results",
|
|
388
387
|
params: [
|
|
389
388
|
{
|
|
390
389
|
kind: "function" as const,
|
|
@@ -470,8 +469,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
470
469
|
returnType: "U",
|
|
471
470
|
},
|
|
472
471
|
find: {
|
|
473
|
-
description:
|
|
474
|
-
"Returns the value of the first element in the array where predicate is true, and undefined otherwise",
|
|
472
|
+
description: "Returns the value of the first element in the array where predicate is true, and undefined otherwise",
|
|
475
473
|
params: [
|
|
476
474
|
{
|
|
477
475
|
kind: "function" as const,
|
|
@@ -569,8 +567,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
569
567
|
kind: "primitive" as const,
|
|
570
568
|
name: "end",
|
|
571
569
|
types: ["number"],
|
|
572
|
-
description:
|
|
573
|
-
"The end index of the specified portion of the array. This is exclusive of the element at the index 'end'",
|
|
570
|
+
description: "The end index of the specified portion of the array. This is exclusive of the element at the index 'end'",
|
|
574
571
|
required: false,
|
|
575
572
|
},
|
|
576
573
|
],
|
|
@@ -590,8 +587,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
590
587
|
kind: "primitive" as const,
|
|
591
588
|
name: "fromIndex",
|
|
592
589
|
types: ["number"],
|
|
593
|
-
description:
|
|
594
|
-
"The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0",
|
|
590
|
+
description: "The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0",
|
|
595
591
|
required: false,
|
|
596
592
|
},
|
|
597
593
|
],
|
|
@@ -611,8 +607,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
611
607
|
kind: "primitive" as const,
|
|
612
608
|
name: "fromIndex",
|
|
613
609
|
types: ["number"],
|
|
614
|
-
description:
|
|
615
|
-
"The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0",
|
|
610
|
+
description: "The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0",
|
|
616
611
|
required: false,
|
|
617
612
|
},
|
|
618
613
|
],
|
|
@@ -639,8 +634,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
639
634
|
kind: "primitive" as const,
|
|
640
635
|
name: "index",
|
|
641
636
|
types: ["number"],
|
|
642
|
-
description:
|
|
643
|
-
"The zero-based index of the desired code unit. A negative index will count back from the last item",
|
|
637
|
+
description: "The zero-based index of the desired code unit. A negative index will count back from the last item",
|
|
644
638
|
required: true,
|
|
645
639
|
},
|
|
646
640
|
],
|
|
@@ -688,8 +682,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
688
682
|
returnType: "number",
|
|
689
683
|
},
|
|
690
684
|
flat: {
|
|
691
|
-
description:
|
|
692
|
-
"Returns a new array with all sub-array elements concatenated into it recursively up to the specified depth",
|
|
685
|
+
description: "Returns a new array with all sub-array elements concatenated into it recursively up to the specified depth",
|
|
693
686
|
params: [
|
|
694
687
|
{
|
|
695
688
|
kind: "primitive" as const,
|
|
@@ -702,8 +695,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
702
695
|
returnType: "T[]",
|
|
703
696
|
},
|
|
704
697
|
flatMap: {
|
|
705
|
-
description:
|
|
706
|
-
"Calls a defined callback function on each element of an array, then flattens the result into a new array",
|
|
698
|
+
description: "Calls a defined callback function on each element of an array, then flattens the result into a new array",
|
|
707
699
|
params: [
|
|
708
700
|
{
|
|
709
701
|
kind: "function" as const,
|
|
@@ -769,8 +761,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
769
761
|
kind: "primitive" as const,
|
|
770
762
|
name: "index",
|
|
771
763
|
types: ["number"],
|
|
772
|
-
description:
|
|
773
|
-
"The zero-based index of the desired character. If there is no character at the specified index, NaN is returned",
|
|
764
|
+
description: "The zero-based index of the desired character. If there is no character at the specified index, NaN is returned",
|
|
774
765
|
required: true,
|
|
775
766
|
},
|
|
776
767
|
],
|
|
@@ -845,8 +836,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
845
836
|
kind: "primitive" as const,
|
|
846
837
|
name: "position",
|
|
847
838
|
types: ["number"],
|
|
848
|
-
description:
|
|
849
|
-
"The index at which to begin searching the String object. If omitted, search starts at the beginning of the string",
|
|
839
|
+
description: "The index at which to begin searching the String object. If omitted, search starts at the beginning of the string",
|
|
850
840
|
required: false,
|
|
851
841
|
},
|
|
852
842
|
],
|
|
@@ -866,8 +856,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
866
856
|
kind: "primitive" as const,
|
|
867
857
|
name: "position",
|
|
868
858
|
types: ["number"],
|
|
869
|
-
description:
|
|
870
|
-
"The index at which to begin searching. If omitted, the search begins at the end of the string",
|
|
859
|
+
description: "The index at which to begin searching. If omitted, the search begins at the end of the string",
|
|
871
860
|
required: false,
|
|
872
861
|
},
|
|
873
862
|
],
|
|
@@ -996,8 +985,7 @@ const BUILTINS: Record<string, BuiltinSchema> = {
|
|
|
996
985
|
kind: "primitive" as const,
|
|
997
986
|
name: "replaceValue",
|
|
998
987
|
types: ["string"],
|
|
999
|
-
description:
|
|
1000
|
-
"A string containing the text to replace for every successful match of searchValue in this string",
|
|
988
|
+
description: "A string containing the text to replace for every successful match of searchValue in this string",
|
|
1001
989
|
required: true,
|
|
1002
990
|
},
|
|
1003
991
|
],
|
|
@@ -1093,19 +1081,20 @@ export function getBuiltins(): Record<string, BuiltinSchema> {
|
|
|
1093
1081
|
return structuredClone(BUILTINS);
|
|
1094
1082
|
}
|
|
1095
1083
|
|
|
1096
|
-
export function getBuiltinGlobals(): string
|
|
1084
|
+
export function getBuiltinGlobals(): Array<string> {
|
|
1085
|
+
// oxlint-disable-next-line typescript/no-unnecessary-boolean-literal-compare
|
|
1097
1086
|
return Object.keys(BUILTINS).filter((name) => BUILTINS[name].global === true);
|
|
1098
1087
|
}
|
|
1099
1088
|
|
|
1100
1089
|
export function isAllowedOnArray(prop: string): boolean {
|
|
1101
|
-
const arrayMethods = BUILTINS[ARRAY_PROTOTYPE]?.methods
|
|
1102
|
-
const arrayProperties = BUILTINS[ARRAY_PROTOTYPE]?.properties
|
|
1090
|
+
const arrayMethods = BUILTINS[ARRAY_PROTOTYPE]?.methods ?? {};
|
|
1091
|
+
const arrayProperties = BUILTINS[ARRAY_PROTOTYPE]?.properties ?? {};
|
|
1103
1092
|
return prop in arrayMethods || prop in arrayProperties;
|
|
1104
1093
|
}
|
|
1105
1094
|
|
|
1106
1095
|
export function isAllowedOnString(prop: string): boolean {
|
|
1107
|
-
const stringMethods = BUILTINS[STRING_PROTOTYPE]?.methods
|
|
1108
|
-
const stringProperties = BUILTINS[STRING_PROTOTYPE]?.properties
|
|
1096
|
+
const stringMethods = BUILTINS[STRING_PROTOTYPE]?.methods ?? {};
|
|
1097
|
+
const stringProperties = BUILTINS[STRING_PROTOTYPE]?.properties ?? {};
|
|
1109
1098
|
return prop in stringMethods || prop in stringProperties;
|
|
1110
1099
|
}
|
|
1111
1100
|
|
|
@@ -1127,17 +1116,17 @@ export function getMethodDefinition(methodName: string): BuiltinMethodSchema | n
|
|
|
1127
1116
|
return null;
|
|
1128
1117
|
}
|
|
1129
1118
|
|
|
1130
|
-
export function getAvailableArrayMembers(): string
|
|
1119
|
+
export function getAvailableArrayMembers(): Array<string> {
|
|
1131
1120
|
const arrayNamespace = BUILTINS[ARRAY_PROTOTYPE];
|
|
1132
|
-
const methods = Object.keys(arrayNamespace?.methods
|
|
1133
|
-
const properties = Object.keys(arrayNamespace?.properties
|
|
1121
|
+
const methods = Object.keys(arrayNamespace?.methods ?? {});
|
|
1122
|
+
const properties = Object.keys(arrayNamespace?.properties ?? {});
|
|
1134
1123
|
return [...methods, ...properties];
|
|
1135
1124
|
}
|
|
1136
1125
|
|
|
1137
|
-
export function getAvailableStringMembers(): string
|
|
1126
|
+
export function getAvailableStringMembers(): Array<string> {
|
|
1138
1127
|
const stringNamespace = BUILTINS[STRING_PROTOTYPE];
|
|
1139
|
-
const methods = Object.keys(stringNamespace?.methods
|
|
1140
|
-
const properties = Object.keys(stringNamespace?.properties
|
|
1128
|
+
const methods = Object.keys(stringNamespace?.methods ?? {});
|
|
1129
|
+
const properties = Object.keys(stringNamespace?.properties ?? {});
|
|
1141
1130
|
return [...methods, ...properties];
|
|
1142
1131
|
}
|
|
1143
1132
|
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { getBuiltins } from "../../builtins.js";
|
|
2
|
-
import type {
|
|
3
|
-
BuiltinSchema,
|
|
4
|
-
BuiltinMethodSchema,
|
|
5
|
-
BuiltinParamSchema,
|
|
6
|
-
BuiltinPropertySchema,
|
|
7
|
-
BuiltinCallbackParamSchema,
|
|
8
|
-
} from "../../builtins.js";
|
|
2
|
+
import type { BuiltinSchema, BuiltinMethodSchema, BuiltinParamSchema, BuiltinPropertySchema, BuiltinCallbackParamSchema } from "../../builtins.js";
|
|
9
3
|
|
|
10
4
|
function generateJSDoc(description?: string, indent: string = ""): string {
|
|
11
|
-
if (!description)
|
|
5
|
+
if (!description) {
|
|
6
|
+
return "";
|
|
7
|
+
}
|
|
12
8
|
return `${indent}/**\n${indent} * ${description}\n${indent} */\n`;
|
|
13
9
|
}
|
|
14
10
|
|
|
15
|
-
function generateCallbackSignature(signature: { params: BuiltinCallbackParamSchema
|
|
11
|
+
function generateCallbackSignature(signature: { params: Array<BuiltinCallbackParamSchema>; returnType: string }): string {
|
|
16
12
|
const params = signature.params.map((p) => `${p.name}: ${p.type}`).join(", ");
|
|
17
13
|
return `(${params}) => ${signature.returnType}`;
|
|
18
14
|
}
|
|
@@ -21,23 +17,20 @@ function extractGenerics(method: BuiltinMethodSchema): string {
|
|
|
21
17
|
for (const param of method.params) {
|
|
22
18
|
if (param.kind === "function") {
|
|
23
19
|
const usesU = param.signature.returnType === "U" || param.signature.params.some((p) => p.type === "U");
|
|
24
|
-
if (usesU)
|
|
20
|
+
if (usesU) {
|
|
21
|
+
return "<U>";
|
|
22
|
+
}
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
25
|
return "";
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
function generateParam(param: BuiltinParamSchema): string {
|
|
31
|
-
let typeStr: string;
|
|
29
|
+
let typeStr: string = param.kind === "function" ? generateCallbackSignature(param.signature) : param.types.join(" | ");
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
typeStr = param.types.join(" | ");
|
|
37
|
-
// The type should be an array for variadic parameters
|
|
38
|
-
if (param.variadic) {
|
|
39
|
-
typeStr = `${typeStr}[]`;
|
|
40
|
-
}
|
|
31
|
+
// The type should be an array for variadic parameters
|
|
32
|
+
if (param.kind !== "function" && param.variadic) {
|
|
33
|
+
typeStr = `${typeStr}[]`;
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
const optional = param.required || param.variadic ? "" : "?";
|
|
@@ -93,7 +86,7 @@ function generateNamespaceDeclaration(namespace: string, schema: BuiltinSchema):
|
|
|
93
86
|
|
|
94
87
|
if (schema.intrinsic) {
|
|
95
88
|
const interfaceName = namespace.replace(".prototype", "");
|
|
96
|
-
const genericParam = schema.generic
|
|
89
|
+
const genericParam = schema.generic ?? "";
|
|
97
90
|
|
|
98
91
|
result += `interface ${interfaceName}${genericParam} {\n`;
|
|
99
92
|
|