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.
Files changed (180) 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 +8 -9
  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.js.map +1 -1
  94. package/lib/codegen/schema/utils.d.ts +4 -3
  95. package/lib/codegen/schema/utils.d.ts.map +1 -1
  96. package/lib/codegen/schema/utils.js +12 -8
  97. package/lib/codegen/schema/utils.js.map +1 -1
  98. package/lib/compile/compilation-error.d.ts +1 -1
  99. package/lib/compile/compilation-error.d.ts.map +1 -1
  100. package/lib/compile/compilation-error.js +3 -1
  101. package/lib/compile/compilation-error.js.map +1 -1
  102. package/lib/compile/compile.d.ts.map +1 -1
  103. package/lib/compile/compile.js +5 -11
  104. package/lib/compile/compile.js.map +1 -1
  105. package/lib/evaluate/evaluate.d.ts +6 -6
  106. package/lib/evaluate/evaluate.d.ts.map +1 -1
  107. package/lib/evaluate/evaluate.js +2 -2
  108. package/lib/evaluate/evaluate.js.map +1 -1
  109. package/lib/evaluate/evaluation-error.d.ts.map +1 -1
  110. package/lib/evaluate/evaluation-error.js +1 -0
  111. package/lib/evaluate/evaluation-error.js.map +1 -1
  112. package/lib/index.d.ts.map +1 -1
  113. package/lib/index.js.map +1 -1
  114. package/lib/jsx.d.ts +3 -3
  115. package/lib/jsx.d.ts.map +1 -1
  116. package/lib/jsx.js.map +1 -1
  117. package/lib/parse/parse-error.d.ts.map +1 -1
  118. package/lib/parse/parse-error.js +1 -0
  119. package/lib/parse/parse-error.js.map +1 -1
  120. package/lib/render.d.ts +25 -33
  121. package/lib/render.d.ts.map +1 -1
  122. package/lib/render.js +21 -26
  123. package/lib/render.js.map +1 -1
  124. package/lib/schema.d.ts +9 -9
  125. package/lib/schema.d.ts.map +1 -1
  126. package/lib/schema.js +1 -1
  127. package/lib/schema.js.map +1 -1
  128. package/lib/traverse.d.ts.map +1 -1
  129. package/lib/traverse.js +0 -1
  130. package/lib/traverse.js.map +1 -1
  131. package/lib/validate.d.ts +14 -17
  132. package/lib/validate.d.ts.map +1 -1
  133. package/lib/validate.js +13 -14
  134. package/lib/validate.js.map +1 -1
  135. package/package.json +14 -14
  136. package/src/analyze/analysis-error.ts +2 -6
  137. package/src/analyze/analysis-report.ts +73 -62
  138. package/src/analyze/analyze.test.ts +14 -18
  139. package/src/analyze/analyze.ts +4 -4
  140. package/src/analyze/data/analyze.ts +5 -8
  141. package/src/analyze/data/data-access.ts +49 -46
  142. package/src/analyze/data/method-calls.ts +9 -18
  143. package/src/analyze/data/utils.ts +15 -19
  144. package/src/analyze/index.ts +1 -1
  145. package/src/analyze/jsx/analyze.ts +4 -4
  146. package/src/analyze/jsx/element-attributes.ts +6 -19
  147. package/src/analyze/jsx/element-children.ts +9 -13
  148. package/src/analyze/jsx/element-tags.ts +2 -2
  149. package/src/analyze/security/analyze.ts +4 -4
  150. package/src/analyze/security/call-expressions.ts +5 -18
  151. package/src/analyze/security/declarations.ts +14 -43
  152. package/src/analyze/security/expressions.ts +12 -49
  153. package/src/analyze/security/identifiers.ts +39 -41
  154. package/src/analyze/utils.ts +25 -19
  155. package/src/analyze/validation-context.ts +32 -23
  156. package/src/builtins.ts +28 -39
  157. package/src/codegen/builtins/builtin-types.ts +13 -20
  158. package/src/codegen/generate-typescript-definitions.test.ts +29 -29
  159. package/src/codegen/generate-typescript-definitions.ts +19 -23
  160. package/src/codegen/schema/component-types.ts +22 -12
  161. package/src/codegen/schema/data-types.ts +6 -6
  162. package/src/codegen/schema/function-types.ts +1 -1
  163. package/src/codegen/schema/utils.ts +24 -23
  164. package/src/compile/compilation-error.ts +5 -1
  165. package/src/compile/compile.test.ts +7 -21
  166. package/src/compile/compile.ts +33 -45
  167. package/src/evaluate/evaluate.test.ts +95 -111
  168. package/src/evaluate/evaluate.ts +16 -21
  169. package/src/evaluate/evaluation-error.ts +1 -0
  170. package/src/index.ts +1 -7
  171. package/src/jsx.ts +4 -6
  172. package/src/parse/parse-error.ts +1 -0
  173. package/src/parse/parse.test.ts +1 -1
  174. package/src/render.test.ts +4 -4
  175. package/src/render.ts +27 -39
  176. package/src/schema.ts +12 -12
  177. package/src/traverse.test.ts +6 -6
  178. package/src/traverse.ts +15 -16
  179. package/src/validate.ts +14 -17
  180. package/CHANGELOG.md +0 -8
