@pattern-algebra/core 0.0.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/README.md +571 -0
- package/dist/automaton/complement.d.ts +20 -0
- package/dist/automaton/complement.d.ts.map +1 -0
- package/dist/automaton/complement.js +36 -0
- package/dist/automaton/complement.js.map +1 -0
- package/dist/automaton/complement.test.d.ts +2 -0
- package/dist/automaton/complement.test.d.ts.map +1 -0
- package/dist/automaton/complement.test.js +114 -0
- package/dist/automaton/complement.test.js.map +1 -0
- package/dist/automaton/determinize.d.ts +41 -0
- package/dist/automaton/determinize.d.ts.map +1 -0
- package/dist/automaton/determinize.js +310 -0
- package/dist/automaton/determinize.js.map +1 -0
- package/dist/automaton/determinize.test.d.ts +2 -0
- package/dist/automaton/determinize.test.d.ts.map +1 -0
- package/dist/automaton/determinize.test.js +134 -0
- package/dist/automaton/determinize.test.js.map +1 -0
- package/dist/automaton/emptiness.d.ts +41 -0
- package/dist/automaton/emptiness.d.ts.map +1 -0
- package/dist/automaton/emptiness.js +262 -0
- package/dist/automaton/emptiness.js.map +1 -0
- package/dist/automaton/emptiness.test.d.ts +2 -0
- package/dist/automaton/emptiness.test.d.ts.map +1 -0
- package/dist/automaton/emptiness.test.js +154 -0
- package/dist/automaton/emptiness.test.js.map +1 -0
- package/dist/automaton/index.d.ts +10 -0
- package/dist/automaton/index.d.ts.map +1 -0
- package/dist/automaton/index.js +11 -0
- package/dist/automaton/index.js.map +1 -0
- package/dist/automaton/intersect.d.ts +35 -0
- package/dist/automaton/intersect.d.ts.map +1 -0
- package/dist/automaton/intersect.js +302 -0
- package/dist/automaton/intersect.js.map +1 -0
- package/dist/automaton/pattern-algebra.d.ts +62 -0
- package/dist/automaton/pattern-algebra.d.ts.map +1 -0
- package/dist/automaton/pattern-algebra.js +309 -0
- package/dist/automaton/pattern-algebra.js.map +1 -0
- package/dist/automaton/pattern-algebra.test.d.ts +2 -0
- package/dist/automaton/pattern-algebra.test.d.ts.map +1 -0
- package/dist/automaton/pattern-algebra.test.js +223 -0
- package/dist/automaton/pattern-algebra.test.js.map +1 -0
- package/dist/compile/automaton-builder.d.ts +47 -0
- package/dist/compile/automaton-builder.d.ts.map +1 -0
- package/dist/compile/automaton-builder.js +211 -0
- package/dist/compile/automaton-builder.js.map +1 -0
- package/dist/compile/compiler.d.ts +32 -0
- package/dist/compile/compiler.d.ts.map +1 -0
- package/dist/compile/compiler.js +47 -0
- package/dist/compile/compiler.js.map +1 -0
- package/dist/compile/index.d.ts +8 -0
- package/dist/compile/index.d.ts.map +1 -0
- package/dist/compile/index.js +8 -0
- package/dist/compile/index.js.map +1 -0
- package/dist/compile/quick-reject.d.ts +28 -0
- package/dist/compile/quick-reject.d.ts.map +1 -0
- package/dist/compile/quick-reject.js +147 -0
- package/dist/compile/quick-reject.js.map +1 -0
- package/dist/containment/analysis.d.ts +60 -0
- package/dist/containment/analysis.d.ts.map +1 -0
- package/dist/containment/analysis.js +378 -0
- package/dist/containment/analysis.js.map +1 -0
- package/dist/containment/containment.d.ts +23 -0
- package/dist/containment/containment.d.ts.map +1 -0
- package/dist/containment/containment.js +681 -0
- package/dist/containment/containment.js.map +1 -0
- package/dist/containment/containment.test.d.ts +2 -0
- package/dist/containment/containment.test.d.ts.map +1 -0
- package/dist/containment/containment.test.js +209 -0
- package/dist/containment/containment.test.js.map +1 -0
- package/dist/containment/index.d.ts +7 -0
- package/dist/containment/index.d.ts.map +1 -0
- package/dist/containment/index.js +7 -0
- package/dist/containment/index.js.map +1 -0
- package/dist/core-alpha.d.ts +1253 -0
- package/dist/core-beta.d.ts +1253 -0
- package/dist/core-public.d.ts +1253 -0
- package/dist/core-unstripped.d.ts +1253 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/match/index.d.ts +8 -0
- package/dist/match/index.d.ts.map +1 -0
- package/dist/match/index.js +8 -0
- package/dist/match/index.js.map +1 -0
- package/dist/match/matcher.d.ts +40 -0
- package/dist/match/matcher.d.ts.map +1 -0
- package/dist/match/matcher.js +256 -0
- package/dist/match/matcher.js.map +1 -0
- package/dist/match/matcher.test.d.ts +2 -0
- package/dist/match/matcher.test.d.ts.map +1 -0
- package/dist/match/matcher.test.js +185 -0
- package/dist/match/matcher.test.js.map +1 -0
- package/dist/match/path-utils.d.ts +132 -0
- package/dist/match/path-utils.d.ts.map +1 -0
- package/dist/match/path-utils.js +223 -0
- package/dist/match/path-utils.js.map +1 -0
- package/dist/match/path-utils.test.d.ts +2 -0
- package/dist/match/path-utils.test.d.ts.map +1 -0
- package/dist/match/path-utils.test.js +193 -0
- package/dist/match/path-utils.test.js.map +1 -0
- package/dist/match/segment-matcher.d.ts +25 -0
- package/dist/match/segment-matcher.d.ts.map +1 -0
- package/dist/match/segment-matcher.js +267 -0
- package/dist/match/segment-matcher.js.map +1 -0
- package/dist/parse/brace-expansion.d.ts +34 -0
- package/dist/parse/brace-expansion.d.ts.map +1 -0
- package/dist/parse/brace-expansion.js +294 -0
- package/dist/parse/brace-expansion.js.map +1 -0
- package/dist/parse/brace-expansion.test.d.ts +2 -0
- package/dist/parse/brace-expansion.test.d.ts.map +1 -0
- package/dist/parse/brace-expansion.test.js +105 -0
- package/dist/parse/brace-expansion.test.js.map +1 -0
- package/dist/parse/index.d.ts +8 -0
- package/dist/parse/index.d.ts.map +1 -0
- package/dist/parse/index.js +8 -0
- package/dist/parse/index.js.map +1 -0
- package/dist/parse/parser.d.ts +15 -0
- package/dist/parse/parser.d.ts.map +1 -0
- package/dist/parse/parser.js +526 -0
- package/dist/parse/parser.js.map +1 -0
- package/dist/parse/parser.test.d.ts +2 -0
- package/dist/parse/parser.test.d.ts.map +1 -0
- package/dist/parse/parser.test.js +266 -0
- package/dist/parse/parser.test.js.map +1 -0
- package/dist/parse/validator.d.ts +30 -0
- package/dist/parse/validator.d.ts.map +1 -0
- package/dist/parse/validator.js +115 -0
- package/dist/parse/validator.js.map +1 -0
- package/dist/parse/validator.test.d.ts +2 -0
- package/dist/parse/validator.test.d.ts.map +1 -0
- package/dist/parse/validator.test.js +45 -0
- package/dist/parse/validator.test.js.map +1 -0
- package/dist/types/ast.d.ts +158 -0
- package/dist/types/ast.d.ts.map +1 -0
- package/dist/types/ast.js +2 -0
- package/dist/types/ast.js.map +1 -0
- package/dist/types/automaton.d.ts +150 -0
- package/dist/types/automaton.d.ts.map +1 -0
- package/dist/types/automaton.js +2 -0
- package/dist/types/automaton.js.map +1 -0
- package/dist/types/containment.d.ts +257 -0
- package/dist/types/containment.d.ts.map +1 -0
- package/dist/types/containment.js +5 -0
- package/dist/types/containment.js.map +1 -0
- package/dist/types/errors.d.ts +37 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +24 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,1253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Pattern Language Library
|
|
3
|
+
*
|
|
4
|
+
* A library for parsing, compiling, matching, and comparing path patterns
|
|
5
|
+
* (globs and restricted regexes). Designed for downstream use by policy systems.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Brace expansion creates alternation between pattern branches.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* "\{src,lib\}/**\/*.ts" becomes:
|
|
15
|
+
* Alternation([
|
|
16
|
+
* SegmentSequence([Literal("src"), Globstar, Wildcard("*.ts")]),
|
|
17
|
+
* SegmentSequence([Literal("lib"), Globstar, Wildcard("*.ts")])
|
|
18
|
+
* ])
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export declare interface Alternation {
|
|
23
|
+
readonly type: 'alternation';
|
|
24
|
+
readonly branches: readonly PatternNode[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Analyze the relationship between two patterns in detail.
|
|
29
|
+
*
|
|
30
|
+
* Provides comprehensive information about how patterns relate,
|
|
31
|
+
* including the intersection and set differences.
|
|
32
|
+
*
|
|
33
|
+
* @param a - First compiled pattern
|
|
34
|
+
* @param b - Second compiled pattern
|
|
35
|
+
* @returns Full analysis of pattern relationship
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export declare function analyzePatterns(a: CompiledPattern, b: CompiledPattern): PatternAnalysis;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Comparison of pattern anchoring (absolute vs relative).
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export declare interface AnchoringComparison {
|
|
46
|
+
/** Whether the anchoring differs between patterns */
|
|
47
|
+
readonly differ: boolean;
|
|
48
|
+
/** Whether pattern A is absolute (starts with / or ~) */
|
|
49
|
+
readonly patternAAbsolute: boolean;
|
|
50
|
+
/** Whether pattern B is absolute (starts with / or ~) */
|
|
51
|
+
readonly patternBAbsolute: boolean;
|
|
52
|
+
/** Human-readable explanation of the difference */
|
|
53
|
+
readonly explanation?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Apply quick-reject filter to a path.
|
|
58
|
+
*
|
|
59
|
+
* @param path - Normalized path to check
|
|
60
|
+
* @param filter - Quick-reject filter
|
|
61
|
+
* @returns false if path definitely doesn't match, true if it might match
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
export declare function applyQuickReject(path: string, filter: QuickRejectFilter): boolean;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Determine if two patterns are disjoint (no common paths).
|
|
69
|
+
*
|
|
70
|
+
* @param a - First pattern
|
|
71
|
+
* @param b - Second pattern
|
|
72
|
+
* @returns true if patterns have no paths in common
|
|
73
|
+
*
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export declare function areDisjoint(a: CompiledPattern, b: CompiledPattern): boolean;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Determine if two patterns are equivalent (match the same set of paths).
|
|
80
|
+
*
|
|
81
|
+
* @param a - First pattern
|
|
82
|
+
* @param b - Second pattern
|
|
83
|
+
* @returns true if patterns are equivalent
|
|
84
|
+
*
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
export declare function areEquivalent(a: CompiledPattern, b: CompiledPattern): boolean;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Error thrown when automaton operations exceed configured limits.
|
|
91
|
+
*
|
|
92
|
+
* This typically occurs during DFA construction when a pattern
|
|
93
|
+
* would result in exponential state explosion.
|
|
94
|
+
*
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
export declare class AutomatonLimitError extends Error {
|
|
98
|
+
/** Error classification code */
|
|
99
|
+
readonly code: PatternErrorCode;
|
|
100
|
+
/** The limit that was exceeded */
|
|
101
|
+
readonly limit: number;
|
|
102
|
+
/** The actual value that exceeded the limit */
|
|
103
|
+
readonly actual: number;
|
|
104
|
+
constructor(code: PatternErrorCode, message: string, limit: number, actual: number);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A state in the segment automaton.
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
export declare interface AutomatonState {
|
|
112
|
+
/** Unique identifier for this state (index in the states array) */
|
|
113
|
+
readonly id: number;
|
|
114
|
+
/** Transitions from this state */
|
|
115
|
+
readonly transitions: readonly AutomatonTransition[];
|
|
116
|
+
/** Is this an accepting state? */
|
|
117
|
+
readonly accepting: boolean;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* A transition in the segment automaton.
|
|
122
|
+
* @public
|
|
123
|
+
*/
|
|
124
|
+
export declare type AutomatonTransition = LiteralTransition | WildcardTransition | GlobstarTransition | EpsilonTransition;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Build a segment automaton from a pattern AST.
|
|
128
|
+
*
|
|
129
|
+
* The automaton operates on path segments (not characters).
|
|
130
|
+
* This representation enables:
|
|
131
|
+
* - O(n) matching where n is number of path segments
|
|
132
|
+
* - Standard automaton operations for containment checking
|
|
133
|
+
*
|
|
134
|
+
* @param pattern - Parsed pattern AST
|
|
135
|
+
* @returns Segment automaton (NFA)
|
|
136
|
+
*
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
export declare function buildAutomaton(pattern: PathPattern): SegmentAutomaton;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Build quick-reject filters for a pattern.
|
|
143
|
+
*
|
|
144
|
+
* Quick-reject filters enable fast elimination of non-matching paths
|
|
145
|
+
* before full automaton simulation.
|
|
146
|
+
*
|
|
147
|
+
* @param pattern - Pattern AST
|
|
148
|
+
* @returns Quick-reject filter configuration
|
|
149
|
+
*
|
|
150
|
+
* @public
|
|
151
|
+
*/
|
|
152
|
+
export declare function buildQuickRejectFilter(pattern: PathPattern): QuickRejectFilter;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* A character class like [a-z] or [!0-9].
|
|
156
|
+
* @public
|
|
157
|
+
*/
|
|
158
|
+
export declare interface CharClassSegment {
|
|
159
|
+
readonly type: 'charclass';
|
|
160
|
+
/** Whether this is a negated class (e.g., [!abc] or [^abc]) */
|
|
161
|
+
readonly negated: boolean;
|
|
162
|
+
/** Character ranges (e.g., a-z, 0-9) */
|
|
163
|
+
readonly ranges: readonly CharRange[];
|
|
164
|
+
/** Individual characters not in ranges */
|
|
165
|
+
readonly chars: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* A character range within a character class.
|
|
170
|
+
* @public
|
|
171
|
+
*/
|
|
172
|
+
export declare interface CharRange {
|
|
173
|
+
/** Single character - start of range */
|
|
174
|
+
readonly start: string;
|
|
175
|
+
/** Single character - end of range */
|
|
176
|
+
readonly end: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Check if pattern A is contained within pattern B.
|
|
181
|
+
*
|
|
182
|
+
* A ⊆ B means: every path that matches A also matches B.
|
|
183
|
+
*
|
|
184
|
+
* Uses a hybrid approach:
|
|
185
|
+
* 1. Structural analysis for quick checks
|
|
186
|
+
* 2. Sample-based testing for validation
|
|
187
|
+
* 3. Automaton operations for complex cases (when available)
|
|
188
|
+
*
|
|
189
|
+
* @param a - First compiled pattern
|
|
190
|
+
* @param b - Second compiled pattern
|
|
191
|
+
* @returns Containment result with explanation data
|
|
192
|
+
*
|
|
193
|
+
* @public
|
|
194
|
+
*/
|
|
195
|
+
export declare function checkContainment(a: CompiledPattern, b: CompiledPattern): ContainmentResult;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Find the common prefix path between two paths.
|
|
199
|
+
*
|
|
200
|
+
* @param pathA - First path
|
|
201
|
+
* @param pathB - Second path
|
|
202
|
+
* @returns The longest common ancestor path
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* commonPrefix('/home/user/a/b', '/home/user/c/d')
|
|
206
|
+
* // => '/home/user'
|
|
207
|
+
*
|
|
208
|
+
* @public
|
|
209
|
+
*/
|
|
210
|
+
export declare function commonPrefix(pathA: string, pathB: string): string;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* A compiled pattern ready for efficient matching.
|
|
214
|
+
*
|
|
215
|
+
* Patterns are compiled to a form optimized for:
|
|
216
|
+
* 1. Fast rejection of non-matching paths
|
|
217
|
+
* 2. Minimal backtracking during matching
|
|
218
|
+
* 3. Support for containment analysis
|
|
219
|
+
*
|
|
220
|
+
* @public
|
|
221
|
+
*/
|
|
222
|
+
export declare interface CompiledPattern {
|
|
223
|
+
/** Original source pattern */
|
|
224
|
+
readonly source: string;
|
|
225
|
+
/** Parsed AST (for containment analysis) */
|
|
226
|
+
readonly ast: PathPattern;
|
|
227
|
+
/**
|
|
228
|
+
* Quick-reject filters applied before full matching.
|
|
229
|
+
* If any filter fails, the path definitely doesn't match.
|
|
230
|
+
*/
|
|
231
|
+
readonly quickReject: QuickRejectFilter;
|
|
232
|
+
/**
|
|
233
|
+
* Segment automaton for matching.
|
|
234
|
+
* Operates on path segments, not characters.
|
|
235
|
+
*/
|
|
236
|
+
readonly automaton: SegmentAutomaton;
|
|
237
|
+
/** Whether pattern can match paths of any depth (contains **) */
|
|
238
|
+
readonly isUnbounded: boolean;
|
|
239
|
+
/** Minimum number of segments this pattern requires */
|
|
240
|
+
readonly minSegments: number;
|
|
241
|
+
/** Maximum segments (undefined if unbounded) */
|
|
242
|
+
readonly maxSegments?: number;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Compile a pattern to an efficient matching form.
|
|
247
|
+
*
|
|
248
|
+
* The compiled pattern includes:
|
|
249
|
+
* - Original source and AST for debugging/analysis
|
|
250
|
+
* - Quick-reject filters for fast path elimination
|
|
251
|
+
* - Segment automaton for full matching
|
|
252
|
+
* - Depth constraints for optimization
|
|
253
|
+
*
|
|
254
|
+
* @param pattern - Parsed pattern AST
|
|
255
|
+
* @returns Compiled pattern ready for matching
|
|
256
|
+
*
|
|
257
|
+
* @public
|
|
258
|
+
*/
|
|
259
|
+
export declare function compilePattern(pattern: PathPattern): CompiledPattern;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Complement a DFA by swapping accepting and non-accepting states.
|
|
263
|
+
*
|
|
264
|
+
* The complemented automaton accepts exactly the strings that the
|
|
265
|
+
* original automaton rejects, and vice versa.
|
|
266
|
+
*
|
|
267
|
+
* Note: Input must be deterministic. NFAs are automatically converted.
|
|
268
|
+
*
|
|
269
|
+
* @param automaton - The automaton to complement
|
|
270
|
+
* @returns Complemented automaton
|
|
271
|
+
*
|
|
272
|
+
* @public
|
|
273
|
+
*/
|
|
274
|
+
export declare function complement(automaton: SegmentAutomaton): SegmentAutomaton;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* A segment composed of multiple parts (literal + wildcard + charclass).
|
|
278
|
+
*
|
|
279
|
+
* @example "test-[0-9]*-spec.ts" is a composite of:
|
|
280
|
+
* - literal "test-"
|
|
281
|
+
* - charclass [0-9]
|
|
282
|
+
* - star *
|
|
283
|
+
* - literal "-spec.ts"
|
|
284
|
+
*
|
|
285
|
+
* @public
|
|
286
|
+
*/
|
|
287
|
+
export declare interface CompositeSegment {
|
|
288
|
+
readonly type: 'composite';
|
|
289
|
+
readonly parts: readonly SegmentPart[];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Structured explanation of why two patterns have a particular relationship.
|
|
294
|
+
* Provides sufficient data for downstream systems to generate human-readable explanations.
|
|
295
|
+
* @public
|
|
296
|
+
*/
|
|
297
|
+
export declare interface ContainmentExplanation {
|
|
298
|
+
/**
|
|
299
|
+
* High-level categorization of why containment fails (if it does).
|
|
300
|
+
* Empty array if A ⊆ B.
|
|
301
|
+
*/
|
|
302
|
+
readonly failureReasons: readonly ContainmentFailureReason[];
|
|
303
|
+
/**
|
|
304
|
+
* Segment-by-segment comparison showing where patterns differ.
|
|
305
|
+
* Each entry describes one position in the path.
|
|
306
|
+
*/
|
|
307
|
+
readonly segmentComparison: readonly SegmentComparisonEntry[];
|
|
308
|
+
/**
|
|
309
|
+
* Structural differences between the patterns.
|
|
310
|
+
*/
|
|
311
|
+
readonly structuralDiffs: StructuralDifferences;
|
|
312
|
+
/**
|
|
313
|
+
* Witness paths that demonstrate the relationship.
|
|
314
|
+
* Includes counterexamples, shared paths, and illustrative examples.
|
|
315
|
+
*/
|
|
316
|
+
readonly witnesses: readonly WitnessPath[];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Categories of reasons why containment may fail.
|
|
321
|
+
* Used to provide structured explanation data.
|
|
322
|
+
* @public
|
|
323
|
+
*/
|
|
324
|
+
export declare type ContainmentFailureReason = 'depth_mismatch' | 'prefix_mismatch' | 'suffix_mismatch' | 'segment_mismatch' | 'charclass_mismatch' | 'negation_conflict' | 'alternation_escape';
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Result of checking whether pattern A is contained within pattern B.
|
|
328
|
+
*
|
|
329
|
+
* A ⊆ B means: every path that matches A also matches B.
|
|
330
|
+
*
|
|
331
|
+
* This type provides rich structured data to enable downstream systems
|
|
332
|
+
* to generate human-readable explanations of containment results.
|
|
333
|
+
*
|
|
334
|
+
* @example
|
|
335
|
+
* - "src/*.ts" ⊆ "src/**" (true)
|
|
336
|
+
* - "src/**" ⊆ "src/*.ts" (false)
|
|
337
|
+
* - "*.ts" ⊆ "*" (true)
|
|
338
|
+
* - "\{src,lib\}/*.ts" ⊆ "**\/*.ts" (true)
|
|
339
|
+
*
|
|
340
|
+
* @public
|
|
341
|
+
*/
|
|
342
|
+
export declare interface ContainmentResult {
|
|
343
|
+
/** The first pattern being compared */
|
|
344
|
+
readonly patternA: string;
|
|
345
|
+
/** The second pattern being compared */
|
|
346
|
+
readonly patternB: string;
|
|
347
|
+
/** Is A a subset of B? (A ⊆ B) */
|
|
348
|
+
readonly isSubset: boolean;
|
|
349
|
+
/** Is B a subset of A? (B ⊆ A) */
|
|
350
|
+
readonly isSuperset: boolean;
|
|
351
|
+
/** Is A equal to B (mutual containment)? */
|
|
352
|
+
readonly isEqual: boolean;
|
|
353
|
+
/** Do the patterns have any overlap? (A ∩ B ≠ ∅) */
|
|
354
|
+
readonly hasOverlap: boolean;
|
|
355
|
+
/** Relationship classification */
|
|
356
|
+
readonly relationship: PatternRelationship;
|
|
357
|
+
/**
|
|
358
|
+
* Primary counterexample: a path that matches A but not B.
|
|
359
|
+
* Present when isSubset is false.
|
|
360
|
+
*/
|
|
361
|
+
readonly counterexample?: string;
|
|
362
|
+
/**
|
|
363
|
+
* Reverse counterexample: a path that matches B but not A.
|
|
364
|
+
* Present when isSuperset is false.
|
|
365
|
+
*/
|
|
366
|
+
readonly reverseCounterexample?: string;
|
|
367
|
+
/**
|
|
368
|
+
* Structured explanation data for generating human-readable descriptions.
|
|
369
|
+
*/
|
|
370
|
+
readonly explanation: ContainmentExplanation;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Count the number of patterns that would result from expansion.
|
|
375
|
+
* Does not actually expand - useful for limit checking.
|
|
376
|
+
*
|
|
377
|
+
* @param source - Pattern source string
|
|
378
|
+
* @returns Estimated expansion count, or Infinity if it would exceed reasonable limits
|
|
379
|
+
*
|
|
380
|
+
* @public
|
|
381
|
+
*/
|
|
382
|
+
export declare function countBraceExpansions(source: string): number;
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Count the number of accepting paths of a given length.
|
|
386
|
+
*
|
|
387
|
+
* Useful for understanding the "size" of a pattern's language.
|
|
388
|
+
*
|
|
389
|
+
* @param automaton - The automaton
|
|
390
|
+
* @param maxDepth - Maximum path length to consider
|
|
391
|
+
* @returns Object with counts per depth
|
|
392
|
+
*
|
|
393
|
+
* @public
|
|
394
|
+
*/
|
|
395
|
+
export declare function countPaths(automaton: SegmentAutomaton, maxDepth: number): Map<number, number>;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Default maximum number of DFA states before throwing an error.
|
|
399
|
+
* This prevents exponential blowup from patterns with many alternations.
|
|
400
|
+
*
|
|
401
|
+
* @public
|
|
402
|
+
*/
|
|
403
|
+
export declare const DEFAULT_MAX_DFA_STATES = 10000;
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Comparison of pattern depth constraints.
|
|
407
|
+
* @public
|
|
408
|
+
*/
|
|
409
|
+
export declare interface DepthComparison {
|
|
410
|
+
/** Whether the depth constraints differ between patterns */
|
|
411
|
+
readonly differ: boolean;
|
|
412
|
+
/** Minimum segment depth for pattern A */
|
|
413
|
+
readonly patternAMin: number;
|
|
414
|
+
/** Maximum segment depth for pattern A (or 'unbounded' for **) */
|
|
415
|
+
readonly patternAMax: number | 'unbounded';
|
|
416
|
+
/** Minimum segment depth for pattern B */
|
|
417
|
+
readonly patternBMin: number;
|
|
418
|
+
/** Maximum segment depth for pattern B (or 'unbounded' for **) */
|
|
419
|
+
readonly patternBMax: number | 'unbounded';
|
|
420
|
+
/** Human-readable explanation of the difference */
|
|
421
|
+
readonly explanation?: string;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Convert an NFA to a DFA using subset construction.
|
|
426
|
+
*
|
|
427
|
+
* The resulting DFA has states that correspond to sets of NFA states.
|
|
428
|
+
* Globstar transitions are handled by treating them as transitions
|
|
429
|
+
* that can match any segment.
|
|
430
|
+
*
|
|
431
|
+
* @param nfa - The NFA to determinize
|
|
432
|
+
* @param options - Optional configuration for the conversion
|
|
433
|
+
* @returns An equivalent DFA
|
|
434
|
+
* @throws AutomatonLimitError if DFA state count exceeds the configured limit
|
|
435
|
+
*
|
|
436
|
+
* @public
|
|
437
|
+
*/
|
|
438
|
+
export declare function determinize(nfa: SegmentAutomaton, options?: DeterminizeOptions): SegmentAutomaton;
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Options for DFA construction.
|
|
442
|
+
*
|
|
443
|
+
* @public
|
|
444
|
+
*/
|
|
445
|
+
export declare interface DeterminizeOptions {
|
|
446
|
+
/**
|
|
447
|
+
* Maximum number of DFA states to create before throwing an error.
|
|
448
|
+
* Set to `Infinity` to disable the limit (not recommended).
|
|
449
|
+
* @defaultValue 10000
|
|
450
|
+
*/
|
|
451
|
+
maxStates?: number;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Epsilon transition (no input consumed).
|
|
456
|
+
* Used for NFA construction and alternation.
|
|
457
|
+
* @public
|
|
458
|
+
*/
|
|
459
|
+
export declare interface EpsilonTransition {
|
|
460
|
+
readonly type: 'epsilon';
|
|
461
|
+
readonly target: number;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Expand brace expressions in a pattern, creating multiple patterns.
|
|
466
|
+
*
|
|
467
|
+
* @example
|
|
468
|
+
* expandBraces(parsePattern('{src,lib}/*.ts'))
|
|
469
|
+
* // => [parsePattern('src/*.ts'), parsePattern('lib/*.ts')]
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* expandBraces(parsePattern('file{1..3}.txt'))
|
|
473
|
+
* // => [parsePattern('file1.txt'), parsePattern('file2.txt'), parsePattern('file3.txt')]
|
|
474
|
+
*
|
|
475
|
+
* @param pattern - The pattern to expand
|
|
476
|
+
* @param maxExpansion - Maximum number of expanded patterns (default: 100)
|
|
477
|
+
* @returns Array of expanded patterns
|
|
478
|
+
*
|
|
479
|
+
* @public
|
|
480
|
+
*/
|
|
481
|
+
export declare function expandBraces(pattern: PathPattern, maxExpansion?: number): readonly PathPattern[];
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Find a witness string accepted by the automaton.
|
|
485
|
+
*
|
|
486
|
+
* If the automaton is non-empty, returns a path (sequence of segments)
|
|
487
|
+
* that leads to an accepting state.
|
|
488
|
+
*
|
|
489
|
+
* @param automaton - The automaton to find a witness for
|
|
490
|
+
* @returns A witness path string, or undefined if the language is empty
|
|
491
|
+
*
|
|
492
|
+
* @public
|
|
493
|
+
*/
|
|
494
|
+
export declare function findWitness(automaton: SegmentAutomaton): string | undefined;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Get the basename (final segment) from a path.
|
|
498
|
+
*
|
|
499
|
+
* @param path - Path to extract basename from
|
|
500
|
+
* @returns The final segment of the path
|
|
501
|
+
*
|
|
502
|
+
* @public
|
|
503
|
+
*/
|
|
504
|
+
export declare function getBasename(path: string): string;
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Get the directory portion of a path (everything except the last segment).
|
|
508
|
+
*
|
|
509
|
+
* @param path - Path to extract directory from
|
|
510
|
+
* @returns The directory path
|
|
511
|
+
*
|
|
512
|
+
* @public
|
|
513
|
+
*/
|
|
514
|
+
export declare function getDirname(path: string): string;
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Get the file extension from a path segment or full path.
|
|
518
|
+
*
|
|
519
|
+
* @param pathOrSegment - A path or segment to extract extension from
|
|
520
|
+
* @returns The extension including the dot, or empty string if none
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* getExtension('file.ts') // => '.ts'
|
|
524
|
+
* getExtension('file.test.ts') // => '.ts'
|
|
525
|
+
* getExtension('.gitignore') // => '' (dotfiles have no extension)
|
|
526
|
+
* getExtension('Makefile') // => ''
|
|
527
|
+
*
|
|
528
|
+
* @public
|
|
529
|
+
*/
|
|
530
|
+
export declare function getExtension(pathOrSegment: string): string;
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Get the maximum number of segments a pattern can match.
|
|
534
|
+
*
|
|
535
|
+
* @param pattern - Pattern AST
|
|
536
|
+
* @returns Maximum segment count, or undefined if unbounded (contains **)
|
|
537
|
+
*
|
|
538
|
+
* @public
|
|
539
|
+
*/
|
|
540
|
+
export declare function getMaxSegments(pattern: PathPattern): number | undefined;
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Get the minimum number of segments a pattern can match.
|
|
544
|
+
*
|
|
545
|
+
* @param pattern - Pattern AST
|
|
546
|
+
* @returns Minimum segment count
|
|
547
|
+
*
|
|
548
|
+
* @public
|
|
549
|
+
*/
|
|
550
|
+
export declare function getMinSegments(pattern: PathPattern): number;
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* The ** globstar - matches zero or more complete segments.
|
|
554
|
+
* @public
|
|
555
|
+
*/
|
|
556
|
+
export declare interface GlobstarSegment {
|
|
557
|
+
readonly type: 'globstar';
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Globstar transition for ** (matches zero or more segments).
|
|
562
|
+
*
|
|
563
|
+
* Modeled as: epsilon to exit OR consume one segment and stay.
|
|
564
|
+
* @public
|
|
565
|
+
*/
|
|
566
|
+
export declare interface GlobstarTransition {
|
|
567
|
+
readonly type: 'globstar';
|
|
568
|
+
/** Self-loop state (stays in same state consuming segments) */
|
|
569
|
+
readonly selfLoop: number;
|
|
570
|
+
/** Exit state (moves forward without consuming) */
|
|
571
|
+
readonly exit: number;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Determine if two patterns have any overlap.
|
|
576
|
+
*
|
|
577
|
+
* @param a - First pattern
|
|
578
|
+
* @param b - Second pattern
|
|
579
|
+
* @returns true if there exists a path matching both patterns
|
|
580
|
+
*
|
|
581
|
+
* @public
|
|
582
|
+
*/
|
|
583
|
+
export declare function hasOverlap(a: CompiledPattern, b: CompiledPattern): boolean;
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Compute the intersection of two automata using product construction.
|
|
587
|
+
*
|
|
588
|
+
* The resulting automaton accepts a string iff both input automata accept it.
|
|
589
|
+
* L(A ∩ B) = L(A) ∩ L(B)
|
|
590
|
+
*
|
|
591
|
+
* @param a - First automaton
|
|
592
|
+
* @param b - Second automaton
|
|
593
|
+
* @returns Intersection automaton
|
|
594
|
+
*
|
|
595
|
+
* @public
|
|
596
|
+
*/
|
|
597
|
+
export declare function intersect(a: SegmentAutomaton, b: SegmentAutomaton): SegmentAutomaton;
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Check if a path is absolute (starts with / or ~).
|
|
601
|
+
*
|
|
602
|
+
* @param path - Path to check
|
|
603
|
+
* @returns true if the path is absolute
|
|
604
|
+
*
|
|
605
|
+
* @public
|
|
606
|
+
*/
|
|
607
|
+
export declare function isAbsolutePath(path: string): boolean;
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Check if path A is a prefix of path B (A is an ancestor directory of B).
|
|
611
|
+
*
|
|
612
|
+
* @param ancestor - Potential ancestor path
|
|
613
|
+
* @param descendant - Potential descendant path
|
|
614
|
+
* @returns true if ancestor is a prefix of descendant
|
|
615
|
+
*
|
|
616
|
+
* @example
|
|
617
|
+
* isAncestorPath('/home/user', '/home/user/dev/file.ts') // => true
|
|
618
|
+
* isAncestorPath('/home/user', '/home/user') // => true (same path)
|
|
619
|
+
* isAncestorPath('/home/user', '/home/other') // => false
|
|
620
|
+
*
|
|
621
|
+
* @public
|
|
622
|
+
*/
|
|
623
|
+
export declare function isAncestorPath(ancestor: string, descendant: string): boolean;
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Check if an automaton's language is empty.
|
|
627
|
+
*
|
|
628
|
+
* Uses reachability analysis from the initial state to any accepting state.
|
|
629
|
+
*
|
|
630
|
+
* @param automaton - The automaton to check
|
|
631
|
+
* @returns true if the automaton accepts no strings
|
|
632
|
+
*
|
|
633
|
+
* @public
|
|
634
|
+
*/
|
|
635
|
+
export declare function isEmpty(automaton: SegmentAutomaton): boolean;
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Check if a pattern contains a globstar (**).
|
|
639
|
+
*
|
|
640
|
+
* @param pattern - Pattern AST
|
|
641
|
+
* @returns true if pattern is unbounded
|
|
642
|
+
*
|
|
643
|
+
* @public
|
|
644
|
+
*/
|
|
645
|
+
export declare function isUnbounded(pattern: PathPattern): boolean;
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Check if a pattern is valid (has no errors).
|
|
649
|
+
*
|
|
650
|
+
* @param pattern - The pattern to check
|
|
651
|
+
* @returns true if the pattern has no errors
|
|
652
|
+
*
|
|
653
|
+
* @public
|
|
654
|
+
*/
|
|
655
|
+
export declare function isValidPattern(pattern: PathPattern): boolean;
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* An exact literal match for a path segment.
|
|
659
|
+
*
|
|
660
|
+
* @example "package.json" matches only "package.json"
|
|
661
|
+
*
|
|
662
|
+
* @public
|
|
663
|
+
*/
|
|
664
|
+
export declare interface LiteralSegment {
|
|
665
|
+
readonly type: 'literal';
|
|
666
|
+
readonly value: string;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Transition on an exact segment match.
|
|
671
|
+
* @public
|
|
672
|
+
*/
|
|
673
|
+
export declare interface LiteralTransition {
|
|
674
|
+
readonly type: 'literal';
|
|
675
|
+
readonly segment: string;
|
|
676
|
+
/** Target state ID */
|
|
677
|
+
readonly target: number;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Test if a path matches a compiled pattern.
|
|
682
|
+
*
|
|
683
|
+
* @param path - Absolute, normalized path (e.g., "/home/user/dev/foo.ts")
|
|
684
|
+
* @param pattern - Compiled pattern
|
|
685
|
+
* @returns true if path matches
|
|
686
|
+
*
|
|
687
|
+
* @public
|
|
688
|
+
*/
|
|
689
|
+
export declare function matchPath(path: string, pattern: CompiledPattern): boolean;
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Match a path against a pattern AST directly (without compilation).
|
|
693
|
+
*
|
|
694
|
+
* This is less efficient than using compiled patterns but useful for one-off matching.
|
|
695
|
+
*
|
|
696
|
+
* @param path - Normalized path
|
|
697
|
+
* @param pattern - Pattern AST
|
|
698
|
+
* @returns true if path matches
|
|
699
|
+
*
|
|
700
|
+
* @public
|
|
701
|
+
*/
|
|
702
|
+
export declare function matchPathDirect(path: string, pattern: PathPattern): boolean;
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Match a path with context (for ~ expansion and relative paths).
|
|
706
|
+
*
|
|
707
|
+
* @param path - Path to match (may be relative or contain ~)
|
|
708
|
+
* @param pattern - Compiled pattern
|
|
709
|
+
* @param context - Path context for normalization
|
|
710
|
+
* @returns true if normalized path matches
|
|
711
|
+
*
|
|
712
|
+
* @public
|
|
713
|
+
*/
|
|
714
|
+
export declare function matchPathWithContext(path: string, pattern: CompiledPattern, context: PathContext): boolean;
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Check if a path segment matches a segment pattern.
|
|
718
|
+
*
|
|
719
|
+
* @param segment - The actual path segment (e.g., "file.ts")
|
|
720
|
+
* @param pattern - The pattern segment from AST
|
|
721
|
+
* @returns true if the segment matches
|
|
722
|
+
*
|
|
723
|
+
* @public
|
|
724
|
+
*/
|
|
725
|
+
export declare function matchSegment(segment: string, pattern: Segment): boolean;
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Normalize a path to absolute form for consistent matching.
|
|
729
|
+
*
|
|
730
|
+
* Handles:
|
|
731
|
+
* - ~ expansion to home directory
|
|
732
|
+
* - Relative path resolution against cwd
|
|
733
|
+
* - . and .. resolution
|
|
734
|
+
* - Trailing slash normalization (removed)
|
|
735
|
+
* - Duplicate slash removal
|
|
736
|
+
* - Backslash to forward slash conversion (Windows compatibility)
|
|
737
|
+
*
|
|
738
|
+
* @param path - Input path (may be relative or contain ~)
|
|
739
|
+
* @param context - Context for resolution
|
|
740
|
+
* @returns Absolute, normalized path
|
|
741
|
+
*
|
|
742
|
+
* @public
|
|
743
|
+
*/
|
|
744
|
+
export declare function normalizePath(path: string, context: PathContext): string;
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Parse a pattern string into an AST.
|
|
748
|
+
*
|
|
749
|
+
* @param source - The pattern string to parse
|
|
750
|
+
* @returns Parsed PathPattern with AST and any errors
|
|
751
|
+
*
|
|
752
|
+
* @public
|
|
753
|
+
*/
|
|
754
|
+
export declare function parsePattern(source: string): PathPattern;
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Context for path resolution operations.
|
|
758
|
+
* @public
|
|
759
|
+
*/
|
|
760
|
+
export declare interface PathContext {
|
|
761
|
+
/** User's home directory for ~ expansion */
|
|
762
|
+
readonly homeDir: string;
|
|
763
|
+
/** Current working directory for relative path resolution */
|
|
764
|
+
readonly cwd: string;
|
|
765
|
+
/** Optional project root for project-relative patterns */
|
|
766
|
+
readonly projectRoot?: string;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Root pattern node - the entry point for any parsed pattern.
|
|
771
|
+
* @public
|
|
772
|
+
*/
|
|
773
|
+
export declare interface PathPattern {
|
|
774
|
+
/** Original pattern string for error messages and debugging */
|
|
775
|
+
readonly source: string;
|
|
776
|
+
/** Parsed structure */
|
|
777
|
+
readonly root: PatternNode;
|
|
778
|
+
/** Whether this is an absolute pattern (starts with / or ~) */
|
|
779
|
+
readonly isAbsolute: boolean;
|
|
780
|
+
/** Whether this is a negation pattern (starts with !) */
|
|
781
|
+
readonly isNegation: boolean;
|
|
782
|
+
/** Validation errors, if any */
|
|
783
|
+
readonly errors?: readonly PatternError[];
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Split a normalized path into segments.
|
|
788
|
+
*
|
|
789
|
+
* @param path - A normalized absolute path (starting with /)
|
|
790
|
+
* @returns Array of path segments (excluding the root)
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* pathToSegments('/home/user/dev/file.ts')
|
|
794
|
+
* // => ['home', 'user', 'dev', 'file.ts']
|
|
795
|
+
*
|
|
796
|
+
* @public
|
|
797
|
+
*/
|
|
798
|
+
export declare function pathToSegments(path: string): readonly string[];
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Detailed analysis of two patterns' relationship.
|
|
802
|
+
*
|
|
803
|
+
* Provides comprehensive data for understanding how two patterns relate,
|
|
804
|
+
* including the intersection and set differences.
|
|
805
|
+
*
|
|
806
|
+
* @public
|
|
807
|
+
*/
|
|
808
|
+
export declare interface PatternAnalysis {
|
|
809
|
+
readonly patternA: string;
|
|
810
|
+
readonly patternB: string;
|
|
811
|
+
readonly relationship: PatternRelationship;
|
|
812
|
+
/** Full containment result with explanation */
|
|
813
|
+
readonly containment: ContainmentResult;
|
|
814
|
+
/** Description of paths matching both patterns */
|
|
815
|
+
readonly intersection: PatternDescription;
|
|
816
|
+
/** Description of paths matching A but not B */
|
|
817
|
+
readonly aMinusB: PatternDescription;
|
|
818
|
+
/** Description of paths matching B but not A */
|
|
819
|
+
readonly bMinusA: PatternDescription;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Compute the complement of a pattern.
|
|
824
|
+
*
|
|
825
|
+
* The result matches paths that do NOT match the input pattern.
|
|
826
|
+
* L(result) = Σ* - L(a)
|
|
827
|
+
*
|
|
828
|
+
* @param a - Pattern to complement
|
|
829
|
+
* @returns Pattern matching paths not matched by a
|
|
830
|
+
*
|
|
831
|
+
* @public
|
|
832
|
+
*/
|
|
833
|
+
export declare function patternComplement(a: CompiledPattern): CompiledPattern;
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* A human-readable description of a set of paths.
|
|
837
|
+
* @public
|
|
838
|
+
*/
|
|
839
|
+
export declare interface PatternDescription {
|
|
840
|
+
/** Is this set empty? */
|
|
841
|
+
readonly isEmpty: boolean;
|
|
842
|
+
/** Example paths from this set (if non-empty) */
|
|
843
|
+
readonly examples?: readonly string[];
|
|
844
|
+
/** Pattern representation (if expressible as a single pattern) */
|
|
845
|
+
readonly pattern?: string;
|
|
846
|
+
/** Natural language description */
|
|
847
|
+
readonly description: string;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Compute the difference of two patterns.
|
|
852
|
+
*
|
|
853
|
+
* The result matches paths that match a but NOT b.
|
|
854
|
+
* L(result) = L(a) - L(b) = L(a) ∩ L(¬b)
|
|
855
|
+
*
|
|
856
|
+
* @param a - Pattern to subtract from
|
|
857
|
+
* @param b - Pattern to subtract
|
|
858
|
+
* @returns Pattern matching paths in a but not in b
|
|
859
|
+
*
|
|
860
|
+
* @public
|
|
861
|
+
*/
|
|
862
|
+
export declare function patternDifference(a: CompiledPattern, b: CompiledPattern): CompiledPattern;
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* A pattern validation error with location information.
|
|
866
|
+
* @public
|
|
867
|
+
*/
|
|
868
|
+
export declare interface PatternError {
|
|
869
|
+
/** Error classification code */
|
|
870
|
+
readonly code: PatternErrorCode;
|
|
871
|
+
/** Human-readable error description */
|
|
872
|
+
readonly message: string;
|
|
873
|
+
/** Character position in source where error starts */
|
|
874
|
+
readonly position?: number;
|
|
875
|
+
/** Length of the problematic section */
|
|
876
|
+
readonly length?: number;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Error codes for pattern validation failures.
|
|
881
|
+
* @public
|
|
882
|
+
*/
|
|
883
|
+
export declare type PatternErrorCode = 'INVALID_GLOBSTAR' | 'UNCLOSED_BRACKET' | 'UNCLOSED_BRACE' | 'EMPTY_CHARCLASS' | 'INVALID_RANGE' | 'EXPANSION_LIMIT' | 'NESTED_BRACES' | 'INVALID_ESCAPE' | 'BANNED_FEATURE' | 'INVALID_REGEX' | 'UNSAFE_REGEX' | 'DFA_STATE_LIMIT';
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Compute the intersection of two patterns.
|
|
887
|
+
*
|
|
888
|
+
* The result matches paths that match BOTH input patterns.
|
|
889
|
+
* L(result) = L(a) ∩ L(b)
|
|
890
|
+
*
|
|
891
|
+
* @param a - First pattern
|
|
892
|
+
* @param b - Second pattern
|
|
893
|
+
* @returns Pattern matching paths in both a and b
|
|
894
|
+
*
|
|
895
|
+
* @public
|
|
896
|
+
*/
|
|
897
|
+
export declare function patternIntersect(a: CompiledPattern, b: CompiledPattern): CompiledPattern;
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* A node in the pattern AST. Patterns are sequences of segments or alternations.
|
|
901
|
+
* @public
|
|
902
|
+
*/
|
|
903
|
+
export declare type PatternNode = SegmentSequence | Alternation;
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Describes the relationship between two pattern sets.
|
|
907
|
+
* @public
|
|
908
|
+
*/
|
|
909
|
+
export declare type PatternRelationship = 'subset' | 'equal' | 'superset' | 'overlapping' | 'disjoint';
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Compute the union of two patterns.
|
|
913
|
+
*
|
|
914
|
+
* The result matches paths that match EITHER input pattern.
|
|
915
|
+
* L(result) = L(a) ∪ L(b)
|
|
916
|
+
*
|
|
917
|
+
* @param a - First pattern
|
|
918
|
+
* @param b - Second pattern
|
|
919
|
+
* @returns Pattern matching paths in a or b (or both)
|
|
920
|
+
*
|
|
921
|
+
* @public
|
|
922
|
+
*/
|
|
923
|
+
export declare function patternUnion(a: CompiledPattern, b: CompiledPattern): CompiledPattern;
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Comparison of required path prefixes.
|
|
927
|
+
* @public
|
|
928
|
+
*/
|
|
929
|
+
export declare interface PrefixComparison {
|
|
930
|
+
/** Whether the required prefixes differ between patterns */
|
|
931
|
+
readonly differ: boolean;
|
|
932
|
+
/** Required prefix for pattern A (if any) */
|
|
933
|
+
readonly patternAPrefix?: string;
|
|
934
|
+
/** Required prefix for pattern B (if any) */
|
|
935
|
+
readonly patternBPrefix?: string;
|
|
936
|
+
/** Human-readable explanation of the difference */
|
|
937
|
+
readonly explanation?: string;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/**
|
|
941
|
+
* Quick rejection filters for fast path elimination.
|
|
942
|
+
* @public
|
|
943
|
+
*/
|
|
944
|
+
export declare interface QuickRejectFilter {
|
|
945
|
+
/** If pattern requires specific prefix, check it first */
|
|
946
|
+
readonly requiredPrefix?: string;
|
|
947
|
+
/** If pattern requires specific suffix, check it first */
|
|
948
|
+
readonly requiredSuffix?: string;
|
|
949
|
+
/** Minimum path length (characters) */
|
|
950
|
+
readonly minLength?: number;
|
|
951
|
+
/** Required literal segments that must appear somewhere */
|
|
952
|
+
readonly requiredLiterals?: readonly string[];
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* A segment represents one path component between slashes.
|
|
957
|
+
* @public
|
|
958
|
+
*/
|
|
959
|
+
export declare type Segment = LiteralSegment | WildcardSegment | GlobstarSegment | CharClassSegment | CompositeSegment;
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* A finite automaton that operates on path segments rather than characters.
|
|
963
|
+
*
|
|
964
|
+
* Key insight: treating segments as tokens rather than character-by-character
|
|
965
|
+
* matching dramatically simplifies the automaton and enables efficient
|
|
966
|
+
* containment checking.
|
|
967
|
+
*
|
|
968
|
+
* Alphabet:
|
|
969
|
+
* - Each literal segment is a symbol
|
|
970
|
+
* - "*" matches any single segment (wildcard transition)
|
|
971
|
+
* - "**" is an epsilon loop (zero or more segments)
|
|
972
|
+
*
|
|
973
|
+
* This representation supports:
|
|
974
|
+
* - O(n) matching where n is number of path segments
|
|
975
|
+
* - Standard automaton operations (union, intersection, complement)
|
|
976
|
+
* - Containment checking via (A ∩ B̄ = ∅)
|
|
977
|
+
*
|
|
978
|
+
* @public
|
|
979
|
+
*/
|
|
980
|
+
export declare interface SegmentAutomaton {
|
|
981
|
+
/** All states in the automaton */
|
|
982
|
+
readonly states: readonly AutomatonState[];
|
|
983
|
+
/** Index of the initial state */
|
|
984
|
+
readonly initialState: number;
|
|
985
|
+
/** Indices of accepting (final) states */
|
|
986
|
+
readonly acceptingStates: readonly number[];
|
|
987
|
+
/** Whether this automaton is deterministic */
|
|
988
|
+
readonly isDeterministic: boolean;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Comparison of what patterns allow at a specific segment position.
|
|
993
|
+
* @public
|
|
994
|
+
*/
|
|
995
|
+
export declare interface SegmentComparisonEntry {
|
|
996
|
+
/** Segment position (0-indexed from path root) */
|
|
997
|
+
readonly position: number;
|
|
998
|
+
/** What pattern A allows at this position */
|
|
999
|
+
readonly patternAAllows: SegmentConstraint;
|
|
1000
|
+
/** What pattern B allows at this position */
|
|
1001
|
+
readonly patternBAllows: SegmentConstraint;
|
|
1002
|
+
/** Whether A's constraint is a subset of B's at this position */
|
|
1003
|
+
readonly aSubsetOfB: boolean;
|
|
1004
|
+
/** Brief description of the difference (if any) */
|
|
1005
|
+
readonly difference?: string;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/**
|
|
1009
|
+
* Describes what a pattern allows at a segment position.
|
|
1010
|
+
* @public
|
|
1011
|
+
*/
|
|
1012
|
+
export declare interface SegmentConstraint {
|
|
1013
|
+
/** The type of constraint */
|
|
1014
|
+
readonly type: SegmentConstraintType;
|
|
1015
|
+
/** For literal: the exact value required */
|
|
1016
|
+
readonly literalValue?: string;
|
|
1017
|
+
/** For wildcard: the pattern (e.g., "*.ts") */
|
|
1018
|
+
readonly wildcardPattern?: string;
|
|
1019
|
+
/** For charclass: description of allowed characters */
|
|
1020
|
+
readonly charclassDescription?: string;
|
|
1021
|
+
/** Whether this position can be skipped (due to ** before it) */
|
|
1022
|
+
readonly optional: boolean;
|
|
1023
|
+
/** Whether this position can repeat (is within a ** range) */
|
|
1024
|
+
readonly repeatable: boolean;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Types of segment constraints.
|
|
1029
|
+
* @public
|
|
1030
|
+
*/
|
|
1031
|
+
export declare type SegmentConstraintType = 'literal' | 'wildcard' | 'charclass' | 'any' | 'any_sequence' | 'end' | 'unreachable';
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* A pattern matcher that can test if a segment matches.
|
|
1035
|
+
* This can be either a native RegExp or a composite pattern.
|
|
1036
|
+
* @public
|
|
1037
|
+
*/
|
|
1038
|
+
declare interface SegmentMatcher {
|
|
1039
|
+
/** Test if a string matches the pattern */
|
|
1040
|
+
test(str: string): boolean;
|
|
1041
|
+
/** The pattern source for debugging/serialization */
|
|
1042
|
+
readonly source: string;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* A part of a composite segment.
|
|
1047
|
+
* @public
|
|
1048
|
+
*/
|
|
1049
|
+
export declare type SegmentPart = {
|
|
1050
|
+
readonly type: 'literal';
|
|
1051
|
+
readonly value: string;
|
|
1052
|
+
} | {
|
|
1053
|
+
readonly type: 'star';
|
|
1054
|
+
} | {
|
|
1055
|
+
readonly type: 'question';
|
|
1056
|
+
} | {
|
|
1057
|
+
readonly type: 'charclass';
|
|
1058
|
+
readonly spec: CharClassSegment;
|
|
1059
|
+
};
|
|
1060
|
+
|
|
1061
|
+
/**
|
|
1062
|
+
* A sequence of path segments (the most common case).
|
|
1063
|
+
*
|
|
1064
|
+
* @example
|
|
1065
|
+
* "src/**\/*.ts" becomes:
|
|
1066
|
+
* segments: [Literal("src"), Globstar, Wildcard("*.ts")]
|
|
1067
|
+
*
|
|
1068
|
+
* @public
|
|
1069
|
+
*/
|
|
1070
|
+
export declare interface SegmentSequence {
|
|
1071
|
+
readonly type: 'sequence';
|
|
1072
|
+
readonly segments: readonly Segment[];
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* Join segments back into a path.
|
|
1077
|
+
*
|
|
1078
|
+
* @param segments - Array of path segments
|
|
1079
|
+
* @returns Absolute path string
|
|
1080
|
+
*
|
|
1081
|
+
* @example
|
|
1082
|
+
* segmentsToPath(['home', 'user', 'dev', 'file.ts'])
|
|
1083
|
+
* // => '/home/user/dev/file.ts'
|
|
1084
|
+
*
|
|
1085
|
+
* @public
|
|
1086
|
+
*/
|
|
1087
|
+
export declare function segmentsToPath(segments: readonly string[]): string;
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* Build a RegExp from a segment pattern for automaton transitions.
|
|
1091
|
+
*
|
|
1092
|
+
* @param pattern - Segment pattern
|
|
1093
|
+
* @returns RegExp that matches the segment, or null for globstar/literal
|
|
1094
|
+
*
|
|
1095
|
+
* @public
|
|
1096
|
+
*/
|
|
1097
|
+
export declare function segmentToRegex(pattern: Segment): RegExp | null;
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* High-level structural differences between patterns.
|
|
1101
|
+
* @public
|
|
1102
|
+
*/
|
|
1103
|
+
export declare interface StructuralDifferences {
|
|
1104
|
+
/** Whether patterns have different depth bounds */
|
|
1105
|
+
readonly depthDifference: DepthComparison;
|
|
1106
|
+
/** Whether patterns require different prefixes */
|
|
1107
|
+
readonly prefixDifference: PrefixComparison;
|
|
1108
|
+
/** Whether patterns require different suffixes */
|
|
1109
|
+
readonly suffixDifference: SuffixComparison;
|
|
1110
|
+
/** Whether one pattern is anchored and the other isn't */
|
|
1111
|
+
readonly anchoringDifference: AnchoringComparison;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Comparison of required path suffixes (e.g., file extensions).
|
|
1116
|
+
* @public
|
|
1117
|
+
*/
|
|
1118
|
+
export declare interface SuffixComparison {
|
|
1119
|
+
/** Whether the required suffixes differ between patterns */
|
|
1120
|
+
readonly differ: boolean;
|
|
1121
|
+
/** Required suffix for pattern A (e.g., ".ts") */
|
|
1122
|
+
readonly patternASuffix?: string;
|
|
1123
|
+
/** Required suffix for pattern B (e.g., ".js") */
|
|
1124
|
+
readonly patternBSuffix?: string;
|
|
1125
|
+
/** Human-readable explanation of the difference */
|
|
1126
|
+
readonly explanation?: string;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/**
|
|
1130
|
+
* Get a human-readable summary of the relationship between patterns.
|
|
1131
|
+
*
|
|
1132
|
+
* @param relationship - The pattern relationship
|
|
1133
|
+
* @param patternA - Source of pattern A
|
|
1134
|
+
* @param patternB - Source of pattern B
|
|
1135
|
+
* @returns Human-readable description
|
|
1136
|
+
*
|
|
1137
|
+
* @public
|
|
1138
|
+
*/
|
|
1139
|
+
export declare function summarizeRelationship(relationship: PatternRelationship, patternA: string, patternB: string): string;
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Compute the union of two automata using NFA construction.
|
|
1143
|
+
*
|
|
1144
|
+
* The resulting automaton accepts a string iff either input automaton accepts it.
|
|
1145
|
+
* L(A ∪ B) = L(A) ∪ L(B)
|
|
1146
|
+
*
|
|
1147
|
+
* We use NFA union: create a new initial state with epsilon transitions
|
|
1148
|
+
* to both automata's initial states, then merge the states.
|
|
1149
|
+
*
|
|
1150
|
+
* @param a - First automaton
|
|
1151
|
+
* @param b - Second automaton
|
|
1152
|
+
* @returns Union automaton (NFA)
|
|
1153
|
+
*
|
|
1154
|
+
* @public
|
|
1155
|
+
*/
|
|
1156
|
+
export declare function union(a: SegmentAutomaton, b: SegmentAutomaton): SegmentAutomaton;
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* Validate a pattern against the allowed feature set.
|
|
1160
|
+
*
|
|
1161
|
+
* Returns errors for:
|
|
1162
|
+
* - Patterns that already have errors from parsing
|
|
1163
|
+
* - Invalid globstar usage
|
|
1164
|
+
* - Empty patterns
|
|
1165
|
+
* - Other structural issues
|
|
1166
|
+
*
|
|
1167
|
+
* @param pattern - The parsed pattern to validate
|
|
1168
|
+
* @returns Array of validation errors (empty if valid)
|
|
1169
|
+
*
|
|
1170
|
+
* @public
|
|
1171
|
+
*/
|
|
1172
|
+
export declare function validatePattern(pattern: PathPattern): readonly PatternError[];
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Library version.
|
|
1176
|
+
* @public
|
|
1177
|
+
*/
|
|
1178
|
+
export declare const version = "0.0.0";
|
|
1179
|
+
|
|
1180
|
+
/**
|
|
1181
|
+
* A part of a wildcard segment pattern.
|
|
1182
|
+
* @public
|
|
1183
|
+
*/
|
|
1184
|
+
export declare type WildcardPart = {
|
|
1185
|
+
readonly type: 'literal';
|
|
1186
|
+
readonly value: string;
|
|
1187
|
+
} | {
|
|
1188
|
+
readonly type: 'star';
|
|
1189
|
+
} | {
|
|
1190
|
+
readonly type: 'question';
|
|
1191
|
+
};
|
|
1192
|
+
|
|
1193
|
+
/**
|
|
1194
|
+
* A segment containing wildcards (* or ?).
|
|
1195
|
+
*
|
|
1196
|
+
* Compiles to a regex pattern for the segment.
|
|
1197
|
+
*
|
|
1198
|
+
* @example
|
|
1199
|
+
* "*.ts" -> parts: [{ type: "star" }, { type: "literal", value: ".ts" }]
|
|
1200
|
+
* "test-*-spec.js" -> complex pattern
|
|
1201
|
+
*
|
|
1202
|
+
* @public
|
|
1203
|
+
*/
|
|
1204
|
+
export declare interface WildcardSegment {
|
|
1205
|
+
readonly type: 'wildcard';
|
|
1206
|
+
/** Original pattern text for this segment */
|
|
1207
|
+
readonly pattern: string;
|
|
1208
|
+
/** Components for efficient prefix/suffix matching */
|
|
1209
|
+
readonly parts: readonly WildcardPart[];
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* Transition matching any single segment (from * or ?).
|
|
1214
|
+
* May have constraints from character classes or wildcards.
|
|
1215
|
+
* @public
|
|
1216
|
+
*/
|
|
1217
|
+
export declare interface WildcardTransition {
|
|
1218
|
+
readonly type: 'wildcard';
|
|
1219
|
+
/** Pattern for segment matching (from *.ts, test-*, etc.) */
|
|
1220
|
+
readonly pattern: RegExp | SegmentMatcher;
|
|
1221
|
+
/** Original pattern string for serialization/debugging */
|
|
1222
|
+
readonly patternSource: string;
|
|
1223
|
+
readonly target: number;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Classification of witness paths for explanation generation.
|
|
1228
|
+
* @public
|
|
1229
|
+
*/
|
|
1230
|
+
export declare type WitnessCategory = 'counterexample' | 'reverse_counterexample' | 'shared' | 'neither';
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* A witness path that demonstrates a containment property.
|
|
1234
|
+
* @public
|
|
1235
|
+
*/
|
|
1236
|
+
export declare interface WitnessPath {
|
|
1237
|
+
/** The actual path string */
|
|
1238
|
+
readonly path: string;
|
|
1239
|
+
/** Which pattern(s) this path matches */
|
|
1240
|
+
readonly matchesA: boolean;
|
|
1241
|
+
readonly matchesB: boolean;
|
|
1242
|
+
/**
|
|
1243
|
+
* For counterexamples, the segment index where patterns diverge.
|
|
1244
|
+
* Useful for highlighting the specific point of difference.
|
|
1245
|
+
*/
|
|
1246
|
+
readonly divergenceIndex?: number;
|
|
1247
|
+
/**
|
|
1248
|
+
* Human-oriented classification of this witness.
|
|
1249
|
+
*/
|
|
1250
|
+
readonly category: WitnessCategory;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
export { }
|