Skip to content

Commit 5cf69a7

Browse files
committed
refactor: consolidate duplicated predicates and drop test-only re-export shims
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dr6XbcGLkM1bE4y1VrdVTw
1 parent b6afa66 commit 5cf69a7

25 files changed

Lines changed: 174 additions & 252 deletions

src/internal/emit-wrappers/emit-intrinsic-simple.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ import {
2424
import { withLeadingCommentsOnFirstFunction } from "./comments.js";
2525
import { collectCompoundVariantKeys, type EmitIntrinsicContext } from "./emit-intrinsic-helpers.js";
2626
import { buildPolymorphicTypeParams } from "./jsx-builders.js";
27-
import { collectIdentifiers } from "../utilities/jscodeshift-utils.js";
27+
import {
28+
collectIdentifiers,
29+
identifierName,
30+
isIdentifierNamed,
31+
} from "../utilities/jscodeshift-utils.js";
2832
import { isMemberExpression } from "../lower-rules/utils.js";
2933
import { getPositiveWhen, parseVariantWhenToAst } from "./variant-condition.js";
3034
import { typeContainsPolymorphicAs } from "../utilities/polymorphic-as-detection.js";
@@ -1613,14 +1617,6 @@ function extractPropEqUndefined(expr: ExpressionKind): string | null {
16131617
return null;
16141618
}
16151619

1616-
function isIdentifierNamed(expr: ExpressionKind, name: string): boolean {
1617-
return expr.type === "Identifier" && expr.name === name;
1618-
}
1619-
1620-
function identifierName(expr: ExpressionKind): string | null {
1621-
return expr.type === "Identifier" ? expr.name : null;
1622-
}
1623-
16241620
function collectPropsFromPropsMemberAccess(node: ExpressionKind, out: Set<string>): void {
16251621
const visit = (value: unknown): void => {
16261622
if (!value || typeof value !== "object") {

src/internal/emit-wrappers/style-merger.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { StyleMergerConfig } from "../../adapter.js";
77
import type { InlineStyleProp } from "./types.js";
88
import type { WrapperEmitter } from "./wrapper-emitter.js";
99
import { mergeAdjacentComplementaryStyleExprs } from "./variant-condition.js";
10+
import { isUndefinedIdentifier } from "../utilities/jscodeshift-utils.js";
1011

1112
/**
1213
* Result of emitting style merging logic.
@@ -912,10 +913,6 @@ function isExpressionField(node: unknown, field: string): boolean {
912913
);
913914
}
914915

915-
function isUndefinedIdentifier(node: unknown): node is { type: "Identifier"; name: "undefined" } {
916-
return getNodeType(node) === "Identifier" && (node as { name?: unknown }).name === "undefined";
917-
}
918-
919916
function getNodeType(node: unknown): string | undefined {
920917
if (!node || typeof node !== "object") {
921918
return undefined;

src/internal/emit-wrappers/type-reference-names.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
import type { ASTNode } from "jscodeshift";
77
import jscodeshift from "jscodeshift";
8+
import { isReactComponentPropsUtilityName } from "../utilities/jscodeshift-utils.js";
89

910
export type TypeReferenceName =
1011
| { kind: "identifier"; name: string }
@@ -194,14 +195,6 @@ function isUtilityTypeReference(typeName: TypeReferenceName | null): boolean {
194195
);
195196
}
196197

197-
function isReactComponentPropsUtilityName(name: string): boolean {
198-
return (
199-
name === "ComponentProps" ||
200-
name === "ComponentPropsWithRef" ||
201-
name === "ComponentPropsWithoutRef"
202-
);
203-
}
204-
205198
function getTypeQueryExpressionName(exprName: unknown): string | null {
206199
const node = exprName as
207200
| {

src/internal/lower-rules/dynamic-helper-call.ts

Lines changed: 9 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import {
1616
getArrowFnParamBindings,
1717
getMemberPathFromIdentifier,
1818
getNodeLocStart,
19+
isFunctionNode,
20+
isIdentifierNamed,
21+
isNumericTsType,
22+
patternBindsAnyName,
1923
resolveIdentifierToPropName,
2024
} from "../utilities/jscodeshift-utils.js";
2125
import type { DeclProcessingState } from "./decl-setup.js";
@@ -130,7 +134,10 @@ export function numericIdentifierSetForJsxProp(
130134
jsxProp: string,
131135
findJsxPropTsType: (propName: string) => unknown,
132136
): ReadonlySet<string> {
133-
if (jsxProp === "__props" || !isNumericOrOptionalTsType(findJsxPropTsType(jsxProp))) {
137+
if (
138+
jsxProp === "__props" ||
139+
!isNumericTsType(findJsxPropTsType(jsxProp), { allowOptional: true })
140+
) {
134141
return new Set();
135142
}
136143
const names = new Set([jsxProp]);
@@ -140,30 +147,6 @@ export function numericIdentifierSetForJsxProp(
140147
return names;
141148
}
142149

143-
function isNumericOrOptionalTsType(tsType: unknown): boolean {
144-
if (!tsType || typeof tsType !== "object") {
145-
return false;
146-
}
147-
const type = tsType as { type?: string; types?: unknown[]; literal?: { value?: unknown } };
148-
if (type.type === "TSNumberKeyword") {
149-
return true;
150-
}
151-
if (type.type === "TSLiteralType") {
152-
return typeof type.literal?.value === "number";
153-
}
154-
if (type.type === "TSUnionType" && Array.isArray(type.types)) {
155-
return type.types.every((member) => {
156-
const memberType = (member as { type?: string } | null)?.type;
157-
return (
158-
memberType === "TSUndefinedKeyword" ||
159-
memberType === "TSNullKeyword" ||
160-
isNumericOrOptionalTsType(member)
161-
);
162-
});
163-
}
164-
return false;
165-
}
166-
167150
/**
168151
* Handles dynamic interpolations inside pseudo-elements (::before / ::after / ::placeholder)
169152
* by emitting a StyleX dynamic style function whose body wraps the value in the pseudo-element
@@ -693,7 +676,7 @@ function expressionContainsFunctionBindingName(node: unknown, names: ReadonlySet
693676
}
694677

695678
const record = node as Record<string, unknown>;
696-
if (isFunctionLikeNode(record)) {
679+
if (isFunctionNode(record)) {
697680
const params = record.params;
698681
if (Array.isArray(params) && params.some((param) => patternBindsAnyName(param, names))) {
699682
return true;
@@ -711,48 +694,6 @@ function expressionContainsFunctionBindingName(node: unknown, names: ReadonlySet
711694
return false;
712695
}
713696

714-
function isFunctionLikeNode(node: Record<string, unknown>): boolean {
715-
return (
716-
node.type === "ArrowFunctionExpression" ||
717-
node.type === "FunctionExpression" ||
718-
node.type === "FunctionDeclaration" ||
719-
node.type === "ObjectMethod" ||
720-
node.type === "ClassMethod"
721-
);
722-
}
723-
724-
function patternBindsAnyName(node: unknown, names: ReadonlySet<string>): boolean {
725-
if (!node || typeof node !== "object") {
726-
return false;
727-
}
728-
const record = node as Record<string, unknown>;
729-
if (record.type === "Identifier") {
730-
return typeof record.name === "string" && names.has(record.name);
731-
}
732-
if (record.type === "RestElement") {
733-
return patternBindsAnyName(record.argument, names);
734-
}
735-
if (record.type === "AssignmentPattern") {
736-
return patternBindsAnyName(record.left, names);
737-
}
738-
if (record.type === "ObjectPattern") {
739-
return (
740-
Array.isArray(record.properties) &&
741-
record.properties.some((prop) => patternBindsAnyName(prop, names))
742-
);
743-
}
744-
if (record.type === "ObjectProperty" || record.type === "Property") {
745-
return patternBindsAnyName(record.value, names);
746-
}
747-
if (record.type === "ArrayPattern") {
748-
return (
749-
Array.isArray(record.elements) &&
750-
record.elements.some((element) => patternBindsAnyName(element, names))
751-
);
752-
}
753-
return false;
754-
}
755-
756697
type DynamicHelperCallResult = {
757698
value: ExpressionKind;
758699
binding: DynamicHelperCallArgument;
@@ -1103,10 +1044,6 @@ function getStyledHelperCall(callExpr: CallExpressionLike): StyledHelperCall | n
11031044
};
11041045
}
11051046

1106-
function isIdentifierNamed(node: ExpressionKind, name: string): boolean {
1107-
return node?.type === "Identifier" && node.name === name;
1108-
}
1109-
11101047
type NullishLogicalExpression = ExpressionKind & {
11111048
type: "LogicalExpression";
11121049
operator: "??";

src/internal/lower-rules/finalize-decl.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, it } from "vitest";
22
import jscodeshift from "jscodeshift";
3-
import { extractSingleRawCssVarStyleFnProperty } from "./finalize-decl.js";
3+
import { extractSingleRawCssVarStyleFnProperty } from "./raw-css-var-inlining.js";
44

55
const j = jscodeshift.withParser("tsx");
66

src/internal/lower-rules/finalize-decl.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ import {
6060
collectRawCssVarStyleObjectProps,
6161
collectStyleOverrideProps,
6262
dropCssVariableDefinitionsFromBucket,
63-
extractSingleRawCssVarStyleFnProperty,
6463
findLocalCustomPropertyFallbackFromRules,
6564
moveCustomPropertyOnlyBaseToInlineStyles,
6665
moveUnsafeRawCssVarPropsToInlineStyles,
@@ -74,9 +73,6 @@ import {
7473
mergeBaseIntoSingleStyleFn,
7574
mergeVariantBucketsIntoStyleFns,
7675
} from "./style-fn-merging.js";
77-
import { replaceIdentifierInAst } from "./ast-style-utils.js";
78-
79-
export { extractSingleRawCssVarStyleFnProperty, replaceIdentifierInAst };
8076

8177
export function finalizeDeclProcessing(ctx: DeclProcessingState): void {
8278
const {

src/internal/lower-rules/imported-value-resolver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import { resolveDynamicNode } from "../builtin-handlers.js";
1414
import { isStylexImportSource } from "../utilities/stylex-import-source.js";
1515
import { extractRootAndPath, getNodeLocStart } from "../utilities/jscodeshift-utils.js";
1616
import { literalToStaticValue } from "./types.js";
17+
import { isCssCalcOperator } from "../builtin-handlers/conditional-css-calc.js";
1718
import {
1819
buildCssCalcTemplateExpression,
1920
buildNegatedCssTokenTemplate,
2021
hasAdjacentTemplateUnit,
21-
isCssCalcOperator,
2222
} from "./interpolated-calc.js";
2323
import {
2424
getSingleSlotStaticParts,

src/internal/lower-rules/inline-styles.ts

Lines changed: 4 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import {
1010
getArrowFnParamBindings,
1111
getArrowFnSingleParamName,
1212
getFunctionBodyExpr,
13+
isFunctionNode,
1314
literalToStaticValue,
15+
patternBindsAnyName,
1416
} from "../utilities/jscodeshift-utils.js";
1517
import type { ExpressionKind } from "./decl-types.js";
1618
import {
@@ -464,7 +466,7 @@ export function inlineArrowFunctionBody(j: JSCodeshift, expr: any): ExpressionKi
464466
if (param?.type === "Identifier") {
465467
const paramName = param.name;
466468
return mapAst(cloneAstNode(bodyExpr), (node, recurse) => {
467-
if (isFunctionLikeNode(node) && functionBindsAnyName(node, new Set([paramName]))) {
469+
if (isFunctionNode(node) && functionBindsAnyName(node, new Set([paramName]))) {
468470
return node;
469471
}
470472
if (node.type === "Identifier" && node.name === paramName) {
@@ -484,7 +486,7 @@ export function inlineArrowFunctionBody(j: JSCodeshift, expr: any): ExpressionKi
484486
// If there's a default value, wrap with nullish coalescing: props.propName ?? defaultValue
485487
const bindingNames = new Set(bindings.bindings.keys());
486488
return mapAst(cloneAstNode(bodyExpr), (node, recurse) => {
487-
if (isFunctionLikeNode(node) && functionBindsAnyName(node, bindingNames)) {
489+
if (isFunctionNode(node) && functionBindsAnyName(node, bindingNames)) {
488490
return node;
489491
}
490492
if (node.type === "Identifier" && bindings.bindings.has(node.name as string)) {
@@ -626,53 +628,11 @@ function makePropsWithThemeObject(j: JSCodeshift) {
626628
return j.objectExpression([j.spreadElement(j.identifier("props")), themeProperty]);
627629
}
628630

629-
function isFunctionLikeNode(node: Record<string, unknown>): boolean {
630-
return (
631-
node.type === "ArrowFunctionExpression" ||
632-
node.type === "FunctionExpression" ||
633-
node.type === "FunctionDeclaration" ||
634-
node.type === "ObjectMethod" ||
635-
node.type === "ClassMethod"
636-
);
637-
}
638-
639631
function functionBindsAnyName(node: Record<string, unknown>, names: ReadonlySet<string>): boolean {
640632
const params = node.params;
641633
return Array.isArray(params) && params.some((param) => patternBindsAnyName(param, names));
642634
}
643635

644-
function patternBindsAnyName(node: unknown, names: ReadonlySet<string>): boolean {
645-
if (!node || typeof node !== "object") {
646-
return false;
647-
}
648-
const record = node as Record<string, unknown>;
649-
if (record.type === "Identifier") {
650-
return typeof record.name === "string" && names.has(record.name);
651-
}
652-
if (record.type === "RestElement") {
653-
return patternBindsAnyName(record.argument, names);
654-
}
655-
if (record.type === "AssignmentPattern") {
656-
return patternBindsAnyName(record.left, names);
657-
}
658-
if (record.type === "ObjectPattern") {
659-
return (
660-
Array.isArray(record.properties) &&
661-
record.properties.some((prop) => patternBindsAnyName(prop, names))
662-
);
663-
}
664-
if (record.type === "ObjectProperty" || record.type === "Property") {
665-
return patternBindsAnyName(record.value, names);
666-
}
667-
if (record.type === "ArrayPattern") {
668-
return (
669-
Array.isArray(record.elements) &&
670-
record.elements.some((element) => patternBindsAnyName(element, names))
671-
);
672-
}
673-
return false;
674-
}
675-
676636
function collectCurriedCallKeys(node: unknown): Set<string> {
677637
const keys = new Set<string>();
678638
walkAst(node, (rec) => {

src/internal/lower-rules/interpolated-calc.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@ export function buildFullInterpolatedDeclarationValueExpr(
5959
return j.templateLiteral(quasis, expressions);
6060
}
6161

62-
export function isCssCalcOperator(operator: string | undefined): boolean {
63-
return operator === "+" || operator === "-" || operator === "*" || operator === "/";
64-
}
65-
6662
export function buildCssCalcTemplateExpression(args: {
6763
j: JSCodeshift;
6864
operator: string;

src/internal/lower-rules/numeric-css-props.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -202,23 +202,6 @@ export function buildObservedExpressionFallbackValueExpr(args: {
202202
: rewritten;
203203
}
204204

205-
export function isNumberLikeTsType(tsType: unknown): boolean {
206-
if (!tsType || typeof tsType !== "object") {
207-
return false;
208-
}
209-
const type = tsType as { type?: string; types?: unknown[]; literal?: { value?: unknown } };
210-
if (type.type === "TSNumberKeyword") {
211-
return true;
212-
}
213-
if (type.type === "TSLiteralType") {
214-
return typeof type.literal?.value === "number";
215-
}
216-
if (type.type === "TSUnionType" && Array.isArray(type.types)) {
217-
return type.types.length > 0 && type.types.every(isNumberLikeTsType);
218-
}
219-
return false;
220-
}
221-
222205
const UNITLESS_NUMERIC_STYLEX_PROPS = new Set([
223206
"animationIterationCount",
224207
"aspectRatio",

0 commit comments

Comments
 (0)