@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.
- package/LICENSE +21 -0
- package/README.md +430 -0
- package/dist/chunk-JBBGDG7M.js +1943 -0
- package/dist/chunk-JBBGDG7M.js.map +1 -0
- package/dist/chunk-RB7SZIJX.js +37396 -0
- package/dist/chunk-RB7SZIJX.js.map +1 -0
- package/dist/eslint-plugin.cjs +37216 -0
- package/dist/eslint-plugin.cjs.map +1 -0
- package/dist/eslint-plugin.d.cts +40 -0
- package/dist/eslint-plugin.d.ts +40 -0
- package/dist/eslint-plugin.js +301 -0
- package/dist/eslint-plugin.js.map +1 -0
- package/dist/index.cjs +39583 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3133 -0
- package/dist/index.d.ts +3133 -0
- package/dist/index.js +358 -0
- package/dist/index.js.map +1 -0
- package/dist/rules-manifest.cjs +1972 -0
- package/dist/rules-manifest.cjs.map +1 -0
- package/dist/rules-manifest.d.cts +33 -0
- package/dist/rules-manifest.d.ts +33 -0
- package/dist/rules-manifest.js +13 -0
- package/dist/rules-manifest.js.map +1 -0
- package/package.json +92 -0
package/dist/index.d.cts
ADDED
|
@@ -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.cjs';
|
|
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 };
|