driftdetect-core 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/dist/analyzers/ast-analyzer.d.ts +251 -0
- package/dist/analyzers/ast-analyzer.d.ts.map +1 -0
- package/dist/analyzers/ast-analyzer.js +548 -0
- package/dist/analyzers/ast-analyzer.js.map +1 -0
- package/dist/analyzers/flow-analyzer.d.ts +241 -0
- package/dist/analyzers/flow-analyzer.d.ts.map +1 -0
- package/dist/analyzers/flow-analyzer.js +1219 -0
- package/dist/analyzers/flow-analyzer.js.map +1 -0
- package/dist/analyzers/index.d.ts +18 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +19 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/semantic-analyzer.d.ts +252 -0
- package/dist/analyzers/semantic-analyzer.d.ts.map +1 -0
- package/dist/analyzers/semantic-analyzer.js +1182 -0
- package/dist/analyzers/semantic-analyzer.js.map +1 -0
- package/dist/analyzers/type-analyzer.d.ts +289 -0
- package/dist/analyzers/type-analyzer.d.ts.map +1 -0
- package/dist/analyzers/type-analyzer.js +1269 -0
- package/dist/analyzers/type-analyzer.js.map +1 -0
- package/dist/analyzers/types.d.ts +537 -0
- package/dist/analyzers/types.d.ts.map +1 -0
- package/dist/analyzers/types.js +11 -0
- package/dist/analyzers/types.js.map +1 -0
- package/dist/config/config-loader.d.ts +166 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +429 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/config-validator.d.ts +204 -0
- package/dist/config/config-validator.d.ts.map +1 -0
- package/dist/config/config-validator.js +632 -0
- package/dist/config/config-validator.js.map +1 -0
- package/dist/config/defaults.d.ts +8 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +26 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +10 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +47 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +7 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest/exporter.d.ts +21 -0
- package/dist/manifest/exporter.d.ts.map +1 -0
- package/dist/manifest/exporter.js +339 -0
- package/dist/manifest/exporter.js.map +1 -0
- package/dist/manifest/index.d.ts +14 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +15 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/manifest-store.d.ts +111 -0
- package/dist/manifest/manifest-store.d.ts.map +1 -0
- package/dist/manifest/manifest-store.js +418 -0
- package/dist/manifest/manifest-store.js.map +1 -0
- package/dist/manifest/types.d.ts +238 -0
- package/dist/manifest/types.d.ts.map +1 -0
- package/dist/manifest/types.js +11 -0
- package/dist/manifest/types.js.map +1 -0
- package/dist/matcher/confidence-scorer.d.ts +188 -0
- package/dist/matcher/confidence-scorer.d.ts.map +1 -0
- package/dist/matcher/confidence-scorer.js +302 -0
- package/dist/matcher/confidence-scorer.js.map +1 -0
- package/dist/matcher/index.d.ts +24 -0
- package/dist/matcher/index.d.ts.map +1 -0
- package/dist/matcher/index.js +26 -0
- package/dist/matcher/index.js.map +1 -0
- package/dist/matcher/outlier-detector.d.ts +252 -0
- package/dist/matcher/outlier-detector.d.ts.map +1 -0
- package/dist/matcher/outlier-detector.js +544 -0
- package/dist/matcher/outlier-detector.js.map +1 -0
- package/dist/matcher/pattern-matcher.d.ts +169 -0
- package/dist/matcher/pattern-matcher.d.ts.map +1 -0
- package/dist/matcher/pattern-matcher.js +692 -0
- package/dist/matcher/pattern-matcher.js.map +1 -0
- package/dist/matcher/types.d.ts +476 -0
- package/dist/matcher/types.d.ts.map +1 -0
- package/dist/matcher/types.js +36 -0
- package/dist/matcher/types.js.map +1 -0
- package/dist/parsers/base-parser.d.ts +282 -0
- package/dist/parsers/base-parser.d.ts.map +1 -0
- package/dist/parsers/base-parser.js +421 -0
- package/dist/parsers/base-parser.js.map +1 -0
- package/dist/parsers/css-parser.d.ts +225 -0
- package/dist/parsers/css-parser.d.ts.map +1 -0
- package/dist/parsers/css-parser.js +477 -0
- package/dist/parsers/css-parser.js.map +1 -0
- package/dist/parsers/index.d.ts +15 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +15 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/json-parser.d.ts +219 -0
- package/dist/parsers/json-parser.d.ts.map +1 -0
- package/dist/parsers/json-parser.js +602 -0
- package/dist/parsers/json-parser.js.map +1 -0
- package/dist/parsers/markdown-parser.d.ts +276 -0
- package/dist/parsers/markdown-parser.d.ts.map +1 -0
- package/dist/parsers/markdown-parser.js +731 -0
- package/dist/parsers/markdown-parser.js.map +1 -0
- package/dist/parsers/parser-manager.d.ts +294 -0
- package/dist/parsers/parser-manager.d.ts.map +1 -0
- package/dist/parsers/parser-manager.js +738 -0
- package/dist/parsers/parser-manager.js.map +1 -0
- package/dist/parsers/python-parser.d.ts +204 -0
- package/dist/parsers/python-parser.d.ts.map +1 -0
- package/dist/parsers/python-parser.js +517 -0
- package/dist/parsers/python-parser.js.map +1 -0
- package/dist/parsers/types.d.ts +43 -0
- package/dist/parsers/types.d.ts.map +1 -0
- package/dist/parsers/types.js +7 -0
- package/dist/parsers/types.js.map +1 -0
- package/dist/parsers/typescript-parser.d.ts +264 -0
- package/dist/parsers/typescript-parser.d.ts.map +1 -0
- package/dist/parsers/typescript-parser.js +658 -0
- package/dist/parsers/typescript-parser.js.map +1 -0
- package/dist/rules/evaluator.d.ts +305 -0
- package/dist/rules/evaluator.d.ts.map +1 -0
- package/dist/rules/evaluator.js +579 -0
- package/dist/rules/evaluator.js.map +1 -0
- package/dist/rules/index.d.ts +13 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +13 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/quick-fix-generator.d.ts +334 -0
- package/dist/rules/quick-fix-generator.d.ts.map +1 -0
- package/dist/rules/quick-fix-generator.js +1075 -0
- package/dist/rules/quick-fix-generator.js.map +1 -0
- package/dist/rules/rule-engine.d.ts +241 -0
- package/dist/rules/rule-engine.d.ts.map +1 -0
- package/dist/rules/rule-engine.js +585 -0
- package/dist/rules/rule-engine.js.map +1 -0
- package/dist/rules/severity-manager.d.ts +394 -0
- package/dist/rules/severity-manager.d.ts.map +1 -0
- package/dist/rules/severity-manager.js +619 -0
- package/dist/rules/severity-manager.js.map +1 -0
- package/dist/rules/types.d.ts +370 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +133 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/variant-manager.d.ts +388 -0
- package/dist/rules/variant-manager.d.ts.map +1 -0
- package/dist/rules/variant-manager.js +777 -0
- package/dist/rules/variant-manager.js.map +1 -0
- package/dist/scanner/change-detector.d.ts +164 -0
- package/dist/scanner/change-detector.d.ts.map +1 -0
- package/dist/scanner/change-detector.js +263 -0
- package/dist/scanner/change-detector.js.map +1 -0
- package/dist/scanner/dependency-graph.d.ts +270 -0
- package/dist/scanner/dependency-graph.d.ts.map +1 -0
- package/dist/scanner/dependency-graph.js +436 -0
- package/dist/scanner/dependency-graph.js.map +1 -0
- package/dist/scanner/file-walker.d.ts +127 -0
- package/dist/scanner/file-walker.d.ts.map +1 -0
- package/dist/scanner/file-walker.js +526 -0
- package/dist/scanner/file-walker.js.map +1 -0
- package/dist/scanner/index.d.ts +12 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +12 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/types.d.ts +218 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +10 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/scanner/worker-pool.d.ts +317 -0
- package/dist/scanner/worker-pool.d.ts.map +1 -0
- package/dist/scanner/worker-pool.js +571 -0
- package/dist/scanner/worker-pool.js.map +1 -0
- package/dist/store/cache-manager.d.ts +179 -0
- package/dist/store/cache-manager.d.ts.map +1 -0
- package/dist/store/cache-manager.js +391 -0
- package/dist/store/cache-manager.js.map +1 -0
- package/dist/store/history-store.d.ts +314 -0
- package/dist/store/history-store.d.ts.map +1 -0
- package/dist/store/history-store.js +707 -0
- package/dist/store/history-store.js.map +1 -0
- package/dist/store/index.d.ts +20 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +26 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/lock-file-manager.d.ts +202 -0
- package/dist/store/lock-file-manager.d.ts.map +1 -0
- package/dist/store/lock-file-manager.js +475 -0
- package/dist/store/lock-file-manager.js.map +1 -0
- package/dist/store/pattern-store.d.ts +289 -0
- package/dist/store/pattern-store.d.ts.map +1 -0
- package/dist/store/pattern-store.js +936 -0
- package/dist/store/pattern-store.js.map +1 -0
- package/dist/store/schema-validator.d.ts +159 -0
- package/dist/store/schema-validator.d.ts.map +1 -0
- package/dist/store/schema-validator.js +1096 -0
- package/dist/store/schema-validator.js.map +1 -0
- package/dist/store/types.d.ts +585 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +82 -0
- package/dist/store/types.js.map +1 -0
- package/dist/types/analysis.d.ts +19 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/analysis.js +5 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/common.d.ts +7 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +5 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/patterns.d.ts +40 -0
- package/dist/types/patterns.d.ts.map +1 -0
- package/dist/types/patterns.js +7 -0
- package/dist/types/patterns.js.map +1 -0
- package/dist/types/violations.d.ts +7 -0
- package/dist/types/violations.d.ts.map +1 -0
- package/dist/types/violations.js +7 -0
- package/dist/types/violations.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Parser - Abstract parser interface
|
|
3
|
+
*
|
|
4
|
+
* Defines the common interface for all language parsers.
|
|
5
|
+
* Provides a unified AST query interface across all languages.
|
|
6
|
+
*
|
|
7
|
+
* @requirements 3.5
|
|
8
|
+
*/
|
|
9
|
+
import type { AST, ASTNode, Language, ParseError, ParseResult, Position } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Options for parsing source code
|
|
12
|
+
*/
|
|
13
|
+
export interface ParseOptions {
|
|
14
|
+
/** Optional file path for error reporting */
|
|
15
|
+
filePath?: string;
|
|
16
|
+
/** Whether to include comments in the AST */
|
|
17
|
+
includeComments?: boolean;
|
|
18
|
+
/** Whether to perform incremental parsing */
|
|
19
|
+
incremental?: boolean;
|
|
20
|
+
/** Previous AST for incremental parsing */
|
|
21
|
+
previousAst?: AST;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Options for querying the AST
|
|
25
|
+
*/
|
|
26
|
+
export interface QueryOptions {
|
|
27
|
+
/** Maximum number of results to return */
|
|
28
|
+
limit?: number;
|
|
29
|
+
/** Whether to include nested matches */
|
|
30
|
+
includeNested?: boolean;
|
|
31
|
+
/** Starting position for the search */
|
|
32
|
+
startPosition?: Position;
|
|
33
|
+
/** Ending position for the search */
|
|
34
|
+
endPosition?: Position;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result of an AST traversal
|
|
38
|
+
*/
|
|
39
|
+
export interface TraversalResult {
|
|
40
|
+
/** The visited node */
|
|
41
|
+
node: ASTNode;
|
|
42
|
+
/** Parent node, if any */
|
|
43
|
+
parent: ASTNode | null;
|
|
44
|
+
/** Depth in the tree */
|
|
45
|
+
depth: number;
|
|
46
|
+
/** Path from root to this node (indices) */
|
|
47
|
+
path: number[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Visitor function for AST traversal
|
|
51
|
+
*/
|
|
52
|
+
export type ASTVisitor = (result: TraversalResult) => boolean | void;
|
|
53
|
+
/**
|
|
54
|
+
* Abstract base class for all language parsers.
|
|
55
|
+
*
|
|
56
|
+
* Provides a unified interface for parsing source code and querying ASTs
|
|
57
|
+
* across different languages. Concrete implementations should extend this
|
|
58
|
+
* class and implement the abstract methods.
|
|
59
|
+
*
|
|
60
|
+
* @requirements 3.5 - Unified AST query interface across all languages
|
|
61
|
+
*/
|
|
62
|
+
export declare abstract class BaseParser {
|
|
63
|
+
/**
|
|
64
|
+
* The language this parser handles
|
|
65
|
+
*/
|
|
66
|
+
abstract readonly language: Language;
|
|
67
|
+
/**
|
|
68
|
+
* File extensions this parser can handle
|
|
69
|
+
*/
|
|
70
|
+
abstract readonly extensions: string[];
|
|
71
|
+
/**
|
|
72
|
+
* Parse source code into an AST.
|
|
73
|
+
*
|
|
74
|
+
* @param source - The source code to parse
|
|
75
|
+
* @param filePath - Optional file path for error reporting
|
|
76
|
+
* @returns ParseResult containing the AST or errors
|
|
77
|
+
*
|
|
78
|
+
* @requirements 3.5
|
|
79
|
+
*/
|
|
80
|
+
abstract parse(source: string, filePath?: string): ParseResult;
|
|
81
|
+
/**
|
|
82
|
+
* Parse source code with additional options.
|
|
83
|
+
*
|
|
84
|
+
* @param source - The source code to parse
|
|
85
|
+
* @param options - Parsing options
|
|
86
|
+
* @returns ParseResult containing the AST or errors
|
|
87
|
+
*/
|
|
88
|
+
parseWithOptions(source: string, options?: ParseOptions): ParseResult;
|
|
89
|
+
/**
|
|
90
|
+
* Query the AST for nodes matching a pattern.
|
|
91
|
+
*
|
|
92
|
+
* The pattern syntax depends on the parser implementation but typically
|
|
93
|
+
* supports Tree-sitter query syntax or similar.
|
|
94
|
+
*
|
|
95
|
+
* @param ast - The AST to query
|
|
96
|
+
* @param pattern - The query pattern (e.g., Tree-sitter query string)
|
|
97
|
+
* @returns Array of matching AST nodes
|
|
98
|
+
*
|
|
99
|
+
* @requirements 3.5
|
|
100
|
+
*/
|
|
101
|
+
abstract query(ast: AST, pattern: string): ASTNode[];
|
|
102
|
+
/**
|
|
103
|
+
* Query the AST with additional options.
|
|
104
|
+
*
|
|
105
|
+
* @param ast - The AST to query
|
|
106
|
+
* @param pattern - The query pattern
|
|
107
|
+
* @param options - Query options
|
|
108
|
+
* @returns Array of matching AST nodes
|
|
109
|
+
*/
|
|
110
|
+
queryWithOptions(ast: AST, pattern: string, options?: QueryOptions): ASTNode[];
|
|
111
|
+
/**
|
|
112
|
+
* Check if this parser can handle the given file extension.
|
|
113
|
+
*
|
|
114
|
+
* @param extension - File extension (with or without leading dot)
|
|
115
|
+
* @returns true if this parser can handle the extension
|
|
116
|
+
*/
|
|
117
|
+
canHandle(extension: string): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Traverse the AST depth-first, calling the visitor for each node.
|
|
120
|
+
*
|
|
121
|
+
* @param ast - The AST to traverse
|
|
122
|
+
* @param visitor - Function called for each node. Return false to stop traversal.
|
|
123
|
+
*/
|
|
124
|
+
traverse(ast: AST, visitor: ASTVisitor): void;
|
|
125
|
+
/**
|
|
126
|
+
* Internal recursive traversal helper.
|
|
127
|
+
*/
|
|
128
|
+
private traverseNode;
|
|
129
|
+
/**
|
|
130
|
+
* Find all nodes of a specific type in the AST.
|
|
131
|
+
*
|
|
132
|
+
* @param ast - The AST to search
|
|
133
|
+
* @param nodeType - The type of node to find
|
|
134
|
+
* @returns Array of matching nodes
|
|
135
|
+
*/
|
|
136
|
+
findNodesByType(ast: AST, nodeType: string): ASTNode[];
|
|
137
|
+
/**
|
|
138
|
+
* Find the first node of a specific type in the AST.
|
|
139
|
+
*
|
|
140
|
+
* @param ast - The AST to search
|
|
141
|
+
* @param nodeType - The type of node to find
|
|
142
|
+
* @returns The first matching node, or null if not found
|
|
143
|
+
*/
|
|
144
|
+
findFirstNodeByType(ast: AST, nodeType: string): ASTNode | null;
|
|
145
|
+
/**
|
|
146
|
+
* Find the node at a specific position in the source.
|
|
147
|
+
*
|
|
148
|
+
* @param ast - The AST to search
|
|
149
|
+
* @param position - The position to find
|
|
150
|
+
* @returns The most specific node at that position, or null
|
|
151
|
+
*/
|
|
152
|
+
findNodeAtPosition(ast: AST, position: Position): ASTNode | null;
|
|
153
|
+
/**
|
|
154
|
+
* Get the parent chain from root to a specific node.
|
|
155
|
+
*
|
|
156
|
+
* @param ast - The AST to search
|
|
157
|
+
* @param targetNode - The node to find parents for
|
|
158
|
+
* @returns Array of parent nodes from root to immediate parent
|
|
159
|
+
*/
|
|
160
|
+
getParentChain(ast: AST, targetNode: ASTNode): ASTNode[];
|
|
161
|
+
/**
|
|
162
|
+
* Get all descendants of a node.
|
|
163
|
+
*
|
|
164
|
+
* @param node - The node to get descendants of
|
|
165
|
+
* @returns Array of all descendant nodes
|
|
166
|
+
*/
|
|
167
|
+
getDescendants(node: ASTNode): ASTNode[];
|
|
168
|
+
/**
|
|
169
|
+
* Get siblings of a node (nodes with the same parent).
|
|
170
|
+
*
|
|
171
|
+
* @param ast - The AST containing the node
|
|
172
|
+
* @param node - The node to get siblings for
|
|
173
|
+
* @returns Array of sibling nodes (excluding the node itself)
|
|
174
|
+
*/
|
|
175
|
+
getSiblings(ast: AST, node: ASTNode): ASTNode[];
|
|
176
|
+
/**
|
|
177
|
+
* Create a parse error object.
|
|
178
|
+
*
|
|
179
|
+
* @param message - Error message
|
|
180
|
+
* @param position - Position where the error occurred
|
|
181
|
+
* @returns ParseError object
|
|
182
|
+
*/
|
|
183
|
+
protected createError(message: string, position: Position): ParseError;
|
|
184
|
+
/**
|
|
185
|
+
* Create a successful parse result.
|
|
186
|
+
*
|
|
187
|
+
* @param ast - The parsed AST
|
|
188
|
+
* @returns ParseResult with success=true
|
|
189
|
+
*/
|
|
190
|
+
protected createSuccessResult(ast: AST): ParseResult;
|
|
191
|
+
/**
|
|
192
|
+
* Create a failed parse result.
|
|
193
|
+
*
|
|
194
|
+
* @param errors - Array of parse errors
|
|
195
|
+
* @returns ParseResult with success=false
|
|
196
|
+
*/
|
|
197
|
+
protected createFailureResult(errors: ParseError[]): ParseResult;
|
|
198
|
+
/**
|
|
199
|
+
* Create a partial success result (parsed with errors).
|
|
200
|
+
*
|
|
201
|
+
* @param ast - The partially parsed AST
|
|
202
|
+
* @param errors - Array of parse errors
|
|
203
|
+
* @returns ParseResult with success=true but containing errors
|
|
204
|
+
*/
|
|
205
|
+
protected createPartialResult(ast: AST, errors: ParseError[]): ParseResult;
|
|
206
|
+
/**
|
|
207
|
+
* Check if a position is within a range.
|
|
208
|
+
*
|
|
209
|
+
* @param position - The position to check
|
|
210
|
+
* @param start - Start of the range
|
|
211
|
+
* @param end - End of the range
|
|
212
|
+
* @returns true if position is within the range
|
|
213
|
+
*/
|
|
214
|
+
protected positionInRange(position: Position, start: Position, end: Position): boolean;
|
|
215
|
+
/**
|
|
216
|
+
* Compare two positions.
|
|
217
|
+
*
|
|
218
|
+
* @param a - First position
|
|
219
|
+
* @param b - Second position
|
|
220
|
+
* @returns -1 if a < b, 0 if a === b, 1 if a > b
|
|
221
|
+
*/
|
|
222
|
+
protected comparePositions(a: Position, b: Position): number;
|
|
223
|
+
/**
|
|
224
|
+
* Get the text between two positions in the source.
|
|
225
|
+
*
|
|
226
|
+
* @param source - The source text
|
|
227
|
+
* @param start - Start position
|
|
228
|
+
* @param end - End position
|
|
229
|
+
* @returns The text between the positions
|
|
230
|
+
*/
|
|
231
|
+
protected getTextBetween(source: string, start: Position, end: Position): string;
|
|
232
|
+
/**
|
|
233
|
+
* Create an AST node.
|
|
234
|
+
*
|
|
235
|
+
* @param type - Node type
|
|
236
|
+
* @param text - Node text
|
|
237
|
+
* @param startPosition - Start position
|
|
238
|
+
* @param endPosition - End position
|
|
239
|
+
* @param children - Child nodes
|
|
240
|
+
* @returns ASTNode object
|
|
241
|
+
*/
|
|
242
|
+
protected createNode(type: string, text: string, startPosition: Position, endPosition: Position, children?: ASTNode[]): ASTNode;
|
|
243
|
+
/**
|
|
244
|
+
* Create an AST object.
|
|
245
|
+
*
|
|
246
|
+
* @param rootNode - The root node of the AST
|
|
247
|
+
* @param text - The source text
|
|
248
|
+
* @returns AST object
|
|
249
|
+
*/
|
|
250
|
+
protected createAST(rootNode: ASTNode, text: string): AST;
|
|
251
|
+
/**
|
|
252
|
+
* Check if two nodes are equal (same type, position, and text).
|
|
253
|
+
*
|
|
254
|
+
* @param a - First node
|
|
255
|
+
* @param b - Second node
|
|
256
|
+
* @returns true if nodes are equal
|
|
257
|
+
*/
|
|
258
|
+
protected nodesEqual(a: ASTNode, b: ASTNode): boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Get the depth of a node in the AST.
|
|
261
|
+
*
|
|
262
|
+
* @param ast - The AST containing the node
|
|
263
|
+
* @param node - The node to get depth for
|
|
264
|
+
* @returns The depth (0 for root)
|
|
265
|
+
*/
|
|
266
|
+
getNodeDepth(ast: AST, node: ASTNode): number;
|
|
267
|
+
/**
|
|
268
|
+
* Check if a node is a leaf node (has no children).
|
|
269
|
+
*
|
|
270
|
+
* @param node - The node to check
|
|
271
|
+
* @returns true if the node has no children
|
|
272
|
+
*/
|
|
273
|
+
isLeafNode(node: ASTNode): boolean;
|
|
274
|
+
/**
|
|
275
|
+
* Count the total number of nodes in an AST.
|
|
276
|
+
*
|
|
277
|
+
* @param ast - The AST to count nodes in
|
|
278
|
+
* @returns Total number of nodes
|
|
279
|
+
*/
|
|
280
|
+
countNodes(ast: AST): number;
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=base-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/base-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Parser - Abstract parser interface
|
|
3
|
+
*
|
|
4
|
+
* Defines the common interface for all language parsers.
|
|
5
|
+
* Provides a unified AST query interface across all languages.
|
|
6
|
+
*
|
|
7
|
+
* @requirements 3.5
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Abstract base class for all language parsers.
|
|
11
|
+
*
|
|
12
|
+
* Provides a unified interface for parsing source code and querying ASTs
|
|
13
|
+
* across different languages. Concrete implementations should extend this
|
|
14
|
+
* class and implement the abstract methods.
|
|
15
|
+
*
|
|
16
|
+
* @requirements 3.5 - Unified AST query interface across all languages
|
|
17
|
+
*/
|
|
18
|
+
export class BaseParser {
|
|
19
|
+
/**
|
|
20
|
+
* Parse source code with additional options.
|
|
21
|
+
*
|
|
22
|
+
* @param source - The source code to parse
|
|
23
|
+
* @param options - Parsing options
|
|
24
|
+
* @returns ParseResult containing the AST or errors
|
|
25
|
+
*/
|
|
26
|
+
parseWithOptions(source, options = {}) {
|
|
27
|
+
return this.parse(source, options.filePath);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Query the AST with additional options.
|
|
31
|
+
*
|
|
32
|
+
* @param ast - The AST to query
|
|
33
|
+
* @param pattern - The query pattern
|
|
34
|
+
* @param options - Query options
|
|
35
|
+
* @returns Array of matching AST nodes
|
|
36
|
+
*/
|
|
37
|
+
queryWithOptions(ast, pattern, options = {}) {
|
|
38
|
+
let results = this.query(ast, pattern);
|
|
39
|
+
// Apply position filtering
|
|
40
|
+
if (options.startPosition || options.endPosition) {
|
|
41
|
+
results = results.filter((node) => {
|
|
42
|
+
if (options.startPosition) {
|
|
43
|
+
if (node.endPosition.row < options.startPosition.row ||
|
|
44
|
+
(node.endPosition.row === options.startPosition.row &&
|
|
45
|
+
node.endPosition.column < options.startPosition.column)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (options.endPosition) {
|
|
50
|
+
if (node.startPosition.row > options.endPosition.row ||
|
|
51
|
+
(node.startPosition.row === options.endPosition.row &&
|
|
52
|
+
node.startPosition.column > options.endPosition.column)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Apply limit
|
|
60
|
+
if (options.limit !== undefined && options.limit > 0) {
|
|
61
|
+
results = results.slice(0, options.limit);
|
|
62
|
+
}
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if this parser can handle the given file extension.
|
|
67
|
+
*
|
|
68
|
+
* @param extension - File extension (with or without leading dot)
|
|
69
|
+
* @returns true if this parser can handle the extension
|
|
70
|
+
*/
|
|
71
|
+
canHandle(extension) {
|
|
72
|
+
const normalizedExt = extension.startsWith('.') ? extension : `.${extension}`;
|
|
73
|
+
return this.extensions.includes(normalizedExt.toLowerCase());
|
|
74
|
+
}
|
|
75
|
+
// ============================================
|
|
76
|
+
// AST Traversal Utilities
|
|
77
|
+
// ============================================
|
|
78
|
+
/**
|
|
79
|
+
* Traverse the AST depth-first, calling the visitor for each node.
|
|
80
|
+
*
|
|
81
|
+
* @param ast - The AST to traverse
|
|
82
|
+
* @param visitor - Function called for each node. Return false to stop traversal.
|
|
83
|
+
*/
|
|
84
|
+
traverse(ast, visitor) {
|
|
85
|
+
this.traverseNode(ast.rootNode, null, 0, [], visitor);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Internal recursive traversal helper.
|
|
89
|
+
*/
|
|
90
|
+
traverseNode(node, parent, depth, path, visitor) {
|
|
91
|
+
const result = visitor({ node, parent, depth, path });
|
|
92
|
+
// If visitor returns false, stop traversal
|
|
93
|
+
if (result === false) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
// Traverse children
|
|
97
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
98
|
+
const child = node.children[i];
|
|
99
|
+
if (child) {
|
|
100
|
+
const shouldContinue = this.traverseNode(child, node, depth + 1, [...path, i], visitor);
|
|
101
|
+
if (!shouldContinue) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Find all nodes of a specific type in the AST.
|
|
110
|
+
*
|
|
111
|
+
* @param ast - The AST to search
|
|
112
|
+
* @param nodeType - The type of node to find
|
|
113
|
+
* @returns Array of matching nodes
|
|
114
|
+
*/
|
|
115
|
+
findNodesByType(ast, nodeType) {
|
|
116
|
+
const results = [];
|
|
117
|
+
this.traverse(ast, ({ node }) => {
|
|
118
|
+
if (node.type === nodeType) {
|
|
119
|
+
results.push(node);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Find the first node of a specific type in the AST.
|
|
126
|
+
*
|
|
127
|
+
* @param ast - The AST to search
|
|
128
|
+
* @param nodeType - The type of node to find
|
|
129
|
+
* @returns The first matching node, or null if not found
|
|
130
|
+
*/
|
|
131
|
+
findFirstNodeByType(ast, nodeType) {
|
|
132
|
+
let result = null;
|
|
133
|
+
this.traverse(ast, ({ node }) => {
|
|
134
|
+
if (node.type === nodeType) {
|
|
135
|
+
result = node;
|
|
136
|
+
return false; // Stop traversal
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
});
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Find the node at a specific position in the source.
|
|
144
|
+
*
|
|
145
|
+
* @param ast - The AST to search
|
|
146
|
+
* @param position - The position to find
|
|
147
|
+
* @returns The most specific node at that position, or null
|
|
148
|
+
*/
|
|
149
|
+
findNodeAtPosition(ast, position) {
|
|
150
|
+
let result = null;
|
|
151
|
+
this.traverse(ast, ({ node }) => {
|
|
152
|
+
if (this.positionInRange(position, node.startPosition, node.endPosition)) {
|
|
153
|
+
result = node; // Keep updating to get the most specific (deepest) node
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get the parent chain from root to a specific node.
|
|
160
|
+
*
|
|
161
|
+
* @param ast - The AST to search
|
|
162
|
+
* @param targetNode - The node to find parents for
|
|
163
|
+
* @returns Array of parent nodes from root to immediate parent
|
|
164
|
+
*/
|
|
165
|
+
getParentChain(ast, targetNode) {
|
|
166
|
+
const parents = [];
|
|
167
|
+
let found = false;
|
|
168
|
+
const findParents = (node, chain) => {
|
|
169
|
+
if (node === targetNode) {
|
|
170
|
+
parents.push(...chain);
|
|
171
|
+
found = true;
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
for (const child of node.children) {
|
|
175
|
+
if (findParents(child, [...chain, node])) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return found;
|
|
180
|
+
};
|
|
181
|
+
findParents(ast.rootNode, []);
|
|
182
|
+
return parents;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get all descendants of a node.
|
|
186
|
+
*
|
|
187
|
+
* @param node - The node to get descendants of
|
|
188
|
+
* @returns Array of all descendant nodes
|
|
189
|
+
*/
|
|
190
|
+
getDescendants(node) {
|
|
191
|
+
const descendants = [];
|
|
192
|
+
const collect = (n) => {
|
|
193
|
+
for (const child of n.children) {
|
|
194
|
+
descendants.push(child);
|
|
195
|
+
collect(child);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
collect(node);
|
|
199
|
+
return descendants;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get siblings of a node (nodes with the same parent).
|
|
203
|
+
*
|
|
204
|
+
* @param ast - The AST containing the node
|
|
205
|
+
* @param node - The node to get siblings for
|
|
206
|
+
* @returns Array of sibling nodes (excluding the node itself)
|
|
207
|
+
*/
|
|
208
|
+
getSiblings(ast, node) {
|
|
209
|
+
const parents = this.getParentChain(ast, node);
|
|
210
|
+
if (parents.length === 0) {
|
|
211
|
+
return []; // Root node has no siblings
|
|
212
|
+
}
|
|
213
|
+
const parent = parents[parents.length - 1];
|
|
214
|
+
if (!parent) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
return parent.children.filter((child) => child !== node);
|
|
218
|
+
}
|
|
219
|
+
// ============================================
|
|
220
|
+
// Error Handling Utilities
|
|
221
|
+
// ============================================
|
|
222
|
+
/**
|
|
223
|
+
* Create a parse error object.
|
|
224
|
+
*
|
|
225
|
+
* @param message - Error message
|
|
226
|
+
* @param position - Position where the error occurred
|
|
227
|
+
* @returns ParseError object
|
|
228
|
+
*/
|
|
229
|
+
createError(message, position) {
|
|
230
|
+
return { message, position };
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Create a successful parse result.
|
|
234
|
+
*
|
|
235
|
+
* @param ast - The parsed AST
|
|
236
|
+
* @returns ParseResult with success=true
|
|
237
|
+
*/
|
|
238
|
+
createSuccessResult(ast) {
|
|
239
|
+
return {
|
|
240
|
+
ast,
|
|
241
|
+
language: this.language,
|
|
242
|
+
errors: [],
|
|
243
|
+
success: true,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Create a failed parse result.
|
|
248
|
+
*
|
|
249
|
+
* @param errors - Array of parse errors
|
|
250
|
+
* @returns ParseResult with success=false
|
|
251
|
+
*/
|
|
252
|
+
createFailureResult(errors) {
|
|
253
|
+
return {
|
|
254
|
+
ast: null,
|
|
255
|
+
language: this.language,
|
|
256
|
+
errors,
|
|
257
|
+
success: false,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Create a partial success result (parsed with errors).
|
|
262
|
+
*
|
|
263
|
+
* @param ast - The partially parsed AST
|
|
264
|
+
* @param errors - Array of parse errors
|
|
265
|
+
* @returns ParseResult with success=true but containing errors
|
|
266
|
+
*/
|
|
267
|
+
createPartialResult(ast, errors) {
|
|
268
|
+
return {
|
|
269
|
+
ast,
|
|
270
|
+
language: this.language,
|
|
271
|
+
errors,
|
|
272
|
+
success: true,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// ============================================
|
|
276
|
+
// Position Utilities
|
|
277
|
+
// ============================================
|
|
278
|
+
/**
|
|
279
|
+
* Check if a position is within a range.
|
|
280
|
+
*
|
|
281
|
+
* @param position - The position to check
|
|
282
|
+
* @param start - Start of the range
|
|
283
|
+
* @param end - End of the range
|
|
284
|
+
* @returns true if position is within the range
|
|
285
|
+
*/
|
|
286
|
+
positionInRange(position, start, end) {
|
|
287
|
+
// Check if position is after start
|
|
288
|
+
if (position.row < start.row)
|
|
289
|
+
return false;
|
|
290
|
+
if (position.row === start.row && position.column < start.column)
|
|
291
|
+
return false;
|
|
292
|
+
// Check if position is before end
|
|
293
|
+
if (position.row > end.row)
|
|
294
|
+
return false;
|
|
295
|
+
if (position.row === end.row && position.column > end.column)
|
|
296
|
+
return false;
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Compare two positions.
|
|
301
|
+
*
|
|
302
|
+
* @param a - First position
|
|
303
|
+
* @param b - Second position
|
|
304
|
+
* @returns -1 if a < b, 0 if a === b, 1 if a > b
|
|
305
|
+
*/
|
|
306
|
+
comparePositions(a, b) {
|
|
307
|
+
if (a.row !== b.row) {
|
|
308
|
+
return a.row < b.row ? -1 : 1;
|
|
309
|
+
}
|
|
310
|
+
if (a.column !== b.column) {
|
|
311
|
+
return a.column < b.column ? -1 : 1;
|
|
312
|
+
}
|
|
313
|
+
return 0;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Get the text between two positions in the source.
|
|
317
|
+
*
|
|
318
|
+
* @param source - The source text
|
|
319
|
+
* @param start - Start position
|
|
320
|
+
* @param end - End position
|
|
321
|
+
* @returns The text between the positions
|
|
322
|
+
*/
|
|
323
|
+
getTextBetween(source, start, end) {
|
|
324
|
+
const lines = source.split('\n');
|
|
325
|
+
const result = [];
|
|
326
|
+
for (let row = start.row; row <= end.row; row++) {
|
|
327
|
+
if (row >= lines.length)
|
|
328
|
+
break;
|
|
329
|
+
const line = lines[row];
|
|
330
|
+
if (line === undefined)
|
|
331
|
+
break;
|
|
332
|
+
const startCol = row === start.row ? start.column : 0;
|
|
333
|
+
const endCol = row === end.row ? end.column : line.length;
|
|
334
|
+
result.push(line.slice(startCol, endCol));
|
|
335
|
+
}
|
|
336
|
+
return result.join('\n');
|
|
337
|
+
}
|
|
338
|
+
// ============================================
|
|
339
|
+
// AST Node Utilities
|
|
340
|
+
// ============================================
|
|
341
|
+
/**
|
|
342
|
+
* Create an AST node.
|
|
343
|
+
*
|
|
344
|
+
* @param type - Node type
|
|
345
|
+
* @param text - Node text
|
|
346
|
+
* @param startPosition - Start position
|
|
347
|
+
* @param endPosition - End position
|
|
348
|
+
* @param children - Child nodes
|
|
349
|
+
* @returns ASTNode object
|
|
350
|
+
*/
|
|
351
|
+
createNode(type, text, startPosition, endPosition, children = []) {
|
|
352
|
+
return {
|
|
353
|
+
type,
|
|
354
|
+
text,
|
|
355
|
+
startPosition,
|
|
356
|
+
endPosition,
|
|
357
|
+
children,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Create an AST object.
|
|
362
|
+
*
|
|
363
|
+
* @param rootNode - The root node of the AST
|
|
364
|
+
* @param text - The source text
|
|
365
|
+
* @returns AST object
|
|
366
|
+
*/
|
|
367
|
+
createAST(rootNode, text) {
|
|
368
|
+
return {
|
|
369
|
+
rootNode,
|
|
370
|
+
text,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Check if two nodes are equal (same type, position, and text).
|
|
375
|
+
*
|
|
376
|
+
* @param a - First node
|
|
377
|
+
* @param b - Second node
|
|
378
|
+
* @returns true if nodes are equal
|
|
379
|
+
*/
|
|
380
|
+
nodesEqual(a, b) {
|
|
381
|
+
return (a.type === b.type &&
|
|
382
|
+
a.text === b.text &&
|
|
383
|
+
a.startPosition.row === b.startPosition.row &&
|
|
384
|
+
a.startPosition.column === b.startPosition.column &&
|
|
385
|
+
a.endPosition.row === b.endPosition.row &&
|
|
386
|
+
a.endPosition.column === b.endPosition.column);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get the depth of a node in the AST.
|
|
390
|
+
*
|
|
391
|
+
* @param ast - The AST containing the node
|
|
392
|
+
* @param node - The node to get depth for
|
|
393
|
+
* @returns The depth (0 for root)
|
|
394
|
+
*/
|
|
395
|
+
getNodeDepth(ast, node) {
|
|
396
|
+
return this.getParentChain(ast, node).length;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Check if a node is a leaf node (has no children).
|
|
400
|
+
*
|
|
401
|
+
* @param node - The node to check
|
|
402
|
+
* @returns true if the node has no children
|
|
403
|
+
*/
|
|
404
|
+
isLeafNode(node) {
|
|
405
|
+
return node.children.length === 0;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Count the total number of nodes in an AST.
|
|
409
|
+
*
|
|
410
|
+
* @param ast - The AST to count nodes in
|
|
411
|
+
* @returns Total number of nodes
|
|
412
|
+
*/
|
|
413
|
+
countNodes(ast) {
|
|
414
|
+
let count = 0;
|
|
415
|
+
this.traverse(ast, () => {
|
|
416
|
+
count++;
|
|
417
|
+
});
|
|
418
|
+
return count;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
//# sourceMappingURL=base-parser.js.map
|