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,658 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript Parser - TypeScript/JavaScript parsing using TypeScript Compiler API
|
|
3
|
+
*
|
|
4
|
+
* Extracts imports, exports, classes, functions, interfaces, and type aliases
|
|
5
|
+
* from TypeScript and JavaScript files.
|
|
6
|
+
*
|
|
7
|
+
* @requirements 3.2
|
|
8
|
+
*/
|
|
9
|
+
import ts from 'typescript';
|
|
10
|
+
import { BaseParser } from './base-parser.js';
|
|
11
|
+
/**
|
|
12
|
+
* TypeScript/JavaScript parser using the TypeScript Compiler API.
|
|
13
|
+
*
|
|
14
|
+
* Provides AST parsing and extraction of imports, exports, classes,
|
|
15
|
+
* functions, interfaces, and type aliases.
|
|
16
|
+
*
|
|
17
|
+
* @requirements 3.2 - Support TypeScript and JavaScript
|
|
18
|
+
*/
|
|
19
|
+
export class TypeScriptParser extends BaseParser {
|
|
20
|
+
language = 'typescript';
|
|
21
|
+
extensions = ['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts', '.mjs', '.cjs'];
|
|
22
|
+
/**
|
|
23
|
+
* Parse TypeScript/JavaScript source code into an AST.
|
|
24
|
+
*
|
|
25
|
+
* @param source - The source code to parse
|
|
26
|
+
* @param filePath - Optional file path for error reporting
|
|
27
|
+
* @returns ParseResult containing the AST or errors
|
|
28
|
+
*
|
|
29
|
+
* @requirements 3.2, 3.3
|
|
30
|
+
*/
|
|
31
|
+
parse(source, filePath) {
|
|
32
|
+
const fileName = filePath || 'anonymous.ts';
|
|
33
|
+
const scriptKind = this.getScriptKind(fileName);
|
|
34
|
+
try {
|
|
35
|
+
// Create a source file using TypeScript compiler API
|
|
36
|
+
const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, scriptKind);
|
|
37
|
+
// Convert TypeScript AST to our unified AST format
|
|
38
|
+
const rootNode = this.convertNode(sourceFile, source);
|
|
39
|
+
const ast = this.createAST(rootNode, source);
|
|
40
|
+
// Extract semantic information
|
|
41
|
+
const imports = this.extractImports(sourceFile, source);
|
|
42
|
+
const exports = this.extractExports(sourceFile, source);
|
|
43
|
+
const classes = this.extractClasses(sourceFile, source);
|
|
44
|
+
const functions = this.extractFunctions(sourceFile, source);
|
|
45
|
+
const interfaces = this.extractInterfaces(sourceFile, source);
|
|
46
|
+
const typeAliases = this.extractTypeAliases(sourceFile, source);
|
|
47
|
+
// Check for syntax errors
|
|
48
|
+
const errors = this.extractErrors(sourceFile);
|
|
49
|
+
if (errors.length > 0) {
|
|
50
|
+
return {
|
|
51
|
+
...this.createPartialResult(ast, errors),
|
|
52
|
+
imports,
|
|
53
|
+
exports,
|
|
54
|
+
classes,
|
|
55
|
+
functions,
|
|
56
|
+
interfaces,
|
|
57
|
+
typeAliases,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
...this.createSuccessResult(ast),
|
|
62
|
+
imports,
|
|
63
|
+
exports,
|
|
64
|
+
classes,
|
|
65
|
+
functions,
|
|
66
|
+
interfaces,
|
|
67
|
+
typeAliases,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown parse error';
|
|
72
|
+
return {
|
|
73
|
+
...this.createFailureResult([this.createError(errorMessage, { row: 0, column: 0 })]),
|
|
74
|
+
imports: [],
|
|
75
|
+
exports: [],
|
|
76
|
+
classes: [],
|
|
77
|
+
functions: [],
|
|
78
|
+
interfaces: [],
|
|
79
|
+
typeAliases: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Query the AST for nodes matching a pattern.
|
|
85
|
+
*
|
|
86
|
+
* Supports querying by node type (e.g., 'ImportDeclaration', 'ClassDeclaration').
|
|
87
|
+
*
|
|
88
|
+
* @param ast - The AST to query
|
|
89
|
+
* @param pattern - The node type to search for
|
|
90
|
+
* @returns Array of matching AST nodes
|
|
91
|
+
*
|
|
92
|
+
* @requirements 3.5
|
|
93
|
+
*/
|
|
94
|
+
query(ast, pattern) {
|
|
95
|
+
return this.findNodesByType(ast, pattern);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the TypeScript ScriptKind based on file extension.
|
|
99
|
+
*/
|
|
100
|
+
getScriptKind(fileName) {
|
|
101
|
+
const ext = fileName.toLowerCase().split('.').pop();
|
|
102
|
+
switch (ext) {
|
|
103
|
+
case 'tsx':
|
|
104
|
+
return ts.ScriptKind.TSX;
|
|
105
|
+
case 'jsx':
|
|
106
|
+
return ts.ScriptKind.JSX;
|
|
107
|
+
case 'js':
|
|
108
|
+
case 'mjs':
|
|
109
|
+
case 'cjs':
|
|
110
|
+
return ts.ScriptKind.JS;
|
|
111
|
+
case 'ts':
|
|
112
|
+
case 'mts':
|
|
113
|
+
case 'cts':
|
|
114
|
+
default:
|
|
115
|
+
return ts.ScriptKind.TS;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Convert a TypeScript AST node to our unified AST format.
|
|
120
|
+
*/
|
|
121
|
+
convertNode(node, source) {
|
|
122
|
+
const startPos = this.getPosition(node.getStart(), source);
|
|
123
|
+
const endPos = this.getPosition(node.getEnd(), source);
|
|
124
|
+
const nodeType = ts.SyntaxKind[node.kind];
|
|
125
|
+
const text = node.getText();
|
|
126
|
+
const children = [];
|
|
127
|
+
ts.forEachChild(node, (child) => {
|
|
128
|
+
children.push(this.convertNode(child, source));
|
|
129
|
+
});
|
|
130
|
+
return this.createNode(nodeType, text, startPos, endPos, children);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Convert a character offset to a Position (row, column).
|
|
134
|
+
*/
|
|
135
|
+
getPosition(offset, source) {
|
|
136
|
+
let row = 0;
|
|
137
|
+
let column = 0;
|
|
138
|
+
for (let i = 0; i < offset && i < source.length; i++) {
|
|
139
|
+
if (source[i] === '\n') {
|
|
140
|
+
row++;
|
|
141
|
+
column = 0;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
column++;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return { row, column };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Extract syntax errors from the source file.
|
|
151
|
+
*/
|
|
152
|
+
extractErrors(sourceFile) {
|
|
153
|
+
const errors = [];
|
|
154
|
+
// Get parse diagnostics (syntax errors)
|
|
155
|
+
const diagnostics = sourceFile.parseDiagnostics || [];
|
|
156
|
+
for (const diagnostic of diagnostics) {
|
|
157
|
+
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
|
158
|
+
const position = diagnostic.start !== undefined ? this.getPosition(diagnostic.start, sourceFile.text) : { row: 0, column: 0 };
|
|
159
|
+
errors.push({ message, position });
|
|
160
|
+
}
|
|
161
|
+
return errors;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Extract import information from the source file.
|
|
165
|
+
*/
|
|
166
|
+
extractImports(sourceFile, source) {
|
|
167
|
+
const imports = [];
|
|
168
|
+
const visit = (node) => {
|
|
169
|
+
if (ts.isImportDeclaration(node)) {
|
|
170
|
+
const importInfo = this.parseImportDeclaration(node, source);
|
|
171
|
+
if (importInfo) {
|
|
172
|
+
imports.push(importInfo);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
ts.forEachChild(node, visit);
|
|
176
|
+
};
|
|
177
|
+
visit(sourceFile);
|
|
178
|
+
return imports;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Parse a single import declaration.
|
|
182
|
+
*/
|
|
183
|
+
parseImportDeclaration(node, source) {
|
|
184
|
+
const moduleSpecifier = node.moduleSpecifier.text;
|
|
185
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
186
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
187
|
+
const importInfo = {
|
|
188
|
+
moduleSpecifier,
|
|
189
|
+
namedImports: [],
|
|
190
|
+
defaultImport: null,
|
|
191
|
+
namespaceImport: null,
|
|
192
|
+
isTypeOnly: node.importClause?.isTypeOnly ?? false,
|
|
193
|
+
startPosition,
|
|
194
|
+
endPosition,
|
|
195
|
+
};
|
|
196
|
+
const importClause = node.importClause;
|
|
197
|
+
if (importClause) {
|
|
198
|
+
// Default import
|
|
199
|
+
if (importClause.name) {
|
|
200
|
+
importInfo.defaultImport = importClause.name.text;
|
|
201
|
+
}
|
|
202
|
+
// Named or namespace imports
|
|
203
|
+
const namedBindings = importClause.namedBindings;
|
|
204
|
+
if (namedBindings) {
|
|
205
|
+
if (ts.isNamespaceImport(namedBindings)) {
|
|
206
|
+
importInfo.namespaceImport = namedBindings.name.text;
|
|
207
|
+
}
|
|
208
|
+
else if (ts.isNamedImports(namedBindings)) {
|
|
209
|
+
importInfo.namedImports = namedBindings.elements.map((element) => {
|
|
210
|
+
if (element.propertyName) {
|
|
211
|
+
return `${element.propertyName.text} as ${element.name.text}`;
|
|
212
|
+
}
|
|
213
|
+
return element.name.text;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return importInfo;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Extract export information from the source file.
|
|
222
|
+
*/
|
|
223
|
+
extractExports(sourceFile, source) {
|
|
224
|
+
const exports = [];
|
|
225
|
+
const visit = (node) => {
|
|
226
|
+
// Export declaration (export { foo } or export { foo } from './bar')
|
|
227
|
+
if (ts.isExportDeclaration(node)) {
|
|
228
|
+
const exportInfos = this.parseExportDeclaration(node, source);
|
|
229
|
+
exports.push(...exportInfos);
|
|
230
|
+
}
|
|
231
|
+
// Export assignment (export default foo or export = foo)
|
|
232
|
+
else if (ts.isExportAssignment(node)) {
|
|
233
|
+
const exportInfo = this.parseExportAssignment(node, source);
|
|
234
|
+
if (exportInfo) {
|
|
235
|
+
exports.push(exportInfo);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// Exported declarations (export function foo, export class Bar, etc.)
|
|
239
|
+
else if (this.hasExportModifier(node)) {
|
|
240
|
+
const exportInfo = this.parseExportedDeclaration(node, source);
|
|
241
|
+
if (exportInfo) {
|
|
242
|
+
exports.push(exportInfo);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
ts.forEachChild(node, visit);
|
|
246
|
+
};
|
|
247
|
+
visit(sourceFile);
|
|
248
|
+
return exports;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Check if a node has an export modifier.
|
|
252
|
+
*/
|
|
253
|
+
hasExportModifier(node) {
|
|
254
|
+
const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
|
|
255
|
+
return modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Check if a node has a default modifier.
|
|
259
|
+
*/
|
|
260
|
+
hasDefaultModifier(node) {
|
|
261
|
+
const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
|
|
262
|
+
return modifiers?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword) ?? false;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Parse an export declaration.
|
|
266
|
+
*/
|
|
267
|
+
parseExportDeclaration(node, source) {
|
|
268
|
+
const exports = [];
|
|
269
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
270
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
271
|
+
const moduleSpecifier = node.moduleSpecifier ? node.moduleSpecifier.text : null;
|
|
272
|
+
const isTypeOnly = node.isTypeOnly;
|
|
273
|
+
// Export all from module (export * from './foo')
|
|
274
|
+
if (!node.exportClause) {
|
|
275
|
+
exports.push({
|
|
276
|
+
name: '*',
|
|
277
|
+
localName: null,
|
|
278
|
+
isDefault: false,
|
|
279
|
+
isTypeOnly,
|
|
280
|
+
isReExport: true,
|
|
281
|
+
moduleSpecifier,
|
|
282
|
+
startPosition,
|
|
283
|
+
endPosition,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
// Named exports
|
|
287
|
+
else if (ts.isNamedExports(node.exportClause)) {
|
|
288
|
+
for (const element of node.exportClause.elements) {
|
|
289
|
+
exports.push({
|
|
290
|
+
name: element.name.text,
|
|
291
|
+
localName: element.propertyName?.text ?? null,
|
|
292
|
+
isDefault: false,
|
|
293
|
+
isTypeOnly: isTypeOnly || element.isTypeOnly,
|
|
294
|
+
isReExport: moduleSpecifier !== null,
|
|
295
|
+
moduleSpecifier,
|
|
296
|
+
startPosition,
|
|
297
|
+
endPosition,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Namespace export (export * as ns from './foo')
|
|
302
|
+
else if (ts.isNamespaceExport(node.exportClause)) {
|
|
303
|
+
exports.push({
|
|
304
|
+
name: node.exportClause.name.text,
|
|
305
|
+
localName: '*',
|
|
306
|
+
isDefault: false,
|
|
307
|
+
isTypeOnly,
|
|
308
|
+
isReExport: true,
|
|
309
|
+
moduleSpecifier,
|
|
310
|
+
startPosition,
|
|
311
|
+
endPosition,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
return exports;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Parse an export assignment (export default or export =).
|
|
318
|
+
*/
|
|
319
|
+
parseExportAssignment(node, source) {
|
|
320
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
321
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
322
|
+
let name = 'default';
|
|
323
|
+
if (ts.isIdentifier(node.expression)) {
|
|
324
|
+
name = node.expression.text;
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
name,
|
|
328
|
+
localName: null,
|
|
329
|
+
isDefault: !node.isExportEquals,
|
|
330
|
+
isTypeOnly: false,
|
|
331
|
+
isReExport: false,
|
|
332
|
+
moduleSpecifier: null,
|
|
333
|
+
startPosition,
|
|
334
|
+
endPosition,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Parse an exported declaration.
|
|
339
|
+
*/
|
|
340
|
+
parseExportedDeclaration(node, source) {
|
|
341
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
342
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
343
|
+
const isDefault = this.hasDefaultModifier(node);
|
|
344
|
+
let name = null;
|
|
345
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
346
|
+
name = node.name.text;
|
|
347
|
+
}
|
|
348
|
+
else if (ts.isClassDeclaration(node) && node.name) {
|
|
349
|
+
name = node.name.text;
|
|
350
|
+
}
|
|
351
|
+
else if (ts.isVariableStatement(node)) {
|
|
352
|
+
const declarations = node.declarationList.declarations;
|
|
353
|
+
const firstDecl = declarations[0];
|
|
354
|
+
if (declarations.length > 0 && firstDecl && ts.isIdentifier(firstDecl.name)) {
|
|
355
|
+
name = firstDecl.name.text;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else if (ts.isInterfaceDeclaration(node)) {
|
|
359
|
+
name = node.name.text;
|
|
360
|
+
}
|
|
361
|
+
else if (ts.isTypeAliasDeclaration(node)) {
|
|
362
|
+
name = node.name.text;
|
|
363
|
+
}
|
|
364
|
+
else if (ts.isEnumDeclaration(node)) {
|
|
365
|
+
name = node.name.text;
|
|
366
|
+
}
|
|
367
|
+
if (!name) {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
name,
|
|
372
|
+
localName: null,
|
|
373
|
+
isDefault,
|
|
374
|
+
isTypeOnly: ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node),
|
|
375
|
+
isReExport: false,
|
|
376
|
+
moduleSpecifier: null,
|
|
377
|
+
startPosition,
|
|
378
|
+
endPosition,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Extract class information from the source file.
|
|
383
|
+
*/
|
|
384
|
+
extractClasses(sourceFile, source) {
|
|
385
|
+
const classes = [];
|
|
386
|
+
const visit = (node) => {
|
|
387
|
+
if (ts.isClassDeclaration(node)) {
|
|
388
|
+
const classInfo = this.parseClassDeclaration(node, source);
|
|
389
|
+
if (classInfo) {
|
|
390
|
+
classes.push(classInfo);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
ts.forEachChild(node, visit);
|
|
394
|
+
};
|
|
395
|
+
visit(sourceFile);
|
|
396
|
+
return classes;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Parse a class declaration.
|
|
400
|
+
*/
|
|
401
|
+
parseClassDeclaration(node, source) {
|
|
402
|
+
const name = node.name?.text;
|
|
403
|
+
if (!name) {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
407
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
408
|
+
const isExported = this.hasExportModifier(node);
|
|
409
|
+
const isDefault = this.hasDefaultModifier(node);
|
|
410
|
+
// Check for abstract modifier
|
|
411
|
+
const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
|
|
412
|
+
const isAbstract = modifiers?.some((m) => m.kind === ts.SyntaxKind.AbstractKeyword) ?? false;
|
|
413
|
+
// Get extends clause
|
|
414
|
+
let extendsClass = null;
|
|
415
|
+
const implementsInterfaces = [];
|
|
416
|
+
if (node.heritageClauses) {
|
|
417
|
+
for (const clause of node.heritageClauses) {
|
|
418
|
+
if (clause.token === ts.SyntaxKind.ExtendsKeyword) {
|
|
419
|
+
const type = clause.types[0];
|
|
420
|
+
if (type && ts.isIdentifier(type.expression)) {
|
|
421
|
+
extendsClass = type.expression.text;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
else if (clause.token === ts.SyntaxKind.ImplementsKeyword) {
|
|
425
|
+
for (const type of clause.types) {
|
|
426
|
+
if (ts.isIdentifier(type.expression)) {
|
|
427
|
+
implementsInterfaces.push(type.expression.text);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// Extract methods and properties
|
|
434
|
+
const methods = [];
|
|
435
|
+
const properties = [];
|
|
436
|
+
for (const member of node.members) {
|
|
437
|
+
if (ts.isMethodDeclaration(member) && member.name) {
|
|
438
|
+
const memberName = ts.isIdentifier(member.name) ? member.name.text : member.name.getText();
|
|
439
|
+
methods.push(memberName);
|
|
440
|
+
}
|
|
441
|
+
else if (ts.isPropertyDeclaration(member) && member.name) {
|
|
442
|
+
const memberName = ts.isIdentifier(member.name) ? member.name.text : member.name.getText();
|
|
443
|
+
properties.push(memberName);
|
|
444
|
+
}
|
|
445
|
+
else if (ts.isConstructorDeclaration(member)) {
|
|
446
|
+
methods.push('constructor');
|
|
447
|
+
}
|
|
448
|
+
else if (ts.isGetAccessorDeclaration(member) && member.name) {
|
|
449
|
+
const memberName = ts.isIdentifier(member.name) ? member.name.text : member.name.getText();
|
|
450
|
+
properties.push(`get ${memberName}`);
|
|
451
|
+
}
|
|
452
|
+
else if (ts.isSetAccessorDeclaration(member) && member.name) {
|
|
453
|
+
const memberName = ts.isIdentifier(member.name) ? member.name.text : member.name.getText();
|
|
454
|
+
properties.push(`set ${memberName}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
name,
|
|
459
|
+
isExported,
|
|
460
|
+
isDefault,
|
|
461
|
+
isAbstract,
|
|
462
|
+
extends: extendsClass,
|
|
463
|
+
implements: implementsInterfaces,
|
|
464
|
+
methods,
|
|
465
|
+
properties,
|
|
466
|
+
startPosition,
|
|
467
|
+
endPosition,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Extract function information from the source file.
|
|
472
|
+
*/
|
|
473
|
+
extractFunctions(sourceFile, source) {
|
|
474
|
+
const functions = [];
|
|
475
|
+
const visit = (node) => {
|
|
476
|
+
if (ts.isFunctionDeclaration(node)) {
|
|
477
|
+
const funcInfo = this.parseFunctionDeclaration(node, source);
|
|
478
|
+
if (funcInfo) {
|
|
479
|
+
functions.push(funcInfo);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// Also extract arrow functions assigned to variables at module level
|
|
483
|
+
else if (ts.isVariableStatement(node)) {
|
|
484
|
+
for (const decl of node.declarationList.declarations) {
|
|
485
|
+
if (decl.initializer && (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer))) {
|
|
486
|
+
const funcInfo = this.parseVariableFunction(node, decl, source);
|
|
487
|
+
if (funcInfo) {
|
|
488
|
+
functions.push(funcInfo);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
ts.forEachChild(node, visit);
|
|
494
|
+
};
|
|
495
|
+
visit(sourceFile);
|
|
496
|
+
return functions;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Parse a function declaration.
|
|
500
|
+
*/
|
|
501
|
+
parseFunctionDeclaration(node, source) {
|
|
502
|
+
const name = node.name?.text;
|
|
503
|
+
if (!name) {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
507
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
508
|
+
const isExported = this.hasExportModifier(node);
|
|
509
|
+
const isDefault = this.hasDefaultModifier(node);
|
|
510
|
+
// Check for async modifier
|
|
511
|
+
const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
|
|
512
|
+
const isAsync = modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) ?? false;
|
|
513
|
+
// Check for generator
|
|
514
|
+
const isGenerator = node.asteriskToken !== undefined;
|
|
515
|
+
// Extract parameters
|
|
516
|
+
const parameters = node.parameters.map((param) => {
|
|
517
|
+
if (ts.isIdentifier(param.name)) {
|
|
518
|
+
return param.name.text;
|
|
519
|
+
}
|
|
520
|
+
return param.name.getText();
|
|
521
|
+
});
|
|
522
|
+
return {
|
|
523
|
+
name,
|
|
524
|
+
isExported,
|
|
525
|
+
isDefault,
|
|
526
|
+
isAsync,
|
|
527
|
+
isGenerator,
|
|
528
|
+
parameters,
|
|
529
|
+
startPosition,
|
|
530
|
+
endPosition,
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Parse a variable declaration with a function expression or arrow function.
|
|
535
|
+
*/
|
|
536
|
+
parseVariableFunction(statement, decl, source) {
|
|
537
|
+
if (!ts.isIdentifier(decl.name)) {
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
const name = decl.name.text;
|
|
541
|
+
const startPosition = this.getPosition(statement.getStart(), source);
|
|
542
|
+
const endPosition = this.getPosition(statement.getEnd(), source);
|
|
543
|
+
const isExported = this.hasExportModifier(statement);
|
|
544
|
+
const func = decl.initializer;
|
|
545
|
+
// Check for async modifier
|
|
546
|
+
const modifiers = ts.canHaveModifiers(func) ? ts.getModifiers(func) : undefined;
|
|
547
|
+
const isAsync = modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) ?? false;
|
|
548
|
+
// Check for generator (only for function expressions)
|
|
549
|
+
const isGenerator = ts.isFunctionExpression(func) && func.asteriskToken !== undefined;
|
|
550
|
+
// Extract parameters
|
|
551
|
+
const parameters = func.parameters.map((param) => {
|
|
552
|
+
if (ts.isIdentifier(param.name)) {
|
|
553
|
+
return param.name.text;
|
|
554
|
+
}
|
|
555
|
+
return param.name.getText();
|
|
556
|
+
});
|
|
557
|
+
return {
|
|
558
|
+
name,
|
|
559
|
+
isExported,
|
|
560
|
+
isDefault: false,
|
|
561
|
+
isAsync,
|
|
562
|
+
isGenerator,
|
|
563
|
+
parameters,
|
|
564
|
+
startPosition,
|
|
565
|
+
endPosition,
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Extract interface information from the source file.
|
|
570
|
+
*/
|
|
571
|
+
extractInterfaces(sourceFile, source) {
|
|
572
|
+
const interfaces = [];
|
|
573
|
+
const visit = (node) => {
|
|
574
|
+
if (ts.isInterfaceDeclaration(node)) {
|
|
575
|
+
const interfaceInfo = this.parseInterfaceDeclaration(node, source);
|
|
576
|
+
interfaces.push(interfaceInfo);
|
|
577
|
+
}
|
|
578
|
+
ts.forEachChild(node, visit);
|
|
579
|
+
};
|
|
580
|
+
visit(sourceFile);
|
|
581
|
+
return interfaces;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Parse an interface declaration.
|
|
585
|
+
*/
|
|
586
|
+
parseInterfaceDeclaration(node, source) {
|
|
587
|
+
const name = node.name.text;
|
|
588
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
589
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
590
|
+
const isExported = this.hasExportModifier(node);
|
|
591
|
+
// Get extends clause
|
|
592
|
+
const extendsInterfaces = [];
|
|
593
|
+
if (node.heritageClauses) {
|
|
594
|
+
for (const clause of node.heritageClauses) {
|
|
595
|
+
if (clause.token === ts.SyntaxKind.ExtendsKeyword) {
|
|
596
|
+
for (const type of clause.types) {
|
|
597
|
+
if (ts.isIdentifier(type.expression)) {
|
|
598
|
+
extendsInterfaces.push(type.expression.text);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
// Extract properties and methods
|
|
605
|
+
const properties = [];
|
|
606
|
+
const methods = [];
|
|
607
|
+
for (const member of node.members) {
|
|
608
|
+
if (ts.isPropertySignature(member) && member.name) {
|
|
609
|
+
const memberName = ts.isIdentifier(member.name) ? member.name.text : member.name.getText();
|
|
610
|
+
properties.push(memberName);
|
|
611
|
+
}
|
|
612
|
+
else if (ts.isMethodSignature(member) && member.name) {
|
|
613
|
+
const memberName = ts.isIdentifier(member.name) ? member.name.text : member.name.getText();
|
|
614
|
+
methods.push(memberName);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return {
|
|
618
|
+
name,
|
|
619
|
+
isExported,
|
|
620
|
+
extends: extendsInterfaces,
|
|
621
|
+
properties,
|
|
622
|
+
methods,
|
|
623
|
+
startPosition,
|
|
624
|
+
endPosition,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Extract type alias information from the source file.
|
|
629
|
+
*/
|
|
630
|
+
extractTypeAliases(sourceFile, source) {
|
|
631
|
+
const typeAliases = [];
|
|
632
|
+
const visit = (node) => {
|
|
633
|
+
if (ts.isTypeAliasDeclaration(node)) {
|
|
634
|
+
const typeAliasInfo = this.parseTypeAliasDeclaration(node, source);
|
|
635
|
+
typeAliases.push(typeAliasInfo);
|
|
636
|
+
}
|
|
637
|
+
ts.forEachChild(node, visit);
|
|
638
|
+
};
|
|
639
|
+
visit(sourceFile);
|
|
640
|
+
return typeAliases;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Parse a type alias declaration.
|
|
644
|
+
*/
|
|
645
|
+
parseTypeAliasDeclaration(node, source) {
|
|
646
|
+
const name = node.name.text;
|
|
647
|
+
const startPosition = this.getPosition(node.getStart(), source);
|
|
648
|
+
const endPosition = this.getPosition(node.getEnd(), source);
|
|
649
|
+
const isExported = this.hasExportModifier(node);
|
|
650
|
+
return {
|
|
651
|
+
name,
|
|
652
|
+
isExported,
|
|
653
|
+
startPosition,
|
|
654
|
+
endPosition,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
//# sourceMappingURL=typescript-parser.js.map
|