@@ -1,10 +1,10 @@
1
1
  import type { Program } from "acorn";
2
2
  import type { Schema } from "../schema.js";
3
- import { AnalysisReport } from "./analysis-report.js";
4
- import { analyzeSecurity } from "./security/index.js";
5
- import { analyzeJsx } from "./jsx/index.js";
3
+ import { createAnalysisReport, type AnalysisReport } from "./analysis-report.js";
6
4
  import { analyzeData } from "./data/index.js";
5
+ import { analyzeJsx } from "./jsx/index.js";
6
+ import { analyzeSecurity } from "./security/index.js";
7
7
 
8
8
  export function analyze(ast: Program, schema: Schema): AnalysisReport {
9
- return new AnalysisReport().merge(analyzeSecurity(ast, schema), analyzeJsx(ast, schema), analyzeData(ast, schema));
9
+ return createAnalysisReport().merge(analyzeSecurity(ast, schema), analyzeJsx(ast, schema), analyzeData(ast, schema));
10
10
  }
@@ -1,15 +1,12 @@
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";
5
- import { analyzeMethodCalls } from "./method-calls.js";
3
+ import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
4
+ import { createValidationContext } from "../validation-context.js";
6
5
  import { analyzeDataAccess } from "./data-access.js";
6
+ import { analyzeMethodCalls } from "./method-calls.js";
7
7
 
8
8
  export function analyzeData(ast: Program, schema: Schema): AnalysisReport {
9
- const validationContext = new ValidationContext();
9
+ const validationContext = createValidationContext();
10
10
 
11
- return new AnalysisReport().merge(
12
- analyzeMethodCalls(ast, schema, validationContext),
13
- analyzeDataAccess(ast, schema, validationContext)
14
- );
11
+ return createAnalysisReport().merge(analyzeMethodCalls(ast, schema, validationContext), analyzeDataAccess(ast, schema, validationContext));
15
12
  }
@@ -1,20 +1,20 @@
1
- import type { Program } from "acorn";
2
- import { traverse } from "../../traverse.js";
1
+ import type { AnyNode, ArrowFunctionExpression, CallExpression, Identifier, MemberExpression, Program } from "acorn";
3
2
  import type { ArrayPropertySchema, PropertySchema, Schema } from "../../schema.js";
3
+ import { traverse } from "../../traverse.js";
4
+ import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
5
+ import { getNodeRange } from "../utils.js";
4
6
  import type { ValidationContext } from "../validation-context.js";
5
- import { AnalysisReport } from "../analysis-report.js";
6
7
  import { isSimpleDataAccess, extractPath, validateSchemaPath } from "./utils.js";
7
- import { getNodeRange } from "../utils.js";
8
8
 
