jsxpression 0.1.41 → 0.2.1

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.
Files changed (183) hide show
  1. package/lib/analyze/analysis-error.d.ts.map +1 -1
  2. package/lib/analyze/analysis-error.js +2 -7
  3. package/lib/analyze/analysis-error.js.map +1 -1
  4. package/lib/analyze/analysis-report.d.ts +13 -13
  5. package/lib/analyze/analysis-report.d.ts.map +1 -1
  6. package/lib/analyze/analysis-report.js +48 -45
  7. package/lib/analyze/analysis-report.js.map +1 -1
  8. package/lib/analyze/analyze.d.ts +1 -1
  9. package/lib/analyze/analyze.d.ts.map +1 -1
  10. package/lib/analyze/analyze.js +4 -4
  11. package/lib/analyze/analyze.js.map +1 -1
  12. package/lib/analyze/data/analyze.d.ts +1 -1
  13. package/lib/analyze/data/analyze.d.ts.map +1 -1
  14. package/lib/analyze/data/analyze.js +5 -5
  15. package/lib/analyze/data/analyze.js.map +1 -1
  16. package/lib/analyze/data/data-access.d.ts +1 -1
  17. package/lib/analyze/data/data-access.d.ts.map +1 -1
  18. package/lib/analyze/data/data-access.js +19 -15
  19. package/lib/analyze/data/data-access.js.map +1 -1
  20. package/lib/analyze/data/method-calls.d.ts +1 -1
  21. package/lib/analyze/data/method-calls.d.ts.map +1 -1
  22. package/lib/analyze/data/method-calls.js +5 -5
  23. package/lib/analyze/data/method-calls.js.map +1 -1
  24. package/lib/analyze/data/utils.d.ts +3 -3
  25. package/lib/analyze/data/utils.d.ts.map +1 -1
  26. package/lib/analyze/data/utils.js +6 -5
  27. package/lib/analyze/data/utils.js.map +1 -1
  28. package/lib/analyze/index.d.ts +1 -1
  29. package/lib/analyze/index.d.ts.map +1 -1
  30. package/lib/analyze/index.js +1 -1
  31. package/lib/analyze/index.js.map +1 -1
  32. package/lib/analyze/jsx/analyze.d.ts +1 -1
  33. package/lib/analyze/jsx/analyze.d.ts.map +1 -1
  34. package/lib/analyze/jsx/analyze.js +4 -4
  35. package/lib/analyze/jsx/analyze.js.map +1 -1
  36. package/lib/analyze/jsx/element-attributes.d.ts +1 -1
  37. package/lib/analyze/jsx/element-attributes.d.ts.map +1 -1
  38. package/lib/analyze/jsx/element-attributes.js +3 -3
  39. package/lib/analyze/jsx/element-attributes.js.map +1 -1
  40. package/lib/analyze/jsx/element-children.d.ts +1 -1
  41. package/lib/analyze/jsx/element-children.d.ts.map +1 -1
  42. package/lib/analyze/jsx/element-children.js +3 -3
  43. package/lib/analyze/jsx/element-children.js.map +1 -1
  44. package/lib/analyze/jsx/element-tags.d.ts +1 -1
  45. package/lib/analyze/jsx/element-tags.d.ts.map +1 -1
  46. package/lib/analyze/jsx/element-tags.js +2 -2
  47. package/lib/analyze/jsx/element-tags.js.map +1 -1
  48. package/lib/analyze/security/analyze.d.ts +1 -1
  49. package/lib/analyze/security/analyze.d.ts.map +1 -1
  50. package/lib/analyze/security/analyze.js +4 -4
  51. package/lib/analyze/security/analyze.js.map +1 -1
  52. package/lib/analyze/security/call-expressions.d.ts +1 -1
  53. package/lib/analyze/security/call-expressions.d.ts.map +1 -1
  54. package/lib/analyze/security/call-expressions.js +3 -5
  55. package/lib/analyze/security/call-expressions.js.map +1 -1
  56. package/lib/analyze/security/declarations.d.ts +1 -1
  57. package/lib/analyze/security/declarations.d.ts.map +1 -1
  58. package/lib/analyze/security/declarations.js +6 -6
  59. package/lib/analyze/security/declarations.js.map +1 -1
  60. package/lib/analyze/security/expressions.d.ts +1 -1
  61. package/lib/analyze/security/expressions.d.ts.map +1 -1
  62. package/lib/analyze/security/expressions.js +3 -6
  63. package/lib/analyze/security/expressions.js.map +1 -1
  64. package/lib/analyze/security/identifiers.d.ts +1 -1
  65. package/lib/analyze/security/identifiers.d.ts.map +1 -1
  66. package/lib/analyze/security/identifiers.js +19 -22
  67. package/lib/analyze/security/identifiers.js.map +1 -1
  68. package/lib/analyze/utils.d.ts +4 -4
  69. package/lib/analyze/utils.d.ts.map +1 -1
  70. package/lib/analyze/utils.js +5 -3
  71. package/lib/analyze/utils.js.map +1 -1
  72. package/lib/analyze/validation-context.d.ts +8 -8
  73. package/lib/analyze/validation-context.d.ts.map +1 -1
  74. package/lib/analyze/validation-context.js +23 -21
  75. package/lib/analyze/validation-context.js.map +1 -1
  76. package/lib/builtins.d.ts +6 -6
  77. package/lib/builtins.d.ts.map +1 -1
  78. package/lib/builtins.js +9 -8
  79. package/lib/builtins.js.map +1 -1
  80. package/lib/codegen/builtins/builtin-types.d.ts.map +1 -1
  81. package/lib/codegen/builtins/builtin-types.js +9 -13
  82. package/lib/codegen/builtins/builtin-types.js.map +1 -1
  83. package/lib/codegen/generate-typescript-definitions.d.ts +18 -17
  84. package/lib/codegen/generate-typescript-definitions.d.ts.map +1 -1
  85. package/lib/codegen/generate-typescript-definitions.js +19 -23
  86. package/lib/codegen/generate-typescript-definitions.js.map +1 -1
  87. package/lib/codegen/schema/component-types.d.ts.map +1 -1
  88. package/lib/codegen/schema/component-types.js +7 -4
  89. package/lib/codegen/schema/component-types.js.map +1 -1
  90. package/lib/codegen/schema/data-types.d.ts.map +1 -1
  91. package/lib/codegen/schema/data-types.js +1 -1
  92. package/lib/codegen/schema/data-types.js.map +1 -1
  93. package/lib/codegen/schema/function-types.d.ts.map +1 -1
  94. package/lib/codegen/schema/function-types.js +1 -3
  95. package/lib/codegen/schema/function-types.js.map +1 -1
  96. package/lib/codegen/schema/utils.d.ts +4 -3
  97. package/lib/codegen/schema/utils.d.ts.map +1 -1
  98. package/lib/codegen/schema/utils.js +12 -8
  99. package/lib/codegen/schema/utils.js.map +1 -1
  100. package/lib/compile/compilation-error.d.ts +1 -1
  101. package/lib/compile/compilation-error.d.ts.map +1 -1
  102. package/lib/compile/compilation-error.js +3 -1
  103. package/lib/compile/compilation-error.js.map +1 -1
  104. package/lib/compile/compile.d.ts.map +1 -1
  105. package/lib/compile/compile.js +5 -11
  106. package/lib/compile/compile.js.map +1 -1
  107. package/lib/evaluate/evaluate.d.ts +6 -6
  108. package/lib/evaluate/evaluate.d.ts.map +1 -1
  109. package/lib/evaluate/evaluate.js +1 -1
  110. package/lib/evaluate/evaluate.js.map +1 -1
  111. package/lib/evaluate/evaluation-error.d.ts.map +1 -1
  112. package/lib/evaluate/evaluation-error.js +1 -0
  113. package/lib/evaluate/evaluation-error.js.map +1 -1
  114. package/lib/index.d.ts +1 -1
  115. package/lib/index.d.ts.map +1 -1
  116. package/lib/index.js +1 -1
  117. package/lib/index.js.map +1 -1
  118. package/lib/jsx.d.ts +3 -3
  119. package/lib/jsx.d.ts.map +1 -1
  120. package/lib/jsx.js.map +1 -1
  121. package/lib/parse/parse-error.d.ts.map +1 -1
  122. package/lib/parse/parse-error.js +1 -0
  123. package/lib/parse/parse-error.js.map +1 -1
  124. package/lib/render.d.ts +25 -33
  125. package/lib/render.d.ts.map +1 -1
  126. package/lib/render.js +21 -26
  127. package/lib/render.js.map +1 -1
  128. package/lib/schema.d.ts +9 -9
  129. package/lib/schema.d.ts.map +1 -1
  130. package/lib/schema.js +1 -1
  131. package/lib/schema.js.map +1 -1
  132. package/lib/traverse.d.ts.map +1 -1
  133. package/lib/traverse.js.map +1 -1
  134. package/lib/validate.d.ts +14 -17
  135. package/lib/validate.d.ts.map +1 -1
  136. package/lib/validate.js +13 -14
  137. package/lib/validate.js.map +1 -1
  138. package/package.json +12 -12
  139. package/src/analyze/analysis-error.ts +2 -6
  140. package/src/analyze/analysis-report.ts +73 -62
  141. package/src/analyze/analyze.test.ts +60 -60
  142. package/src/analyze/analyze.ts +4 -4
  143. package/src/analyze/data/analyze.ts +5 -8
  144. package/src/analyze/data/data-access.ts +49 -46
  145. package/src/analyze/data/method-calls.ts +9 -18
  146. package/src/analyze/data/utils.ts +15 -19
  147. package/src/analyze/index.ts +1 -1
  148. package/src/analyze/jsx/analyze.ts +4 -4
  149. package/src/analyze/jsx/element-attributes.ts +5 -18
  150. package/src/analyze/jsx/element-children.ts +4 -8
  151. package/src/analyze/jsx/element-tags.ts +2 -2
  152. package/src/analyze/security/analyze.ts +4 -4
  153. package/src/analyze/security/call-expressions.ts +5 -18
  154. package/src/analyze/security/declarations.ts +14 -43
  155. package/src/analyze/security/expressions.ts +12 -49
  156. package/src/analyze/security/identifiers.ts +37 -39
  157. package/src/analyze/utils.ts +25 -19
  158. package/src/analyze/validation-context.ts +32 -23
  159. package/src/builtins.ts +27 -38
  160. package/src/codegen/builtins/builtin-types.ts +13 -20
  161. package/src/codegen/generate-typescript-definitions.test.ts +6 -6
  162. package/src/codegen/generate-typescript-definitions.ts +19 -23
  163. package/src/codegen/schema/component-types.ts +22 -12
  164. package/src/codegen/schema/data-types.ts +6 -6
  165. package/src/codegen/schema/function-types.ts +1 -3
  166. package/src/codegen/schema/utils.ts +24 -23
  167. package/src/compile/compilation-error.ts +5 -1
  168. package/src/compile/compile.test.ts +7 -21
  169. package/src/compile/compile.ts +18 -30
  170. package/src/evaluate/evaluate.test.ts +78 -94
  171. package/src/evaluate/evaluate.ts +15 -20
  172. package/src/evaluate/evaluation-error.ts +1 -0
  173. package/src/index.ts +1 -7
  174. package/src/jsx.ts +4 -6
  175. package/src/parse/parse-error.ts +1 -0
  176. package/src/parse/parse.test.ts +16 -18
  177. package/src/render.test.ts +4 -4
  178. package/src/render.ts +26 -38
  179. package/src/schema.ts +11 -11
  180. package/src/traverse.test.ts +6 -6
  181. package/src/traverse.ts +3 -3
  182. package/src/validate.ts +14 -17
  183. package/CHANGELOG.md +0 -8
