@drskillissue/ganko 0.1.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.
@@ -0,0 +1,3133 @@
1
+ import { RuleOverrides, Logger, StringInterner } from '@drskillissue/ganko-shared';
2
+ import { TSESLint, ParserServices, TSESTree } from '@typescript-eslint/utils';
3
+ import ts from 'typescript';
4
+ import { Declaration, AtRule, Root, Rule } from 'postcss';
5
+ export { RULES, RULES_BY_CATEGORY, RuleEntry, getRule } from './rules-manifest.js';
6
+
7
+ type MessageId = string;
8
+ type Message = string;
9
+ /**
10
+ * Diagnostic severity — matches RuleSeverityOverride minus "off".
11
+ * Rules that are "off" never emit, so diagnostics only carry "error" or "warn".
12
+ */
13
+ type DiagnosticSeverity = "error" | "warn";
14
+ interface SourceLocation {
15
+ readonly start: {
16
+ readonly line: number;
17
+ readonly column: number;
18
+ };
19
+ readonly end: {
20
+ readonly line: number;
21
+ readonly column: number;
22
+ };
23
+ }
24
+ interface FixOperation {
25
+ readonly range: readonly [number, number];
26
+ readonly text: string;
27
+ }
28
+ type Fix = readonly FixOperation[];
29
+ interface Suggestion {
30
+ readonly messageId: MessageId;
31
+ readonly message: Message;
32
+ readonly fix: Fix;
33
+ }
34
+ interface Diagnostic {
35
+ readonly file: string;
36
+ readonly rule: string;
37
+ readonly messageId: MessageId;
38
+ readonly message: Message;
39
+ readonly severity: DiagnosticSeverity;
40
+ readonly loc: SourceLocation;
41
+ readonly fix?: Fix;
42
+ readonly suggest?: readonly Suggestion[];
43
+ }
44
+
45
+ /** Emit callback type for pushing diagnostics */
46
+ type Emit = (d: Diagnostic) => void;
47
+ /**
48
+ * A plugin provides a graph type and its rules.
49
+ *
50
+ * Plugins push data OUT via callbacks. The runner never stores typed graphs.
51
+ * Plugins run their own rules internally via the analyze() method.
52
+ *
53
+ * @typeParam K - The plugin kind string
54
+ */
55
+ interface Plugin<K extends string> {
56
+ readonly kind: K;
57
+ readonly extensions: readonly string[];
58
+ /** Analyze files and emit diagnostics via callback */
59
+ analyze(files: readonly string[], emit: Emit): void;
60
+ }
61
+
62
+ /**
63
+ * Runner - Plugin-agnostic runner for ganko
64
+ *
65
+ * The runner takes a configuration with plugins and runs them against files.
66
+ * It never stores typed graphs - plugins handle their own graph building
67
+ * and rule execution internally via the analyze() method.
68
+ *
69
+ * Rule overrides allow callers (LSP, CLI) to disable rules or remap their
70
+ * severity without modifying rule definitions. The runner intercepts the
71
+ * Emit callback to enforce overrides before diagnostics reach the caller.
72
+ */
73
+
74
+ /** Runner configuration */
75
+ interface RunnerConfig {
76
+ readonly plugins: readonly Plugin<string>[];
77
+ readonly rules?: RuleOverrides;
78
+ }
79
+ /** Runner interface */
80
+ interface Runner {
81
+ run(files: readonly string[]): readonly Diagnostic[];
82
+ /** Replace rule overrides. Takes effect on the next run() call. */
83
+ setRuleOverrides(overrides: RuleOverrides): void;
84
+ }
85
+ /**
86
+ * Build an Emit wrapper that enforces rule overrides.
87
+ *
88
+ * @param target - The underlying emit that collects diagnostics
89
+ * @param overrides - Current rule override map
90
+ * @returns Wrapped emit that suppresses/remaps per overrides
91
+ */
92
+ declare function createOverrideEmit(target: Emit, overrides: RuleOverrides): Emit;
93
+ /**
94
+ * Create a runner from configuration.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const runner = createRunner({
99
+ * plugins: [SolidPlugin, CSSPlugin, CrossFilePlugin],
100
+ * rules: { "missing-jsdoc-comments": "off", "signal-call": "warn" },
101
+ * })
102
+ * const diagnostics = runner.run(projectFiles)
103
+ * ```
104
+ */
105
+ declare function createRunner(config: RunnerConfig): Runner;
106
+
107
+ /**
108
+ * SolidInput - Input type for building SolidGraph from ESLint-parsed source.
109
+ *
110
+ * This defines the contract for what data is needed to build a Solid.js
111
+ * program graph. It requires ESLint's SourceCode object which contains
112
+ * the AST, scope manager, and parser services.
113
+ */
114
+
115
+ /**
116
+ * Input for building a SolidGraph from ESLint-parsed source.
117
+ */
118
+ interface SolidInput {
119
+ /** Absolute path to the source file */
120
+ readonly file: string;
121
+ /** ESLint SourceCode object containing AST and scope manager */
122
+ readonly sourceCode: TSESLint.SourceCode;
123
+ /** TypeScript parser services for type information (null if unavailable) */
124
+ readonly parserServices: Partial<ParserServices> | null;
125
+ /** TypeScript type checker for advanced type queries (null if unavailable) */
126
+ readonly checker: ts.TypeChecker | null;
127
+ /** Logger for debug output (omit for silent operation) */
128
+ readonly logger?: Logger;
129
+ }
130
+
131
+ /**
132
+ * TypeScript Integration Module
133
+ *
134
+ * This module provides TypeScript type resolution for the program graph.
135
+ * When TypeScript parser services are available, we can:
136
+ * - Get the type of any expression
137
+ * - Detect Solid-specific types (Accessor, Signal, Store, Component)
138
+ * - Mark variables as reactive based on their types
139
+ */
140
+
141
+ /**
142
+ * Type information for a node resolved from TypeScript.
143
+ *
144
+ * Provides reactive kind detection, type flags, and serialized type representation.
145
+ * The `flags` field contains TypeScript's TypeFlags bitmask for the type.
146
+ */
147
+ interface TypeInfo {
148
+ raw: string;
149
+ flags: number;
150
+ isAccessor: boolean;
151
+ isSignal: boolean;
152
+ isStore: boolean;
153
+ isComponent: boolean;
154
+ }
155
+ /**
156
+ * Information about a property on an object type.
157
+ * Used for expanding object spreads into explicit property assignments.
158
+ */
159
+ interface ObjectPropertyInfo {
160
+ /** The property name */
161
+ readonly name: string;
162
+ /** Whether the property is optional (has ? modifier) */
163
+ readonly optional: boolean;
164
+ /** The TypeScript type as a string */
165
+ readonly type: string;
166
+ }
167
+ /**
168
+ * Service for resolving TypeScript types from ESLint parser services.
169
+ */
170
+ declare class TypeResolver {
171
+ private services;
172
+ private typeChecker;
173
+ private typeCache;
174
+ private solidSymbolCache;
175
+ readonly logger: Logger;
176
+ constructor(logger?: Logger);
177
+ /**
178
+ * Configure the type resolver with ESLint parser services.
179
+ *
180
+ * Returns true if TypeScript services are available, false otherwise.
181
+ * When false, all type queries will return null/false gracefully.
182
+ */
183
+ initialize(parserServices: Partial<ParserServices> | undefined): boolean;
184
+ private isSymbolFromSolid;
185
+ private isSolidSymbol;
186
+ /**
187
+ * Check if TypeScript services are available.
188
+ */
189
+ hasTypeInfo(): boolean;
190
+ /**
191
+ * Get the type info for a node.
192
+ *
193
+ * Returns null if TypeScript services are not available or if the type
194
+ * cannot be determined.
195
+ */
196
+ getType(node: TSESTree.Node): TypeInfo | null;
197
+ /**
198
+ * Check if a node's type is an Accessor type (Accessor<T>).
199
+ */
200
+ isAccessorType(node: TSESTree.Node): boolean;
201
+ /**
202
+ * Check if a node's type is a Signal type (Signal<T>).
203
+ */
204
+ isSignalType(node: TSESTree.Node): boolean;
205
+ /**
206
+ * Check if a node's type is a Store type (Store<T>).
207
+ */
208
+ isStoreType(node: TSESTree.Node): boolean;
209
+ /**
210
+ * Check if a node's type is a Component type (Component<P>).
211
+ */
212
+ isComponentType(node: TSESTree.Node): boolean;
213
+ /**
214
+ * Determine the reactive kind of a variable based on its type.
215
+ *
216
+ * Returns null if the type is not reactive.
217
+ */
218
+ getReactiveKind(node: TSESTree.Node): ReactiveKind | null;
219
+ /**
220
+ * Get both reactive kind AND type info in a single call.
221
+ */
222
+ getReactiveKindWithType(node: TSESTree.Node): {
223
+ kind: ReactiveKind | null;
224
+ type: TypeInfo | null;
225
+ };
226
+ /**
227
+ * Classify the element type of an array expression.
228
+ * Uses TypeScript's type system directly.
229
+ *
230
+ * @param node The array expression node (e.g., props.users in `<For each={props.users}>`)
231
+ * @returns "primitive" | "object" | "unknown"
232
+ */
233
+ getArrayElementKind(node: TSESTree.Node): "primitive" | "object" | "unknown";
234
+ /**
235
+ * Check if a node's type is an array type.
236
+ * Detects Array<T>, T[], ReadonlyArray<T>, and tuple types.
237
+ */
238
+ isArrayType(node: TSESTree.Node): boolean;
239
+ private checkIsArrayType;
240
+ /**
241
+ * Check if a node's type is callable (has call signatures).
242
+ * Detects functions, arrow functions, and callable objects.
243
+ */
244
+ isCallableType(node: TSESTree.Node): boolean;
245
+ /**
246
+ * Check if a type assertion is unnecessary because the expression
247
+ * is already assignable to the target type.
248
+ *
249
+ * Detects AI slop patterns like:
250
+ * - `node.left as T.Expression` when node.left is already Expression
251
+ * - `node.expression as T.Expression` when it's already Expression
252
+ *
253
+ * @param expression - The expression being cast
254
+ * @param targetType - The TypeNode being cast to
255
+ * @returns true if the cast is unnecessary, false otherwise
256
+ */
257
+ isUnnecessaryCast(expression: TSESTree.Expression, targetType: TSESTree.TypeNode): boolean;
258
+ /**
259
+ * Get a human-readable string for a TypeScript type at a node.
260
+ * Returns null if type info is unavailable.
261
+ */
262
+ getTypeString(node: TSESTree.Node): string | null;
263
+ /**
264
+ * Check if a property exists on an object's type.
265
+ * Handles union types by checking the non-null/undefined constituents.
266
+ *
267
+ * @param objectNode The object expression to check
268
+ * @param propertyName The property name to look for
269
+ * @returns true if property exists on type, false otherwise
270
+ */
271
+ hasPropertyOnType(objectNode: TSESTree.Node, propertyName: string): boolean;
272
+ /**
273
+ * Check if a property exists on a type, handling unions specially.
274
+ */
275
+ private checkPropertyOnType;
276
+ /**
277
+ * Get properties of an object type for spread expansion.
278
+ * Returns null if the type cannot be safely expanded.
279
+ *
280
+ * @param node The AST node to analyze
281
+ * @param maxProperties Maximum properties to return (default 10)
282
+ * @param includeCallable Include function-typed properties (for JSX props)
283
+ * @returns Array of property info or null if not expandable
284
+ */
285
+ getObjectProperties(node: TSESTree.Node, maxProperties?: number, includeCallable?: boolean): readonly ObjectPropertyInfo[] | null;
286
+ /**
287
+ * Extract properties from a TypeScript type.
288
+ * Returns null for types that can't be safely expanded.
289
+ *
290
+ * @param tsType The TypeScript type to extract from
291
+ * @param maxProperties Maximum number of properties
292
+ * @param includeCallable Whether to include function-typed properties
293
+ */
294
+ private extractObjectProperties;
295
+ /**
296
+ * Get the props properties of a Solid component from its JSX tag identifier.
297
+ *
298
+ * Resolves the component function's type, gets its first call signature's
299
+ * first parameter type, and extracts properties from that. This is the
300
+ * fallback path when the spread argument type itself is unresolvable (e.g.
301
+ * `any` inside a Show callback) but the component's props type is known.
302
+ *
303
+ * @param tagNode - The JSX identifier node (e.g. the `ConfirmActionDialog` in `<ConfirmActionDialog>`)
304
+ * @returns Property info or null if not resolvable
305
+ */
306
+ getComponentPropsProperties(tagNode: TSESTree.Node): readonly ObjectPropertyInfo[] | null;
307
+ private analyzeType;
308
+ /**
309
+ * Get aggregated TypeFlags for a type.
310
+ * For union/intersection types, combines flags from all constituent types.
311
+ */
312
+ private getAggregatedFlags;
313
+ /**
314
+ * Check if a type is a Solid Accessor type.
315
+ *
316
+ * An Accessor<T> is structurally () => T - a zero-parameter callable.
317
+ * Only uses symbol-based detection to avoid false positives on regular functions.
318
+ */
319
+ private isSolidAccessorType;
320
+ /**
321
+ * Check if a type is a Solid Signal type.
322
+ * Detects Signal<T> via symbol or [Accessor<T>, Setter<T>] tuple structure.
323
+ */
324
+ private isSolidSignalType;
325
+ /**
326
+ * Check if a type is a Solid Store type (for reactive reads).
327
+ * Excludes SetStoreFunction which is a setter, not a reactive read.
328
+ */
329
+ private isSolidStoreType;
330
+ /**
331
+ * Check if a type is a Solid Component type.
332
+ */
333
+ private isSolidComponentType;
334
+ }
335
+
336
+ /**
337
+ * Variable Entity
338
+ *
339
+ * Represents a variable binding in the program graph.
340
+ */
341
+
342
+ /**
343
+ * Represents a variable binding in the SolidGraph.
344
+ */
345
+ interface VariableEntity$1 {
346
+ id: number;
347
+ name: string;
348
+ file: FileEntity$1;
349
+ scope: ScopeEntity;
350
+ declarations: TSESTree.Node[];
351
+ assignments: AssignmentEntity[];
352
+ reads: ReadEntity[];
353
+ type: TypeInfo | null;
354
+ isReactive: boolean;
355
+ reactiveKind: ReactiveKind | null;
356
+ isSignalLike: boolean;
357
+ isMemoVariable: boolean;
358
+ hasPropertyAssignment: boolean;
359
+ }
360
+ /**
361
+ * Describes the kind of reactive variable.
362
+ *
363
+ * Different kinds have different behaviors and tracking rules.
364
+ */
365
+ type ReactiveKind = "signal" | "store" | "props" | "memo" | "derived" | "accessor" | "resource";
366
+ /** Assignment operator type extracted from AssignmentExpression */
367
+ type AssignmentOperator = TSESTree.AssignmentExpression["operator"];
368
+ /**
369
+ * Represents an assignment to a variable.
370
+ */
371
+ interface AssignmentEntity {
372
+ id: number;
373
+ node: TSESTree.Node;
374
+ /** The assigned value expression */
375
+ value: TSESTree.Expression;
376
+ /** The assignment operator ("=" for simple, "+=" etc for compound) */
377
+ operator: AssignmentOperator | null;
378
+ /** Whether this assignment is inside a loop */
379
+ isInLoop: boolean;
380
+ /** Whether this assignment is inside a conditional (if, switch, ternary, logical) */
381
+ isInConditional: boolean;
382
+ }
383
+ /**
384
+ * Represents a location where a variable is read/accessed.
385
+ */
386
+ interface ReadEntity {
387
+ id: number;
388
+ node: TSESTree.Node;
389
+ scope: ScopeEntity;
390
+ isProperAccess: boolean;
391
+ /** Whether this read is inside a loop */
392
+ isInLoop: boolean;
393
+ /** Whether this read is inside a conditional (if, switch, ternary, logical) */
394
+ isInConditional: boolean;
395
+ }
396
+
397
+ /**
398
+ * Call Entity
399
+ *
400
+ * Represents a call expression in the program graph.
401
+ */
402
+
403
+ /**
404
+ * Callee type for call expressions.
405
+ * Includes T.Super for super() calls in class constructors.
406
+ */
407
+ type CalleeExpression = TSESTree.Expression | TSESTree.Super;
408
+ /**
409
+ * Represents a call expression in the SolidGraph.
410
+ */
411
+ interface CallEntity {
412
+ id: number;
413
+ node: TSESTree.CallExpression | TSESTree.NewExpression;
414
+ file: FileEntity$1;
415
+ callee: CalleeExpression;
416
+ arguments: ArgumentEntity[];
417
+ scope: ScopeEntity;
418
+ resolvedTarget: FunctionEntity | null;
419
+ /**
420
+ * The VariableEntity for the root identifier of the callee expression.
421
+ *
422
+ * Resolved during the wiring phase by walking the callee's MemberExpression
423
+ * chain to the leftmost identifier and looking it up in scope.
424
+ *
425
+ * - `foo()` → VariableEntity for `foo` (or null if `foo` is a global)
426
+ * - `obj.method()` → VariableEntity for `obj` (or null if `obj` is global like `console`)
427
+ * - `a.b.c()` → VariableEntity for `a`
428
+ * - `getObj().method()` → null (root is a CallExpression, not an Identifier)
429
+ * - `console.log()` → null (`console` has no user-declared VariableEntity)
430
+ */
431
+ calleeRootVariable: VariableEntity$1 | null;
432
+ primitive: PrimitiveInfo | null;
433
+ argumentSemantics: ArgumentSemantic[];
434
+ /** @internal ID of resolved target for deferred resolution */
435
+ _resolvedTargetId: number;
436
+ }
437
+ /**
438
+ * Represents a single argument in a call expression.
439
+ */
440
+ interface ArgumentEntity {
441
+ id: number;
442
+ node: TSESTree.Node;
443
+ index: number;
444
+ /** Semantic for this argument position, or null if unknown */
445
+ semantic: ArgumentSemantic | null;
446
+ }
447
+ /**
448
+ * Semantic information for an argument position.
449
+ *
450
+ * Describes how the argument affects reactivity tracking
451
+ * (tracked, deferred, etc.) and what parameter information is available.
452
+ */
453
+ interface ArgumentSemantic {
454
+ position: number;
455
+ semantic: {
456
+ type: "tracked";
457
+ } | {
458
+ type: "deferred";
459
+ } | {
460
+ type: "passthrough";
461
+ } | {
462
+ type: "sync";
463
+ } | {
464
+ type: "untracked";
465
+ } | {
466
+ type: "value";
467
+ } | {
468
+ type: "unknown";
469
+ };
470
+ parameterSemantics?: ParameterSemantic[];
471
+ }
472
+ /**
473
+ * Semantic information about a function parameter.
474
+ */
475
+ interface ParameterSemantic {
476
+ index: number;
477
+ isAccessor: boolean;
478
+ isStore: boolean;
479
+ description: string;
480
+ }
481
+ /**
482
+ * Information about a Solid primitive call.
483
+ */
484
+ interface PrimitiveInfo {
485
+ name: string;
486
+ module: "solid-js" | "solid-js/store" | "solid-js/web";
487
+ returns: PrimitiveReturn;
488
+ }
489
+ /**
490
+ * Describes the return type of a Solid primitive.
491
+ */
492
+ type PrimitiveReturn = {
493
+ type: "signal";
494
+ writable: boolean;
495
+ } | {
496
+ type: "accessor";
497
+ } | {
498
+ type: "store";
499
+ writable: boolean;
500
+ } | {
501
+ type: "void";
502
+ } | {
503
+ type: "owner";
504
+ } | {
505
+ type: "context";
506
+ } | {
507
+ type: "resource";
508
+ } | {
509
+ type: "other";
510
+ };
511
+
512
+ /**
513
+ * Return Statement Entity
514
+ *
515
+ * Represents a return statement in the program graph.
516
+ */
517
+
518
+ /**
519
+ * Represents a return statement in the SolidGraph.
520
+ */
521
+ interface ReturnStatementEntity {
522
+ id: number;
523
+ node: TSESTree.ReturnStatement;
524
+ /** The containing function's ID */
525
+ functionId: number;
526
+ /** Whether this return has an argument (non-void return) */
527
+ hasArgument: boolean;
528
+ /** Whether this is an early return (not the last statement in function body) */
529
+ isEarly: boolean;
530
+ }
531
+
532
+ /**
533
+ * Function Utilities
534
+ *
535
+ * Helper functions for working with function nodes.
536
+ */
537
+
538
+ type FunctionNode = TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression;
539
+
540
+ /**
541
+ * Function Entity
542
+ *
543
+ * Represents a function in the program graph.
544
+ */
545
+
546
+ /**
547
+ * Represents a function in the SolidGraph.
548
+ */
549
+ interface FunctionEntity {
550
+ id: number;
551
+ node: FunctionNode;
552
+ file: FileEntity$1;
553
+ name: string | null;
554
+ variableName: string | null;
555
+ params: ParameterEntity[];
556
+ body: TSESTree.BlockStatement | TSESTree.Expression;
557
+ async: boolean;
558
+ generator: boolean;
559
+ scope: ScopeEntity;
560
+ captures: VariableEntity$1[];
561
+ callSites: CallEntity[];
562
+ /** True if body contains at least one return with an argument */
563
+ hasNonVoidReturn: boolean;
564
+ /** True if body contains at least one throw statement */
565
+ hasThrowStatement: boolean;
566
+ /** Character ranges of AwaitExpression nodes directly in this function (not nested functions) */
567
+ awaitRanges: [number, number][];
568
+ /** True if body contains at least one return with JSX */
569
+ hasJSXReturn: boolean;
570
+ /** The declaration node for JSDoc attachment (export wrapper, variable decl, or self) */
571
+ declarationNode: TSESTree.Node;
572
+ /** All return statements in this function */
573
+ returnStatements: ReturnStatementEntity[];
574
+ /** @internal Cached reactive captures for iteration */
575
+ _cachedReactiveCaptures: VariableEntity$1[] | null;
576
+ /** Variable entity if this function is assigned to a variable */
577
+ variable: VariableEntity$1 | null;
578
+ /** @internal Reachability flags (bitmask) */
579
+ _reachability: number;
580
+ /** @internal Cached member accesses indexed by object identifier name */
581
+ _memberAccessesByIdentifier: Map<string, TSESTree.MemberExpression[]> | null;
582
+ }
583
+ /**
584
+ * Represents a function parameter.
585
+ */
586
+ interface ParameterEntity {
587
+ id: number;
588
+ node: TSESTree.Parameter;
589
+ name: string | null;
590
+ index: number;
591
+ }
592
+
593
+ /**
594
+ * JSX Utilities
595
+ *
596
+ * Helper functions for working with JSX elements and attributes.
597
+ */
598
+
599
+ /**
600
+ * JSX Attribute Kind (for classification)
601
+ */
602
+ type JSXAttributeKind = "prop" | "event-handler" | "ref" | "directive" | "spread" | "style" | "class" | "classList";
603
+
604
+ /**
605
+ * JSX Entity
606
+ *
607
+ * Represents JSX elements in the program graph.
608
+ */
609
+
610
+ /**
611
+ * Represents a JSX element or fragment in the SolidGraph.
612
+ */
613
+ interface JSXElementEntity {
614
+ id: number;
615
+ node: TSESTree.JSXElement | TSESTree.JSXFragment;
616
+ file: FileEntity$1;
617
+ tag: string | null;
618
+ tagName: string | null;
619
+ isDomElement: boolean;
620
+ attributes: JSXAttributeEntity[];
621
+ children: JSXChildEntity[];
622
+ scope: ScopeEntity;
623
+ parent: JSXElementEntity | null;
624
+ childElements: JSXElementEntity[];
625
+ }
626
+ /**
627
+ * Represents a property extracted from a spread attribute.
628
+ *
629
+ * Only populated for literal spreads like `{...{ a: 1, b: 2 }}`.
630
+ */
631
+ interface SpreadProp {
632
+ name: string;
633
+ keyNode: TSESTree.Node;
634
+ valueNode: TSESTree.Node | null;
635
+ }
636
+ /**
637
+ * Describes the complexity of a style object.
638
+ */
639
+ interface StyleComplexityInfo {
640
+ conditionalCount: number;
641
+ hasConditionalSpread: boolean;
642
+ }
643
+ /**
644
+ * Information about spread attributes in JSX.
645
+ */
646
+ interface SpreadInfo {
647
+ hasCallExpression: boolean;
648
+ callExpressionNode: TSESTree.CallExpression | null;
649
+ hasMemberExpression: boolean;
650
+ memberExpressionNode: TSESTree.MemberExpression | null;
651
+ isConditionalSpread: boolean;
652
+ conditionalSpreadType: "ternary" | "logical-and" | null;
653
+ }
654
+ /**
655
+ * Represents a JSX attribute on an element.
656
+ */
657
+ interface JSXAttributeEntity {
658
+ id: number;
659
+ node: TSESTree.JSXAttribute | TSESTree.JSXSpreadAttribute;
660
+ name: string | null;
661
+ kind: JSXAttributeKind;
662
+ namespace: string | null;
663
+ spreadProps: SpreadProp[];
664
+ valueNode: TSESTree.Node | null;
665
+ styleComplexity: StyleComplexityInfo | null;
666
+ spreadInfo: SpreadInfo | null;
667
+ }
668
+ /**
669
+ * Represents a child node of a JSX element (text, expression, or element).
670
+ */
671
+ interface JSXChildEntity {
672
+ id: number;
673
+ node: TSESTree.Node;
674
+ kind: "element" | "expression" | "text";
675
+ }
676
+ /**
677
+ * Describes the context and location of a node within JSX.
678
+ *
679
+ * Used to determine if a node is inside JSX and where (attribute, child, expression, etc.).
680
+ */
681
+ interface JSXContext {
682
+ element: JSXElementEntity;
683
+ attribute: JSXAttributeEntity | null;
684
+ kind: "expression" | "attribute" | "child";
685
+ containerNode: TSESTree.JSXExpressionContainer | null;
686
+ }
687
+
688
+ /**
689
+ * Import Entity
690
+ *
691
+ * Represents import declarations in the program graph.
692
+ */
693
+
694
+ /**
695
+ * Represents an import declaration in the SolidGraph.
696
+ */
697
+ interface ImportEntity {
698
+ readonly id: number;
699
+ readonly node: TSESTree.ImportDeclaration;
700
+ readonly file: FileEntity$1;
701
+ readonly source: string;
702
+ readonly specifiers: readonly ImportSpecifierEntity[];
703
+ readonly isTypeOnly: boolean;
704
+ }
705
+ /**
706
+ * Represents an individual import specifier within an import declaration.
707
+ *
708
+ * Examples:
709
+ * - `import { foo }` - named specifier
710
+ * - `import foo from "mod"` - default specifier
711
+ * - `import * as foo from "mod"` - namespace specifier
712
+ */
713
+ interface ImportSpecifierEntity {
714
+ readonly id: number;
715
+ readonly node: TSESTree.ImportSpecifier | TSESTree.ImportDefaultSpecifier | TSESTree.ImportNamespaceSpecifier;
716
+ readonly localName: string;
717
+ readonly importedName: string | null;
718
+ readonly kind: "named" | "default" | "namespace";
719
+ readonly isTypeOnly: boolean;
720
+ }
721
+
722
+ /**
723
+ * Spread Entity
724
+ *
725
+ * Represents spread patterns in the program graph.
726
+ */
727
+
728
+ /**
729
+ * JSX attribute context for specialized handling.
730
+ * Computed during registration from AST parent structure.
731
+ */
732
+ type SpreadAttributeContext = "classList" | "style" | "props" | "other";
733
+ /**
734
+ * Kind of expression being spread.
735
+ * Computed during registration from spread argument.
736
+ */
737
+ type SpreadSourceKind = "identifier" | "member" | "call" | "literal" | "logical" | "conditional" | "other";
738
+ /**
739
+ * Information about a single property in a fixable spread pattern.
740
+ * Computed during graph building for autofix support.
741
+ */
742
+ interface FixableSpreadProperty {
743
+ /** The key text - identifier name or computed expression source */
744
+ readonly key: string;
745
+ /** Range of the key expression for source extraction */
746
+ readonly keyRange: readonly [number, number];
747
+ /** Whether key is computed [expr] vs static identifier */
748
+ readonly computed: boolean;
749
+ /** The value text */
750
+ readonly value: string;
751
+ /** Range of the value expression for source extraction */
752
+ readonly valueRange: readonly [number, number];
753
+ /** Whether value is literal `true` (common classList pattern) */
754
+ readonly isBooleanTrue: boolean;
755
+ }
756
+ /**
757
+ * Pattern info for fixable conditional spreads.
758
+ * Only populated when the spread has a simple single-property pattern.
759
+ */
760
+ interface FixableSpreadPattern {
761
+ /** Which branch has the non-empty object (true = consequent, false = alternate) */
762
+ readonly truthyBranch: boolean;
763
+ /** Single property info (only populated if exactly one property) */
764
+ readonly property: FixableSpreadProperty;
765
+ /** Range of the condition expression for source extraction */
766
+ readonly conditionRange: readonly [number, number];
767
+ /**
768
+ * Whether condition text matches key text (for computed keys).
769
+ * When true, `local.class ? { [local.class]: true } : {}` can become `[local.class ?? ""]: true`
770
+ * instead of `[local.class ?? ""]: !!local.class`.
771
+ */
772
+ readonly conditionMatchesKey: boolean;
773
+ }
774
+ /**
775
+ * Represents a conditional spread pattern in the SolidGraph.
776
+ *
777
+ * This includes spreads in any object expression, whether in JSX or standalone.
778
+ * Patterns detected:
779
+ * - ...(condition ? {...} : {}) - ternary with empty object fallback
780
+ * - ...(condition && {...}) - logical AND spread pattern
781
+ *
782
+ * For JSX spreads, the node is a JSXSpreadAttribute and parentContext provides
783
+ * access to the JSX opening element.
784
+ */
785
+ interface ConditionalSpreadEntity {
786
+ readonly id: number;
787
+ /** The spread node - SpreadElement for object spreads, JSXSpreadAttribute for JSX */
788
+ readonly node: TSESTree.SpreadElement | TSESTree.JSXSpreadAttribute;
789
+ readonly spreadType: "ternary" | "logical-and";
790
+ /** The parent object expression (null for JSX spreads) */
791
+ readonly parentObject: TSESTree.ObjectExpression | null;
792
+ /** For JSX spreads, the opening element containing the spread attribute */
793
+ readonly parentJSXElement: TSESTree.JSXOpeningElement | null;
794
+ readonly isInJSX: boolean;
795
+ /**
796
+ * Context where this spread appears.
797
+ * Enables specialized fix strategies for classList vs style vs generic objects.
798
+ */
799
+ readonly attributeContext: SpreadAttributeContext;
800
+ /**
801
+ * Fixable pattern info. Null if not a simple fixable pattern.
802
+ * Only populated for single-property ternary patterns.
803
+ */
804
+ readonly fixablePattern: FixableSpreadPattern | null;
805
+ }
806
+ /**
807
+ * Type of object spread pattern detected.
808
+ */
809
+ type ObjectSpreadKind = "object-copy" | "object-merge" | "object-update" | "jsx-spread" | "rest-destructure";
810
+ /**
811
+ * Represents any object spread pattern in the SolidGraph.
812
+ *
813
+ * This captures all uses of object spread operator, including:
814
+ * - Object copying: const copy = { ...original };
815
+ * - Object merging: const merged = { ...a, ...b };
816
+ * - Object updating: const updated = { ...obj, prop: value };
817
+ * - JSX spreads: <div {...props} />
818
+ * - Rest destructuring: const { a, ...rest } = obj;
819
+ */
820
+ interface ObjectSpreadEntity {
821
+ readonly id: number;
822
+ /** The spread node - SpreadElement, JSXSpreadAttribute, or RestElement */
823
+ readonly node: TSESTree.SpreadElement | TSESTree.JSXSpreadAttribute | TSESTree.RestElement;
824
+ /** The kind of spread pattern */
825
+ readonly kind: ObjectSpreadKind;
826
+ /** The parent object expression (null for JSX spreads and rest patterns) */
827
+ readonly parentObject: TSESTree.ObjectExpression | null;
828
+ /** For JSX spreads, the opening element containing the spread attribute */
829
+ readonly parentJSXElement: TSESTree.JSXOpeningElement | null;
830
+ /** The parent pattern for rest destructuring (null otherwise) */
831
+ readonly parentPattern: TSESTree.ObjectPattern | null;
832
+ /** True if inside a JSX element */
833
+ readonly isInJSX: boolean;
834
+ /** Number of spreads in the same object (for merge detection) */
835
+ readonly spreadCount: number;
836
+ /** Number of regular properties in the same object (for update detection) */
837
+ readonly propertyCount: number;
838
+ /**
839
+ * For spreads inside JSX attribute values, which attribute.
840
+ * Enables specialized messages for classList, style, etc.
841
+ * Computed from parent chain during registration.
842
+ */
843
+ readonly attributeContext: SpreadAttributeContext;
844
+ /**
845
+ * Target JSX element tag name if this is a JSX spread.
846
+ * Examples: "div", "button", "MyComponent"
847
+ * Computed from parentJSXElement during registration.
848
+ */
849
+ readonly targetTag: string | null;
850
+ /**
851
+ * Whether target is a native DOM element (lowercase tag).
852
+ * Used to detect forwarding patterns to native elements.
853
+ * Computed from targetTag during registration.
854
+ */
855
+ readonly targetIsDom: boolean;
856
+ /**
857
+ * Name of the spread source for error messages.
858
+ * Examples: "props", "rest", "store", "local.classList", "signal()"
859
+ * Computed from spread argument during registration.
860
+ */
861
+ readonly sourceName: string | null;
862
+ /**
863
+ * Kind of expression being spread.
864
+ * Used for quick filtering without re-analyzing AST.
865
+ * Computed from spread argument type during registration.
866
+ */
867
+ readonly sourceKind: SpreadSourceKind;
868
+ }
869
+
870
+ /**
871
+ * File Entity
872
+ *
873
+ * Represents a parsed TypeScript/TSX file in the graph.
874
+ */
875
+
876
+ /**
877
+ * File entity representing a parsed TypeScript/TSX file.
878
+ *
879
+ * SourceCode properties (ast, scopeManager, etc.) accessed via sourceCode field.
880
+ * sourceCode may be null only for internal sentinel files used in fallback scopes.
881
+ */
882
+ interface FileEntity$1 {
883
+ id: number;
884
+ path: string;
885
+ sourceCode: TSESLint.SourceCode | null;
886
+ functions: FunctionEntity[];
887
+ calls: CallEntity[];
888
+ variables: VariableEntity$1[];
889
+ scopes: ScopeEntity[];
890
+ jsxElements: JSXElementEntity[];
891
+ imports: ImportEntity[];
892
+ conditionalSpreads: ConditionalSpreadEntity[];
893
+ }
894
+
895
+ /**
896
+ * Scope Entity
897
+ *
898
+ * Represents a lexical scope in the program graph.
899
+ */
900
+
901
+ /**
902
+ * Represents a lexical scope in the SolidGraph.
903
+ *
904
+ * Scopes form a tree structure where each scope has at most one parent
905
+ * and can have multiple children. Module scope is the root.
906
+ */
907
+ interface ScopeEntity {
908
+ id: number;
909
+ /** The AST node that creates this scope. May be null for fallback/synthetic scopes. */
910
+ node: TSESTree.Node | null;
911
+ file: FileEntity$1;
912
+ kind: "program" | "function" | "block";
913
+ parent: ScopeEntity | null;
914
+ children: ScopeEntity[];
915
+ variables: VariableEntity$1[];
916
+ functions: FunctionEntity[];
917
+ trackingContext: TrackingContext | null;
918
+ isModuleScope: boolean;
919
+ /** @internal Resolved context (inherited from parent if trackingContext is null) */
920
+ _resolvedContext: TrackingContext | null;
921
+ /** @internal Scope chain [self, parent, grandparent, ...] for ancestor iteration */
922
+ _scopeChain: ScopeEntity[] | null;
923
+ /** @internal Enclosing component scope if inside a component */
924
+ _enclosingComponent: {
925
+ scope: ScopeEntity;
926
+ name: string;
927
+ } | null;
928
+ /** @internal Set of variable names owned by this scope */
929
+ _ownNames: Set<string> | null;
930
+ /** @internal Map from variable name to entity for direct lookup */
931
+ _variablesByName: Map<string, VariableEntity$1> | null;
932
+ /** @internal Cached descendant scopes */
933
+ _descendantScopes?: ScopeEntity[];
934
+ }
935
+ /**
936
+ * Describes the reactivity tracking context for a scope.
937
+ *
938
+ * Models Solid.js's runtime tracking semantics:
939
+ * - tracked: Inside reactive computations (createEffect, createMemo, createRenderEffect)
940
+ * where `Listener` is set and signal reads register dependencies
941
+ * - jsx-expression: Inside JSX expression holes that compile to implicit effects
942
+ * - deferred: Inside callbacks that execute later (event handlers, onMount, onCleanup)
943
+ * - component-body: Inside a component function body — runs ONCE in `untrack()`,
944
+ * signal reads capture one-time snapshots that never update
945
+ * - untracked: Explicitly untracked regions (untrack(), createRoot())
946
+ * - unknown: Context cannot be determined
947
+ */
948
+ interface TrackingContext {
949
+ type: "tracked" | "jsx-expression" | "deferred" | "component-body" | "untracked" | "unknown";
950
+ source?: string;
951
+ reason?: string;
952
+ }
953
+
954
+ /**
955
+ * Export Entity
956
+ *
957
+ * Represents an exported symbol from a file.
958
+ * Tracks the relationship to the underlying entity (function/variable)
959
+ * and provides metadata for cross-file analysis.
960
+ */
961
+
962
+ /**
963
+ * Export kind classification.
964
+ * Matches ganko's ExportKind for compatibility.
965
+ */
966
+ declare enum ExportKind {
967
+ FUNCTION = 0,
968
+ VARIABLE = 1,
969
+ COMPONENT = 2,
970
+ CLASS = 3,
971
+ TYPE = 4,
972
+ SIGNAL = 5,
973
+ STORE = 6,
974
+ MEMO = 7,
975
+ RESOURCE = 8
976
+ }
977
+ /**
978
+ * Represents a single export from a file.
979
+ */
980
+ interface ExportEntity {
981
+ /** Unique ID within the graph */
982
+ readonly id: number;
983
+ /** Export name (or "default" for default export, "*" for namespace re-export) */
984
+ readonly name: string;
985
+ /** Classification of the export */
986
+ readonly kind: ExportKind;
987
+ /**
988
+ * Entity ID of the underlying function or variable.
989
+ * -1 for type-only exports or external re-exports.
990
+ */
991
+ readonly entityId: number;
992
+ /** Whether this is a type-only export */
993
+ readonly isTypeOnly: boolean;
994
+ /** Whether this is the default export */
995
+ readonly isDefault: boolean;
996
+ /** Reactive kind if this exports a reactive value */
997
+ readonly reactiveKind: ReactiveKind | null;
998
+ /**
999
+ * Signature string for change detection.
1000
+ * Used by workspace layer to detect export API changes.
1001
+ * Format: "fn:2" (function with 2 params), "var:signal", etc.
1002
+ */
1003
+ readonly signature: string;
1004
+ /** AST node for go-to-definition */
1005
+ readonly node: TSESTree.Node;
1006
+ /** Location for quick access */
1007
+ readonly loc: TSESTree.SourceLocation | null;
1008
+ /**
1009
+ * Source module for re-exports, null for local exports.
1010
+ * Set for `export { X } from "./mod"` and `export * from "./mod"`.
1011
+ */
1012
+ readonly source: string | null;
1013
+ /**
1014
+ * Original name in source module for re-exports, null for local exports.
1015
+ * For `export { foo as bar } from "./mod"`, this is "foo".
1016
+ */
1017
+ readonly importedName: string | null;
1018
+ }
1019
+
1020
+ /**
1021
+ * Property Entity
1022
+ *
1023
+ * Represents a class property in the program graph.
1024
+ */
1025
+
1026
+ /**
1027
+ * Represents a class property in the SolidGraph.
1028
+ */
1029
+ interface PropertyEntity {
1030
+ id: number;
1031
+ node: TSESTree.PropertyDefinition;
1032
+ class: ClassEntity;
1033
+ name: string | null;
1034
+ accessibility: "public" | "private" | "protected" | undefined;
1035
+ static: boolean;
1036
+ readonly: boolean;
1037
+ /** The declaration node for JSDoc attachment (same as node for properties) */
1038
+ declarationNode: TSESTree.Node;
1039
+ }
1040
+
1041
+ /**
1042
+ * Class Entity
1043
+ *
1044
+ * Represents a class in the program graph.
1045
+ */
1046
+
1047
+ type ClassNode = TSESTree.ClassDeclaration | TSESTree.ClassExpression;
1048
+ /**
1049
+ * Represents a class in the SolidGraph.
1050
+ */
1051
+ interface ClassEntity {
1052
+ id: number;
1053
+ node: ClassNode;
1054
+ file: FileEntity$1;
1055
+ name: string | null;
1056
+ methods: FunctionEntity[];
1057
+ properties: PropertyEntity[];
1058
+ constructor: FunctionEntity | null;
1059
+ abstract: boolean;
1060
+ /** The declaration node for JSDoc attachment (export wrapper or self) */
1061
+ declarationNode: TSESTree.Node;
1062
+ /** @internal Variable entity if this class is assigned to a variable */
1063
+ _variable: VariableEntity$1 | null;
1064
+ }
1065
+
1066
+ /**
1067
+ * Property Assignment Entity
1068
+ *
1069
+ * Represents property assignments (obj.prop = value) in the program graph.
1070
+ * These are distinct from variable assignments and are tracked separately
1071
+ * because they can cause V8 hidden class transitions.
1072
+ */
1073
+
1074
+ /**
1075
+ * Represents a property assignment expression in the SolidGraph.
1076
+ *
1077
+ * Tracks assignments where the left-hand side is a MemberExpression:
1078
+ * - `obj.prop = value`
1079
+ * - `obj[key] = value`
1080
+ */
1081
+ interface PropertyAssignmentEntity {
1082
+ readonly id: number;
1083
+ /** The AssignmentExpression node */
1084
+ readonly node: TSESTree.AssignmentExpression;
1085
+ /** The MemberExpression on the left side */
1086
+ readonly target: TSESTree.MemberExpression;
1087
+ /** The object being assigned to */
1088
+ readonly object: TSESTree.Expression;
1089
+ /** The property name (if computed, this may be an expression) */
1090
+ readonly property: TSESTree.Expression | TSESTree.PrivateIdentifier;
1091
+ /** Whether property is computed (obj[prop] vs obj.prop) */
1092
+ readonly computed: boolean;
1093
+ /** The assigned value expression */
1094
+ readonly value: TSESTree.Expression;
1095
+ /** The assignment operator */
1096
+ readonly operator: TSESTree.AssignmentExpression["operator"];
1097
+ /** Containing scope */
1098
+ readonly scope: ScopeEntity;
1099
+ /** Containing file */
1100
+ readonly file: FileEntity$1;
1101
+ /** Whether inside a loop */
1102
+ readonly isInLoop: boolean;
1103
+ /** Whether inside a conditional */
1104
+ readonly isInConditional: boolean;
1105
+ /** Whether the property exists on the object's declared type (mutation vs addition) */
1106
+ readonly propertyExistsOnType: boolean;
1107
+ /** Whether this is an array index assignment (arr[i] = value) */
1108
+ readonly isArrayIndexAssignment: boolean;
1109
+ /** Whether the property name is dynamic and cannot be statically determined */
1110
+ readonly hasDynamicPropertyName: boolean;
1111
+ }
1112
+
1113
+ /**
1114
+ * Non-Null Assertion Entity
1115
+ *
1116
+ * Represents a TSNonNullExpression (the `!` operator) in the program graph.
1117
+ */
1118
+
1119
+ /**
1120
+ * Represents a non-null assertion expression (`expr!`) in the SolidGraph.
1121
+ */
1122
+ interface NonNullAssertionEntity {
1123
+ readonly id: number;
1124
+ /** The TSNonNullExpression node */
1125
+ readonly node: TSESTree.TSNonNullExpression;
1126
+ /** The expression being asserted as non-null */
1127
+ readonly expression: TSESTree.Expression;
1128
+ }
1129
+
1130
+ /**
1131
+ * Type Assertion Entity
1132
+ *
1133
+ * Represents type assertions in the program graph, including:
1134
+ * - `as` assertions: `x as Type`
1135
+ * - Double assertions: `x as unknown as Type`
1136
+ * - Angle bracket assertions: `<Type>x`
1137
+ * - `as any` casts
1138
+ */
1139
+
1140
+ /**
1141
+ * The kind of type assertion being performed.
1142
+ */
1143
+ type TypeAssertionKind = "simple" | "double" | "cast-to-any" | "cast-to-unknown" | "const-assertion";
1144
+ /**
1145
+ * Represents a type assertion expression in the SolidGraph.
1146
+ *
1147
+ * Covers both `as` expressions and angle bracket syntax.
1148
+ */
1149
+ interface TypeAssertionEntity {
1150
+ readonly id: number;
1151
+ /** The assertion node (TSAsExpression or TSTypeAssertion) */
1152
+ readonly node: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion;
1153
+ /** The expression being cast */
1154
+ readonly expression: TSESTree.Expression;
1155
+ /** The type being cast to */
1156
+ readonly typeAnnotation: TSESTree.TypeNode;
1157
+ /** The kind of assertion */
1158
+ readonly kind: TypeAssertionKind;
1159
+ /** Whether this is inside a loop */
1160
+ readonly inLoop: boolean;
1161
+ /** Whether this assertion is on an import expression (dynamic or static) */
1162
+ readonly onImport: boolean;
1163
+ /** The scope containing this assertion */
1164
+ readonly scope: ScopeEntity;
1165
+ /** For double assertions, reference to the inner assertion if present */
1166
+ readonly innerAssertion: TypeAssertionEntity | null;
1167
+ /**
1168
+ * Whether the cast is unnecessary because the expression type is
1169
+ * already assignable to the target type. Set during wiring phase
1170
+ * when TypeScript type info is available. null if unknown.
1171
+ */
1172
+ isUnnecessary: boolean | null;
1173
+ /**
1174
+ * The actual type of the expression (for error messages).
1175
+ * Set during wiring phase when TypeScript type info is available.
1176
+ */
1177
+ expressionType: string | null;
1178
+ }
1179
+ /**
1180
+ * Represents a type predicate function (function with `is` keyword).
1181
+ */
1182
+ interface TypePredicateEntity {
1183
+ readonly id: number;
1184
+ /** The function node */
1185
+ readonly node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression;
1186
+ /** The parameter name being narrowed */
1187
+ readonly parameterName: string;
1188
+ /** The type being asserted */
1189
+ readonly typeAnnotation: TSESTree.TypeNode;
1190
+ }
1191
+ /**
1192
+ * Represents a generic function with type assertion in its return.
1193
+ *
1194
+ * Detects patterns like:
1195
+ * ```ts
1196
+ * function getData<T>(id: string): T {
1197
+ * return JSON.parse(apiCall(id)) as T;
1198
+ * }
1199
+ * ```
1200
+ */
1201
+ interface UnsafeGenericAssertionEntity {
1202
+ readonly id: number;
1203
+ /** The function node */
1204
+ readonly node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression;
1205
+ /** The generic type parameter being asserted to */
1206
+ readonly typeParameterName: string;
1207
+ /** The type assertion node within the function */
1208
+ readonly assertion: TSESTree.TSAsExpression | TSESTree.TSTypeAssertion;
1209
+ }
1210
+ /**
1211
+ * Where in the program an unsafe type annotation appears.
1212
+ *
1213
+ * - "parameter": function/method parameter type (`function foo(x: any)`)
1214
+ * - "return": function/method return type (`function foo(): unknown`)
1215
+ * - "variable": variable declaration type (`let x: any`)
1216
+ * - "property": class/object property type (`class Foo { x: any }`)
1217
+ * - "generic-constraint": generic type constraint (`<T extends unknown>`)
1218
+ */
1219
+ type UnsafeAnnotationPosition = "parameter" | "return" | "variable" | "property" | "generic-constraint";
1220
+ /**
1221
+ * Whether the annotation is `any` or `unknown`.
1222
+ */
1223
+ type UnsafeAnnotationKind = "any" | "unknown";
1224
+ /**
1225
+ * Represents an unsafe type annotation (`any` or `unknown`) in a value-level position.
1226
+ *
1227
+ * This entity is NOT created for:
1228
+ * - Type alias bodies (`type Foo = unknown`) — type-level, not value-level
1229
+ * - Interface definitions (`interface Foo { [key: string]: unknown }`) — structural types
1230
+ * - Catch clause parameters (`catch (e: unknown)`) — recommended by TypeScript
1231
+ * - Generic constraints on type parameters (`<T extends unknown>`) with `unknown` — vacuously true
1232
+ * - `Record<string, unknown>` pattern — standard generic constraint pattern
1233
+ */
1234
+ interface UnsafeTypeAnnotationEntity {
1235
+ readonly id: number;
1236
+ /** The TSAnyKeyword or TSUnknownKeyword node */
1237
+ readonly node: TSESTree.TSAnyKeyword | TSESTree.TSUnknownKeyword;
1238
+ /** Whether this is `any` or `unknown` */
1239
+ readonly kind: UnsafeAnnotationKind;
1240
+ /** Where the annotation appears */
1241
+ readonly position: UnsafeAnnotationPosition;
1242
+ /**
1243
+ * Name context for error messages.
1244
+ * For parameters: the parameter name.
1245
+ * For returns: the function name.
1246
+ * For variables: the variable name.
1247
+ * For properties: the property name.
1248
+ * For generic constraints: the type parameter name.
1249
+ */
1250
+ readonly name: string | null;
1251
+ /** The containing function name (for parameters/returns), or null */
1252
+ readonly functionName: string | null;
1253
+ }
1254
+
1255
+ /**
1256
+ * Inline Import Entity
1257
+ *
1258
+ * Represents TSImportType nodes (inline type imports) in the program graph.
1259
+ * Example: `import("@typescript-eslint/utils").TSESLint.RuleFixer`
1260
+ */
1261
+
1262
+ /**
1263
+ * Represents an inline type import in the SolidGraph.
1264
+ *
1265
+ * Inline imports use the `import("module").Type` syntax rather than
1266
+ * top-level import declarations. These should typically be refactored
1267
+ * to use proper import statements for better readability.
1268
+ */
1269
+ interface InlineImportEntity {
1270
+ readonly id: number;
1271
+ /** The TSImportType node */
1272
+ readonly node: TSESTree.TSImportType;
1273
+ /** The file containing this inline import */
1274
+ readonly file: FileEntity$1;
1275
+ /** The module specifier being imported (e.g., "@typescript-eslint/utils") */
1276
+ readonly source: string;
1277
+ /** The qualified path after the import (e.g., "TSESLint.RuleFixer") */
1278
+ readonly qualifier: string;
1279
+ }
1280
+
1281
+ /**
1282
+ * Computation Entity
1283
+ *
1284
+ * Unified representation of a reactive computation node in the
1285
+ * dependency graph. Maps to Solid's runtime Computation interface:
1286
+ * createEffect, createMemo, createComputed, createRenderEffect,
1287
+ * createResource, and createRoot.
1288
+ *
1289
+ * A computation has:
1290
+ * - A backing CallEntity (the primitive invocation)
1291
+ * - A callback FunctionEntity (the tracked/deferred body)
1292
+ * - Dependencies: signals/memos/stores it reads (over-approximated statically)
1293
+ * - An owner: the parent computation or root that owns it for disposal
1294
+ */
1295
+
1296
+ /**
1297
+ * Discriminates the scheduling behavior of a computation.
1298
+ *
1299
+ * - `"effect"` — createEffect: pure=false, user=true, deferred to Effects queue
1300
+ * - `"render-effect"` — createRenderEffect: pure=false, user=false, immediate
1301
+ * - `"computed"` — createComputed: pure=true, synchronous
1302
+ * - `"memo"` — createMemo: pure=true, dual node (also a signal source)
1303
+ * - `"resource"` — createResource: async, internally creates signals + computed
1304
+ * - `"root"` — createRoot: ownership boundary, no tracking
1305
+ * - `"reaction"` — createReaction: split tracking (track fn separate from effect fn)
1306
+ */
1307
+ type ComputationKind = "effect" | "render-effect" | "computed" | "memo" | "resource" | "root" | "reaction";
1308
+ /**
1309
+ * Represents a reactive computation in the SolidGraph.
1310
+ */
1311
+ interface ComputationEntity {
1312
+ readonly id: number;
1313
+ readonly kind: ComputationKind;
1314
+ /** The primitive call that created this computation. */
1315
+ readonly call: CallEntity;
1316
+ /** The callback function body (tracked or deferred). Null for createRoot with no-arg fn. */
1317
+ readonly callback: FunctionEntity | null;
1318
+ /** The scope this computation's callback runs in. */
1319
+ readonly scope: ScopeEntity;
1320
+ /** Variable this computation is assigned to (e.g. the memo accessor, resource tuple). */
1321
+ readonly variable: VariableEntity$1 | null;
1322
+ /** Whether this computation is a signal source (readable by other computations). */
1323
+ readonly isSource: boolean;
1324
+ /** Whether this computation runs in a tracked context (Listener is set). */
1325
+ readonly isTracked: boolean;
1326
+ }
1327
+ /**
1328
+ * A dependency edge: computation reads a reactive source.
1329
+ *
1330
+ * Static over-approximation — any signal-like variable syntactically
1331
+ * reachable from the computation's callback body is included,
1332
+ * regardless of runtime control flow.
1333
+ */
1334
+ interface DependencyEdge {
1335
+ /** The computation that reads the source. */
1336
+ readonly consumer: ComputationEntity;
1337
+ /** The reactive variable being read. */
1338
+ readonly source: VariableEntity$1;
1339
+ /** Whether the read is a proper accessor call (e.g. `count()` vs bare `count`). */
1340
+ readonly isProperAccess: boolean;
1341
+ /** Whether the read is inside an untrack() call within the computation. */
1342
+ readonly isUntracked: boolean;
1343
+ /**
1344
+ * For store/props sources: the property access path (e.g. `["foo", "bar"]`
1345
+ * for `store.foo.bar`). Null for signal/memo reads or when the access
1346
+ * is dynamic and cannot be statically determined.
1347
+ */
1348
+ readonly propertyPath: readonly string[] | null;
1349
+ }
1350
+ /**
1351
+ * An ownership edge: parent computation owns a child computation.
1352
+ *
1353
+ * Models Solid's runtime Owner tree — when a parent is disposed,
1354
+ * all children are recursively disposed. This is structural
1355
+ * (lexical nesting at creation time), not behavioral.
1356
+ */
1357
+ interface OwnershipEdge {
1358
+ /** The parent owner (computation or root). */
1359
+ readonly owner: ComputationEntity;
1360
+ /** The child computation owned by the parent. */
1361
+ readonly child: ComputationEntity;
1362
+ }
1363
+
1364
+ /**
1365
+ * SolidGraph Implementation
1366
+ */
1367
+
1368
+ /** @internal */
1369
+ interface JSXAttributeWithElement {
1370
+ readonly attr: JSXAttributeEntity;
1371
+ readonly element: JSXElementEntity;
1372
+ }
1373
+ interface JSXStaticClassIndex {
1374
+ readonly hasDynamicClass: boolean;
1375
+ readonly tokens: readonly string[];
1376
+ }
1377
+ interface JSXStaticObjectKeyIndex {
1378
+ readonly hasDynamic: boolean;
1379
+ readonly keys: readonly string[];
1380
+ }
1381
+ interface JSXObjectPropertyWithElement {
1382
+ readonly property: TSESTree.ObjectLiteralElementLike;
1383
+ readonly attr: JSXAttributeEntity;
1384
+ readonly element: JSXElementEntity;
1385
+ }
1386
+ /**
1387
+ * The Solid.js program graph implementation.
1388
+ *
1389
+ * Contains all entities extracted from a Solid.js source file:
1390
+ * scopes, variables, functions, calls, JSX elements, imports, exports, etc.
1391
+ *
1392
+ */
1393
+ declare class SolidGraph {
1394
+ readonly kind: "solid";
1395
+ readonly file: string;
1396
+ readonly logger: Logger;
1397
+ readonly sourceCode: TSESLint.SourceCode;
1398
+ readonly typeResolver: TypeResolver;
1399
+ readonly fileEntity: FileEntity$1;
1400
+ private _nextScopeId;
1401
+ private _nextVariableId;
1402
+ private _nextFunctionId;
1403
+ private _nextCallId;
1404
+ private _nextJsxId;
1405
+ private _nextImportId;
1406
+ private _nextExportId;
1407
+ private _nextClassId;
1408
+ private _nextPropertyId;
1409
+ private _nextConditionalSpreadId;
1410
+ private _nextMiscId;
1411
+ readonly scopes: ScopeEntity[];
1412
+ readonly variables: VariableEntity$1[];
1413
+ readonly functions: FunctionEntity[];
1414
+ readonly calls: CallEntity[];
1415
+ readonly jsxElements: JSXElementEntity[];
1416
+ readonly imports: ImportEntity[];
1417
+ readonly exports: ExportEntity[];
1418
+ readonly classes: ClassEntity[];
1419
+ readonly properties: PropertyEntity[];
1420
+ readonly propertyAssignments: PropertyAssignmentEntity[];
1421
+ readonly conditionalSpreads: ConditionalSpreadEntity[];
1422
+ readonly objectSpreads: ObjectSpreadEntity[];
1423
+ readonly nonNullAssertions: NonNullAssertionEntity[];
1424
+ readonly typeAssertions: TypeAssertionEntity[];
1425
+ readonly typePredicates: TypePredicateEntity[];
1426
+ readonly unsafeGenericAssertions: UnsafeGenericAssertionEntity[];
1427
+ readonly unsafeTypeAnnotations: UnsafeTypeAnnotationEntity[];
1428
+ readonly inlineImports: InlineImportEntity[];
1429
+ readonly eslintScopeMap: Map<TSESLint.Scope.Scope, ScopeEntity>;
1430
+ readonly variablesByName: Map<string, VariableEntity$1[]>;
1431
+ readonly functionsByNode: Map<TSESTree.Node, FunctionEntity>;
1432
+ readonly functionsByDeclarationNode: Map<TSESTree.Node, FunctionEntity>;
1433
+ readonly functionsByName: Map<string, FunctionEntity[]>;
1434
+ readonly callsByNode: Map<TSESTree.CallExpression | TSESTree.NewExpression, CallEntity>;
1435
+ readonly callsByPrimitive: Map<string, CallEntity[]>;
1436
+ readonly callsByMethodName: Map<string, CallEntity[]>;
1437
+ readonly callsByArgNode: Map<TSESTree.Node, ArgumentEntity>;
1438
+ readonly jsxByNode: Map<TSESTree.JSXElement | TSESTree.JSXFragment, JSXElementEntity>;
1439
+ readonly jsxByTag: Map<string, JSXElementEntity[]>;
1440
+ readonly jsxAttributesByElementId: Map<number, ReadonlyMap<string, JSXAttributeEntity>>;
1441
+ readonly jsxAttrsByKind: Map<JSXAttributeKind, JSXAttributeWithElement[]>;
1442
+ readonly jsxClassAttributes: JSXAttributeWithElement[];
1443
+ readonly jsxClassListAttributes: JSXAttributeWithElement[];
1444
+ readonly jsxStyleAttributes: JSXAttributeWithElement[];
1445
+ readonly fillImageElements: JSXElementEntity[];
1446
+ readonly staticClassTokensByElementId: Map<number, JSXStaticClassIndex>;
1447
+ readonly staticClassListKeysByElementId: Map<number, JSXStaticObjectKeyIndex>;
1448
+ readonly staticStyleKeysByElementId: Map<number, JSXStaticObjectKeyIndex>;
1449
+ readonly classListProperties: JSXObjectPropertyWithElement[];
1450
+ readonly styleProperties: JSXObjectPropertyWithElement[];
1451
+ /** CSS class names defined in inline `<style>` elements within JSX (e.g., SVG icons with embedded CSS). */
1452
+ readonly inlineStyleClassNames: Set<string>;
1453
+ readonly importsBySource: Map<string, ImportEntity[]>;
1454
+ readonly exportsByName: Map<string, ExportEntity>;
1455
+ readonly exportsByEntityId: Map<number, ExportEntity>;
1456
+ readonly classesByNode: Map<TSESTree.ClassDeclaration | TSESTree.ClassExpression, ClassEntity>;
1457
+ readonly classesByName: Map<string, ClassEntity[]>;
1458
+ readonly unaryExpressionsByOperator: Map<string, TSESTree.UnaryExpression[]>;
1459
+ readonly spreadElements: TSESTree.SpreadElement[];
1460
+ readonly newExpressionsByCallee: Map<string, TSESTree.NewExpression[]>;
1461
+ readonly identifiersByName: Map<string, TSESTree.Identifier[]>;
1462
+ readonly positionIndex: PositionIndex;
1463
+ firstScope: ScopeEntity | null;
1464
+ readonly componentScopes: Map<ScopeEntity, {
1465
+ scope: ScopeEntity;
1466
+ name: string;
1467
+ }>;
1468
+ componentFunctions: FunctionEntity[];
1469
+ functionsWithReactiveCaptures: FunctionEntity[];
1470
+ reactiveVariables: VariableEntity$1[];
1471
+ propsVariables: VariableEntity$1[];
1472
+ storeVariables: VariableEntity$1[];
1473
+ resourceVariables: VariableEntity$1[];
1474
+ variablesWithPropertyAssignment: VariableEntity$1[];
1475
+ /** Reactive computation nodes (effects, memos, computed, roots, resources). */
1476
+ computations: ComputationEntity[];
1477
+ /** Computation lookup by CallEntity ID. */
1478
+ readonly computationByCallId: Map<number, ComputationEntity>;
1479
+ /** Dependency edges: computation reads reactive source. */
1480
+ dependencyEdges: DependencyEdge[];
1481
+ /** Ownership edges: parent owns child computation. */
1482
+ ownershipEdges: OwnershipEdge[];
1483
+ readonly jsxContextCache: WeakMap<TSESTree.Node, JSXContext | null>;
1484
+ readonly scopeForCache: WeakMap<TSESTree.Node, ScopeEntity>;
1485
+ readonly onDepsCache: WeakMap<TSESTree.Node, boolean>;
1486
+ readonly passthroughCache: WeakMap<TSESTree.Node, boolean>;
1487
+ /**
1488
+ * Creates a new SolidGraph instance.
1489
+ *
1490
+ * @param input - The graph input containing source code and parser services
1491
+ */
1492
+ constructor(input: SolidInput);
1493
+ /** @internal Generate next scope ID */
1494
+ nextScopeId(): number;
1495
+ /** @internal Generate next variable ID */
1496
+ nextVariableId(): number;
1497
+ /** @internal Generate next function ID */
1498
+ nextFunctionId(): number;
1499
+ /** @internal Generate next call ID */
1500
+ nextCallId(): number;
1501
+ /** @internal Generate next JSX element ID */
1502
+ nextJsxId(): number;
1503
+ /** @internal Generate next import ID */
1504
+ nextImportId(): number;
1505
+ /** @internal Generate next export ID */
1506
+ nextExportId(): number;
1507
+ /** @internal Generate next class ID */
1508
+ nextClassId(): number;
1509
+ /** @internal Generate next property ID */
1510
+ nextPropertyId(): number;
1511
+ /** @internal Generate next conditional spread ID */
1512
+ nextConditionalSpreadId(): number;
1513
+ /** @internal Generate next misc entity ID */
1514
+ nextMiscId(): number;
1515
+ /**
1516
+ * @internal Add a scope entity to the graph. Called by scopesPhase.
1517
+ */
1518
+ addScope(scope: ScopeEntity, eslintScope: TSESLint.Scope.Scope): void;
1519
+ /**
1520
+ * @internal Add a variable entity to the graph. Called by scopesPhase.
1521
+ */
1522
+ addVariable(variable: VariableEntity$1): void;
1523
+ /**
1524
+ * @internal Add a function entity to the graph. Called by entitiesPhase.
1525
+ */
1526
+ addFunction(fn: FunctionEntity): void;
1527
+ /**
1528
+ * @internal Add a call entity to the graph. Called by entitiesPhase.
1529
+ */
1530
+ addCall(call: CallEntity): void;
1531
+ /**
1532
+ * @internal Add a JSX element entity to the graph. Called by entitiesPhase.
1533
+ */
1534
+ addJSXElement(element: JSXElementEntity): void;
1535
+ /**
1536
+ * Extract CSS class names from inline `<style>` JSX elements.
1537
+ *
1538
+ * Handles patterns like `<style>{`.foo { ... }`}</style>` found in SVG icons.
1539
+ * Scans template literal and literal string children for `.className` patterns.
1540
+ */
1541
+ private extractInlineStyleClassNames;
1542
+ private indexObjectAttribute;
1543
+ /**
1544
+ * @internal Add an import entity to the graph. Called by entitiesPhase.
1545
+ */
1546
+ addImport(imp: ImportEntity): void;
1547
+ /**
1548
+ * @internal Add an export entity to the graph. Called by exportsPhase.
1549
+ */
1550
+ addExport(exp: ExportEntity): void;
1551
+ /** @internal Add a class entity to the graph. Called by entitiesPhase. */
1552
+ addClass(cls: ClassEntity): void;
1553
+ /** @internal Add a property entity to the graph. */
1554
+ addProperty(prop: PropertyEntity): void;
1555
+ /** @internal Add a property assignment entity to the graph. */
1556
+ addPropertyAssignment(pa: PropertyAssignmentEntity): void;
1557
+ /** @internal Add a conditional spread entity to the graph. */
1558
+ addConditionalSpread(spread: ConditionalSpreadEntity): void;
1559
+ /** @internal Add an object spread entity to the graph. */
1560
+ addObjectSpread(spread: ObjectSpreadEntity): void;
1561
+ /** @internal Add a non-null assertion entity to the graph. */
1562
+ addNonNullAssertion(assertion: NonNullAssertionEntity): void;
1563
+ /** @internal Add a type assertion entity to the graph. */
1564
+ addTypeAssertion(assertion: TypeAssertionEntity): void;
1565
+ /** @internal Add a type predicate entity to the graph. */
1566
+ addTypePredicate(predicate: TypePredicateEntity): void;
1567
+ /** @internal Add an unsafe generic assertion entity to the graph. */
1568
+ addUnsafeGenericAssertion(assertion: UnsafeGenericAssertionEntity): void;
1569
+ /** @internal Add an unsafe type annotation entity to the graph. */
1570
+ addUnsafeTypeAnnotation(annotation: UnsafeTypeAnnotationEntity): void;
1571
+ /** @internal Add an inline import entity to the graph. */
1572
+ addInlineImport(imp: InlineImportEntity): void;
1573
+ /** @internal Add a computation entity to the graph. Called by dependenciesPhase. */
1574
+ addComputation(computation: ComputationEntity): void;
1575
+ /** @internal Add a dependency edge to the graph. Called by dependenciesPhase. */
1576
+ addDependencyEdge(edge: DependencyEdge): void;
1577
+ /** @internal Add an ownership edge to the graph. Called by dependenciesPhase. */
1578
+ addOwnershipEdge(edge: OwnershipEdge): void;
1579
+ /**
1580
+ * @internal Build reactive variable indexes. Called by reactivityPhase.
1581
+ */
1582
+ buildReactiveIndex(): void;
1583
+ /** @internal */
1584
+ addUnaryExpression(node: TSESTree.UnaryExpression): void;
1585
+ /** @internal */
1586
+ addSpreadElement(node: TSESTree.SpreadElement): void;
1587
+ /** @internal */
1588
+ addNewExpressionByCallee(name: string, node: TSESTree.NewExpression): void;
1589
+ /** @internal */
1590
+ addIdentifierReference(node: TSESTree.Identifier): void;
1591
+ /** @internal Index node for O(1) position lookup. Children overwrite parents. */
1592
+ addToPositionIndex(node: TSESTree.Node): void;
1593
+ }
1594
+ /**
1595
+ * O(1) position lookup index.
1596
+ * - nodeAtOffset[i] = smallest node containing character offset i
1597
+ * - lineStartOffsets[i] = character offset where line (i+1) starts
1598
+ */
1599
+ interface PositionIndex {
1600
+ readonly nodeAtOffset: Array<TSESTree.Node | null>;
1601
+ readonly lineStartOffsets: readonly number[];
1602
+ }
1603
+
1604
+ /**
1605
+ * Validates whether a CSS class name is a known Tailwind utility.
1606
+ *
1607
+ * Implementations are provided by callers depending on their execution
1608
+ * context (async vs sync). The CSSGraph stores this as an optional field
1609
+ * and the undefined-css-class rule falls back to it when `classNameIndex`
1610
+ * misses.
1611
+ */
1612
+ interface TailwindValidator {
1613
+ has(className: string): boolean;
1614
+ /**
1615
+ * Resolves a Tailwind utility class to its generated CSS string.
1616
+ *
1617
+ * Returns the full CSS rule text (e.g. `.flex { display: flex; }`) or null
1618
+ * if the class is not a valid Tailwind utility or resolution is not supported
1619
+ * (e.g. in the sync/static validator path).
1620
+ */
1621
+ resolve(className: string): string | null;
1622
+ }
1623
+ /**
1624
+ * Resolves a TailwindValidator from CSS files by detecting Tailwind v4
1625
+ * and loading the design system via `@tailwindcss/node`.
1626
+ *
1627
+ * Handles projects where `@tailwindcss/node` is a transitive dependency
1628
+ * (e.g. installed via `@tailwindcss/vite`) by resolving through carrier
1629
+ * packages when direct import fails.
1630
+ *
1631
+ * Returns null if:
1632
+ * - No Tailwind entry file is detected
1633
+ * - `@tailwindcss/node` is not installed (directly or transitively)
1634
+ * - The design system fails to load
1635
+ */
1636
+ declare function resolveTailwindValidator(files: readonly {
1637
+ path: string;
1638
+ content: string;
1639
+ }[]): Promise<TailwindValidator | null>;
1640
+
1641
+ /**
1642
+ * CSSInput - Input type for building CSSGraph from CSS/SCSS source files.
1643
+ *
1644
+ * This defines the contract for what data is needed to build a CSS
1645
+ * program graph. Unlike SolidInput which handles single files via ESLint,
1646
+ * CSSInput supports multi-file graphs with explicit file content.
1647
+ */
1648
+
1649
+ /**
1650
+ * A single CSS/SCSS file to be processed.
1651
+ */
1652
+ interface CSSFile {
1653
+ /** File path (used for error reporting and import resolution) */
1654
+ readonly path: string;
1655
+ /** Raw file content */
1656
+ readonly content: string;
1657
+ }
1658
+ /**
1659
+ * Input for building a CSSGraph from CSS/SCSS source files.
1660
+ */
1661
+ interface CSSInput {
1662
+ /** Files to process */
1663
+ readonly files: readonly CSSFile[];
1664
+ /** Optional build options */
1665
+ readonly options?: CSSOptions;
1666
+ /** Pre-resolved Tailwind validator for utility class validation */
1667
+ readonly tailwind?: TailwindValidator;
1668
+ /** Logger for diagnostic output from CSS rules */
1669
+ readonly logger?: Logger;
1670
+ /**
1671
+ * CSS custom property names provided by external libraries at runtime.
1672
+ *
1673
+ * These are discovered by scanning dependency packages for CSS custom property
1674
+ * definitions injected via JavaScript (e.g., inline style attributes in JSX).
1675
+ * Properties in this set are registered in the CSS graph as globally-scoped
1676
+ * definitions so the resolution engine treats them as defined.
1677
+ *
1678
+ * Use `scanDependencyCustomProperties()` from `./library-analysis` to populate this.
1679
+ */
1680
+ readonly externalCustomProperties?: ReadonlySet<string>;
1681
+ }
1682
+ /**
1683
+ * Options for CSS graph building.
1684
+ */
1685
+ interface CSSOptions {
1686
+ /** Enable SCSS parsing (default: auto-detect from extension) */
1687
+ readonly scss?: boolean;
1688
+ /** Enable theme token inference (default: true) */
1689
+ readonly inferTokens?: boolean;
1690
+ /** Enable cascade analysis (default: true) */
1691
+ readonly analyzeCascade?: boolean;
1692
+ /** Enable dead code detection (default: false) */
1693
+ readonly detectDeadCode?: boolean;
1694
+ /** Custom token naming patterns */
1695
+ readonly tokenPatterns?: TokenPatternConfig;
1696
+ /** Maximum parse errors before stopping (default: unlimited) */
1697
+ readonly maxParseErrors?: number;
1698
+ /** Error reporting mode (default: "collect") */
1699
+ readonly errorReporting?: "silent" | "collect" | "throw";
1700
+ }
1701
+ /**
1702
+ * Configuration for token naming pattern detection.
1703
+ */
1704
+ interface TokenPatternConfig {
1705
+ readonly color?: readonly RegExp[];
1706
+ readonly spacing?: readonly RegExp[];
1707
+ readonly typography?: readonly RegExp[];
1708
+ readonly custom?: readonly {
1709
+ category: string;
1710
+ patterns: readonly RegExp[];
1711
+ }[];
1712
+ }
1713
+
1714
+ /**
1715
+ * CSS Specificity Types
1716
+ */
1717
+ /**
1718
+ * CSS specificity tuple [inline, id, class, element].
1719
+ * Inline is always 0 in stylesheets (only 1 for inline styles).
1720
+ */
1721
+ type Specificity = readonly [number, number, number, number];
1722
+
1723
+ /**
1724
+ * CSS Value Parsing Utilities
1725
+ *
1726
+ * Functions for parsing and analyzing CSS values using postcss-value-parser.
1727
+ */
1728
+ /**
1729
+ * Parsed CSS value with component breakdown.
1730
+ */
1731
+ interface ParsedValue {
1732
+ nodes: ParsedValueNode[];
1733
+ hasCalc: boolean;
1734
+ hasVar: boolean;
1735
+ hasUrl: boolean;
1736
+ hasFunction: boolean;
1737
+ colors: string[];
1738
+ units: string[];
1739
+ }
1740
+ /**
1741
+ * A node in a parsed CSS value.
1742
+ */
1743
+ interface ParsedValueNode {
1744
+ type: "word" | "string" | "function" | "space" | "div" | "comment";
1745
+ value: string;
1746
+ sourceIndex: number;
1747
+ }
1748
+ /**
1749
+ * A var() reference extracted from a CSS value.
1750
+ */
1751
+ interface VarReference {
1752
+ name: string;
1753
+ fallback: string | null;
1754
+ sourceIndex: number;
1755
+ raw: string;
1756
+ }
1757
+ /**
1758
+ * Information about a function call in a CSS value.
1759
+ */
1760
+ interface FunctionCallInfo {
1761
+ name: string;
1762
+ arguments: string[];
1763
+ raw: string;
1764
+ sourceIndex: number;
1765
+ }
1766
+
1767
+ /**
1768
+ * CSS Theme Token Types
1769
+ */
1770
+
1771
+ /**
1772
+ * Token category for design system organization.
1773
+ */
1774
+ type TokenCategory = "color" | "spacing" | "typography" | "border" | "shadow" | "radius" | "z-index" | "animation" | "breakpoint" | "other";
1775
+ /**
1776
+ * Theme token variant (e.g., "500", "light", "hover").
1777
+ */
1778
+ interface ThemeTokenVariant {
1779
+ name: string;
1780
+ variable: VariableEntity;
1781
+ value: string;
1782
+ }
1783
+ /**
1784
+ * Represents a theme/design system token.
1785
+ */
1786
+ interface ThemeTokenEntity {
1787
+ id: number;
1788
+ name: string;
1789
+ category: TokenCategory;
1790
+ file: FileEntity;
1791
+ variables: VariableEntity[];
1792
+ variants: ThemeTokenVariant[];
1793
+ isComplete: boolean;
1794
+ missingVariants: string[];
1795
+ namingPattern: string;
1796
+ }
1797
+
1798
+ /**
1799
+ * CSS Value Types
1800
+ */
1801
+
1802
+ /**
1803
+ * Position in the CSS cascade.
1804
+ */
1805
+ interface CascadePosition {
1806
+ layer: string | null;
1807
+ layerOrder: number;
1808
+ sourceOrder: number;
1809
+ specificity: Specificity;
1810
+ specificityScore: number;
1811
+ isImportant: boolean;
1812
+ }
1813
+
1814
+ /**
1815
+ * CSS Variable Types
1816
+ */
1817
+
1818
+ /**
1819
+ * Variable scope information.
1820
+ */
1821
+ interface VariableScope {
1822
+ type: "global" | "selector" | "media" | "supports" | "layer";
1823
+ condition: string | null;
1824
+ specificity: Specificity | null;
1825
+ }
1826
+ /**
1827
+ * Represents a CSS custom property definition (--name: value).
1828
+ */
1829
+ interface VariableEntity {
1830
+ id: number;
1831
+ name: string;
1832
+ declaration: DeclarationEntity;
1833
+ file: FileEntity;
1834
+ scope: VariableScope;
1835
+ scopeSelector: SelectorEntity | null;
1836
+ _flags: number;
1837
+ value: string;
1838
+ parsedValue: ParsedValue;
1839
+ computedValue: string | null;
1840
+ references: VariableReferenceEntity[];
1841
+ shadows: VariableEntity[];
1842
+ shadowedBy: VariableEntity[];
1843
+ themeToken: ThemeTokenEntity | null;
1844
+ scssName: string | null;
1845
+ }
1846
+ /**
1847
+ * Represents a var(--name) usage.
1848
+ */
1849
+ interface VariableReferenceEntity {
1850
+ id: number;
1851
+ name: string;
1852
+ declaration: DeclarationEntity;
1853
+ file: FileEntity;
1854
+ resolvedVariable: VariableEntity | null;
1855
+ _flags: number;
1856
+ fallback: string | null;
1857
+ fallbackReferences: VariableReferenceEntity[];
1858
+ fallbackChainDepth: number;
1859
+ sourceIndex: number;
1860
+ raw: string;
1861
+ }
1862
+
1863
+ /**
1864
+ * CSS Declaration Entity
1865
+ */
1866
+
1867
+ /**
1868
+ * Represents a CSS declaration (property: value).
1869
+ */
1870
+ interface DeclarationEntity {
1871
+ id: number;
1872
+ node: Declaration;
1873
+ rule: RuleEntity | null;
1874
+ file: FileEntity;
1875
+ property: string;
1876
+ value: string;
1877
+ rawValue: string;
1878
+ _flags: number;
1879
+ parsedValue: ParsedValue;
1880
+ variableRefs: VariableReferenceEntity[];
1881
+ functionCalls: FunctionCallInfo[];
1882
+ parsedVarRefs: VarReference[];
1883
+ startLine: number;
1884
+ startColumn: number;
1885
+ startOffset: number;
1886
+ endOffset: number;
1887
+ sourceOrder: number;
1888
+ cascadePosition: CascadePosition;
1889
+ overrides: DeclarationEntity[];
1890
+ overriddenBy: DeclarationEntity[];
1891
+ }
1892
+
1893
+ /**
1894
+ * CSS At-Rule Types
1895
+ */
1896
+
1897
+ /**
1898
+ * Discriminator for common at-rule types.
1899
+ */
1900
+ type AtRuleKind = "media" | "keyframes" | "font-face" | "supports" | "import" | "layer" | "container" | "page" | "charset" | "namespace" | "mixin" | "function" | "include" | "extend" | "use" | "forward" | "other";
1901
+ /**
1902
+ * Media condition for @media rules.
1903
+ */
1904
+ interface MediaCondition {
1905
+ type: "all" | "screen" | "print" | "speech";
1906
+ features: MediaFeature[];
1907
+ isNot: boolean;
1908
+ }
1909
+ /**
1910
+ * Media feature within a media condition.
1911
+ */
1912
+ interface MediaFeature {
1913
+ name: string;
1914
+ value: string | null;
1915
+ operator: "min" | "max" | "exact" | null;
1916
+ }
1917
+ /**
1918
+ * Parsed at-rule parameters.
1919
+ */
1920
+ interface ParsedAtRuleParams {
1921
+ raw: string;
1922
+ mediaConditions?: MediaCondition[];
1923
+ animationName?: string;
1924
+ fontFamily?: string;
1925
+ layerName?: string;
1926
+ layerNames?: string[];
1927
+ containerName?: string;
1928
+ containerCondition?: string;
1929
+ }
1930
+ /**
1931
+ * Represents a CSS at-rule (@media, @keyframes, etc.).
1932
+ */
1933
+ interface AtRuleEntity {
1934
+ id: number;
1935
+ node: AtRule;
1936
+ file: FileEntity;
1937
+ name: string;
1938
+ kind: AtRuleKind;
1939
+ params: string;
1940
+ parsedParams: ParsedAtRuleParams;
1941
+ rules: RuleEntity[];
1942
+ declarations: DeclarationEntity[];
1943
+ nestedAtRules: AtRuleEntity[];
1944
+ parent: RuleEntity | AtRuleEntity | null;
1945
+ depth: number;
1946
+ startLine: number;
1947
+ endLine: number;
1948
+ sourceOrder: number;
1949
+ }
1950
+
1951
+ /**
1952
+ * CSS File Entity
1953
+ */
1954
+
1955
+ /**
1956
+ * Import information for @import/@use directives.
1957
+ */
1958
+ interface ImportInfo {
1959
+ path: string;
1960
+ node: AtRule;
1961
+ isPartial: boolean;
1962
+ resolvedFile: FileEntity | null;
1963
+ mediaQuery: string | null;
1964
+ layer: string | null;
1965
+ }
1966
+ /**
1967
+ * Represents a CSS/SCSS source file.
1968
+ */
1969
+ interface FileEntity {
1970
+ id: number;
1971
+ path: string;
1972
+ content: string;
1973
+ syntax: "css" | "scss" | "sass" | "less";
1974
+ node: Root;
1975
+ lineCount: number;
1976
+ lineStartOffsets: readonly number[];
1977
+ _flags: number;
1978
+ imports: ImportInfo[];
1979
+ importedBy: FileEntity[];
1980
+ rules: RuleEntity[];
1981
+ atRules: AtRuleEntity[];
1982
+ variables: VariableEntity[];
1983
+ }
1984
+
1985
+ /**
1986
+ * CSS Rule Entity
1987
+ */
1988
+
1989
+ /**
1990
+ * Represents a CSS rule (selector block with declarations).
1991
+ */
1992
+ interface RuleEntity {
1993
+ kind: "rule";
1994
+ id: number;
1995
+ node: Rule;
1996
+ file: FileEntity;
1997
+ selectorText: string;
1998
+ selectors: SelectorEntity[];
1999
+ declarations: DeclarationEntity[];
2000
+ nestedRules: RuleEntity[];
2001
+ nestedAtRules: AtRuleEntity[];
2002
+ parent: RuleEntity | AtRuleEntity | null;
2003
+ depth: number;
2004
+ startLine: number;
2005
+ startColumn: number;
2006
+ endLine: number;
2007
+ endColumn: number;
2008
+ startOffset: number;
2009
+ endOffset: number;
2010
+ blockStartOffset: number;
2011
+ blockEndOffset: number;
2012
+ sourceOrder: number;
2013
+ containingMedia: AtRuleEntity | null;
2014
+ containingLayer: AtRuleEntity | null;
2015
+ containingMediaStack: AtRuleEntity[];
2016
+ declarationIndex: Map<string, DeclarationEntity[]>;
2017
+ /** Pre-computed semantic element kinds derived from selector parts. */
2018
+ elementKinds: Set<RuleElementKind>;
2019
+ }
2020
+ /**
2021
+ * Semantic element classification for rules, derived from selector parts.
2022
+ * Used by policy rules to determine applicable thresholds.
2023
+ */
2024
+ type RuleElementKind = "heading" | "button" | "input" | "caption" | "paragraph" | "inline-formatting" | "pseudo-element";
2025
+
2026
+ /**
2027
+ * CSS Selector Types
2028
+ */
2029
+
2030
+ /**
2031
+ * Combinator types between selector parts.
2032
+ */
2033
+ type CombinatorType = "descendant" | "child" | "adjacent" | "sibling";
2034
+ /**
2035
+ * A part of a compound selector.
2036
+ */
2037
+ interface SelectorPart {
2038
+ readonly type: "element" | "id" | "class" | "attribute" | "pseudo-class" | "pseudo-element" | "universal" | "nesting";
2039
+ readonly value: string;
2040
+ readonly raw: string;
2041
+ }
2042
+ interface SelectorAttributeConstraint {
2043
+ name: string;
2044
+ operator: "exists" | "equals" | "includes-word" | "dash-prefix" | "prefix" | "suffix" | "contains";
2045
+ value: string | null;
2046
+ caseInsensitive: boolean;
2047
+ }
2048
+ interface SelectorAnchor {
2049
+ subjectTag: string | null;
2050
+ classes: readonly string[];
2051
+ attributes: readonly SelectorAttributeConstraint[];
2052
+ includesDescendantCombinator: boolean;
2053
+ includesPseudoSelector: boolean;
2054
+ dynamic: boolean;
2055
+ targetsCheckbox: boolean;
2056
+ targetsTableCell: boolean;
2057
+ }
2058
+ /**
2059
+ * Selector complexity metrics for analysis.
2060
+ */
2061
+ interface SelectorComplexity {
2062
+ depth: number;
2063
+ breadth: number;
2064
+ _flags: number;
2065
+ pseudoClasses: string[];
2066
+ pseudoElements: string[];
2067
+ combinators: CombinatorType[];
2068
+ }
2069
+ /**
2070
+ * Represents an individual selector within a rule.
2071
+ */
2072
+ interface SelectorEntity {
2073
+ id: number;
2074
+ raw: string;
2075
+ rule: RuleEntity;
2076
+ specificity: Specificity;
2077
+ specificityScore: number;
2078
+ complexity: SelectorComplexity;
2079
+ parts: SelectorPart[];
2080
+ anchor: SelectorAnchor;
2081
+ overrides: SelectorEntity[];
2082
+ overriddenBy: SelectorEntity[];
2083
+ }
2084
+
2085
+ /**
2086
+ * SCSS-Specific Types
2087
+ */
2088
+
2089
+ /**
2090
+ * Mixin parameter definition.
2091
+ */
2092
+ interface MixinParameter {
2093
+ name: string;
2094
+ defaultValue: string | null;
2095
+ isRest: boolean;
2096
+ }
2097
+ /**
2098
+ * Mixin argument in @include.
2099
+ */
2100
+ interface MixinArgument {
2101
+ name: string | null;
2102
+ value: string;
2103
+ isNamed: boolean;
2104
+ }
2105
+ /**
2106
+ * Function parameter definition.
2107
+ */
2108
+ interface FunctionParameter {
2109
+ name: string;
2110
+ defaultValue: string | null;
2111
+ }
2112
+ /**
2113
+ * @return statement in SCSS function.
2114
+ */
2115
+ interface ReturnStatement {
2116
+ node: AtRule;
2117
+ value: string;
2118
+ }
2119
+ /**
2120
+ * Represents an SCSS mixin definition.
2121
+ */
2122
+ interface MixinEntity {
2123
+ id: number;
2124
+ name: string;
2125
+ node: AtRule;
2126
+ file: FileEntity;
2127
+ parameters: MixinParameter[];
2128
+ _flags: number;
2129
+ declarations: DeclarationEntity[];
2130
+ rules: RuleEntity[];
2131
+ includes: MixinIncludeEntity[];
2132
+ startLine: number;
2133
+ endLine: number;
2134
+ }
2135
+ /**
2136
+ * Represents an SCSS @include directive.
2137
+ */
2138
+ interface MixinIncludeEntity {
2139
+ id: number;
2140
+ name: string;
2141
+ node: AtRule;
2142
+ file: FileEntity;
2143
+ arguments: MixinArgument[];
2144
+ _flags: number;
2145
+ resolvedMixin: MixinEntity | null;
2146
+ rule: RuleEntity | null;
2147
+ atRule: AtRuleEntity | null;
2148
+ }
2149
+ /**
2150
+ * Represents an SCSS function definition.
2151
+ */
2152
+ interface SCSSFunctionEntity {
2153
+ id: number;
2154
+ name: string;
2155
+ node: AtRule;
2156
+ file: FileEntity;
2157
+ parameters: FunctionParameter[];
2158
+ returnStatements: ReturnStatement[];
2159
+ calls: FunctionCallEntity[];
2160
+ _flags: number;
2161
+ startLine: number;
2162
+ endLine: number;
2163
+ }
2164
+ /**
2165
+ * Represents an SCSS function call within a value.
2166
+ */
2167
+ interface FunctionCallEntity {
2168
+ id: number;
2169
+ name: string;
2170
+ declaration: DeclarationEntity;
2171
+ file: FileEntity;
2172
+ arguments: string[];
2173
+ resolvedFunction: SCSSFunctionEntity | null;
2174
+ _flags: number;
2175
+ sourceIndex: number;
2176
+ }
2177
+ /**
2178
+ * Represents an SCSS placeholder selector (%placeholder).
2179
+ */
2180
+ interface PlaceholderEntity {
2181
+ id: number;
2182
+ name: string;
2183
+ node: Rule;
2184
+ file: FileEntity;
2185
+ declarations: DeclarationEntity[];
2186
+ extends: ExtendEntity[];
2187
+ _flags: number;
2188
+ startLine: number;
2189
+ endLine: number;
2190
+ }
2191
+ /**
2192
+ * Represents an SCSS @extend directive.
2193
+ */
2194
+ interface ExtendEntity {
2195
+ id: number;
2196
+ selector: string;
2197
+ node: AtRule;
2198
+ file: FileEntity;
2199
+ rule: RuleEntity;
2200
+ resolvedPlaceholder: PlaceholderEntity | null;
2201
+ resolvedRule: RuleEntity | null;
2202
+ _flags: number;
2203
+ }
2204
+
2205
+ /**
2206
+ * CSS Parse Error
2207
+ */
2208
+ /**
2209
+ * CSS parse error with location information.
2210
+ */
2211
+ interface CSSParseError {
2212
+ readonly message: string;
2213
+ readonly line: number;
2214
+ readonly column: number;
2215
+ readonly endLine: number | null;
2216
+ readonly endColumn: number | null;
2217
+ readonly file: string;
2218
+ readonly severity: "error" | "warn";
2219
+ readonly source: string | null;
2220
+ readonly isRecoverable: boolean;
2221
+ }
2222
+
2223
+ /**
2224
+ * CSSGraphImpl - CSS Program Graph Implementation
2225
+ *
2226
+ */
2227
+
2228
+ /**
2229
+ * A declaration referencing a keyframe name that has no matching @keyframes.
2230
+ */
2231
+ interface UnresolvedAnimationRef {
2232
+ readonly declaration: DeclarationEntity;
2233
+ readonly name: string;
2234
+ }
2235
+ interface KeyframeLayoutMutation {
2236
+ readonly property: string;
2237
+ readonly values: readonly string[];
2238
+ readonly declarations: readonly DeclarationEntity[];
2239
+ }
2240
+ interface FontFaceDescriptor {
2241
+ readonly fontFace: AtRuleEntity;
2242
+ readonly family: string;
2243
+ readonly displayDeclaration: DeclarationEntity | null;
2244
+ readonly srcDeclaration: DeclarationEntity | null;
2245
+ readonly display: string | null;
2246
+ readonly src: string | null;
2247
+ readonly hasWebFontSource: boolean;
2248
+ readonly hasEffectiveMetricOverrides: boolean;
2249
+ }
2250
+ declare class CSSGraph {
2251
+ readonly kind: "css";
2252
+ readonly options: CSSOptions;
2253
+ readonly interner: StringInterner;
2254
+ readonly logger: Logger;
2255
+ sourceOrder: number;
2256
+ hasScssFiles: boolean;
2257
+ readonly files: FileEntity[];
2258
+ readonly rules: RuleEntity[];
2259
+ readonly selectors: SelectorEntity[];
2260
+ readonly declarations: DeclarationEntity[];
2261
+ readonly variables: VariableEntity[];
2262
+ readonly variableRefs: VariableReferenceEntity[];
2263
+ readonly atRules: AtRuleEntity[];
2264
+ readonly tokens: ThemeTokenEntity[];
2265
+ readonly mixins: MixinEntity[];
2266
+ readonly includes: MixinIncludeEntity[];
2267
+ readonly functions: SCSSFunctionEntity[];
2268
+ readonly functionCalls: FunctionCallEntity[];
2269
+ readonly placeholders: PlaceholderEntity[];
2270
+ readonly extends: ExtendEntity[];
2271
+ readonly filesByPath: Map<string, FileEntity>;
2272
+ readonly variablesByName: Map<string, VariableEntity[]>;
2273
+ readonly rulesBySelector: Map<string, RuleEntity[]>;
2274
+ /** @internal Dedup index keyed by file+parent+selector+media+layer for duplicate detection. */
2275
+ readonly _selectorDedupIndex: Map<string, RuleEntity[]>;
2276
+ readonly mixinsByName: Map<string, MixinEntity>;
2277
+ readonly functionsByName: Map<string, SCSSFunctionEntity>;
2278
+ readonly placeholdersByName: Map<string, PlaceholderEntity>;
2279
+ readonly layerOrder: Map<string, number>;
2280
+ readonly declarationsByProperty: Map<string, DeclarationEntity[]>;
2281
+ readonly atRulesByName: Map<string, AtRuleEntity[]>;
2282
+ readonly atRulesByKind: Map<AtRuleKind, AtRuleEntity[]>;
2283
+ readonly atRulesByNode: Map<AtRule, AtRuleEntity>;
2284
+ readonly rulesByNode: Map<Rule, RuleEntity>;
2285
+ readonly duplicateSelectors: Map<string, {
2286
+ selector: string;
2287
+ rules: RuleEntity[];
2288
+ }>;
2289
+ readonly tokensByCategory: Map<TokenCategory, ThemeTokenEntity[]>;
2290
+ readonly importantDeclarations: DeclarationEntity[];
2291
+ readonly globalVariables: VariableEntity[];
2292
+ readonly unusedVariables: VariableEntity[];
2293
+ readonly scssVariables: VariableEntity[];
2294
+ readonly cssCustomProperties: VariableEntity[];
2295
+ readonly unresolvedRefs: VariableReferenceEntity[];
2296
+ readonly mediaQueries: AtRuleEntity[];
2297
+ readonly keyframes: AtRuleEntity[];
2298
+ readonly layers: AtRuleEntity[];
2299
+ readonly fontFaces: AtRuleEntity[];
2300
+ readonly supportsRules: AtRuleEntity[];
2301
+ readonly unusedKeyframes: AtRuleEntity[];
2302
+ readonly unusedMixins: MixinEntity[];
2303
+ readonly unresolvedMixinIncludes: MixinIncludeEntity[];
2304
+ readonly unusedFunctions: SCSSFunctionEntity[];
2305
+ readonly unusedPlaceholders: PlaceholderEntity[];
2306
+ readonly unresolvedExtends: ExtendEntity[];
2307
+ readonly parseErrors: CSSParseError[];
2308
+ readonly failedFilePaths: string[];
2309
+ readonly tokenCategories: TokenCategory[];
2310
+ readonly filesWithLayers: Set<string>;
2311
+ readonly selectorsByPseudoClass: Map<string, SelectorEntity[]>;
2312
+ readonly knownKeyframeNames: Set<string>;
2313
+ readonly unresolvedAnimationRefs: UnresolvedAnimationRef[];
2314
+ readonly declaredContainerNames: Map<string, DeclarationEntity[]>;
2315
+ readonly containerQueryNames: Map<string, AtRuleEntity[]>;
2316
+ readonly unusedContainerNames: Map<string, DeclarationEntity[]>;
2317
+ readonly unknownContainerQueries: AtRuleEntity[];
2318
+ /** Properties with 2+ declarations, each value pre-sorted by sourceOrder. */
2319
+ readonly multiDeclarationProperties: Map<string, readonly DeclarationEntity[]>;
2320
+ /** Declarations whose parent rule is inside a @keyframes block. */
2321
+ readonly keyframeDeclarations: DeclarationEntity[];
2322
+ /** Rules with zero declarations and zero nested rules. */
2323
+ readonly emptyRules: RuleEntity[];
2324
+ /** @keyframes at-rules with no effective keyframe declarations. */
2325
+ readonly emptyKeyframes: AtRuleEntity[];
2326
+ readonly colorDeclarations: DeclarationEntity[];
2327
+ readonly calcDeclarations: DeclarationEntity[];
2328
+ readonly varDeclarations: DeclarationEntity[];
2329
+ readonly urlDeclarations: DeclarationEntity[];
2330
+ readonly vendorPrefixedDeclarations: DeclarationEntity[];
2331
+ readonly hardcodedColorDeclarations: DeclarationEntity[];
2332
+ readonly overqualifiedSelectors: SelectorEntity[];
2333
+ readonly idSelectors: SelectorEntity[];
2334
+ readonly attributeSelectors: SelectorEntity[];
2335
+ readonly universalSelectors: SelectorEntity[];
2336
+ readonly classNameIndex: Map<string, SelectorEntity[]>;
2337
+ readonly selectorsBySubjectTag: Map<string, SelectorEntity[]>;
2338
+ readonly selectorsWithoutSubjectTag: SelectorEntity[];
2339
+ readonly selectorsTargetingCheckbox: SelectorEntity[];
2340
+ readonly selectorsTargetingTableCell: SelectorEntity[];
2341
+ readonly layoutPropertiesByClassToken: Map<string, readonly string[]>;
2342
+ readonly keyframeLayoutMutationsByName: Map<string, readonly KeyframeLayoutMutation[]>;
2343
+ readonly fontFaceDescriptorsByFamily: Map<string, readonly FontFaceDescriptor[]>;
2344
+ readonly usedFontFamiliesByRule: Map<number, readonly string[]>;
2345
+ readonly usedFontFamilies: Set<string>;
2346
+ /** Tailwind validator for utility class lookup (null if not a Tailwind project). */
2347
+ readonly tailwind: TailwindValidator | null;
2348
+ readonly deepNestedRules: RuleEntity[];
2349
+ constructor(input: CSSInput);
2350
+ intern(s: string): string;
2351
+ nextFileId(): number;
2352
+ nextRuleId(): number;
2353
+ nextSelectorId(): number;
2354
+ nextDeclarationId(): number;
2355
+ nextVariableId(): number;
2356
+ nextVariableRefId(): number;
2357
+ nextAtRuleId(): number;
2358
+ nextTokenId(): number;
2359
+ nextMixinId(): number;
2360
+ nextIncludeId(): number;
2361
+ nextFunctionId(): number;
2362
+ nextFunctionCallId(): number;
2363
+ nextPlaceholderId(): number;
2364
+ nextExtendId(): number;
2365
+ nextSourceOrder(): number;
2366
+ addFile(file: FileEntity): void;
2367
+ addRule(rule: RuleEntity): void;
2368
+ addSelector(selector: SelectorEntity): void;
2369
+ addDeclaration(decl: DeclarationEntity): void;
2370
+ addVariable(variable: VariableEntity): void;
2371
+ addVariableRef(ref: VariableReferenceEntity): void;
2372
+ addAtRule(atRule: AtRuleEntity): void;
2373
+ addToken(token: ThemeTokenEntity): void;
2374
+ addMixin(mixin: MixinEntity): void;
2375
+ addMixinInclude(include: MixinIncludeEntity): void;
2376
+ addFunction(fn: SCSSFunctionEntity): void;
2377
+ addFunctionCall(call: FunctionCallEntity): void;
2378
+ addPlaceholder(placeholder: PlaceholderEntity): void;
2379
+ addExtend(ext: ExtendEntity): void;
2380
+ addParseError(error: CSSParseError): void;
2381
+ addFailedFile(path: string): void;
2382
+ registerRuleBySelector(selector: string, rule: RuleEntity): void;
2383
+ registerLayerOrder(name: string, order: number): void;
2384
+ /**
2385
+ * Retrieve declarations matching any of the given property names.
2386
+ * Uses the pre-built declarationsByProperty index for O(k) lookups.
2387
+ */
2388
+ declarationsForProperties(...properties: string[]): readonly DeclarationEntity[];
2389
+ /**
2390
+ * Build derived indexes that require all entities to be populated.
2391
+ * Called after all phases complete.
2392
+ */
2393
+ buildDerivedIndexes(): void;
2394
+ private buildRuleDeclarationIndexes;
2395
+ private buildContainingMediaStacks;
2396
+ private buildKeyframeIndex;
2397
+ private buildContainerNameIndexes;
2398
+ private buildElementKinds;
2399
+ private buildFilesWithLayers;
2400
+ private buildSelectorPseudoClassIndex;
2401
+ /**
2402
+ * Sort each declarationsByProperty list by sourceOrder and populate
2403
+ * multiDeclarationProperties with only those having 2+ entries.
2404
+ */
2405
+ private buildMultiDeclarationProperties;
2406
+ /**
2407
+ * Collect declarations whose parent rule is inside a @keyframes block.
2408
+ */
2409
+ private buildKeyframeDeclarations;
2410
+ private buildKeyframeLayoutMutationsByName;
2411
+ /**
2412
+ * Collect rules with no declarations and no nested rules.
2413
+ */
2414
+ private buildEmptyRules;
2415
+ /**
2416
+ * Collect @keyframes with no effective keyframe declarations.
2417
+ */
2418
+ private buildEmptyKeyframes;
2419
+ private buildDeclarationDerivedIndexes;
2420
+ private buildSelectorDerivedIndexes;
2421
+ private buildLayoutPropertiesByClassToken;
2422
+ private buildFontFamilyUsageByRule;
2423
+ private buildFontFaceDescriptorsByFamily;
2424
+ private buildRuleDerivedIndexes;
2425
+ buildUnusedIndexes(): void;
2426
+ }
2427
+
2428
+ interface LayoutPerfStatsMutable {
2429
+ elementsScanned: number;
2430
+ selectorCandidatesChecked: number;
2431
+ compiledSelectorCount: number;
2432
+ selectorsRejectedUnsupported: number;
2433
+ selectorsGuardedConditional: number;
2434
+ ancestryChecks: number;
2435
+ matchEdgesCreated: number;
2436
+ casesScored: number;
2437
+ casesCollected: number;
2438
+ casesRejectedLowEvidence: number;
2439
+ casesRejectedThreshold: number;
2440
+ casesRejectedUndecidable: number;
2441
+ casesRejectedIdentifiability: number;
2442
+ undecidableInterval: number;
2443
+ conditionalSignals: number;
2444
+ totalSignals: number;
2445
+ cohortUnimodalFalse: number;
2446
+ factorCoverageSum: number;
2447
+ factorCoverageCount: number;
2448
+ posteriorWidths: number[];
2449
+ uncertaintyEscalations: number;
2450
+ signalSnapshotsBuilt: number;
2451
+ signalSnapshotCacheHits: number;
2452
+ measurementIndexHits: number;
2453
+ contextsClassified: number;
2454
+ diagnosticsEmitted: number;
2455
+ selectorIndexMs: number;
2456
+ selectorMatchMs: number;
2457
+ cascadeBuildMs: number;
2458
+ caseBuildMs: number;
2459
+ scoringMs: number;
2460
+ elapsedMs: number;
2461
+ }
2462
+
2463
+ type LayoutAxisModel = "horizontal-tb" | "vertical-rl" | "vertical-lr";
2464
+ type InlineDirectionModel = "ltr" | "rtl";
2465
+ type AlignmentContextKind = "inline-formatting" | "table-cell" | "flex-cross-axis" | "grid-cross-axis" | "block-flow" | "positioned-offset";
2466
+ type LayoutContextContainerKind = "table" | "flex" | "grid" | "inline" | "block";
2467
+ type ContextCertainty = "resolved" | "conditional" | "unknown";
2468
+ interface LayoutContextEvidence {
2469
+ readonly containerKind: LayoutContextContainerKind;
2470
+ readonly containerKindCertainty: ContextCertainty;
2471
+ readonly hasTableSemantics: boolean;
2472
+ readonly hasPositionedOffset: boolean;
2473
+ readonly positionedOffsetCertainty: ContextCertainty;
2474
+ }
2475
+ interface AlignmentContext {
2476
+ readonly kind: AlignmentContextKind;
2477
+ readonly certainty: ContextCertainty;
2478
+ readonly parentSolidFile: string;
2479
+ readonly parentElementId: number;
2480
+ readonly parentElementKey: string;
2481
+ readonly parentTag: string | null;
2482
+ readonly axis: LayoutAxisModel;
2483
+ readonly axisCertainty: ContextCertainty;
2484
+ readonly inlineDirection: InlineDirectionModel;
2485
+ readonly inlineDirectionCertainty: ContextCertainty;
2486
+ readonly parentDisplay: string | null;
2487
+ readonly parentAlignItems: string | null;
2488
+ readonly parentPlaceItems: string | null;
2489
+ readonly hasPositionedOffset: boolean;
2490
+ readonly evidence: LayoutContextEvidence;
2491
+ }
2492
+
2493
+ type LayoutGuardConditionKind = "media" | "supports" | "container";
2494
+ interface LayoutGuardConditionProvenance {
2495
+ readonly kind: LayoutGuardConditionKind;
2496
+ readonly query: string | null;
2497
+ readonly key: string;
2498
+ }
2499
+
2500
+ declare const layoutSignalNames: readonly ["line-height", "font-size", "width", "inline-size", "height", "block-size", "min-width", "min-block-size", "min-height", "aspect-ratio", "vertical-align", "display", "white-space", "object-fit", "overflow", "overflow-y", "overflow-anchor", "scrollbar-gutter", "scrollbar-width", "contain-intrinsic-size", "content-visibility", "align-items", "align-self", "justify-items", "place-items", "place-self", "appearance", "box-sizing", "padding-top", "padding-left", "padding-right", "padding-bottom", "border-top-width", "border-left-width", "border-right-width", "border-bottom-width", "position", "top", "bottom", "margin-top", "margin-bottom", "transform", "translate", "inset-block-start", "inset-block-end", "writing-mode", "direction"];
2501
+ type LayoutSignalName = (typeof layoutSignalNames)[number];
2502
+ type LayoutSignalSource = "selector" | "inline-style";
2503
+ type LayoutSignalGuard = "unconditional" | "conditional";
2504
+ interface LayoutGuardProvenance {
2505
+ readonly kind: LayoutSignalGuard;
2506
+ readonly conditions: readonly LayoutGuardConditionProvenance[];
2507
+ readonly key: string;
2508
+ }
2509
+ type LayoutSignalUnit = "px" | "unitless" | "keyword" | "unknown";
2510
+ interface LayoutKnownSignalValue {
2511
+ readonly kind: "known";
2512
+ readonly name: LayoutSignalName;
2513
+ readonly raw: string;
2514
+ readonly normalized: string;
2515
+ readonly source: LayoutSignalSource;
2516
+ readonly guard: LayoutSignalGuard;
2517
+ readonly guardProvenance: LayoutGuardProvenance;
2518
+ readonly unit: LayoutSignalUnit;
2519
+ readonly px: number | null;
2520
+ readonly quality: "exact" | "estimated";
2521
+ }
2522
+ interface LayoutUnknownSignalValue {
2523
+ readonly kind: "unknown";
2524
+ readonly name: LayoutSignalName;
2525
+ readonly raw: string | null;
2526
+ readonly source: LayoutSignalSource | null;
2527
+ readonly guard: LayoutSignalGuard;
2528
+ readonly guardProvenance: LayoutGuardProvenance;
2529
+ readonly reason: string;
2530
+ }
2531
+ type LayoutSignalValue = LayoutKnownSignalValue | LayoutUnknownSignalValue;
2532
+ type LayoutTextualContentState = "yes" | "no" | "unknown" | "dynamic-text";
2533
+ interface LayoutSignalSnapshot {
2534
+ readonly solidFile: string;
2535
+ readonly elementId: number;
2536
+ readonly elementKey: string;
2537
+ readonly tag: string | null;
2538
+ readonly textualContent: LayoutTextualContentState;
2539
+ readonly isControl: boolean;
2540
+ readonly isReplaced: boolean;
2541
+ readonly signals: ReadonlyMap<LayoutSignalName, LayoutSignalValue>;
2542
+ readonly knownSignalCount: number;
2543
+ readonly unknownSignalCount: number;
2544
+ readonly conditionalSignalCount: number;
2545
+ }
2546
+ interface AlignmentElementEvidence {
2547
+ readonly solidFile: string;
2548
+ readonly elementKey: string;
2549
+ readonly elementId: number;
2550
+ readonly tag: string | null;
2551
+ readonly snapshot: LayoutSignalSnapshot;
2552
+ }
2553
+ type AlignmentTextContrast = "different" | "same" | "unknown";
2554
+ type SignalConflictValue = "conflict" | "aligned" | "unknown";
2555
+ interface SignalConflictEvidence {
2556
+ readonly value: SignalConflictValue;
2557
+ readonly kind: EvidenceValueKind;
2558
+ }
2559
+ interface AlignmentCohortSignals {
2560
+ readonly verticalAlign: SignalConflictEvidence;
2561
+ readonly alignSelf: SignalConflictEvidence;
2562
+ readonly placeSelf: SignalConflictEvidence;
2563
+ readonly hasControlOrReplacedPeer: boolean;
2564
+ readonly textContrastWithPeers: AlignmentTextContrast;
2565
+ }
2566
+ type CohortSubjectMembership = "dominant" | "nondominant" | "ambiguous" | "insufficient";
2567
+ interface CohortIdentifiability {
2568
+ readonly dominantShare: number;
2569
+ readonly subjectExcludedDominantShare: number;
2570
+ readonly subjectMembership: CohortSubjectMembership;
2571
+ readonly ambiguous: boolean;
2572
+ readonly kind: EvidenceValueKind;
2573
+ }
2574
+ interface AlignmentCohortProfile {
2575
+ readonly medianDeclaredOffsetPx: number | null;
2576
+ readonly declaredOffsetDispersionPx: number | null;
2577
+ readonly medianEffectiveOffsetPx: number | null;
2578
+ readonly effectiveOffsetDispersionPx: number | null;
2579
+ readonly medianLineHeightPx: number | null;
2580
+ readonly lineHeightDispersionPx: number | null;
2581
+ readonly dominantClusterSize: number;
2582
+ readonly dominantClusterShare: number;
2583
+ readonly unimodal: boolean;
2584
+ }
2585
+ interface AlignmentCohortFactSummary {
2586
+ readonly exact: number;
2587
+ readonly interval: number;
2588
+ readonly unknown: number;
2589
+ readonly conditional: number;
2590
+ readonly total: number;
2591
+ readonly exactShare: number;
2592
+ readonly intervalShare: number;
2593
+ readonly unknownShare: number;
2594
+ readonly conditionalShare: number;
2595
+ }
2596
+ interface HotEvidenceWitness<T> extends EvidenceWitness<T> {
2597
+ readonly present: boolean;
2598
+ }
2599
+ type HotNumericSignalEvidence = HotEvidenceWitness<number>;
2600
+ type HotNormalizedSignalEvidence = HotEvidenceWitness<string>;
2601
+ interface LayoutSnapshotHotSignals {
2602
+ readonly lineHeight: HotNumericSignalEvidence;
2603
+ readonly verticalAlign: HotNormalizedSignalEvidence;
2604
+ readonly alignSelf: HotNormalizedSignalEvidence;
2605
+ readonly placeSelf: HotNormalizedSignalEvidence;
2606
+ readonly writingMode: HotNormalizedSignalEvidence;
2607
+ readonly direction: HotNormalizedSignalEvidence;
2608
+ readonly display: HotNormalizedSignalEvidence;
2609
+ readonly alignItems: HotNormalizedSignalEvidence;
2610
+ readonly placeItems: HotNormalizedSignalEvidence;
2611
+ readonly position: HotNormalizedSignalEvidence;
2612
+ readonly insetBlockStart: HotNumericSignalEvidence;
2613
+ readonly insetBlockEnd: HotNumericSignalEvidence;
2614
+ readonly transform: HotNumericSignalEvidence;
2615
+ readonly translate: HotNumericSignalEvidence;
2616
+ readonly top: HotNumericSignalEvidence;
2617
+ readonly bottom: HotNumericSignalEvidence;
2618
+ readonly marginTop: HotNumericSignalEvidence;
2619
+ readonly marginBottom: HotNumericSignalEvidence;
2620
+ }
2621
+ interface LayoutCohortSubjectStats {
2622
+ readonly element: AlignmentElementEvidence;
2623
+ readonly declaredOffset: NumericEvidenceValue;
2624
+ readonly effectiveOffset: NumericEvidenceValue;
2625
+ readonly lineHeight: NumericEvidenceValue;
2626
+ readonly baselineProfile: AlignmentCohortProfile;
2627
+ readonly signals: AlignmentCohortSignals;
2628
+ readonly identifiability: CohortIdentifiability;
2629
+ readonly contentComposition: ContentCompositionFingerprint;
2630
+ }
2631
+ interface LayoutCohortStats {
2632
+ readonly profile: AlignmentCohortProfile;
2633
+ readonly snapshots: readonly LayoutSignalSnapshot[];
2634
+ readonly factSummary: AlignmentCohortFactSummary;
2635
+ readonly provenance: EvidenceProvenance;
2636
+ readonly conditionalSignalCount: number;
2637
+ readonly totalSignalCount: number;
2638
+ readonly subjectsByElementKey: ReadonlyMap<string, LayoutCohortSubjectStats>;
2639
+ /** Element keys excluded from cohort analysis (e.g. visually-hidden accessible elements). */
2640
+ readonly excludedElementKeys: ReadonlySet<string>;
2641
+ }
2642
+ type ContentCompositionClassification = "text-only" | "replaced-only" | "mixed-unmitigated" | "mixed-mitigated" | "block-segmented" | "unknown";
2643
+ /**
2644
+ * Distinguishes intrinsically-replaced elements (img, svg, video, canvas) from
2645
+ * inline-block/inline-flex containers. Their baseline rules differ: an img uses
2646
+ * its bottom edge as the baseline, while an inline-block uses its last line of text.
2647
+ */
2648
+ type InlineReplacedKind = "intrinsic" | "container";
2649
+ interface ContentCompositionFingerprint {
2650
+ readonly hasTextContent: boolean;
2651
+ readonly hasInlineReplaced: boolean;
2652
+ readonly inlineReplacedKind: InlineReplacedKind | null;
2653
+ readonly hasHeightContributingDescendant: boolean;
2654
+ readonly wrappingContextMitigates: boolean;
2655
+ readonly hasVerticalAlignMitigation: boolean;
2656
+ readonly mixedContentDepth: number;
2657
+ readonly classification: ContentCompositionClassification;
2658
+ readonly analyzableChildCount: number;
2659
+ readonly totalChildCount: number;
2660
+ readonly hasOnlyBlockChildren: boolean;
2661
+ }
2662
+ type EvidenceValueKind = "exact" | "interval" | "conditional" | "unknown";
2663
+ interface EvidenceWitness<T> {
2664
+ readonly value: T | null;
2665
+ readonly kind: EvidenceValueKind;
2666
+ }
2667
+ type NumericEvidenceValue = EvidenceWitness<number>;
2668
+ interface EvidenceProvenance {
2669
+ readonly reason: string;
2670
+ readonly guardKey: string;
2671
+ readonly guards: readonly LayoutGuardConditionProvenance[];
2672
+ }
2673
+
2674
+ interface LayoutCascadedDeclaration {
2675
+ readonly value: string;
2676
+ readonly source: "selector" | "inline-style";
2677
+ readonly guard: LayoutSignalGuard;
2678
+ readonly guardProvenance: LayoutGuardProvenance;
2679
+ }
2680
+ interface LayoutElementNode {
2681
+ readonly key: string;
2682
+ readonly solidFile: string;
2683
+ readonly elementId: number;
2684
+ readonly tag: string | null;
2685
+ readonly tagName: string | null;
2686
+ readonly classTokens: readonly string[];
2687
+ readonly classTokenSet: ReadonlySet<string>;
2688
+ readonly inlineStyleKeys: readonly string[];
2689
+ readonly parentElementId: number | null;
2690
+ readonly parentElementKey: string | null;
2691
+ readonly parentElementNode: LayoutElementNode | null;
2692
+ readonly previousSiblingNode: LayoutElementNode | null;
2693
+ readonly siblingIndex: number;
2694
+ readonly siblingCount: number;
2695
+ readonly siblingTypeIndex: number;
2696
+ readonly siblingTypeCount: number;
2697
+ readonly selectorDispatchKeys: readonly string[];
2698
+ readonly attributes: ReadonlyMap<string, string | null>;
2699
+ readonly inlineStyleValues: ReadonlyMap<string, string>;
2700
+ readonly textualContent: "yes" | "no" | "unknown" | "dynamic-text";
2701
+ readonly isControl: boolean;
2702
+ readonly isReplaced: boolean;
2703
+ }
2704
+ interface LayoutStyleRuleNode {
2705
+ readonly cssFile: string;
2706
+ readonly ruleId: number;
2707
+ readonly selectorId: number;
2708
+ }
2709
+ interface LayoutMatchEdge {
2710
+ readonly solidFile: string;
2711
+ readonly elementId: number;
2712
+ readonly elementKey: string;
2713
+ readonly selectorId: number;
2714
+ readonly specificityScore: number;
2715
+ readonly sourceOrder: number;
2716
+ }
2717
+ interface LayoutElementRef {
2718
+ readonly solid: SolidGraph;
2719
+ readonly element: JSXElementEntity;
2720
+ }
2721
+ type LayoutReservedSpaceReason = "height" | "block-size" | "min-height" | "min-block-size" | "contain-intrinsic-size" | "aspect-ratio+width" | "aspect-ratio+inline-size" | "aspect-ratio+min-width" | "aspect-ratio+min-block-size" | "aspect-ratio+min-height";
2722
+ interface LayoutReservedSpaceFact {
2723
+ readonly hasReservedSpace: boolean;
2724
+ readonly reasons: readonly LayoutReservedSpaceReason[];
2725
+ readonly hasUsableInlineDimension: boolean;
2726
+ readonly hasUsableBlockDimension: boolean;
2727
+ readonly hasContainIntrinsicSize: boolean;
2728
+ readonly hasUsableAspectRatio: boolean;
2729
+ }
2730
+ type LayoutScrollAxis = "x" | "y" | "both" | "none";
2731
+ interface LayoutScrollContainerFact {
2732
+ readonly isScrollContainer: boolean;
2733
+ readonly axis: LayoutScrollAxis;
2734
+ readonly overflow: string | null;
2735
+ readonly overflowY: string | null;
2736
+ readonly hasConditionalScroll: boolean;
2737
+ readonly hasUnconditionalScroll: boolean;
2738
+ }
2739
+ interface LayoutFlowParticipationFact {
2740
+ readonly inFlow: boolean;
2741
+ readonly position: string | null;
2742
+ readonly hasConditionalOutOfFlow: boolean;
2743
+ readonly hasUnconditionalOutOfFlow: boolean;
2744
+ }
2745
+ interface LayoutContainingBlockFact {
2746
+ readonly nearestPositionedAncestorKey: string | null;
2747
+ readonly nearestPositionedAncestorHasReservedSpace: boolean;
2748
+ }
2749
+ interface LayoutConditionalSignalDeltaFact {
2750
+ readonly hasConditional: boolean;
2751
+ readonly hasDelta: boolean;
2752
+ readonly conditionalValues: readonly string[];
2753
+ readonly unconditionalValues: readonly string[];
2754
+ readonly hasConditionalScrollValue: boolean;
2755
+ readonly hasConditionalNonScrollValue: boolean;
2756
+ readonly hasUnconditionalScrollValue: boolean;
2757
+ readonly hasUnconditionalNonScrollValue: boolean;
2758
+ }
2759
+ interface LayoutStatefulSelectorEntry {
2760
+ readonly raw: string;
2761
+ readonly isStateful: boolean;
2762
+ /** Pseudo-classes from STATE_PSEUDO_SET that caused this selector to be classified as stateful. */
2763
+ readonly statePseudoClasses: readonly string[];
2764
+ /**
2765
+ * True when ALL state pseudo-classes are "direct" interaction (hover, focus, active, etc.),
2766
+ * meaning state changes only from the user physically interacting with the element itself.
2767
+ * False when any pseudo-class is "indirect" (checked, target) — state can change externally.
2768
+ */
2769
+ readonly isDirectInteraction: boolean;
2770
+ readonly baseLookupKeys: readonly string[];
2771
+ }
2772
+ interface LayoutNormalizedRuleDeclaration {
2773
+ readonly declarationId: number;
2774
+ readonly property: string;
2775
+ readonly normalizedValue: string;
2776
+ readonly filePath: string;
2777
+ readonly startLine: number;
2778
+ readonly startColumn: number;
2779
+ readonly propertyLength: number;
2780
+ }
2781
+ interface LayoutGraphTopology {
2782
+ readonly elements: readonly LayoutElementNode[];
2783
+ readonly childrenByParentNode: ReadonlyMap<LayoutElementNode, readonly LayoutElementNode[]>;
2784
+ readonly elementBySolidFileAndId: ReadonlyMap<string, ReadonlyMap<number, LayoutElementNode>>;
2785
+ readonly elementRefsBySolidFileAndId: ReadonlyMap<string, ReadonlyMap<number, LayoutElementRef>>;
2786
+ readonly elementsByTagName: ReadonlyMap<string, readonly LayoutElementNode[]>;
2787
+ readonly measurementNodeByRootKey: ReadonlyMap<string, LayoutElementNode>;
2788
+ }
2789
+ interface LayoutGraphCascade {
2790
+ readonly styleRules: readonly LayoutStyleRuleNode[];
2791
+ readonly applies: readonly LayoutMatchEdge[];
2792
+ readonly cssScopeBySolidFile: ReadonlyMap<string, readonly string[]>;
2793
+ readonly appliesByElementKey: ReadonlyMap<string, readonly LayoutMatchEdge[]>;
2794
+ readonly selectorCandidatesByElementKey: ReadonlyMap<string, readonly number[]>;
2795
+ readonly selectorsById: ReadonlyMap<number, SelectorEntity>;
2796
+ readonly cascadeByElementNode: WeakMap<LayoutElementNode, ReadonlyMap<string, LayoutCascadedDeclaration>>;
2797
+ readonly snapshotByElementNode: WeakMap<LayoutElementNode, LayoutSignalSnapshot>;
2798
+ readonly snapshotHotSignalsByElementKey: ReadonlyMap<string, LayoutSnapshotHotSignals>;
2799
+ }
2800
+ interface LayoutGraphFacts {
2801
+ readonly reservedSpaceFactsByElementKey: ReadonlyMap<string, LayoutReservedSpaceFact>;
2802
+ readonly scrollContainerFactsByElementKey: ReadonlyMap<string, LayoutScrollContainerFact>;
2803
+ readonly flowParticipationFactsByElementKey: ReadonlyMap<string, LayoutFlowParticipationFact>;
2804
+ readonly containingBlockFactsByElementKey: ReadonlyMap<string, LayoutContainingBlockFact>;
2805
+ readonly conditionalSignalDeltaFactsByElementKey: ReadonlyMap<string, ReadonlyMap<LayoutSignalName, LayoutConditionalSignalDeltaFact>>;
2806
+ readonly baselineOffsetFactsByElementKey: ReadonlyMap<string, ReadonlyMap<LayoutSignalName, readonly number[]>>;
2807
+ }
2808
+ interface LayoutGraphCohorts {
2809
+ readonly cohortStatsByParentNode: ReadonlyMap<LayoutElementNode, LayoutCohortStats>;
2810
+ readonly contextByParentNode: ReadonlyMap<LayoutElementNode, AlignmentContext>;
2811
+ }
2812
+ interface LayoutGraphIndexes {
2813
+ readonly elementsWithConditionalDeltaBySignal: ReadonlyMap<LayoutSignalName, readonly LayoutElementNode[]>;
2814
+ readonly elementsWithConditionalOverflowDelta: readonly LayoutElementNode[];
2815
+ readonly elementsWithConditionalOffsetDelta: readonly LayoutElementNode[];
2816
+ readonly elementsByKnownSignalValue: ReadonlyMap<LayoutSignalName, ReadonlyMap<string, readonly LayoutElementNode[]>>;
2817
+ readonly dynamicSlotCandidateElements: readonly LayoutElementNode[];
2818
+ readonly scrollContainerElements: readonly LayoutElementNode[];
2819
+ readonly statefulSelectorEntriesByRuleId: ReadonlyMap<number, readonly LayoutStatefulSelectorEntry[]>;
2820
+ readonly statefulNormalizedDeclarationsByRuleId: ReadonlyMap<number, readonly LayoutNormalizedRuleDeclaration[]>;
2821
+ readonly statefulBaseValueIndex: ReadonlyMap<string, ReadonlyMap<string, ReadonlySet<string>>>;
2822
+ }
2823
+ interface LayoutGraph extends LayoutGraphTopology, LayoutGraphCascade, LayoutGraphFacts, LayoutGraphCohorts, LayoutGraphIndexes {
2824
+ readonly perf: LayoutPerfStatsMutable;
2825
+ }
2826
+
2827
+ /**
2828
+ * Versioned cache for SolidGraph, CSSGraph, and LayoutGraph instances.
2829
+ *
2830
+ * SolidGraphs are cached per file path with a version string.
2831
+ * The CSSGraph is a single instance covering all CSS files,
2832
+ * invalidated via a monotonic generation counter bumped by
2833
+ * `invalidate()` or `invalidateAll()`.
2834
+ */
2835
+ declare class GraphCache {
2836
+ private readonly log;
2837
+ private readonly solids;
2838
+ private readonly crossFileDiagnostics;
2839
+ private crossFileResults;
2840
+ private css;
2841
+ private solidGeneration;
2842
+ private cssGeneration;
2843
+ private layout;
2844
+ constructor(log?: Logger);
2845
+ /**
2846
+ * Check if a SolidGraph is cached and current for a file path.
2847
+ *
2848
+ * Allows callers to skip builder allocation when the cache is warm.
2849
+ *
2850
+ * @param path Absolute file path
2851
+ * @param version Script version string from the TS project service
2852
+ */
2853
+ hasSolidGraph(path: string, version: string): boolean;
2854
+ /**
2855
+ * Store a pre-built SolidGraph in the cache.
2856
+ *
2857
+ * Used by the CLI lint command which builds graphs during single-file
2858
+ * analysis and pre-populates the cache for cross-file reuse.
2859
+ *
2860
+ * @param path Absolute file path
2861
+ * @param version Script version string from the TS project service
2862
+ * @param graph Pre-built SolidGraph
2863
+ */
2864
+ setSolidGraph(path: string, version: string, graph: SolidGraph): void;
2865
+ /**
2866
+ * Get or build a SolidGraph for a file path.
2867
+ *
2868
+ * Returns the cached graph if the version matches.
2869
+ * Otherwise invokes the builder, caches the result, and returns it.
2870
+ *
2871
+ * @param path Absolute file path
2872
+ * @param version Script version string from the TS project service
2873
+ * @param build Builder function invoked on cache miss
2874
+ */
2875
+ getSolidGraph(path: string, version: string, build: () => SolidGraph): SolidGraph;
2876
+ /**
2877
+ * Get the cached CSSGraph, or rebuild it.
2878
+ *
2879
+ * Returns the cached graph if the generation matches the current
2880
+ * CSS generation counter. Otherwise invokes the builder, caches
2881
+ * the result at the current generation, and returns it.
2882
+ *
2883
+ * @param build Builder function invoked on cache miss
2884
+ */
2885
+ getCSSGraph(build: () => CSSGraph): CSSGraph;
2886
+ /**
2887
+ * Get or build a LayoutGraph for current Solid/CSS cache state.
2888
+ *
2889
+ * Returns cached LayoutGraph when both Solid signature (path+version)
2890
+ * and CSS generation match. Otherwise invokes the builder.
2891
+ *
2892
+ * @param build Builder function invoked on cache miss
2893
+ */
2894
+ getLayoutGraph(build: () => LayoutGraph): LayoutGraph;
2895
+ /**
2896
+ * Invalidate cached graphs affected by a file change.
2897
+ *
2898
+ * Classifies the path and invalidates the appropriate cache:
2899
+ * solid files evict their per-file SolidGraph, CSS files bump
2900
+ * the CSSGraph generation counter.
2901
+ *
2902
+ * @param path Absolute file path that changed
2903
+ */
2904
+ invalidate(path: string): void;
2905
+ /**
2906
+ * Invalidate all cached graphs.
2907
+ *
2908
+ * Called on workspace-level events like config changes.
2909
+ */
2910
+ invalidateAll(): void;
2911
+ /**
2912
+ * Get all cached SolidGraphs.
2913
+ *
2914
+ * Returns a snapshot array of all currently-cached graphs.
2915
+ * Used by cross-file analysis which needs all SolidGraphs.
2916
+ */
2917
+ getAllSolidGraphs(): readonly SolidGraph[];
2918
+ /**
2919
+ * Get the cached CSSGraph, or null if not cached.
2920
+ */
2921
+ getCachedCSSGraph(): CSSGraph | null;
2922
+ /**
2923
+ * Get the cached LayoutGraph, or null if not cached.
2924
+ */
2925
+ getCachedLayoutGraph(): LayoutGraph | null;
2926
+ /**
2927
+ * Get cached cross-file diagnostics for a file path.
2928
+ *
2929
+ * Returns the previous cross-file results so single-file-only
2930
+ * re-analysis (during typing) can merge them without re-running
2931
+ * cross-file rules.
2932
+ *
2933
+ * @param path Absolute file path
2934
+ */
2935
+ getCachedCrossFileDiagnostics(path: string): readonly Diagnostic[];
2936
+ /**
2937
+ * Store cross-file diagnostics for a file path.
2938
+ *
2939
+ * @param path Absolute file path
2940
+ * @param diagnostics Cross-file diagnostics for this path
2941
+ */
2942
+ setCachedCrossFileDiagnostics(path: string, diagnostics: readonly Diagnostic[]): void;
2943
+ /**
2944
+ * Get workspace-level cross-file results if the underlying graphs haven't changed.
2945
+ *
2946
+ * Returns the full per-file map when the solid signature and CSS generation
2947
+ * match, meaning no graphs were rebuilt since the last run. Returns null
2948
+ * when results are stale and `runCrossFileRules` must re-execute.
2949
+ */
2950
+ getCachedCrossFileResults(): ReadonlyMap<string, readonly Diagnostic[]> | null;
2951
+ /**
2952
+ * Store workspace-level cross-file results bucketed by file.
2953
+ *
2954
+ * Called after `runCrossFileRules` completes. Captures the current
2955
+ * solid signature and CSS generation so subsequent lookups are O(1)
2956
+ * until a graph changes.
2957
+ *
2958
+ * @param allDiagnostics All cross-file diagnostics from the workspace run
2959
+ */
2960
+ setCachedCrossFileResults(allDiagnostics: readonly Diagnostic[]): void;
2961
+ /** Number of cached SolidGraphs. */
2962
+ get solidCount(): number;
2963
+ /** The logger instance used by this cache. */
2964
+ get logger(): Logger;
2965
+ }
2966
+
2967
+ /**
2968
+ * Build a SolidGraph from input.
2969
+ *
2970
+ * Exported for use by cross-file rules that need to build graphs
2971
+ * without running all solid rules.
2972
+ */
2973
+ declare function buildSolidGraph(input: SolidInput): SolidGraph;
2974
+ /**
2975
+ * Analyze pre-parsed input and emit diagnostics.
2976
+ *
2977
+ * For use by ESLint integration and LSP where the caller
2978
+ * has already parsed the file (e.g. ESLint provides SourceCode).
2979
+ */
2980
+ declare function analyzeInput(input: SolidInput, emit: Emit): void;
2981
+ /**
2982
+ * Run single-file Solid rules on a pre-built graph.
2983
+ *
2984
+ * Separates rule execution from graph construction so callers that
2985
+ * cache graphs (e.g. CLI lint) can build once, run single-file rules,
2986
+ * and reuse the same graph for cross-file analysis.
2987
+ */
2988
+ declare function runSolidRules(graph: SolidGraph, sourceCode: TSESLint.SourceCode, emit: Emit): void;
2989
+ /**
2990
+ * The Solid.js plugin.
2991
+ *
2992
+ * Analyzes Solid.js files by reading from disk, parsing with
2993
+ * @typescript-eslint/parser, building a SolidGraph, and running all rules.
2994
+ * Rules push diagnostics via the emit callback.
2995
+ *
2996
+ * @example
2997
+ * ```ts
2998
+ * import { createRunner, SolidPlugin } from "@drskillissue/ganko"
2999
+ *
3000
+ * const runner = createRunner({ plugins: [SolidPlugin] })
3001
+ * const diagnostics = runner.run(["src/App.tsx"])
3002
+ * ```
3003
+ */
3004
+ declare const SolidPlugin: Plugin<"solid">;
3005
+
3006
+ /**
3007
+ * Parse a file from disk into SolidInput.
3008
+ *
3009
+ * Reads the file, parses with @typescript-eslint/parser,
3010
+ * and wraps into a SourceCode object.
3011
+ *
3012
+ * @param path - Absolute file path
3013
+ * @param logger - Logger for debug output
3014
+ * @returns Parsed SolidInput
3015
+ */
3016
+ declare function parseFile(path: string, logger?: Logger): SolidInput;
3017
+ /**
3018
+ * Parse source content into SolidInput.
3019
+ *
3020
+ * Exposed for cases where content is already in memory
3021
+ * (e.g. LSP with unsaved changes, tests).
3022
+ *
3023
+ * @param path - Absolute file path
3024
+ * @param content - Source text
3025
+ * @param logger - Logger for debug output
3026
+ * @returns Parsed SolidInput
3027
+ */
3028
+ declare function parseContent(path: string, content: string, logger?: Logger): SolidInput;
3029
+ /**
3030
+ * Parse source content with an existing TypeScript Program for full type info.
3031
+ *
3032
+ * Uses parseAndGenerateServices with the `programs` option to build the
3033
+ * ESTree↔TSNode mapping against the caller's ts.Program. This gives the
3034
+ * SolidGraph access to getTypeAtLocation/getSymbolAtLocation for type-aware
3035
+ * rules and fixes (e.g. expanding JSX spreads into explicit props).
3036
+ *
3037
+ * @param path - Absolute file path (must be part of the program)
3038
+ * @param content - In-memory source content
3039
+ * @param program - TypeScript Program from the language service
3040
+ * @param logger - Logger for debug output
3041
+ * @returns Parsed SolidInput with full type info
3042
+ */
3043
+ declare function parseContentWithProgram(path: string, content: string, program: ts.Program, logger?: Logger): SolidInput;
3044
+
3045
+ /**
3046
+ * Build a CSSGraph from input.
3047
+ *
3048
+ * When `externalCustomProperties` is present in the input, generates a synthetic
3049
+ * CSS file declaring those properties in `:root` and includes it in the graph.
3050
+ * This ensures library-provided custom properties resolve through the normal
3051
+ * cascade and resolution pipeline.
3052
+ *
3053
+ * Exported for use by cross-file rules that need to build graphs
3054
+ * without running all CSS rules.
3055
+ */
3056
+ declare function buildCSSGraph(input: CSSInput): CSSGraph;
3057
+ /**
3058
+ * The CSS plugin.
3059
+ *
3060
+ * Analyzes CSS/SCSS files by reading from disk, building a CSSGraph,
3061
+ * and running all rules. Rules push diagnostics via the emit callback.
3062
+ *
3063
+ * @example
3064
+ * ```ts
3065
+ * import { createRunner, CSSPlugin } from "@drskillissue/ganko"
3066
+ *
3067
+ * const runner = createRunner({ plugins: [CSSPlugin] })
3068
+ * const diagnostics = runner.run(["src/styles/app.css"])
3069
+ * ```
3070
+ */
3071
+ declare const CSSPlugin: Plugin<"css">;
3072
+
3073
+ /**
3074
+ * Library Analysis — Extracts CSS custom properties provided by installed dependencies.
3075
+ *
3076
+ * Scans dependency packages for CSS custom property definitions injected at runtime
3077
+ * via JavaScript (e.g., inline style attributes in JSX). This enables the resolution
3078
+ * engine to treat library-provided properties as defined rather than flagging them
3079
+ * as unresolved.
3080
+ *
3081
+ * Architecture:
3082
+ * 1. Read project package.json files to discover direct dependencies
3083
+ * 2. For each dependency, scan its dist/source files for CSS custom property patterns
3084
+ * 3. Return discovered properties as a synthetic CSS `:root` declaration block
3085
+ * 4. The caller feeds this into the normal CSS parsing pipeline as an additional file
3086
+ *
3087
+ * The scanner detects properties set via:
3088
+ * - JSX style object keys: `"--kb-accordion-content-height": value`
3089
+ * - style.setProperty calls: `style.setProperty("--kb-accordion-content-height", ...)`
3090
+ * - CSS-in-JS template literals with custom property definitions
3091
+ */
3092
+ /**
3093
+ * Scan installed dependencies for CSS custom properties they inject at runtime.
3094
+ *
3095
+ * Reads each direct dependency's package.json to find its dist directory,
3096
+ * then scans JavaScript/JSX files for CSS custom property name patterns.
3097
+ *
3098
+ * @param projectRoot - Absolute path to the project root (containing package.json)
3099
+ * @returns Set of CSS custom property names (e.g., "--kb-accordion-content-height")
3100
+ */
3101
+ declare function scanDependencyCustomProperties(projectRoot: string): ReadonlySet<string>;
3102
+
3103
+ /**
3104
+ * Accessibility Policy Templates
3105
+ *
3106
+ * Predefined bundles of sizing, spacing, and contrast constraints
3107
+ * derived from WCAG 2.2, Material Design 3, Apple HIG, and
3108
+ * W3C Low Vision Needs.
3109
+ */
3110
+
3111
+ /** Set the active policy for all policy rules. */
3112
+ declare function setActivePolicy(name: string): void;
3113
+
3114
+ declare function buildLayoutGraph(solids: readonly SolidGraph[], css: CSSGraph, logger?: Logger): LayoutGraph;
3115
+
3116
+ interface CrossRuleContext {
3117
+ readonly solids: readonly SolidGraph[];
3118
+ readonly css: CSSGraph;
3119
+ readonly layout: LayoutGraph;
3120
+ }
3121
+
3122
+ /**
3123
+ * Run cross-file rules against pre-built graphs.
3124
+ *
3125
+ * Separates rule execution from graph construction so that callers
3126
+ * with cached graphs (e.g. LSP GraphCache) can skip redundant parsing.
3127
+ *
3128
+ * @param context Pre-built Solid, CSS, and layout graphs
3129
+ * @param emit Diagnostic emitter
3130
+ */
3131
+ declare function runCrossFileRules(context: CrossRuleContext, emit: Emit, log?: Logger): void;
3132
+
3133
+ export { CSSGraph, type CSSInput, CSSPlugin, type ComputationEntity, type DependencyEdge, type Diagnostic, type Fix, type FixOperation, GraphCache, type Plugin, type ReactiveKind, type ReadEntity, type Runner, SolidGraph, type SolidInput, SolidPlugin, type TailwindValidator, type VariableEntity$1 as VariableEntity, analyzeInput, buildCSSGraph, buildLayoutGraph, buildSolidGraph, createOverrideEmit, createRunner, parseContent, parseContentWithProgram, parseFile, resolveTailwindValidator, runCrossFileRules, runSolidRules, scanDependencyCustomProperties, setActivePolicy };