jsxpression 0.1.40 → 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 +8 -9
- 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.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 +2 -2
- 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.map +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 +0 -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 +6 -19
- package/src/analyze/jsx/element-children.ts +9 -13
- 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 +39 -41
- package/src/analyze/utils.ts +25 -19
- package/src/analyze/validation-context.ts +32 -23
- package/src/builtins.ts +28 -39
- package/src/codegen/builtins/builtin-types.ts +13 -20
- package/src/codegen/generate-typescript-definitions.test.ts +29 -29
- 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 -1
- 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 +33 -45
- package/src/evaluate/evaluate.test.ts +95 -111
- package/src/evaluate/evaluate.ts +16 -21
- 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 +27 -39
- package/src/schema.ts +12 -12
- package/src/traverse.test.ts +6 -6
- package/src/traverse.ts +15 -16
- package/src/validate.ts +14 -17
- package/CHANGELOG.md +0 -8
|
@@ -1,46 +1,29 @@
|
|
|
1
|
-
import type { Program } from "acorn";
|
|
1
|
+
import type { FunctionDeclaration, Program } from "acorn";
|
|
2
2
|
import { isJsxRoot } from "../../jsx.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
|
-
export function analyzeDeclarations(
|
|
10
|
-
|
|
11
|
-
_schema: Schema,
|
|
12
|
-
validationContext: ValidationContext
|
|
13
|
-
): AnalysisReport {
|
|
14
|
-
const analysisReport = new AnalysisReport();
|
|
9
|
+
export function analyzeDeclarations(ast: Program, _schema: Schema, validationContext: ValidationContext): AnalysisReport {
|
|
10
|
+
const analysisReport = createAnalysisReport();
|
|
15
11
|
const topLevelNodes = new Set(ast.body);
|
|
16
12
|
|
|
17
13
|
traverse(ast, {
|
|
18
14
|
ImportDeclaration(node) {
|
|
19
|
-
analysisReport.addIssue(
|
|
20
|
-
"IMPORT_NOT_ALLOWED",
|
|
21
|
-
"import not allowed",
|
|
22
|
-
getNodeRange(node),
|
|
23
|
-
validationContext.getSnapshot()
|
|
24
|
-
);
|
|
15
|
+
analysisReport.addIssue("IMPORT_NOT_ALLOWED", "import not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
25
16
|
},
|
|
26
17
|
ExportNamedDeclaration(node) {
|
|
27
|
-
analysisReport.addIssue(
|
|
28
|
-
"EXPORT_NOT_ALLOWED",
|
|
29
|
-
"export not allowed",
|
|
30
|
-
getNodeRange(node),
|
|
31
|
-
validationContext.getSnapshot()
|
|
32
|
-
);
|
|
18
|
+
analysisReport.addIssue("EXPORT_NOT_ALLOWED", "export not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
33
19
|
},
|
|
34
20
|
ExportDefaultDeclaration(node) {
|
|
35
|
-
analysisReport.addIssue(
|
|
36
|
-
"EXPORT_NOT_ALLOWED",
|
|
37
|
-
"export not allowed",
|
|
38
|
-
getNodeRange(node),
|
|
39
|
-
validationContext.getSnapshot()
|
|
40
|
-
);
|
|
21
|
+
analysisReport.addIssue("EXPORT_NOT_ALLOWED", "export not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
41
22
|
},
|
|
42
23
|
FunctionDeclaration(node) {
|
|
43
|
-
|
|
24
|
+
// acorn-walk types this callback as FunctionDeclaration | AnonymousFunctionDeclaration, but Program-level
|
|
25
|
+
// function declarations always have an id, so the cast reflects that guarantee without changing behavior.
|
|
26
|
+
if (!topLevelNodes.has(node as FunctionDeclaration)) {
|
|
44
27
|
analysisReport.addIssue(
|
|
45
28
|
"FUNCTION_NOT_ALLOWED",
|
|
46
29
|
"nested function declarations not allowed",
|
|
@@ -50,34 +33,22 @@ export function analyzeDeclarations(
|
|
|
50
33
|
}
|
|
51
34
|
},
|
|
52
35
|
ClassDeclaration(node) {
|
|
53
|
-
analysisReport.addIssue(
|
|
54
|
-
"CLASS_NOT_ALLOWED",
|
|
55
|
-
"classes not allowed",
|
|
56
|
-
getNodeRange(node),
|
|
57
|
-
validationContext.getSnapshot()
|
|
58
|
-
);
|
|
36
|
+
analysisReport.addIssue("CLASS_NOT_ALLOWED", "classes not allowed", getNodeRange(node), validationContext.getSnapshot());
|
|
59
37
|
},
|
|
60
38
|
VariableDeclaration(node) {
|
|
61
39
|
if (node.kind === "const") {
|
|
62
40
|
return;
|
|
63
41
|
}
|
|
64
|
-
analysisReport.addIssue(
|
|
65
|
-
"VARIABLE_NOT_ALLOWED",
|
|
66
|
-
`${node.kind} not allowed, use const`,
|
|
67
|
-
getNodeRange(node),
|
|
68
|
-
validationContext.getSnapshot()
|
|
69
|
-
);
|
|
42
|
+
analysisReport.addIssue("VARIABLE_NOT_ALLOWED", `${node.kind} not allowed, use const`, getNodeRange(node), validationContext.getSnapshot());
|
|
70
43
|
},
|
|
71
44
|
});
|
|
72
45
|
|
|
73
46
|
const hasDeclarations = ast.body.some((s) => s.type === "VariableDeclaration" || s.type === "FunctionDeclaration");
|
|
74
47
|
if (hasDeclarations) {
|
|
75
48
|
const lastStatement = ast.body[ast.body.length - 1];
|
|
76
|
-
if (
|
|
49
|
+
if (lastStatement?.type !== "ReturnStatement") {
|
|
77
50
|
const isBareJsx = lastStatement?.type === "ExpressionStatement" && isJsxRoot(lastStatement.expression);
|
|
78
|
-
const range = lastStatement
|
|
79
|
-
? getNodeRange(lastStatement)
|
|
80
|
-
: { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } };
|
|
51
|
+
const range = lastStatement ? getNodeRange(lastStatement) : { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } };
|
|
81
52
|
analysisReport.addIssue(
|
|
82
53
|
"RETURN_REQUIRED",
|
|
83
54
|
isBareJsx
|
|
@@ -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,16 +45,13 @@ 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 as FunctionDeclaration);
|
|
48
|
+
const params = scopeParent.type === "ArrowFunctionExpression" ? arrowParamScopes.get(scopeParent) : functionParamScopes.get(scopeParent);
|
|
59
49
|
if (params?.has(name)) {
|
|
60
50
|
return;
|
|
61
51
|
}
|
|
62
52
|
|
|
63
53
|
if (scopeParent.type === "FunctionDeclaration") {
|
|
64
|
-
const localConsts = functionLocalConsts.get(scopeParent
|
|
54
|
+
const localConsts = functionLocalConsts.get(scopeParent);
|
|
65
55
|
if (localConsts?.has(name)) {
|
|
66
56
|
return;
|
|
67
57
|
}
|
|
@@ -138,10 +128,10 @@ function getFunctionLocalConsts(ast: Program): Map<FunctionDeclaration, Set<stri
|
|
|
138
128
|
function collectParamNames(param: AnyNode, names: Set<string>): void {
|
|
139
129
|
switch (param.type) {
|
|
140
130
|
case "Identifier":
|
|
141
|
-
names.add(
|
|
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
|
}
|