@@ -2,16 +2,12 @@ import type { Program } from "acorn";
2
2
  import { isJsxElement, isJsxFragment, isJsxLeafNode, isJsxText } from "../../jsx.js";
3
3
  import { getAllowedChildren, isSelfClosing, 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 { getBestSimilarityMatcherSuggestion, getElementSimilarityMatchers, getNodeRange } from "../utils.js";
7
7
  import type { ValidationContext } from "../validation-context.js";
8
8
 
9
- export function analyzeElementChildren(
10
- ast: Program,
11
- schema: Schema,
12
- validationContext: ValidationContext
13
- ): AnalysisReport {
14
- const analysisReport = new AnalysisReport();
9
+ export function analyzeElementChildren(ast: Program, schema: Schema, validationContext: ValidationContext): AnalysisReport {
10
+ const analysisReport = createAnalysisReport();
15
11
 
16
12
  const localFunctionNames = new Set<string>();
17
13
  for (const stmt of ast.body) {
@@ -59,7 +55,7 @@ export function analyzeElementChildren(
59
55
  analysisReport.addIssue(
60
56
  "SELF_CLOSING_WITH_CHILDREN",
61
57
  `Element <${parentTag}> cannot have children. It is self-closing.`,
62
- getNodeRange(firstMeaningfulChild || node.children[0]),
58
+ getNodeRange(firstMeaningfulChild ?? node.children[0]),
63
59
  currentContext
64
60
  );
65
61
  }
@@ -1,12 +1,12 @@
1
1
  import type { Program } from "acorn";
2
2
  import { getAllElements, isElementAllowed, type Schema } from "../../schema.js";
3
3
  import { traverse } from "../../traverse.js";
4
- import { AnalysisReport } from "../analysis-report.js";
4
+ import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
5
5
  import { getBestSimilarityMatcherSuggestion, getElementSimilarityMatchers, getNodeRange } from "../utils.js";
6
6
  import type { ValidationContext } from "../validation-context.js";
7
7
 
8
8
  export function analyzeElementTags(ast: Program, schema: Schema, validationContext: ValidationContext): AnalysisReport {
9
- const analysisReport = new AnalysisReport();
9
+ const analysisReport = createAnalysisReport();
10
10
 
11
11
  const localFunctionNames = new Set<string>();
12
12
  for (const stmt of ast.body) {
@@ -1,16 +1,16 @@
1
1
  import type { Program } from "acorn";
2
2
  import type { Schema } from "../../schema.js";
3
- import { AnalysisReport } from "../analysis-report.js";
4
- import { ValidationContext } from "../validation-context.js";
3
+ import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
4
+ import { createValidationContext } from "../validation-context.js";
5
5
  import { analyzeCallExpressions } from "./call-expressions.js";
6
6
  import { analyzeDeclarations } from "./declarations.js";
7
7
  import { analyzeExpressions } from "./expressions.js";
8
8
  // import { analyzeIdentifiers } from "./identifiers.js";
9
9
 
10
10
  export function analyzeSecurity(ast: Program, schema: Schema): AnalysisReport {
11
- const validationContext = new ValidationContext();
11
+ const validationContext = createValidationContext();
12
12
 
13
- return new AnalysisReport().merge(
13
+ return createAnalysisReport().merge(
14
14
  analyzeDeclarations(ast, schema, validationContext),
15
15
  // analyzeIdentifiers(ast, schema, validationContext),
16
16
  analyzeExpressions(ast, schema, validationContext),
@@ -2,16 +2,12 @@ import type { Program } from "acorn";
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
- export function analyzeCallExpressions(
10
- ast: Program,
11
- schema: Schema,
12
- validationContext: ValidationContext
13
- ): AnalysisReport {
14
- const analysisReport = new AnalysisReport();
9
+ export function analyzeCallExpressions(ast: Program, schema: Schema, validationContext: ValidationContext): AnalysisReport {
10
+ const analysisReport = createAnalysisReport();
15
11
 
16
12
  const localFunctionNames = new Set<string>();
17
13
  for (const stmt of ast.body) {
@@ -39,21 +35,12 @@ export function analyzeCallExpressions(
39
35
  }
40
36
 
41
37
  if (callee.type === "Identifier") {
42
- if (
43
- localFunctionNames.has(callee.name) ||
44
- schemaFunctionNames.has(callee.name) ||
45
- builtinGlobals.has(callee.name)
46
- ) {
38
+ if (localFunctionNames.has(callee.name) || schemaFunctionNames.has(callee.name) || builtinGlobals.has(callee.name)) {
47
39
  return;
48
40
  }
49
41
  }
50
42
 
51
- analysisReport.addIssue(
52
- "DIRECT_CALL_NOT_ALLOWED",
53
- "only member calls allowed",
54
- getNodeRange(node),
55
- validationContext.getSnapshot()
56
- );
43
+ analysisReport.addIssue("DIRECT_CALL_NOT_ALLOWED", "only member calls allowed", getNodeRange(node), validationContext.getSnapshot());
57
44
  },
58
45
  });
59
46
 
@@ -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
- ast: Program,
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
- if (!topLevelNodes.has(node as any)) {
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 (!lastStatement || lastStatement.type !== "ReturnStatement") {
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 type { ValidationContext } from "../validation-context.js";
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
- ast: Program,
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 = new 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 (param as any).properties) {
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 (param as any).elements) {
154
- if (el) collectParamNames(el, names);
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((param as any).left, names);
150
+ collectParamNames(param.left, names);
159
151
  break;
160
152
  case "RestElement":
161
- collectParamNames((param as any).argument, names);
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
- for (const key of Object.keys(node)) {
205
- const value = (node as any)[key];
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<any, any> {
232
- const parentMap = new Map<any, any>();
226
+ function buildParentMap(ast: Program): Map<AnyNode, AnyNode | null> {
227
+ const parentMap = new Map<AnyNode, AnyNode | null>();
233
228
 
234
- function visit(node: any, parent: any): void {
235
- if (!node || typeof node !== "object") return;
236
- if (node.type) {
237
- parentMap.set(node, parent);
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(node)) {
240
- const value = node[key];
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.type) {
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.type) {
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
  }
@@ -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(node: any): Range {
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[]): SimilarityMatcher[] {
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[]): SimilarityMatcher[] {
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[]): string | null {
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[], type: SimilarityMatcherType): SimilarityMatcher[] {
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 available
75
- .map((suggestion) => ({
76
- suggestion,
77
- distance: levenshteinDistance(invalid.toLowerCase(), suggestion.toLowerCase()),
78
- type,
79
- }))
80
- .filter((similarityMatcher) => similarityMatcher.distance <= Math.max(2, Math.floor(invalid.length * 0.4)))
81
- .sort((a, b) => a.distance - b.distance)
82
- .slice(0, 3)
83
- .map((similarityMatcher) => ({
84
- ...similarityMatcher,
85
- confidence: 1 - similarityMatcher.distance / Math.max(invalid.length, similarityMatcher.suggestion.length),
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 class ValidationContext {
8
- #elements: string[] = [];
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
- get currentPath(): string {
11
- if (this.#elements.length > 0) {
12
- return this.#elements.join(" > ");
13
- }
14
- return "";
15
- }
17
+ return {
18
+ get currentPath(): string {
19
+ if (elements.length > 0) {
20
+ return elements.join(" > ");
21
+ }
22
+ return "";
23
+ },
16
24
 
17
- enterElement(element: string): void {
18
- this.#elements.push(element);
19
- }
25
+ enterElement(element: string): void {
26
+ elements.push(element);
27
+ },
20
28
 
21
- exitElement(): void {
22
- this.#elements.pop();
23
- }
29
+ exitElement(): void {
30
+ elements.pop();
31
+ },
24
32
 
25
- getSnapshot(): ValidationContextSnapshot {
26
- return {
27
- elements: this.#elements.slice(),
28
- currentElement: this.#elements[this.#elements.length - 1],
29
- parentElements: this.#elements.slice(0, -1),
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
  }