9
9
  export function analyzeDataAccess(ast: Program, schema: Schema, validationContext: ValidationContext): AnalysisReport {
10
- const analysisReport = new AnalysisReport();
10
+ const analysisReport = createAnalysisReport();
11
11
 
12
12
  const dataKeys = new Set(Object.keys(schema.data ?? {}));
13
13
  const dataPaths = new Set<string>();
14
- const arrowFunctionContexts = new Map<any, Map<string, any>>();
14
+ const arrowFunctionContexts = new Map<ArrowFunctionExpression, Map<string, PropertySchema>>();
15
15
 
16
16
  // First pass: collect all data paths and arrow function contexts (including nested ones)
17
- function collectArrowFunctionContexts(node: any): void {
17
+ function collectArrowFunctionContexts(node: AnyNode): void {
18
18
  if (node.type === "CallExpression") {
19
19
  const { callee, arguments: args } = node;
20
20
 
@@ -35,7 +35,7 @@ export function analyzeDataAccess(ast: Program, schema: Schema, validationContex
35
35
  const arrowFunction = args[0];
36
36
 
37
37
  if (arrayElementType && arrowFunction.params.length > 0) {
38
- const parameterTypes = new Map();
38
+ const parameterTypes = new Map<string, PropertySchema>();
39
39
 
40
40
  // First parameter is always the array element
41
41
  if (arrowFunction.params[0].type === "Identifier") {
@@ -54,17 +54,18 @@ export function analyzeDataAccess(ast: Program, schema: Schema, validationContex
54
54
  }
55
55
 
56
56
  // Recursively traverse all child nodes
57
- for (const key of Object.keys(node)) {
58
- const value = node[key];
57
+ const record = node as unknown as Record<string, unknown>;
58
+ for (const key of Object.keys(record)) {
59
+ const value = record[key];
59
60
  if (value && typeof value === "object") {
60
61
  if (Array.isArray(value)) {
61
62
  for (const child of value) {
62
- if (child && typeof child === "object" && child.type) {
63
- collectArrowFunctionContexts(child);
63
+ if (child && typeof child === "object" && (child as Record<string, unknown>)["type"]) {
64
+ collectArrowFunctionContexts(child as AnyNode);
64
65
  }
65
66
  }
66
- } else if (value.type) {
67
- collectArrowFunctionContexts(value);
67
+ } else if ((value as Record<string, unknown>)["type"]) {
68
+ collectArrowFunctionContexts(value as AnyNode);
68
69
  }
69
70
  }
70
71
  }
@@ -105,7 +106,7 @@ export function analyzeDataAccess(ast: Program, schema: Schema, validationContex
105
106
  traverse(ast, {
106
107
  MemberExpression(node) {
107
108
  const parent = parentMap.get(node);
108
- if (parent && parent.type === "CallExpression" && parent.callee === node) {
109
+ if (parent?.type === "CallExpression" && parent.callee === node) {
109
110
  return;
110
111
  }
111
112
 
@@ -138,10 +139,10 @@ export function analyzeDataAccess(ast: Program, schema: Schema, validationContex
138
139
  }
139
140
 
140
141
  function findEnclosingArrowContext(
141
- targetNode: any,
142
- arrowFunctionContexts: Map<any, Map<string, any>>
143
- ): Map<string, any> | null {
144
- let best: { arrowFn: any; size: number } | null = null;
142
+ targetNode: MemberExpression,
143
+ arrowFunctionContexts: Map<ArrowFunctionExpression, Map<string, PropertySchema>>
144
+ ): Map<string, PropertySchema> | null {
145
+ let best: { arrowFn: ArrowFunctionExpression; size: number } | null = null;
145
146
  for (const arrowFn of arrowFunctionContexts.keys()) {
146
147
  if (targetNode.start >= arrowFn.start && targetNode.end <= arrowFn.end) {
147
148
  const size = arrowFn.end - arrowFn.start;
@@ -150,14 +151,14 @@ function findEnclosingArrowContext(
150
151
  }
151
152
  }
152
153
  }
153
- return best ? arrowFunctionContexts.get(best.arrowFn) || null : null;
154
+ return best ? (arrowFunctionContexts.get(best.arrowFn) ?? null) : null;
154
155
  }
155
156
 
156
157
  function getArrayElementTypeFromCall(
157
- node: any,
158
+ node: CallExpression,
158
159
  schema: Schema,
159
- arrowFunctionContexts: Map<any, Map<string, any>>
160
- ): any {
160
+ arrowFunctionContexts: Map<ArrowFunctionExpression, Map<string, PropertySchema>>
161
+ ): PropertySchema | null {
161
162
  const { callee } = node;
162
163
  const dataKeys = new Set(Object.keys(schema.data ?? {}));
163
164
 
@@ -188,9 +189,9 @@ function getArrayElementTypeFromCall(
188
189
  // Find the arrow function context that defines this parameter
189
190
  const parameterType = resolveParameterType(paramName, node, arrowFunctionContexts);
190
191
 
191
- if (parameterType && parameterType.type === "object" && parameterType.shape) {
192
+ if (parameterType?.type === "object" && parameterType.shape) {
192
193
  const propertySchema = parameterType.shape[propertyName];
193
- if (propertySchema && propertySchema.type === "array") {
194
+ if (propertySchema?.type === "array") {
194
195
  return getArrayElementType(propertySchema);
195
196
  }
196
197
  }
@@ -202,9 +203,9 @@ function getArrayElementTypeFromCall(
202
203
 
203
204
  function resolveParameterType(
204
205
  paramName: string,
205
- currentNode: any,
206
- arrowFunctionContexts: Map<any, Map<string, any>>
207
- ): any {
206
+ currentNode: AnyNode,
207
+ arrowFunctionContexts: Map<ArrowFunctionExpression, Map<string, PropertySchema>>
208
+ ): PropertySchema | undefined | null {
208
209
  // Find the arrow function that contains this node and has the parameter
209
210
  for (const [arrowFunction, parameterTypes] of arrowFunctionContexts.entries()) {
210
211
  if (parameterTypes.has(paramName)) {
@@ -217,7 +218,7 @@ function resolveParameterType(
217
218
  return null;
218
219
  }
219
220
 
220
- function isNodeInsideArrowFunction(targetNode: any, arrowFunction: any): boolean {
221
+ function isNodeInsideArrowFunction(targetNode: AnyNode, arrowFunction: ArrowFunctionExpression): boolean {
221
222
  // Simple check: if the target node's position is within the arrow function's range
222
223
  if (targetNode.start >= arrowFunction.start && targetNode.end <= arrowFunction.end) {
223
224
  return true;
@@ -225,9 +226,10 @@ function isNodeInsideArrowFunction(targetNode: any, arrowFunction: any): boolean
225
226
  return false;
226
227
  }
227
228
 
228
- function getSchemaAtPath(path: string[], schema: Schema): any {
229
+ function getSchemaAtPath(path: Array<string>, schema: Schema): PropertySchema | null | undefined {
229
230
  if (!schema.data || path.length === 0) {
230
- return schema.data;
231
+ // oxlint-disable-next-line typescript/no-explicit-any -- this branch returns the raw schema.data record (not a PropertySchema) when no path segments remain; preserved as-is for behavior parity
232
+ return schema.data as any;
231
233
  }
232
234
 
233
235
  let current = schema.data[path[0]];
@@ -244,8 +246,8 @@ function getSchemaAtPath(path: string[], schema: Schema): any {
244
246
  }
245
247
 
246
248
  function validateParameterAccess(
247
- node: any,
248
- paramType: any,
249
+ node: MemberExpression,
250
+ paramType: PropertySchema,
249
251
  analysisReport: AnalysisReport,
250
252
  validationContext: ValidationContext
251
253
  ): void {
@@ -259,7 +261,7 @@ function validateParameterAccess(
259
261
  if (!paramType.shape[propertyName]) {
260
262
  analysisReport.addIssue(
261
263
  "INVALID_PARAMETER_ACCESS",
262
- `Property '${propertyName}' does not exist on parameter '${node.object.name}'`,
264
+ `Property '${propertyName}' does not exist on parameter '${(node.object as Identifier).name}'`,
263
265
  getNodeRange(node),
264
266
  validationContext.getSnapshot(),
265
267
  Object.keys(paramType.shape)
@@ -268,9 +270,7 @@ function validateParameterAccess(
268
270
  } else {
269
271
  analysisReport.addIssue(
270
272
  "INVALID_PARAMETER_ACCESS",
271
- `Cannot access property '${propertyName}' on ${paramType.type || "undefined"} type parameter '${
272
- node.object.name
273
- }'`,
273
+ `Cannot access property '${propertyName}' on ${paramType.type ?? "undefined"} type parameter '${(node.object as Identifier).name}'`,
274
274
  getNodeRange(node),
275
275
  validationContext.getSnapshot()
276
276
  );
@@ -281,20 +281,23 @@ export function getArrayElementType(schema: ArrayPropertySchema): PropertySchema
281
281
  return schema.shape || null;
282
282
  }
283
283
 
284
- function buildParentMap(ast: Program): Map<any, any> {
285
- const map = new Map<any, any>();
286
- function visit(node: any, parent: any): void {
287
- if (!node || typeof node !== "object" || !node.type) return;
288
- map.set(node, parent);
289
- for (const key of Object.keys(node)) {
290
- const value = node[key];
284
+ function buildParentMap(ast: Program): Map<AnyNode, AnyNode | null> {
285
+ const map = new Map<AnyNode, AnyNode | null>();
286
+ function visit(node: unknown, parent: AnyNode | null): void {
287
+ const record = node as Record<string, unknown> | null;
288
+ if (!record || typeof record !== "object" || !record["type"]) {
289
+ return;
290
+ }
291
+ map.set(node as AnyNode, parent);
292
+ for (const key of Object.keys(record)) {
293
+ const value = record[key];
291
294
  if (value && typeof value === "object") {
292
295
  if (Array.isArray(value)) {
293
296
  for (const child of value) {
294
- visit(child, node);
297
+ visit(child, node as AnyNode);
295
298
  }
296
299
  } else {
297
- visit(value, node);
300
+ visit(value, node as AnyNode);
298
301
  }
299
302
  }
300
303
  }
@@ -1,14 +1,14 @@
1
1
  import type { Program } from "acorn";
2
- import { traverse } from "../../traverse.js";
3
- import type { Schema } from "../../schema.js";
4
2
  import { isMethodAllowed, getMethodDefinition, getMethodDisplayName } from "../../builtins.js";
3
+ import type { Schema } from "../../schema.js";
4
+ import { traverse } from "../../traverse.js";
5
+ import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
6
+ import { getNodeRange } from "../utils.js";
5
7
  import type { ValidationContext } from "../validation-context.js";
6
- import { AnalysisReport } from "../analysis-report.js";
7
8
  import { isSimpleDataAccess, extractPath, validateSchemaPath } from "./utils.js";
8
- import { getNodeRange } from "../utils.js";
9
9
 
10
10
  export function analyzeMethodCalls(ast: Program, schema: Schema, validationContext: ValidationContext): AnalysisReport {
11
- const analysisReport = new AnalysisReport();
11
+ const analysisReport = createAnalysisReport();
12
12
  const dataKeys = new Set(Object.keys(schema.data ?? {}));
13
13
 
14
14
  traverse(ast, {
@@ -31,18 +31,13 @@ export function analyzeMethodCalls(ast: Program, schema: Schema, validationConte
31
31
  if (!isMethodAllowed(method)) {
32
32
  const methodContext = callee.object.type === "Identifier" ? `${callee.object.name}.${method}` : `.${method}`;
33
33
 
34
- analysisReport.addIssue(
35
- "METHOD_NOT_ALLOWED",
36
- `method ${methodContext} not allowed`,
37
- getNodeRange(callee),
38
- validationContext.getSnapshot()
39
- );
34
+ analysisReport.addIssue("METHOD_NOT_ALLOWED", `method ${methodContext} not allowed`, getNodeRange(callee), validationContext.getSnapshot());
40
35
  return;
41
36
  }
42
37
 
43
38
  const methodDef = getMethodDefinition(method);
44
39
 
45
- if (!methodDef || !methodDef.params) {
40
+ if (!methodDef?.params) {
46
41
  return;
47
42
  }
48
43
 
@@ -70,9 +65,7 @@ export function analyzeMethodCalls(ast: Program, schema: Schema, validationConte
70
65
  if (args.length < minParams) {
71
66
  analysisReport.addIssue(
72
67
  "INSUFFICIENT_PARAMETERS",
73
- `${getMethodDisplayName(method)} expects at least ${minParams} parameter${
74
- minParams !== 1 ? "s" : ""
75
- }, got ${args.length}`,
68
+ `${getMethodDisplayName(method)} expects at least ${minParams} parameter${minParams !== 1 ? "s" : ""}, got ${args.length}`,
76
69
  getNodeRange(node),
77
70
  validationContext.getSnapshot()
78
71
  );
@@ -81,9 +74,7 @@ export function analyzeMethodCalls(ast: Program, schema: Schema, validationConte
81
74
  if (args.length > maxParams) {
82
75
  analysisReport.addIssue(
83
76
  "TOO_MANY_PARAMETERS",
84
- `${getMethodDisplayName(method)} expects at most ${maxParams} parameter${
85
- maxParams !== 1 ? "s" : ""
86
- }, got ${args.length}`,
77
+ `${getMethodDisplayName(method)} expects at most ${maxParams} parameter${maxParams !== 1 ? "s" : ""}, got ${args.length}`,
87
78
  getNodeRange(node),
88
79
  validationContext.getSnapshot()
89
80
  );
@@ -1,11 +1,6 @@
1
- import type { MemberExpression } from "acorn";
2
- import {
3
- isAllowedOnArray,
4
- isAllowedOnString,
5
- getAvailableArrayMembers,
6
- getAvailableStringMembers,
7
- } from "../../builtins.js";
8
- import type { Schema } from "../../schema.js";
1
+ import type { Expression, MemberExpression, PrivateIdentifier, Super } from "acorn";
2
+ import { isAllowedOnArray, isAllowedOnString, getAvailableArrayMembers, getAvailableStringMembers } from "../../builtins.js";
3
+ import type { PropertySchema, Schema } from "../../schema.js";
9
4
  import type { AnalysisReport } from "../analysis-report.js";
10
5
  import { getNodeRange } from "../utils.js";
11
6
  import type { ValidationContext } from "../validation-context.js";
@@ -42,8 +37,8 @@ export function isSimpleDataAccess(node: MemberExpression, dataKeys: ReadonlySet
42
37
  return false;
43
38
  }
44
39
 
45
- export function extractPath(node: MemberExpression): string[] {
46
- const path: string[] = [];
40
+ export function extractPath(node: MemberExpression): Array<string> {
41
+ const path: Array<string> = [];
47
42
 
48
43
  if (node.property.type === "Identifier") {
49
44
  path.unshift(node.property.name);
@@ -70,7 +65,8 @@ export function extractPath(node: MemberExpression): string[] {
70
65
  return path;
71
66
  }
72
67
 
73
- export function getAvailablePropsAtPath(path: string[], depth: number, schemaData: any): string[] {
68
+ export function getAvailablePropsAtPath(path: Array<string>, depth: number, schemaDataParam: unknown): Array<string> {
69
+ const schemaData = schemaDataParam as Record<string, PropertySchema> | undefined;
74
70
  if (!schemaData || depth < 0) {
75
71
  return schemaData ? Object.keys(schemaData) : [];
76
72
  }
@@ -79,16 +75,16 @@ export function getAvailablePropsAtPath(path: string[], depth: number, schemaDat
79
75
  return Object.keys(schemaData);
80
76
  }
81
77
 
82
- let current = schemaData[path[0]];
78
+ let current: PropertySchema | undefined = schemaData[path[0]];
83
79
 
84
80
  for (let i = 1; i <= depth; i++) {
85
- if (!current || current.type !== "object" || !current.shape) {
81
+ if (current?.type !== "object" || !current.shape) {
86
82
  return [];
87
83
  }
88
84
  current = current.shape[path[i]];
89
85
  }
90
86
 
91
- if (current && current.type === "object" && current.shape) {
87
+ if (current?.type === "object" && current.shape) {
92
88
  return Object.keys(current.shape);
93
89
  }
94
90
 
@@ -96,7 +92,7 @@ export function getAvailablePropsAtPath(path: string[], depth: number, schemaDat
96
92
  }
97
93
 
98
94
  export function validateSchemaPath(
99
- path: string[],
95
+ path: Array<string>,
100
96
  schema: Schema,
101
97
  analysisReport: AnalysisReport,
102
98
  node: MemberExpression,
@@ -268,12 +264,12 @@ export function validateSchemaPath(
268
264
  }
269
265
  }
270
266
 
271
- function getElementAccessFlags(node: MemberExpression, pathLength: number): boolean[] {
267
+ function getElementAccessFlags(node: MemberExpression, pathLength: number): Array<boolean> {
272
268
  const flags = Array(pathLength).fill(false);
273
- const segments: Array<{ property: any; computed: boolean }> = [];
269
+ const segments: Array<{ property: Expression | PrivateIdentifier; computed: boolean }> = [];
274
270
 
275
- let current: any = node;
276
- while (current && current.type === "MemberExpression") {
271
+ let current: Expression | Super | undefined = node;
272
+ while (current?.type === "MemberExpression") {
277
273
  segments.unshift({ property: current.property, computed: current.computed });
278
274
  current = current.object;
279
275
  }
@@ -1,3 +1,3 @@
1
1
  export { analyze } from "./analyze.js";
2
2
  export { AnalysisError } from "./analysis-error.js";
3
- export { AnalysisReport } from "./analysis-report.js";
3
+ export { type AnalysisReport, createAnalysisReport } from "./analysis-report.js";
@@ -1,15 +1,15 @@
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 { analyzeElementAttributes } from "./element-attributes.js";
6
6
  import { analyzeElementChildren } from "./element-children.js";
7
7
  import { analyzeElementTags } from "./element-tags.js";
8
8
 
9
9
  export function analyzeJsx(ast: Program, schema: Schema): AnalysisReport {
10
- const validationContext = new ValidationContext();
10
+ const validationContext = createValidationContext();
11
11
 
12
- return new AnalysisReport().merge(
12
+ return createAnalysisReport().merge(
13
13
  analyzeElementTags(ast, schema, validationContext),
14
14
  analyzeElementAttributes(ast, schema, validationContext),
15
15
  analyzeElementChildren(ast, schema, validationContext)
@@ -1,24 +1,13 @@
1
1
  import type { Program } from "acorn";
2
2
  import { isJsxAttribute, isJsxExpressionContainer, type JSXAttribute } from "../../jsx.js";
3
- import {
4
- getAllowedAttributes,
5
- getAttributeSchema,
6
- getEnumValues,
7
- getRequiredAttributes,
8
- isAttributeAllowed,
9
- type Schema,
10
- } from "../../schema.js";
3
+ import { getAllowedAttributes, getAttributeSchema, getEnumValues, getRequiredAttributes, isAttributeAllowed, type Schema } from "../../schema.js";
11
4
  import { traverse } from "../../traverse.js";
12
- import { AnalysisReport } from "../analysis-report.js";
5
+ import { createAnalysisReport, type AnalysisReport } from "../analysis-report.js";
13
6
  import { getAttributeSimilarityMatchers, getBestSimilarityMatcherSuggestion, getNodeRange } from "../utils.js";
14
7
  import type { ValidationContext } from "../validation-context.js";
15
8
 
16
- export function analyzeElementAttributes(
17
- ast: Program,
18
- schema: Schema,
19
- validationContext: ValidationContext
20
- ): AnalysisReport {
21
- const analysisReport = new AnalysisReport();
9
+ export function analyzeElementAttributes(ast: Program, schema: Schema, validationContext: ValidationContext): AnalysisReport {
10
+ const analysisReport = createAnalysisReport();
22
11
 
23
12
  const localFunctionNames = new Set<string>();
24
13
  for (const stmt of ast.body) {
@@ -87,9 +76,7 @@ export function analyzeElementAttributes(
87
76
  const stringEnumValues = enumValues.map((value) => String(value));
88
77
  const suggestionMatch = getBestSimilarityMatcherSuggestion(String(literalValue), stringEnumValues);
89
78
 
90
- let message = `Value ${JSON.stringify(
91
- literalValue
92
- )} is not allowed for attribute "${attributeName}" on <${tagName}>`;
79
+ let message = `Value ${JSON.stringify(literalValue)} is not allowed for attribute "${attributeName}" on <${tagName}>`;
93
80
 
94
81
  if (suggestionMatch) {
95
82
  message += `. Did you mean "${suggestionMatch}"?`;
@@ -140,7 +127,7 @@ function getAttributeLiteralValue(attribute: JSXAttribute): string | number | bo
140
127
  }
141
128
 
142
129
  if (attribute.value.type === "Literal") {
143
- return attribute.value.value as string | number | boolean | null | undefined;
130
+ return attribute.value.value;
144
131
  }
145
132
 
146
133
  if (isJsxExpressionContainer(attribute.value)) {
@@ -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
  }
@@ -96,11 +92,11 @@ export function analyzeElementChildren(
96
92
  } else if (isJsxFragment(child)) {
97
93
  // TODO: Recursively validate fragment children
98
94
  // For now, we allow fragments but should add more specific validation in the future
99
- } else if (isJsxText(child)) {
100
- const hasContent = child.value.trim().length > 0;
101
- // eslint-disable-next-line no-empty
102
- if (!hasContent) {
103
- }
95
+ // } else if (isJsxText(child)) {
96
+ // const hasContent = child.value.trim().length > 0;
97
+ // // oxlint-disable-next-line no-empty
98
+ // if (!hasContent) {
99
+ // }
104
100
  }
105
101
  }
106
102
 
@@ -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