styled-components-to-stylex-codemod 0.0.53 → 0.0.55

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.
@@ -1,222 +1,84 @@
1
1
  import { n as resolveExistingFilePath } from "./path-utils-BC4U8X_q.mjs";
2
2
  import path from "node:path";
3
3
  import ts from "typescript";
4
- //#region src/internal/prepass/typescript-analysis.ts
5
- function analyzeTypeScriptProgram(options) {
6
- const rootNames = normalizeFilePaths(options.files).filter(isTypeScriptLikeFile);
7
- if (rootNames.length === 0) return {
8
- version: 1,
9
- files: []
10
- };
11
- const program = createProgram(rootNames, options.cwd ?? process.cwd());
12
- const checker = program.getTypeChecker();
13
- const rootNameSet = new Set(rootNames.map((filePath) => path.resolve(filePath)));
14
- const compilerOptions = program.getCompilerOptions();
15
- strictNullChecksOnForCurrentRun = Boolean(compilerOptions.strictNullChecks ?? compilerOptions.strict);
16
- return {
17
- version: 1,
18
- files: program.getSourceFiles().filter((sourceFile) => rootNameSet.has(path.resolve(sourceFile.fileName))).map((sourceFile) => analyzeSourceFile(sourceFile, checker)).filter((file) => file.components.length > 0 || file.functions.length > 0).sort((a, b) => a.filePath.localeCompare(b.filePath))
19
- };
20
- }
21
- function analyzeSourceFile(sourceFile, checker) {
22
- const exportedNames = getExportedNames(sourceFile, checker);
23
- const defaultExportedLocalNames = getDefaultExportedLocalNames(sourceFile);
24
- const localFunctionInitializers = collectLocalFunctionInitializers(sourceFile);
25
- const components = [];
26
- const functions = [];
27
- const visit = (node) => {
28
- if (ts.isFunctionDeclaration(node) && (node.name || isDefaultExport(node))) {
29
- const fn = readFunctionDeclaration(node, checker, exportedNames);
30
- functions.push(fn);
31
- if (isReactComponentFunction(node, checker)) components.push(readReactComponentFromFunction(node, checker, exportedNames, defaultExportedLocalNames));
32
- return;
33
- }
34
- if (ts.isVariableStatement(node)) {
35
- for (const declaration of node.declarationList.declarations) {
36
- if (!ts.isIdentifier(declaration.name)) continue;
37
- if (declaration.initializer && isStyledComponentInitializer(declaration.initializer)) {
38
- components.push(readStyledComponent(declaration, node, checker, exportedNames));
39
- continue;
40
- }
41
- const componentInitializer = declaration.initializer ? getComponentFunctionInitializerInfo(declaration.initializer, localFunctionInitializers) : void 0;
42
- if (componentInitializer) {
43
- functions.push(readVariableFunction(declaration.name.text, componentInitializer.fn, node, checker));
44
- if (isReactComponentName(declaration.name.text) || returnsJsx(componentInitializer.fn)) components.push(readReactComponentFromVariable(declaration.name.text, componentInitializer.fn, componentInitializer.propTypeNode, node, checker, exportedNames, defaultExportedLocalNames));
45
- }
46
- }
47
- return;
48
- }
49
- ts.forEachChild(node, visit);
50
- };
51
- ts.forEachChild(sourceFile, visit);
52
- return {
53
- filePath: normalizeFilePath(sourceFile.fileName),
54
- components: components.sort(byName),
55
- functions: functions.sort(byName)
56
- };
57
- }
58
- function readFunctionDeclaration(node, checker, exportedNames) {
59
- const name = node.name?.text ?? "default";
60
- return {
61
- name,
62
- exported: exportedNames.has(name),
63
- defaultExport: isDefaultExport(node),
64
- typeParameters: readTypeParameters(node.typeParameters),
65
- parameters: readParameters(node.parameters, checker)
66
- };
4
+ //#region src/internal/prepass/ts-ast-shared.ts
5
+ function resolveAliasedSymbol(symbol, checker) {
6
+ if (!symbol || (symbol.flags & ts.SymbolFlags.Alias) === 0) return symbol;
7
+ return checker.getAliasedSymbol(symbol);
67
8
  }
68
- function readVariableFunction(name, node, statement, checker) {
9
+ function readUtilityTypeReference(typeNode) {
69
10
  return {
70
- name,
71
- exported: isExported(statement),
72
- defaultExport: false,
73
- typeParameters: readTypeParameters(node.typeParameters),
74
- parameters: readParameters(node.parameters, checker)
11
+ name: typeNode.typeName.getText(),
12
+ typeArgs: typeNode.typeArguments ?? []
75
13
  };
76
14
  }
77
- function readStyledComponent(declaration, statement, checker, exportedNames) {
78
- const name = declaration.name.getText();
79
- const typeNode = declaration.initializer ? findStyledPropsTypeNode(declaration.initializer) : void 0;
80
- return buildComponentMetadata({
81
- name,
82
- kind: "styled",
83
- exported: exportedNames.has(name) || isExported(statement),
84
- defaultExport: false,
85
- typeParameters: [],
86
- propTypeNode: typeNode,
87
- parameters: [],
88
- restProps: [],
89
- checker,
90
- location: declaration
91
- });
92
- }
93
- function readReactComponentFromFunction(node, checker, exportedNames, defaultExportedLocalNames) {
94
- const name = node.name?.text ?? "default";
95
- return buildComponentMetadata({
96
- name,
97
- kind: "react",
98
- exported: exportedNames.has(name),
99
- defaultExport: isDefaultExport(node) || defaultExportedLocalNames.has(name),
100
- typeParameters: readTypeParameters(node.typeParameters),
101
- propTypeNode: node.parameters[0]?.type,
102
- parameters: readParameters(node.parameters, checker),
103
- restProps: readRestProps(node.parameters[0], node.body),
104
- bodySupportsSxProp: readsSxProp(node.parameters[0], node.body),
105
- bodySxTarget: detectSxTarget(node.parameters[0], node.body),
106
- checker,
107
- location: node
108
- });
15
+ function isTransparentUtilityTypeName(typeName) {
16
+ return typeName === "Partial" || typeName === "Required" || typeName === "Readonly";
109
17
  }
110
- function readReactComponentFromVariable(name, node, propTypeNode, statement, checker, exportedNames, defaultExportedLocalNames) {
111
- return buildComponentMetadata({
112
- name,
113
- kind: "react",
114
- exported: exportedNames.has(name) || isExported(statement),
115
- defaultExport: defaultExportedLocalNames.has(name),
116
- typeParameters: readTypeParameters(node.typeParameters),
117
- propTypeNode: propTypeNode ?? node.parameters[0]?.type,
118
- parameters: readParameters(node.parameters, checker),
119
- restProps: readRestProps(node.parameters[0], node.body),
120
- bodySupportsSxProp: readsSxProp(node.parameters[0], node.body),
121
- bodySxTarget: detectSxTarget(node.parameters[0], node.body),
122
- checker,
123
- location: node
124
- });
18
+ function typeNodeKeyIncludes(typeNode, key) {
19
+ if (!typeNode) return false;
20
+ if (ts.isLiteralTypeNode(typeNode) && ts.isStringLiteral(typeNode.literal)) return typeNode.literal.text === key;
21
+ if (ts.isUnionTypeNode(typeNode)) return typeNode.types.some((part) => typeNodeKeyIncludes(part, key));
22
+ return false;
125
23
  }
126
- function buildComponentMetadata(args) {
127
- const propType = args.propTypeNode ? args.checker.getTypeFromTypeNode(args.propTypeNode) : null;
128
- const props = propType ? readPropsFromType(propType, args.checker, args.location) : [];
129
- const explicitPropNames = args.propTypeNode ? collectExplicitPropNames(args.propTypeNode, args.checker) : [];
130
- const supportsResolvedSxProp = props.some((prop) => prop.name === "sx") && args.propTypeNode !== void 0 && typeNodeHasResolvableSxSurface(args.propTypeNode, args.checker, /* @__PURE__ */ new Set());
131
- const sxExcludedProperties = args.propTypeNode !== void 0 ? collectSxExcludedProperties(args.propTypeNode, args.checker, /* @__PURE__ */ new Set()) : [];
132
- const sxAllowedProperties = args.propTypeNode !== void 0 ? collectSxAllowedProperties(args.propTypeNode, args.checker, /* @__PURE__ */ new Set()) : void 0;
133
- return {
134
- name: args.name,
135
- kind: args.kind,
136
- exported: args.exported,
137
- defaultExport: args.defaultExport,
138
- typeParameters: args.typeParameters,
139
- propType: args.propTypeNode ? describeTypeNode(args.propTypeNode, args.checker) : null,
140
- props,
141
- explicitPropNames,
142
- parameters: args.parameters,
143
- restProps: args.restProps,
144
- hasIndexSignature: propType ? hasIndexSignature(propType, args.checker) : false,
145
- supportsSxProp: explicitPropNames.includes("sx") || supportsResolvedSxProp || args.bodySupportsSxProp === true,
146
- ...args.bodySxTarget ? { sxTarget: args.bodySxTarget } : {},
147
- sxExcludedProperties,
148
- ...sxAllowedProperties !== void 0 ? { sxAllowedProperties } : {}
149
- };
24
+ function isIntrinsicReactPropReference(typeNode) {
25
+ const typeName = typeNode.typeName.getText();
26
+ return /^(?:React\.)?(?:ComponentProps|ComponentPropsWithRef|ComponentPropsWithoutRef|HTMLAttributes|ButtonHTMLAttributes|AnchorHTMLAttributes|InputHTMLAttributes|SVGProps)$/.test(typeName);
150
27
  }
151
- function readPropsFromType(type, checker, location) {
152
- return checker.getPropertiesOfType(type).map((symbol) => {
153
- const declaration = symbol.valueDeclaration ?? symbol.declarations?.[0] ?? location;
154
- const optional = (symbol.flags & ts.SymbolFlags.Optional) !== 0;
155
- return {
156
- name: symbol.getName(),
157
- optional,
158
- readonly: isReadonlyProperty(symbol),
159
- type: withOptionalUndefined(readPropTypeString(symbol, declaration, checker, location), optional)
160
- };
161
- }).sort(byName);
28
+ function isIntrinsicReactHeritageReference(heritageType) {
29
+ const typeName = heritageType.expression.getText();
30
+ return /^(?:React\.)?(?:ComponentProps|ComponentPropsWithRef|ComponentPropsWithoutRef|HTMLAttributes|ButtonHTMLAttributes|AnchorHTMLAttributes|InputHTMLAttributes|SVGProps)$/.test(typeName);
162
31
  }
163
- /**
164
- * TS's resolved type for an optional property includes `| undefined` (because
165
- * the `?` modifier widens it). Syntactic type nodes don't — `?: number` has
166
- * `type === number`, not `number | undefined`. Downstream consumers
167
- * (lower-rules/types.ts) rely on the `| undefined` suffix to gate certain
168
- * emit decisions (e.g. wrapping a possibly-undefined value in a template
169
- * string). Reconstruct it here so the syntactic fast path stays
170
- * behaviorally equivalent to the typeToString path it replaced.
171
- */
172
- function withOptionalUndefined(typeText, optional) {
173
- if (!optional || !strictNullChecksOnForCurrentRun) return typeText;
174
- if (/\bundefined\b/.test(typeText)) return typeText;
175
- return `${typeText} | undefined`;
32
+ function propertyNameText(name) {
33
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
34
+ return null;
176
35
  }
177
- /**
178
- * Per-run capture of strictNullChecks. Set by `analyzeTypeScriptProgram` before
179
- * any per-file work runs; read by `withOptionalUndefined` to decide whether to
180
- * append `| undefined` to optional props. Module-scoped to avoid threading the
181
- * boolean through ~6 helper signatures for a single read site.
182
- */
183
- let strictNullChecksOnForCurrentRun = false;
184
- /**
185
- * Returns the prop's TS type as a string. Prefers the syntactic type annotation
186
- * from the declaration AST (cheap, no checker call) and only falls back to
187
- * `checker.typeToString` when the declaration has no usable type node — typically
188
- * synthesized properties (mapped/intersection/spread-derived) where the checker
189
- * is the only source of truth.
190
- *
191
- * Why: typeToString with NoTruncation dominated the prepass at 39s / 723K calls.
192
- * For the consumers downstream (lower-rules/types.ts parseTypeText), the
193
- * syntactic representation is what they want anyway — they only handle
194
- * TSTypeReference / TSUnionType / TSLiteralType shapes.
195
- */
196
- function readPropTypeString(symbol, declaration, _checker, _location) {
197
- const typeNode = getDeclarationTypeNode(declaration);
198
- if (typeNode) return typeNode.getText();
199
- return "";
36
+ function bindingPatternHasName(pattern, name) {
37
+ return pattern.elements.some((element) => element.name.getText() === name);
200
38
  }
201
- function getDeclarationTypeNode(declaration) {
202
- if (ts.isPropertySignature(declaration) || ts.isPropertyDeclaration(declaration) || ts.isParameter(declaration)) return declaration.type;
39
+ function bindingElementPropertyNameText(element) {
40
+ if (element.propertyName) return ts.isIdentifier(element.propertyName) || ts.isStringLiteral(element.propertyName) ? element.propertyName.text : null;
41
+ return ts.isIdentifier(element.name) ? element.name.text : null;
203
42
  }
204
- function readParameters(parameters, checker) {
205
- return parameters.map((parameter) => ({
206
- name: readParameterName(parameter.name),
207
- optional: Boolean(parameter.questionToken || parameter.initializer),
208
- rest: Boolean(parameter.dotDotDotToken),
209
- type: parameter.type ? parameter.type.getText() : checker.typeToString(checker.getTypeAtLocation(parameter), parameter)
210
- }));
43
+ function unwrapExpression(expression) {
44
+ let current = expression;
45
+ while (ts.isAsExpression(current) || ts.isTypeAssertionExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current)) current = current.expression;
46
+ return current;
211
47
  }
212
- function hasIndexSignature(type, checker) {
213
- return checker.getIndexTypeOfType(type, ts.IndexKind.String) !== void 0 || checker.getIndexTypeOfType(type, ts.IndexKind.Number) !== void 0;
48
+ function isIdentifierNamed(expression, name) {
49
+ return ts.isIdentifier(expression) && expression.text === name;
214
50
  }
51
+ //#endregion
52
+ //#region src/internal/prepass/prop-name-collection.ts
215
53
  function collectExplicitPropNames(typeNode, checker, visited = /* @__PURE__ */ new Set()) {
216
54
  const names = /* @__PURE__ */ new Set();
217
55
  collectExplicitPropNamesInto(names, typeNode, checker, visited);
218
56
  return [...names].sort();
219
57
  }
58
+ function typeNodeHasResolvableSxSurface(typeNode, checker, visited) {
59
+ if (ts.isTypeLiteralNode(typeNode)) return typeNode.members.some((member) => ts.isPropertySignature(member) && propertyNameText(member.name) === "sx");
60
+ if (ts.isIntersectionTypeNode(typeNode)) return typeNode.types.some((part) => typeNodeHasResolvableSxSurface(part, checker, visited));
61
+ if (ts.isUnionTypeNode(typeNode)) return typeNode.types.every((part) => typeNodeHasResolvableSxSurface(part, checker, visited));
62
+ if (!ts.isTypeReferenceNode(typeNode) || isIntrinsicReactPropReference(typeNode)) return false;
63
+ const utilityType = readUtilityTypeReference(typeNode);
64
+ if (utilityType.name === "Pick") return utilityType.typeArgs.length >= 2 && typeNodeKeyIncludes(utilityType.typeArgs[1], "sx");
65
+ if (utilityType.name === "Omit") {
66
+ const baseType = utilityType.typeArgs[0];
67
+ return baseType !== void 0 && utilityType.typeArgs.length >= 2 && !typeNodeKeyIncludes(utilityType.typeArgs[1], "sx") && typeNodeHasResolvableSxSurface(baseType, checker, visited);
68
+ }
69
+ if (isTransparentUtilityTypeName(utilityType.name)) {
70
+ const baseType = utilityType.typeArgs[0];
71
+ return baseType !== void 0 && typeNodeHasResolvableSxSurface(baseType, checker, visited);
72
+ }
73
+ return (resolveAliasedSymbol(checker.getSymbolAtLocation(typeNode.typeName), checker)?.declarations ?? []).some((declaration) => declarationHasResolvableSxSurface(declaration, checker, visited));
74
+ }
75
+ function collectSxExcludedProperties(typeNode, checker, visited) {
76
+ return collectSxSurfaceProperties(typeNode, checker, visited, collectStyleXStylesWithoutKeys).properties;
77
+ }
78
+ function collectSxAllowedProperties(typeNode, checker, visited) {
79
+ const collection = collectSxSurfaceProperties(typeNode, checker, visited, collectStyleXStylesKeys);
80
+ return collection.found ? collection.properties : void 0;
81
+ }
220
82
  function collectExplicitPropNamesInto(names, typeNode, checker, visited) {
221
83
  if (ts.isTypeLiteralNode(typeNode)) {
222
84
  for (const member of typeNode.members) if (ts.isPropertySignature(member)) {
@@ -265,39 +127,6 @@ function collectExplicitPropNamesInto(names, typeNode, checker, visited) {
265
127
  const symbol = resolveAliasedSymbol(checker.getSymbolAtLocation(typeNode.typeName), checker);
266
128
  for (const declaration of symbol?.declarations ?? []) collectExplicitPropNamesFromDeclaration(names, declaration, checker, visited);
267
129
  }
268
- function typeNodeHasResolvableSxSurface(typeNode, checker, visited) {
269
- if (ts.isTypeLiteralNode(typeNode)) return typeNode.members.some((member) => ts.isPropertySignature(member) && propertyNameText(member.name) === "sx");
270
- if (ts.isIntersectionTypeNode(typeNode)) return typeNode.types.some((part) => typeNodeHasResolvableSxSurface(part, checker, visited));
271
- if (ts.isUnionTypeNode(typeNode)) return typeNode.types.every((part) => typeNodeHasResolvableSxSurface(part, checker, visited));
272
- if (!ts.isTypeReferenceNode(typeNode) || isIntrinsicReactPropReference(typeNode)) return false;
273
- const utilityType = readUtilityTypeReference(typeNode);
274
- if (utilityType.name === "Pick") return utilityType.typeArgs.length >= 2 && typeNodeKeyIncludes(utilityType.typeArgs[1], "sx");
275
- if (utilityType.name === "Omit") {
276
- const baseType = utilityType.typeArgs[0];
277
- return baseType !== void 0 && utilityType.typeArgs.length >= 2 && !typeNodeKeyIncludes(utilityType.typeArgs[1], "sx") && typeNodeHasResolvableSxSurface(baseType, checker, visited);
278
- }
279
- if (isTransparentUtilityTypeName(utilityType.name)) {
280
- const baseType = utilityType.typeArgs[0];
281
- return baseType !== void 0 && typeNodeHasResolvableSxSurface(baseType, checker, visited);
282
- }
283
- return (resolveAliasedSymbol(checker.getSymbolAtLocation(typeNode.typeName), checker)?.declarations ?? []).some((declaration) => declarationHasResolvableSxSurface(declaration, checker, visited));
284
- }
285
- function readUtilityTypeReference(typeNode) {
286
- return {
287
- name: typeNode.typeName.getText(),
288
- typeArgs: typeNode.typeArguments ?? []
289
- };
290
- }
291
- function isTransparentUtilityTypeName(typeName) {
292
- return typeName === "Partial" || typeName === "Required" || typeName === "Readonly";
293
- }
294
- function collectSxExcludedProperties(typeNode, checker, visited) {
295
- return collectSxSurfaceProperties(typeNode, checker, visited, collectStyleXStylesWithoutKeys).properties;
296
- }
297
- function collectSxAllowedProperties(typeNode, checker, visited) {
298
- const collection = collectSxSurfaceProperties(typeNode, checker, visited, collectStyleXStylesKeys);
299
- return collection.found ? collection.properties : void 0;
300
- }
301
130
  function collectSxSurfaceProperties(typeNode, checker, visited, collectFromSxType) {
302
131
  const names = /* @__PURE__ */ new Set();
303
132
  const found = collectSxSurfacePropertiesInto(names, typeNode, checker, visited, collectFromSxType);
@@ -507,16 +336,6 @@ function declarationHasResolvableSxSurface(declaration, checker, visited) {
507
336
  function declarationHeritageHasResolvableSxSurface(heritageType, checker, visited) {
508
337
  return (resolveAliasedSymbol(checker.getSymbolAtLocation(heritageType.expression), checker)?.declarations ?? []).some((declaration) => declarationHasResolvableSxSurface(declaration, checker, visited));
509
338
  }
510
- function typeNodeKeyIncludes(typeNode, key) {
511
- if (!typeNode) return false;
512
- if (ts.isLiteralTypeNode(typeNode) && ts.isStringLiteral(typeNode.literal)) return typeNode.literal.text === key;
513
- if (ts.isUnionTypeNode(typeNode)) return typeNode.types.some((part) => typeNodeKeyIncludes(part, key));
514
- return false;
515
- }
516
- function resolveAliasedSymbol(symbol, checker) {
517
- if (!symbol || (symbol.flags & ts.SymbolFlags.Alias) === 0) return symbol;
518
- return checker.getAliasedSymbol(symbol);
519
- }
520
339
  function collectExplicitPropNamesFromDeclaration(names, declaration, checker, visited) {
521
340
  if (visited.has(declaration)) return;
522
341
  visited.add(declaration);
@@ -536,17 +355,423 @@ function collectExplicitPropNamesFromHeritage(names, heritageType, checker, visi
536
355
  const symbol = resolveAliasedSymbol(checker.getSymbolAtLocation(heritageType.expression), checker);
537
356
  for (const declaration of symbol?.declarations ?? []) collectExplicitPropNamesFromDeclaration(names, declaration, checker, visited);
538
357
  }
539
- function isIntrinsicReactPropReference(typeNode) {
540
- const typeName = typeNode.typeName.getText();
541
- return /^(?:React\.)?(?:ComponentProps|ComponentPropsWithRef|ComponentPropsWithoutRef|HTMLAttributes|ButtonHTMLAttributes|AnchorHTMLAttributes|InputHTMLAttributes|SVGProps)$/.test(typeName);
358
+ //#endregion
359
+ //#region src/internal/prepass/sx-target-detection.ts
360
+ function readsSxProp(parameter, body) {
361
+ if (parameter?.name && ts.isObjectBindingPattern(parameter.name)) {
362
+ if (bindingPatternHasName(parameter.name, "sx")) return true;
363
+ }
364
+ if (!body || !parameter?.name || !ts.isIdentifier(parameter.name)) return false;
365
+ const propsName = parameter.name.text;
366
+ let found = false;
367
+ const visit = (node) => {
368
+ if (found) return;
369
+ if (isFunctionWithParameterNamed(node, propsName) || isFunctionWithParameterDestructuringName(node, "sx")) return;
370
+ if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === propsName && node.name.text === "sx") {
371
+ found = true;
372
+ return;
373
+ }
374
+ if (ts.isVariableDeclaration(node) && ts.isObjectBindingPattern(node.name) && node.initializer && isIdentifierNamed(unwrapExpression(node.initializer), propsName) && bindingPatternHasName(node.name, "sx")) {
375
+ found = true;
376
+ return;
377
+ }
378
+ ts.forEachChild(node, visit);
379
+ };
380
+ ts.forEachChild(body, visit);
381
+ return found;
382
+ }
383
+ function detectSxTarget(parameter, body) {
384
+ if (!body) return;
385
+ const sxNames = collectSxBindingNames(parameter, body);
386
+ if (sxNames.size === 0) return;
387
+ const sxPropContainerNames = collectSxPropContainerNames(parameter);
388
+ const sxPropsNames = collectStylexPropsBindingNames(body, sxNames, sxPropContainerNames);
389
+ const root = returnedJsxRoot(body);
390
+ if (!root) return;
391
+ if (jsxOpeningUsesSx(jsxRootOpening(root), sxNames, sxPropsNames, sxPropContainerNames)) return "root";
392
+ return jsxChildrenUseSx(root, sxNames, sxPropsNames, sxPropContainerNames) ? "inner" : void 0;
393
+ }
394
+ function collectSxBindingNames(parameter, body) {
395
+ const names = /* @__PURE__ */ new Set();
396
+ if (parameter?.name && ts.isObjectBindingPattern(parameter.name)) collectBindingElementLocalNames(parameter.name, "sx", names);
397
+ else names.add("sx");
398
+ if (parameter?.name && ts.isIdentifier(parameter.name)) {
399
+ const propsName = parameter.name.text;
400
+ const visit = (node) => {
401
+ if (ts.isVariableDeclaration(node) && ts.isObjectBindingPattern(node.name) && node.initializer && isIdentifierNamed(unwrapExpression(node.initializer), propsName)) collectBindingElementLocalNames(node.name, "sx", names);
402
+ ts.forEachChild(node, visit);
403
+ };
404
+ ts.forEachChild(body, visit);
405
+ }
406
+ return names;
407
+ }
408
+ function collectBindingElementLocalNames(pattern, propertyName, names) {
409
+ for (const element of pattern.elements) if (bindingElementPropertyNameText(element) === propertyName && ts.isIdentifier(element.name)) names.add(element.name.text);
410
+ }
411
+ function collectSxPropContainerNames(parameter) {
412
+ const names = /* @__PURE__ */ new Set();
413
+ if (parameter?.name && ts.isIdentifier(parameter.name)) names.add(parameter.name.text);
414
+ return names;
415
+ }
416
+ function collectStylexPropsBindingNames(body, sxNames, sxPropContainerNames) {
417
+ const names = /* @__PURE__ */ new Set();
418
+ const visit = (node) => {
419
+ if (ts.isVariableDeclaration(node) && node.initializer && isStylexPropsCallWithSx(node.initializer, sxNames, sxPropContainerNames)) {
420
+ if (ts.isIdentifier(node.name)) names.add(node.name.text);
421
+ else if (ts.isObjectBindingPattern(node.name)) collectBindingPatternIdentifierNames(node.name, names);
422
+ }
423
+ ts.forEachChild(node, visit);
424
+ };
425
+ ts.forEachChild(body, visit);
426
+ return names;
427
+ }
428
+ function collectBindingPatternIdentifierNames(pattern, names) {
429
+ for (const element of pattern.elements) if (ts.isIdentifier(element.name)) names.add(element.name.text);
430
+ }
431
+ function isStylexPropsCallWithSx(expr, sxNames, sxPropContainerNames) {
432
+ const unwrapped = unwrapExpression(expr);
433
+ const noSxPropsNames = /* @__PURE__ */ new Set();
434
+ return ts.isCallExpression(unwrapped) && isStylexPropsCallee(unwrapped.expression) && unwrapped.arguments.some((arg) => expressionReferencesNames(arg, sxNames, noSxPropsNames, sxPropContainerNames));
435
+ }
436
+ function isStylexPropsCallee(expr) {
437
+ return ts.isPropertyAccessExpression(expr) && expr.name.text === "props" && ts.isIdentifier(expr.expression) && expr.expression.text === "stylex";
438
+ }
439
+ function returnedJsxRoot(body) {
440
+ if (ts.isJsxElement(body) || ts.isJsxSelfClosingElement(body)) return body;
441
+ if (!ts.isBlock(body)) return null;
442
+ for (const statement of body.statements) {
443
+ if (!ts.isReturnStatement(statement) || !statement.expression) continue;
444
+ const expr = unwrapExpression(statement.expression);
445
+ if (ts.isJsxElement(expr) || ts.isJsxSelfClosingElement(expr)) return expr;
446
+ }
447
+ return null;
448
+ }
449
+ function jsxChildrenUseSx(root, sxNames, sxPropsNames, sxPropContainerNames) {
450
+ if (!ts.isJsxElement(root)) return false;
451
+ let found = false;
452
+ const visit = (node) => {
453
+ if (found) return;
454
+ if (functionShadowsSxReference(node, sxNames, sxPropContainerNames)) return;
455
+ if (ts.isJsxElement(node) && jsxOpeningUsesSx(node.openingElement, sxNames, sxPropsNames, sxPropContainerNames) || ts.isJsxSelfClosingElement(node) && jsxOpeningUsesSx(node, sxNames, sxPropsNames, sxPropContainerNames)) {
456
+ found = true;
457
+ return;
458
+ }
459
+ ts.forEachChild(node, visit);
460
+ };
461
+ for (const child of root.children) visit(child);
462
+ return found;
463
+ }
464
+ function jsxRootOpening(root) {
465
+ return ts.isJsxElement(root) ? root.openingElement : root;
466
+ }
467
+ function jsxOpeningUsesSx(opening, sxNames, sxPropsNames, sxPropContainerNames) {
468
+ return opening.attributes.properties.some((attribute) => {
469
+ if (ts.isJsxSpreadAttribute(attribute)) return expressionReferencesNames(attribute.expression, sxNames, sxPropsNames, sxPropContainerNames);
470
+ if (!ts.isIdentifier(attribute.name) || !attribute.initializer) return false;
471
+ if (!ts.isJsxExpression(attribute.initializer) || !attribute.initializer.expression) return false;
472
+ if (attribute.name.text === "className" || attribute.name.text === "style") return expressionReferencesStylexPropsBinding(attribute.initializer.expression, sxPropsNames);
473
+ if (attribute.name.text !== "sx") return false;
474
+ return expressionReferencesNames(attribute.initializer.expression, sxNames, sxPropsNames, sxPropContainerNames);
475
+ });
476
+ }
477
+ function expressionReferencesStylexPropsBinding(expr, sxPropsNames) {
478
+ const unwrapped = unwrapExpression(expr);
479
+ return ts.isIdentifier(unwrapped) && sxPropsNames.has(unwrapped.text);
480
+ }
481
+ function expressionReferencesNames(expr, sxNames, sxPropsNames, sxPropContainerNames) {
482
+ const unwrapped = unwrapExpression(expr);
483
+ if (ts.isIdentifier(unwrapped)) return sxNames.has(unwrapped.text) || sxPropsNames.has(unwrapped.text);
484
+ if (ts.isPropertyAccessExpression(unwrapped) && unwrapped.name.text === "sx" && ts.isIdentifier(unwrapped.expression)) return sxPropContainerNames.has(unwrapped.expression.text);
485
+ return isStylexPropsCallWithSx(unwrapped, sxNames, sxPropContainerNames);
486
+ }
487
+ function functionShadowsSxReference(node, sxNames, sxPropContainerNames) {
488
+ if (!isFunctionWithParameters(node)) return false;
489
+ for (const name of sxPropContainerNames) if (node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name))) return true;
490
+ for (const name of sxNames) if (node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name))) return true;
491
+ return node.parameters.some((parameter) => ts.isObjectBindingPattern(parameter.name) && bindingPatternHasName(parameter.name, "sx"));
492
+ }
493
+ function isFunctionWithParameterNamed(node, name) {
494
+ return isFunctionWithParameters(node) ? node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name)) : false;
495
+ }
496
+ function isFunctionWithParameterDestructuringName(node, name) {
497
+ return isFunctionWithParameters(node) ? node.parameters.some((parameter) => ts.isObjectBindingPattern(parameter.name) && bindingPatternHasName(parameter.name, name)) : false;
498
+ }
499
+ function isFunctionWithParameters(node) {
500
+ return ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node);
501
+ }
502
+ function isBindingNameNamed(name, expected) {
503
+ return ts.isIdentifier(name) && name.text === expected;
504
+ }
505
+ //#endregion
506
+ //#region src/internal/prepass/ts-program-setup.ts
507
+ function createProgram(rootNames, cwd) {
508
+ const configPath = findTsConfig(rootNames, cwd);
509
+ const options = configPath ? readCompilerOptions(configPath) : defaultCompilerOptions();
510
+ return ts.createProgram({
511
+ rootNames: [...rootNames],
512
+ options: {
513
+ ...options,
514
+ allowJs: true,
515
+ checkJs: false,
516
+ noEmit: true,
517
+ skipLibCheck: true,
518
+ skipDefaultLibCheck: true,
519
+ types: []
520
+ }
521
+ });
522
+ }
523
+ function getExportedNames(sourceFile, checker) {
524
+ const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
525
+ if (!moduleSymbol) return /* @__PURE__ */ new Set();
526
+ return new Set(checker.getExportsOfModule(moduleSymbol).map((symbol) => symbol.getName()));
527
+ }
528
+ function getDefaultExportedLocalNames(sourceFile) {
529
+ const names = /* @__PURE__ */ new Set();
530
+ for (const statement of sourceFile.statements) {
531
+ if (!ts.isExportAssignment(statement) || !ts.isIdentifier(statement.expression)) continue;
532
+ names.add(statement.expression.text);
533
+ }
534
+ return names;
535
+ }
536
+ function normalizeFilePaths(files) {
537
+ return [...new Set(files.map(resolveExistingFilePath))].sort();
538
+ }
539
+ function normalizeFilePath(filePath) {
540
+ return resolveExistingFilePath(filePath);
541
+ }
542
+ function isTypeScriptLikeFile(filePath) {
543
+ return /\.(tsx?|jsx?)$/.test(filePath);
544
+ }
545
+ function readCompilerOptions(configPath) {
546
+ const config = ts.readConfigFile(configPath, (filePath) => ts.sys.readFile(filePath));
547
+ if (config.error) return defaultCompilerOptions();
548
+ return ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath)).options;
549
+ }
550
+ function defaultCompilerOptions() {
551
+ return {
552
+ target: ts.ScriptTarget.ES2022,
553
+ module: ts.ModuleKind.ESNext,
554
+ moduleResolution: ts.ModuleResolutionKind.Node10,
555
+ jsx: ts.JsxEmit.ReactJSX,
556
+ esModuleInterop: true,
557
+ skipLibCheck: true
558
+ };
559
+ }
560
+ function findTsConfig(rootNames, cwd) {
561
+ const start = rootNames.length > 0 ? path.dirname(rootNames[0]) : cwd;
562
+ return ts.findConfigFile(start, (filePath) => ts.sys.fileExists(filePath), "tsconfig.json") ?? void 0;
563
+ }
564
+ //#endregion
565
+ //#region src/internal/prepass/typescript-analysis.ts
566
+ function analyzeTypeScriptProgram(options) {
567
+ const rootNames = normalizeFilePaths(options.files).filter(isTypeScriptLikeFile);
568
+ if (rootNames.length === 0) return {
569
+ version: 1,
570
+ files: []
571
+ };
572
+ const program = createProgram(rootNames, options.cwd ?? process.cwd());
573
+ const checker = program.getTypeChecker();
574
+ const rootNameSet = new Set(rootNames.map((filePath) => path.resolve(filePath)));
575
+ const compilerOptions = program.getCompilerOptions();
576
+ strictNullChecksOnForCurrentRun = Boolean(compilerOptions.strictNullChecks ?? compilerOptions.strict);
577
+ return {
578
+ version: 1,
579
+ files: program.getSourceFiles().filter((sourceFile) => rootNameSet.has(path.resolve(sourceFile.fileName))).map((sourceFile) => analyzeSourceFile(sourceFile, checker)).filter((file) => file.components.length > 0 || file.functions.length > 0).sort((a, b) => a.filePath.localeCompare(b.filePath))
580
+ };
581
+ }
582
+ function analyzeSourceFile(sourceFile, checker) {
583
+ const exportedNames = getExportedNames(sourceFile, checker);
584
+ const defaultExportedLocalNames = getDefaultExportedLocalNames(sourceFile);
585
+ const localFunctionInitializers = collectLocalFunctionInitializers(sourceFile);
586
+ const components = [];
587
+ const functions = [];
588
+ const visit = (node) => {
589
+ if (ts.isFunctionDeclaration(node) && (node.name || isDefaultExport(node))) {
590
+ const fn = readFunctionDeclaration(node, checker, exportedNames);
591
+ functions.push(fn);
592
+ if (isReactComponentFunction(node, checker)) components.push(readReactComponentFromFunction(node, checker, exportedNames, defaultExportedLocalNames));
593
+ return;
594
+ }
595
+ if (ts.isVariableStatement(node)) {
596
+ for (const declaration of node.declarationList.declarations) {
597
+ if (!ts.isIdentifier(declaration.name)) continue;
598
+ if (declaration.initializer && isStyledComponentInitializer(declaration.initializer)) {
599
+ components.push(readStyledComponent(declaration, node, checker, exportedNames));
600
+ continue;
601
+ }
602
+ const componentInitializer = declaration.initializer ? getComponentFunctionInitializerInfo(declaration.initializer, localFunctionInitializers) : void 0;
603
+ if (componentInitializer) {
604
+ functions.push(readVariableFunction(declaration.name.text, componentInitializer.fn, node, checker));
605
+ if (isReactComponentName(declaration.name.text) || returnsJsx(componentInitializer.fn)) components.push(readReactComponentFromVariable(declaration.name.text, componentInitializer.fn, componentInitializer.propTypeNode, node, checker, exportedNames, defaultExportedLocalNames));
606
+ }
607
+ }
608
+ return;
609
+ }
610
+ ts.forEachChild(node, visit);
611
+ };
612
+ ts.forEachChild(sourceFile, visit);
613
+ return {
614
+ filePath: normalizeFilePath(sourceFile.fileName),
615
+ components: components.sort(byName),
616
+ functions: functions.sort(byName)
617
+ };
618
+ }
619
+ function readFunctionDeclaration(node, checker, exportedNames) {
620
+ const name = node.name?.text ?? "default";
621
+ return {
622
+ name,
623
+ exported: exportedNames.has(name),
624
+ defaultExport: isDefaultExport(node),
625
+ typeParameters: readTypeParameters(node.typeParameters),
626
+ parameters: readParameters(node.parameters, checker)
627
+ };
628
+ }
629
+ function readVariableFunction(name, node, statement, checker) {
630
+ return {
631
+ name,
632
+ exported: isExported(statement),
633
+ defaultExport: false,
634
+ typeParameters: readTypeParameters(node.typeParameters),
635
+ parameters: readParameters(node.parameters, checker)
636
+ };
637
+ }
638
+ function readStyledComponent(declaration, statement, checker, exportedNames) {
639
+ const name = declaration.name.getText();
640
+ const typeNode = declaration.initializer ? findStyledPropsTypeNode(declaration.initializer) : void 0;
641
+ return buildComponentMetadata({
642
+ name,
643
+ kind: "styled",
644
+ exported: exportedNames.has(name) || isExported(statement),
645
+ defaultExport: false,
646
+ typeParameters: [],
647
+ propTypeNode: typeNode,
648
+ parameters: [],
649
+ restProps: [],
650
+ checker,
651
+ location: declaration
652
+ });
653
+ }
654
+ function readReactComponentFromFunction(node, checker, exportedNames, defaultExportedLocalNames) {
655
+ const name = node.name?.text ?? "default";
656
+ return buildComponentMetadata({
657
+ name,
658
+ kind: "react",
659
+ exported: exportedNames.has(name),
660
+ defaultExport: isDefaultExport(node) || defaultExportedLocalNames.has(name),
661
+ typeParameters: readTypeParameters(node.typeParameters),
662
+ propTypeNode: node.parameters[0]?.type,
663
+ parameters: readParameters(node.parameters, checker),
664
+ restProps: readRestProps(node.parameters[0], node.body),
665
+ bodySupportsSxProp: readsSxProp(node.parameters[0], node.body),
666
+ bodySxTarget: detectSxTarget(node.parameters[0], node.body),
667
+ checker,
668
+ location: node
669
+ });
670
+ }
671
+ function readReactComponentFromVariable(name, node, propTypeNode, statement, checker, exportedNames, defaultExportedLocalNames) {
672
+ return buildComponentMetadata({
673
+ name,
674
+ kind: "react",
675
+ exported: exportedNames.has(name) || isExported(statement),
676
+ defaultExport: defaultExportedLocalNames.has(name),
677
+ typeParameters: readTypeParameters(node.typeParameters),
678
+ propTypeNode: propTypeNode ?? node.parameters[0]?.type,
679
+ parameters: readParameters(node.parameters, checker),
680
+ restProps: readRestProps(node.parameters[0], node.body),
681
+ bodySupportsSxProp: readsSxProp(node.parameters[0], node.body),
682
+ bodySxTarget: detectSxTarget(node.parameters[0], node.body),
683
+ checker,
684
+ location: node
685
+ });
686
+ }
687
+ function buildComponentMetadata(args) {
688
+ const propType = args.propTypeNode ? args.checker.getTypeFromTypeNode(args.propTypeNode) : null;
689
+ const props = propType ? readPropsFromType(propType, args.checker, args.location) : [];
690
+ const explicitPropNames = args.propTypeNode ? collectExplicitPropNames(args.propTypeNode, args.checker) : [];
691
+ const supportsResolvedSxProp = props.some((prop) => prop.name === "sx") && args.propTypeNode !== void 0 && typeNodeHasResolvableSxSurface(args.propTypeNode, args.checker, /* @__PURE__ */ new Set());
692
+ const sxExcludedProperties = args.propTypeNode !== void 0 ? collectSxExcludedProperties(args.propTypeNode, args.checker, /* @__PURE__ */ new Set()) : [];
693
+ const sxAllowedProperties = args.propTypeNode !== void 0 ? collectSxAllowedProperties(args.propTypeNode, args.checker, /* @__PURE__ */ new Set()) : void 0;
694
+ return {
695
+ name: args.name,
696
+ kind: args.kind,
697
+ exported: args.exported,
698
+ defaultExport: args.defaultExport,
699
+ typeParameters: args.typeParameters,
700
+ propType: args.propTypeNode ? describeTypeNode(args.propTypeNode, args.checker) : null,
701
+ props,
702
+ explicitPropNames,
703
+ parameters: args.parameters,
704
+ restProps: args.restProps,
705
+ hasIndexSignature: propType ? hasIndexSignature(propType, args.checker) : false,
706
+ supportsSxProp: explicitPropNames.includes("sx") || supportsResolvedSxProp || args.bodySupportsSxProp === true,
707
+ ...args.bodySxTarget ? { sxTarget: args.bodySxTarget } : {},
708
+ sxExcludedProperties,
709
+ ...sxAllowedProperties !== void 0 ? { sxAllowedProperties } : {}
710
+ };
711
+ }
712
+ function readPropsFromType(type, checker, location) {
713
+ return checker.getPropertiesOfType(type).map((symbol) => {
714
+ const declaration = symbol.valueDeclaration ?? symbol.declarations?.[0] ?? location;
715
+ const optional = (symbol.flags & ts.SymbolFlags.Optional) !== 0;
716
+ return {
717
+ name: symbol.getName(),
718
+ optional,
719
+ readonly: isReadonlyProperty(symbol),
720
+ type: withOptionalUndefined(readPropTypeString(symbol, declaration, checker, location), optional)
721
+ };
722
+ }).sort(byName);
723
+ }
724
+ /**
725
+ * TS's resolved type for an optional property includes `| undefined` (because
726
+ * the `?` modifier widens it). Syntactic type nodes don't — `?: number` has
727
+ * `type === number`, not `number | undefined`. Downstream consumers
728
+ * (lower-rules/types.ts) rely on the `| undefined` suffix to gate certain
729
+ * emit decisions (e.g. wrapping a possibly-undefined value in a template
730
+ * string). Reconstruct it here so the syntactic fast path stays
731
+ * behaviorally equivalent to the typeToString path it replaced.
732
+ */
733
+ function withOptionalUndefined(typeText, optional) {
734
+ if (!optional || !strictNullChecksOnForCurrentRun) return typeText;
735
+ if (/\bundefined\b/.test(typeText)) return typeText;
736
+ return `${typeText} | undefined`;
737
+ }
738
+ /**
739
+ * Per-run capture of strictNullChecks. Set by `analyzeTypeScriptProgram` before
740
+ * any per-file work runs; read by `withOptionalUndefined` to decide whether to
741
+ * append `| undefined` to optional props. Module-scoped to avoid threading the
742
+ * boolean through ~6 helper signatures for a single read site.
743
+ */
744
+ let strictNullChecksOnForCurrentRun = false;
745
+ /**
746
+ * Returns the prop's TS type as a string. Prefers the syntactic type annotation
747
+ * from the declaration AST (cheap, no checker call) and only falls back to
748
+ * `checker.typeToString` when the declaration has no usable type node — typically
749
+ * synthesized properties (mapped/intersection/spread-derived) where the checker
750
+ * is the only source of truth.
751
+ *
752
+ * Why: typeToString with NoTruncation dominated the prepass at 39s / 723K calls.
753
+ * For the consumers downstream (lower-rules/types.ts parseTypeText), the
754
+ * syntactic representation is what they want anyway — they only handle
755
+ * TSTypeReference / TSUnionType / TSLiteralType shapes.
756
+ */
757
+ function readPropTypeString(symbol, declaration, _checker, _location) {
758
+ const typeNode = getDeclarationTypeNode(declaration);
759
+ if (typeNode) return typeNode.getText();
760
+ return "";
761
+ }
762
+ function getDeclarationTypeNode(declaration) {
763
+ if (ts.isPropertySignature(declaration) || ts.isPropertyDeclaration(declaration) || ts.isParameter(declaration)) return declaration.type;
542
764
  }
543
- function isIntrinsicReactHeritageReference(heritageType) {
544
- const typeName = heritageType.expression.getText();
545
- return /^(?:React\.)?(?:ComponentProps|ComponentPropsWithRef|ComponentPropsWithoutRef|HTMLAttributes|ButtonHTMLAttributes|AnchorHTMLAttributes|InputHTMLAttributes|SVGProps)$/.test(typeName);
765
+ function readParameters(parameters, checker) {
766
+ return parameters.map((parameter) => ({
767
+ name: readParameterName(parameter.name),
768
+ optional: Boolean(parameter.questionToken || parameter.initializer),
769
+ rest: Boolean(parameter.dotDotDotToken),
770
+ type: parameter.type ? parameter.type.getText() : checker.typeToString(checker.getTypeAtLocation(parameter), parameter)
771
+ }));
546
772
  }
547
- function propertyNameText(name) {
548
- if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
549
- return null;
773
+ function hasIndexSignature(type, checker) {
774
+ return checker.getIndexTypeOfType(type, ts.IndexKind.String) !== void 0 || checker.getIndexTypeOfType(type, ts.IndexKind.Number) !== void 0;
550
775
  }
551
776
  function readRestProps(parameter, body) {
552
777
  const restProps = [];
@@ -571,166 +796,6 @@ function readRestProps(parameter, body) {
571
796
  ts.forEachChild(body, visit);
572
797
  return restProps.sort(byName);
573
798
  }
574
- function readsSxProp(parameter, body) {
575
- if (parameter?.name && ts.isObjectBindingPattern(parameter.name)) {
576
- if (bindingPatternHasName(parameter.name, "sx")) return true;
577
- }
578
- if (!body || !parameter?.name || !ts.isIdentifier(parameter.name)) return false;
579
- const propsName = parameter.name.text;
580
- let found = false;
581
- const visit = (node) => {
582
- if (found) return;
583
- if (isFunctionWithParameterNamed(node, propsName) || isFunctionWithParameterDestructuringName(node, "sx")) return;
584
- if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === propsName && node.name.text === "sx") {
585
- found = true;
586
- return;
587
- }
588
- if (ts.isVariableDeclaration(node) && ts.isObjectBindingPattern(node.name) && node.initializer && isIdentifierNamed(unwrapExpression(node.initializer), propsName) && bindingPatternHasName(node.name, "sx")) {
589
- found = true;
590
- return;
591
- }
592
- ts.forEachChild(node, visit);
593
- };
594
- ts.forEachChild(body, visit);
595
- return found;
596
- }
597
- function detectSxTarget(parameter, body) {
598
- if (!body) return;
599
- const sxNames = collectSxBindingNames(parameter, body);
600
- if (sxNames.size === 0) return;
601
- const sxPropContainerNames = collectSxPropContainerNames(parameter);
602
- const sxPropsNames = collectStylexPropsBindingNames(body, sxNames, sxPropContainerNames);
603
- const root = returnedJsxRoot(body);
604
- if (!root) return;
605
- if (jsxOpeningUsesSx(jsxRootOpening(root), sxNames, sxPropsNames, sxPropContainerNames)) return "root";
606
- return jsxChildrenUseSx(root, sxNames, sxPropsNames, sxPropContainerNames) ? "inner" : void 0;
607
- }
608
- function collectSxBindingNames(parameter, body) {
609
- const names = /* @__PURE__ */ new Set();
610
- if (parameter?.name && ts.isObjectBindingPattern(parameter.name)) collectBindingElementLocalNames(parameter.name, "sx", names);
611
- else names.add("sx");
612
- if (parameter?.name && ts.isIdentifier(parameter.name)) {
613
- const propsName = parameter.name.text;
614
- const visit = (node) => {
615
- if (ts.isVariableDeclaration(node) && ts.isObjectBindingPattern(node.name) && node.initializer && isIdentifierNamed(unwrapExpression(node.initializer), propsName)) collectBindingElementLocalNames(node.name, "sx", names);
616
- ts.forEachChild(node, visit);
617
- };
618
- ts.forEachChild(body, visit);
619
- }
620
- return names;
621
- }
622
- function collectBindingElementLocalNames(pattern, propertyName, names) {
623
- for (const element of pattern.elements) if (bindingElementPropertyNameText(element) === propertyName && ts.isIdentifier(element.name)) names.add(element.name.text);
624
- }
625
- function collectSxPropContainerNames(parameter) {
626
- const names = /* @__PURE__ */ new Set();
627
- if (parameter?.name && ts.isIdentifier(parameter.name)) names.add(parameter.name.text);
628
- return names;
629
- }
630
- function bindingElementPropertyNameText(element) {
631
- if (element.propertyName) return ts.isIdentifier(element.propertyName) || ts.isStringLiteral(element.propertyName) ? element.propertyName.text : null;
632
- return ts.isIdentifier(element.name) ? element.name.text : null;
633
- }
634
- function collectStylexPropsBindingNames(body, sxNames, sxPropContainerNames) {
635
- const names = /* @__PURE__ */ new Set();
636
- const visit = (node) => {
637
- if (ts.isVariableDeclaration(node) && node.initializer && isStylexPropsCallWithSx(node.initializer, sxNames, sxPropContainerNames)) {
638
- if (ts.isIdentifier(node.name)) names.add(node.name.text);
639
- else if (ts.isObjectBindingPattern(node.name)) collectBindingPatternIdentifierNames(node.name, names);
640
- }
641
- ts.forEachChild(node, visit);
642
- };
643
- ts.forEachChild(body, visit);
644
- return names;
645
- }
646
- function collectBindingPatternIdentifierNames(pattern, names) {
647
- for (const element of pattern.elements) if (ts.isIdentifier(element.name)) names.add(element.name.text);
648
- }
649
- function isStylexPropsCallWithSx(expr, sxNames, sxPropContainerNames) {
650
- const unwrapped = unwrapExpression(expr);
651
- const noSxPropsNames = /* @__PURE__ */ new Set();
652
- return ts.isCallExpression(unwrapped) && isStylexPropsCallee(unwrapped.expression) && unwrapped.arguments.some((arg) => expressionReferencesNames(arg, sxNames, noSxPropsNames, sxPropContainerNames));
653
- }
654
- function isStylexPropsCallee(expr) {
655
- return ts.isPropertyAccessExpression(expr) && expr.name.text === "props" && ts.isIdentifier(expr.expression) && expr.expression.text === "stylex";
656
- }
657
- function returnedJsxRoot(body) {
658
- if (ts.isJsxElement(body) || ts.isJsxSelfClosingElement(body)) return body;
659
- if (!ts.isBlock(body)) return null;
660
- for (const statement of body.statements) {
661
- if (!ts.isReturnStatement(statement) || !statement.expression) continue;
662
- const expr = unwrapExpression(statement.expression);
663
- if (ts.isJsxElement(expr) || ts.isJsxSelfClosingElement(expr)) return expr;
664
- }
665
- return null;
666
- }
667
- function jsxChildrenUseSx(root, sxNames, sxPropsNames, sxPropContainerNames) {
668
- if (!ts.isJsxElement(root)) return false;
669
- let found = false;
670
- const visit = (node) => {
671
- if (found) return;
672
- if (functionShadowsSxReference(node, sxNames, sxPropContainerNames)) return;
673
- if (ts.isJsxElement(node) && jsxOpeningUsesSx(node.openingElement, sxNames, sxPropsNames, sxPropContainerNames) || ts.isJsxSelfClosingElement(node) && jsxOpeningUsesSx(node, sxNames, sxPropsNames, sxPropContainerNames)) {
674
- found = true;
675
- return;
676
- }
677
- ts.forEachChild(node, visit);
678
- };
679
- for (const child of root.children) visit(child);
680
- return found;
681
- }
682
- function jsxRootOpening(root) {
683
- return ts.isJsxElement(root) ? root.openingElement : root;
684
- }
685
- function jsxOpeningUsesSx(opening, sxNames, sxPropsNames, sxPropContainerNames) {
686
- return opening.attributes.properties.some((attribute) => {
687
- if (ts.isJsxSpreadAttribute(attribute)) return expressionReferencesNames(attribute.expression, sxNames, sxPropsNames, sxPropContainerNames);
688
- if (!ts.isIdentifier(attribute.name) || !attribute.initializer) return false;
689
- if (!ts.isJsxExpression(attribute.initializer) || !attribute.initializer.expression) return false;
690
- if (attribute.name.text === "className" || attribute.name.text === "style") return expressionReferencesStylexPropsBinding(attribute.initializer.expression, sxPropsNames);
691
- if (attribute.name.text !== "sx") return false;
692
- return expressionReferencesNames(attribute.initializer.expression, sxNames, sxPropsNames, sxPropContainerNames);
693
- });
694
- }
695
- function expressionReferencesStylexPropsBinding(expr, sxPropsNames) {
696
- const unwrapped = unwrapExpression(expr);
697
- return ts.isIdentifier(unwrapped) && sxPropsNames.has(unwrapped.text);
698
- }
699
- function expressionReferencesNames(expr, sxNames, sxPropsNames, sxPropContainerNames) {
700
- const unwrapped = unwrapExpression(expr);
701
- if (ts.isIdentifier(unwrapped)) return sxNames.has(unwrapped.text) || sxPropsNames.has(unwrapped.text);
702
- if (ts.isPropertyAccessExpression(unwrapped) && unwrapped.name.text === "sx" && ts.isIdentifier(unwrapped.expression)) return sxPropContainerNames.has(unwrapped.expression.text);
703
- return isStylexPropsCallWithSx(unwrapped, sxNames, sxPropContainerNames);
704
- }
705
- function functionShadowsSxReference(node, sxNames, sxPropContainerNames) {
706
- if (!isFunctionWithParameters(node)) return false;
707
- for (const name of sxPropContainerNames) if (node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name))) return true;
708
- for (const name of sxNames) if (node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name))) return true;
709
- return node.parameters.some((parameter) => ts.isObjectBindingPattern(parameter.name) && bindingPatternHasName(parameter.name, "sx"));
710
- }
711
- function isFunctionWithParameterNamed(node, name) {
712
- return isFunctionWithParameters(node) ? node.parameters.some((parameter) => isBindingNameNamed(parameter.name, name)) : false;
713
- }
714
- function isFunctionWithParameterDestructuringName(node, name) {
715
- return isFunctionWithParameters(node) ? node.parameters.some((parameter) => ts.isObjectBindingPattern(parameter.name) && bindingPatternHasName(parameter.name, name)) : false;
716
- }
717
- function isFunctionWithParameters(node) {
718
- return ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node);
719
- }
720
- function isBindingNameNamed(name, expected) {
721
- return ts.isIdentifier(name) && name.text === expected;
722
- }
723
- function bindingPatternHasName(pattern, name) {
724
- return pattern.elements.some((element) => element.name.getText() === name);
725
- }
726
- function unwrapExpression(expression) {
727
- let current = expression;
728
- while (ts.isAsExpression(current) || ts.isTypeAssertionExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current)) current = current.expression;
729
- return current;
730
- }
731
- function isIdentifierNamed(expression, name) {
732
- return ts.isIdentifier(expression) && expression.text === name;
733
- }
734
799
  function describeTypeNode(typeNode, checker) {
735
800
  const declaration = resolveTypeDeclaration(typeNode, checker);
736
801
  return {
@@ -871,19 +936,6 @@ function readParameterName(name) {
871
936
  function isReadonlyProperty(symbol) {
872
937
  return Boolean(symbol.declarations?.some((declaration) => (ts.isPropertySignature(declaration) || ts.isPropertyDeclaration(declaration)) && declaration.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ReadonlyKeyword)));
873
938
  }
874
- function getExportedNames(sourceFile, checker) {
875
- const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
876
- if (!moduleSymbol) return /* @__PURE__ */ new Set();
877
- return new Set(checker.getExportsOfModule(moduleSymbol).map((symbol) => symbol.getName()));
878
- }
879
- function getDefaultExportedLocalNames(sourceFile) {
880
- const names = /* @__PURE__ */ new Set();
881
- for (const statement of sourceFile.statements) {
882
- if (!ts.isExportAssignment(statement) || !ts.isIdentifier(statement.expression)) continue;
883
- names.add(statement.expression.text);
884
- }
885
- return names;
886
- }
887
939
  function isExported(node) {
888
940
  return Boolean(ts.canHaveModifiers(node) && ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
889
941
  }
@@ -893,50 +945,6 @@ function isDefaultExport(node) {
893
945
  function isReactComponentName(name) {
894
946
  return /^[A-Z]/.test(name);
895
947
  }
896
- function createProgram(rootNames, cwd) {
897
- const configPath = findTsConfig(rootNames, cwd);
898
- const options = configPath ? readCompilerOptions(configPath) : defaultCompilerOptions();
899
- return ts.createProgram({
900
- rootNames: [...rootNames],
901
- options: {
902
- ...options,
903
- allowJs: true,
904
- checkJs: false,
905
- noEmit: true,
906
- skipLibCheck: true,
907
- skipDefaultLibCheck: true,
908
- types: []
909
- }
910
- });
911
- }
912
- function readCompilerOptions(configPath) {
913
- const config = ts.readConfigFile(configPath, (filePath) => ts.sys.readFile(filePath));
914
- if (config.error) return defaultCompilerOptions();
915
- return ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath)).options;
916
- }
917
- function defaultCompilerOptions() {
918
- return {
919
- target: ts.ScriptTarget.ES2022,
920
- module: ts.ModuleKind.ESNext,
921
- moduleResolution: ts.ModuleResolutionKind.Node10,
922
- jsx: ts.JsxEmit.ReactJSX,
923
- esModuleInterop: true,
924
- skipLibCheck: true
925
- };
926
- }
927
- function findTsConfig(rootNames, cwd) {
928
- const start = rootNames.length > 0 ? path.dirname(rootNames[0]) : cwd;
929
- return ts.findConfigFile(start, (filePath) => ts.sys.fileExists(filePath), "tsconfig.json") ?? void 0;
930
- }
931
- function normalizeFilePaths(files) {
932
- return [...new Set(files.map(resolveExistingFilePath))].sort();
933
- }
934
- function normalizeFilePath(filePath) {
935
- return resolveExistingFilePath(filePath);
936
- }
937
- function isTypeScriptLikeFile(filePath) {
938
- return /\.(tsx?|jsx?)$/.test(filePath);
939
- }
940
948
  function byName(a, b) {
941
949
  return a.name.localeCompare(b.name);
942
950
  }