archicore 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/README.md +530 -0
- package/dist/analyzers/dead-code.d.ts +95 -0
- package/dist/analyzers/dead-code.js +327 -0
- package/dist/analyzers/duplication.d.ts +90 -0
- package/dist/analyzers/duplication.js +344 -0
- package/dist/analyzers/security.d.ts +79 -0
- package/dist/analyzers/security.js +484 -0
- package/dist/architecture/index.d.ts +35 -0
- package/dist/architecture/index.js +249 -0
- package/dist/cli/commands/analyzers.d.ts +6 -0
- package/dist/cli/commands/analyzers.js +431 -0
- package/dist/cli/commands/export.d.ts +6 -0
- package/dist/cli/commands/export.js +78 -0
- package/dist/cli/commands/index.d.ts +8 -0
- package/dist/cli/commands/index.js +8 -0
- package/dist/cli/commands/init.d.ts +26 -0
- package/dist/cli/commands/init.js +140 -0
- package/dist/cli/commands/interactive.d.ts +7 -0
- package/dist/cli/commands/interactive.js +522 -0
- package/dist/cli/commands/projects.d.ts +6 -0
- package/dist/cli/commands/projects.js +249 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/ui/box.d.ts +17 -0
- package/dist/cli/ui/box.js +62 -0
- package/dist/cli/ui/colors.d.ts +49 -0
- package/dist/cli/ui/colors.js +86 -0
- package/dist/cli/ui/index.d.ts +9 -0
- package/dist/cli/ui/index.js +9 -0
- package/dist/cli/ui/prompt.d.ts +34 -0
- package/dist/cli/ui/prompt.js +122 -0
- package/dist/cli/ui/spinner.d.ts +29 -0
- package/dist/cli/ui/spinner.js +80 -0
- package/dist/cli/ui/table.d.ts +33 -0
- package/dist/cli/ui/table.js +84 -0
- package/dist/cli/utils/config.d.ts +23 -0
- package/dist/cli/utils/config.js +73 -0
- package/dist/cli/utils/index.d.ts +6 -0
- package/dist/cli/utils/index.js +6 -0
- package/dist/cli/utils/session.d.ts +27 -0
- package/dist/cli/utils/session.js +117 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +295 -0
- package/dist/code-index/ast-parser.d.ts +16 -0
- package/dist/code-index/ast-parser.js +330 -0
- package/dist/code-index/dependency-graph.d.ts +16 -0
- package/dist/code-index/dependency-graph.js +161 -0
- package/dist/code-index/index.d.ts +44 -0
- package/dist/code-index/index.js +124 -0
- package/dist/code-index/symbol-extractor.d.ts +13 -0
- package/dist/code-index/symbol-extractor.js +150 -0
- package/dist/export/index.d.ts +92 -0
- package/dist/export/index.js +676 -0
- package/dist/github/github-service.d.ts +146 -0
- package/dist/github/github-service.js +609 -0
- package/dist/impact-engine/index.d.ts +25 -0
- package/dist/impact-engine/index.js +284 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +149 -0
- package/dist/metrics/index.d.ts +136 -0
- package/dist/metrics/index.js +525 -0
- package/dist/orchestrator/deepseek-optimizer.d.ts +67 -0
- package/dist/orchestrator/deepseek-optimizer.js +320 -0
- package/dist/orchestrator/index.d.ts +34 -0
- package/dist/orchestrator/index.js +305 -0
- package/dist/pr-guardian/index.d.ts +143 -0
- package/dist/pr-guardian/index.js +553 -0
- package/dist/refactoring/index.d.ts +108 -0
- package/dist/refactoring/index.js +580 -0
- package/dist/rules-engine/index.d.ts +129 -0
- package/dist/rules-engine/index.js +482 -0
- package/dist/semantic-memory/embedding-service.d.ts +24 -0
- package/dist/semantic-memory/embedding-service.js +120 -0
- package/dist/semantic-memory/index.d.ts +45 -0
- package/dist/semantic-memory/index.js +206 -0
- package/dist/semantic-memory/vector-store.d.ts +27 -0
- package/dist/semantic-memory/vector-store.js +166 -0
- package/dist/server/index.d.ts +28 -0
- package/dist/server/index.js +141 -0
- package/dist/server/middleware/api-auth.d.ts +43 -0
- package/dist/server/middleware/api-auth.js +256 -0
- package/dist/server/routes/admin.d.ts +5 -0
- package/dist/server/routes/admin.js +123 -0
- package/dist/server/routes/api.d.ts +7 -0
- package/dist/server/routes/api.js +362 -0
- package/dist/server/routes/auth.d.ts +16 -0
- package/dist/server/routes/auth.js +191 -0
- package/dist/server/routes/developer.d.ts +8 -0
- package/dist/server/routes/developer.js +439 -0
- package/dist/server/routes/github.d.ts +7 -0
- package/dist/server/routes/github.js +495 -0
- package/dist/server/routes/upload.d.ts +7 -0
- package/dist/server/routes/upload.js +196 -0
- package/dist/server/services/api-key-service.d.ts +81 -0
- package/dist/server/services/api-key-service.js +281 -0
- package/dist/server/services/auth-service.d.ts +40 -0
- package/dist/server/services/auth-service.js +315 -0
- package/dist/server/services/project-service.d.ts +123 -0
- package/dist/server/services/project-service.js +533 -0
- package/dist/server/services/token-service.d.ts +107 -0
- package/dist/server/services/token-service.js +416 -0
- package/dist/server/services/upload-service.d.ts +93 -0
- package/dist/server/services/upload-service.js +464 -0
- package/dist/types/api.d.ts +188 -0
- package/dist/types/api.js +86 -0
- package/dist/types/github.d.ts +335 -0
- package/dist/types/github.js +5 -0
- package/dist/types/index.d.ts +265 -0
- package/dist/types/index.js +32 -0
- package/dist/types/user.d.ts +69 -0
- package/dist/types/user.js +42 -0
- package/dist/utils/file-utils.d.ts +20 -0
- package/dist/utils/file-utils.js +163 -0
- package/dist/utils/logger.d.ts +17 -0
- package/dist/utils/logger.js +41 -0
- package/dist/watcher/index.d.ts +125 -0
- package/dist/watcher/index.js +397 -0
- package/package.json +71 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { EdgeType } from '../types/index.js';
|
|
2
|
+
import { Logger } from '../utils/logger.js';
|
|
3
|
+
export class DependencyGraphBuilder {
|
|
4
|
+
buildGraph(symbols, asts) {
|
|
5
|
+
Logger.progress('Building dependency graph...');
|
|
6
|
+
const graph = {
|
|
7
|
+
nodes: new Map(),
|
|
8
|
+
edges: new Map()
|
|
9
|
+
};
|
|
10
|
+
this.buildNodes(symbols, asts, graph);
|
|
11
|
+
this.buildEdges(symbols, graph);
|
|
12
|
+
Logger.success(`Dependency graph built: ${graph.nodes.size} nodes, ${this.countEdges(graph)} edges`);
|
|
13
|
+
return graph;
|
|
14
|
+
}
|
|
15
|
+
buildNodes(symbols, asts, graph) {
|
|
16
|
+
for (const [filePath, ast] of asts) {
|
|
17
|
+
const fileNode = {
|
|
18
|
+
id: filePath,
|
|
19
|
+
type: 'file',
|
|
20
|
+
filePath,
|
|
21
|
+
name: this.getFileName(filePath),
|
|
22
|
+
metadata: {
|
|
23
|
+
linesOfCode: ast.endLine - ast.startLine,
|
|
24
|
+
complexity: this.estimateComplexity(ast)
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
graph.nodes.set(filePath, fileNode);
|
|
28
|
+
}
|
|
29
|
+
for (const symbol of symbols.values()) {
|
|
30
|
+
const node = {
|
|
31
|
+
id: symbol.id,
|
|
32
|
+
type: symbol.kind === 'function' ? 'function' : 'class',
|
|
33
|
+
filePath: symbol.filePath,
|
|
34
|
+
name: symbol.name,
|
|
35
|
+
metadata: {}
|
|
36
|
+
};
|
|
37
|
+
graph.nodes.set(symbol.id, node);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
buildEdges(symbols, graph) {
|
|
41
|
+
for (const symbol of symbols.values()) {
|
|
42
|
+
if (!symbol.imports)
|
|
43
|
+
continue;
|
|
44
|
+
for (const imp of symbol.imports) {
|
|
45
|
+
const targetSymbols = this.findSymbolsBySource(symbols, imp.source);
|
|
46
|
+
for (const targetSymbol of targetSymbols) {
|
|
47
|
+
const edge = {
|
|
48
|
+
from: symbol.id,
|
|
49
|
+
to: targetSymbol.id,
|
|
50
|
+
type: EdgeType.Import,
|
|
51
|
+
weight: 1
|
|
52
|
+
};
|
|
53
|
+
this.addEdge(graph, edge);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const ref of symbol.references) {
|
|
57
|
+
if (ref.kind === 'call') {
|
|
58
|
+
const targetSymbol = this.findSymbolAtLocation(symbols, ref.location.filePath, ref.location.startLine);
|
|
59
|
+
if (targetSymbol) {
|
|
60
|
+
const edge = {
|
|
61
|
+
from: symbol.id,
|
|
62
|
+
to: targetSymbol.id,
|
|
63
|
+
type: EdgeType.Call,
|
|
64
|
+
weight: 1
|
|
65
|
+
};
|
|
66
|
+
this.addEdge(graph, edge);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
addEdge(graph, edge) {
|
|
73
|
+
if (!graph.edges.has(edge.from)) {
|
|
74
|
+
graph.edges.set(edge.from, []);
|
|
75
|
+
}
|
|
76
|
+
graph.edges.get(edge.from).push(edge);
|
|
77
|
+
}
|
|
78
|
+
findSymbolsBySource(symbols, source) {
|
|
79
|
+
const results = [];
|
|
80
|
+
for (const symbol of symbols.values()) {
|
|
81
|
+
if (symbol.filePath.includes(source)) {
|
|
82
|
+
results.push(symbol);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return results;
|
|
86
|
+
}
|
|
87
|
+
findSymbolAtLocation(symbols, filePath, line) {
|
|
88
|
+
for (const symbol of symbols.values()) {
|
|
89
|
+
if (symbol.filePath === filePath &&
|
|
90
|
+
symbol.location.startLine <= line &&
|
|
91
|
+
symbol.location.endLine >= line) {
|
|
92
|
+
return symbol;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
getFileName(filePath) {
|
|
98
|
+
return filePath.split('/').pop() || filePath;
|
|
99
|
+
}
|
|
100
|
+
estimateComplexity(node) {
|
|
101
|
+
let complexity = 1;
|
|
102
|
+
const complexNodes = [
|
|
103
|
+
'if_statement',
|
|
104
|
+
'for_statement',
|
|
105
|
+
'while_statement',
|
|
106
|
+
'switch_statement',
|
|
107
|
+
'catch_clause'
|
|
108
|
+
];
|
|
109
|
+
if (complexNodes.includes(node.type)) {
|
|
110
|
+
complexity++;
|
|
111
|
+
}
|
|
112
|
+
for (const child of node.children) {
|
|
113
|
+
complexity += this.estimateComplexity(child);
|
|
114
|
+
}
|
|
115
|
+
return complexity;
|
|
116
|
+
}
|
|
117
|
+
countEdges(graph) {
|
|
118
|
+
let count = 0;
|
|
119
|
+
for (const edges of graph.edges.values()) {
|
|
120
|
+
count += edges.length;
|
|
121
|
+
}
|
|
122
|
+
return count;
|
|
123
|
+
}
|
|
124
|
+
findDependents(graph, nodeId) {
|
|
125
|
+
const dependents = new Set();
|
|
126
|
+
for (const [from, edges] of graph.edges) {
|
|
127
|
+
for (const edge of edges) {
|
|
128
|
+
if (edge.to === nodeId) {
|
|
129
|
+
dependents.add(from);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return dependents;
|
|
134
|
+
}
|
|
135
|
+
findDependencies(graph, nodeId) {
|
|
136
|
+
const dependencies = new Set();
|
|
137
|
+
const edges = graph.edges.get(nodeId) || [];
|
|
138
|
+
for (const edge of edges) {
|
|
139
|
+
dependencies.add(edge.to);
|
|
140
|
+
}
|
|
141
|
+
return dependencies;
|
|
142
|
+
}
|
|
143
|
+
getTransitiveDependencies(graph, nodeId, maxDepth = 10) {
|
|
144
|
+
const visited = new Set();
|
|
145
|
+
const queue = [{ id: nodeId, depth: 0 }];
|
|
146
|
+
while (queue.length > 0) {
|
|
147
|
+
const current = queue.shift();
|
|
148
|
+
if (current.depth >= maxDepth || visited.has(current.id)) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
visited.add(current.id);
|
|
152
|
+
const deps = this.findDependencies(graph, current.id);
|
|
153
|
+
for (const dep of deps) {
|
|
154
|
+
queue.push({ id: dep, depth: current.depth + 1 });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
visited.delete(nodeId);
|
|
158
|
+
return visited;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=dependency-graph.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Index Module
|
|
3
|
+
*
|
|
4
|
+
* Основной модуль для индексации кода:
|
|
5
|
+
* - Парсинг AST через Tree-sitter
|
|
6
|
+
* - Извлечение символов (функции, классы, интерфейсы)
|
|
7
|
+
* - Построение графа зависимостей
|
|
8
|
+
* - Анализ связей между компонентами
|
|
9
|
+
*/
|
|
10
|
+
import { ASTParser } from './ast-parser.js';
|
|
11
|
+
import { SymbolExtractor } from './symbol-extractor.js';
|
|
12
|
+
import { DependencyGraphBuilder } from './dependency-graph.js';
|
|
13
|
+
import { DependencyGraph, Symbol, ASTNode } from '../types/index.js';
|
|
14
|
+
export declare class CodeIndex {
|
|
15
|
+
private astParser;
|
|
16
|
+
private symbolExtractor;
|
|
17
|
+
private graphBuilder;
|
|
18
|
+
private rootDir;
|
|
19
|
+
private asts;
|
|
20
|
+
private symbols;
|
|
21
|
+
private graph;
|
|
22
|
+
constructor(rootDir?: string);
|
|
23
|
+
indexProject(rootDir?: string): Promise<void>;
|
|
24
|
+
parseProject(): Promise<Map<string, ASTNode>>;
|
|
25
|
+
extractSymbols(asts: Map<string, ASTNode>): Map<string, Symbol>;
|
|
26
|
+
buildDependencyGraph(asts: Map<string, ASTNode>, symbols: Map<string, Symbol>): DependencyGraph;
|
|
27
|
+
getGraph(): DependencyGraph | null;
|
|
28
|
+
getSymbols(): Map<string, Symbol>;
|
|
29
|
+
getASTs(): Map<string, ASTNode>;
|
|
30
|
+
findSymbol(name: string): Symbol | null;
|
|
31
|
+
findSymbolsInFile(filePath: string): Symbol[];
|
|
32
|
+
reindexFile(filePath: string): Promise<void>;
|
|
33
|
+
getStatistics(): {
|
|
34
|
+
totalFiles: number;
|
|
35
|
+
totalSymbols: number;
|
|
36
|
+
totalNodes: number;
|
|
37
|
+
totalEdges: number;
|
|
38
|
+
symbolsByKind: Record<string, number>;
|
|
39
|
+
};
|
|
40
|
+
private countGraphEdges;
|
|
41
|
+
private getSymbolsByKind;
|
|
42
|
+
}
|
|
43
|
+
export { ASTParser, SymbolExtractor, DependencyGraphBuilder };
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Index Module
|
|
3
|
+
*
|
|
4
|
+
* Основной модуль для индексации кода:
|
|
5
|
+
* - Парсинг AST через Tree-sitter
|
|
6
|
+
* - Извлечение символов (функции, классы, интерфейсы)
|
|
7
|
+
* - Построение графа зависимостей
|
|
8
|
+
* - Анализ связей между компонентами
|
|
9
|
+
*/
|
|
10
|
+
import { ASTParser } from './ast-parser.js';
|
|
11
|
+
import { SymbolExtractor } from './symbol-extractor.js';
|
|
12
|
+
import { DependencyGraphBuilder } from './dependency-graph.js';
|
|
13
|
+
import { Logger } from '../utils/logger.js';
|
|
14
|
+
export class CodeIndex {
|
|
15
|
+
astParser;
|
|
16
|
+
symbolExtractor;
|
|
17
|
+
graphBuilder;
|
|
18
|
+
rootDir;
|
|
19
|
+
asts = new Map();
|
|
20
|
+
symbols = new Map();
|
|
21
|
+
graph = null;
|
|
22
|
+
constructor(rootDir) {
|
|
23
|
+
this.rootDir = rootDir || process.cwd();
|
|
24
|
+
this.astParser = new ASTParser();
|
|
25
|
+
this.symbolExtractor = new SymbolExtractor();
|
|
26
|
+
this.graphBuilder = new DependencyGraphBuilder();
|
|
27
|
+
}
|
|
28
|
+
async indexProject(rootDir) {
|
|
29
|
+
const dir = rootDir || this.rootDir;
|
|
30
|
+
Logger.info(`Starting indexing of project: ${dir}`);
|
|
31
|
+
this.asts = await this.astParser.parseProject(dir);
|
|
32
|
+
this.symbols = this.symbolExtractor.extractSymbols(this.asts);
|
|
33
|
+
this.symbolExtractor.extractReferences(this.symbols, this.asts);
|
|
34
|
+
this.graph = this.graphBuilder.buildGraph(this.symbols, this.asts);
|
|
35
|
+
Logger.success('Project indexed successfully');
|
|
36
|
+
}
|
|
37
|
+
// Методы для использования в ProjectService
|
|
38
|
+
async parseProject() {
|
|
39
|
+
this.asts = await this.astParser.parseProject(this.rootDir);
|
|
40
|
+
return this.asts;
|
|
41
|
+
}
|
|
42
|
+
extractSymbols(asts) {
|
|
43
|
+
this.symbols = this.symbolExtractor.extractSymbols(asts);
|
|
44
|
+
this.symbolExtractor.extractReferences(this.symbols, asts);
|
|
45
|
+
return this.symbols;
|
|
46
|
+
}
|
|
47
|
+
buildDependencyGraph(asts, symbols) {
|
|
48
|
+
this.graph = this.graphBuilder.buildGraph(symbols, asts);
|
|
49
|
+
return this.graph;
|
|
50
|
+
}
|
|
51
|
+
getGraph() {
|
|
52
|
+
return this.graph;
|
|
53
|
+
}
|
|
54
|
+
getSymbols() {
|
|
55
|
+
return this.symbols;
|
|
56
|
+
}
|
|
57
|
+
getASTs() {
|
|
58
|
+
return this.asts;
|
|
59
|
+
}
|
|
60
|
+
findSymbol(name) {
|
|
61
|
+
for (const symbol of this.symbols.values()) {
|
|
62
|
+
if (symbol.name === name) {
|
|
63
|
+
return symbol;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
findSymbolsInFile(filePath) {
|
|
69
|
+
const results = [];
|
|
70
|
+
for (const symbol of this.symbols.values()) {
|
|
71
|
+
if (symbol.filePath === filePath) {
|
|
72
|
+
results.push(symbol);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
async reindexFile(filePath) {
|
|
78
|
+
Logger.progress(`Reindexing file: ${filePath}`);
|
|
79
|
+
const ast = await this.astParser.parseFile(filePath);
|
|
80
|
+
if (ast) {
|
|
81
|
+
this.asts.set(filePath, ast);
|
|
82
|
+
for (const [id, symbol] of this.symbols) {
|
|
83
|
+
if (symbol.filePath === filePath) {
|
|
84
|
+
this.symbols.delete(id);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const newSymbols = this.symbolExtractor.extractSymbols(new Map([[filePath, ast]]));
|
|
88
|
+
for (const [id, symbol] of newSymbols) {
|
|
89
|
+
this.symbols.set(id, symbol);
|
|
90
|
+
}
|
|
91
|
+
if (this.graph) {
|
|
92
|
+
this.graph = this.graphBuilder.buildGraph(this.symbols, this.asts);
|
|
93
|
+
}
|
|
94
|
+
Logger.success(`File reindexed: ${filePath}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
getStatistics() {
|
|
98
|
+
return {
|
|
99
|
+
totalFiles: this.asts.size,
|
|
100
|
+
totalSymbols: this.symbols.size,
|
|
101
|
+
totalNodes: this.graph?.nodes.size || 0,
|
|
102
|
+
totalEdges: this.countGraphEdges(),
|
|
103
|
+
symbolsByKind: this.getSymbolsByKind()
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
countGraphEdges() {
|
|
107
|
+
if (!this.graph)
|
|
108
|
+
return 0;
|
|
109
|
+
let count = 0;
|
|
110
|
+
for (const edges of this.graph.edges.values()) {
|
|
111
|
+
count += edges.length;
|
|
112
|
+
}
|
|
113
|
+
return count;
|
|
114
|
+
}
|
|
115
|
+
getSymbolsByKind() {
|
|
116
|
+
const counts = {};
|
|
117
|
+
for (const symbol of this.symbols.values()) {
|
|
118
|
+
counts[symbol.kind] = (counts[symbol.kind] || 0) + 1;
|
|
119
|
+
}
|
|
120
|
+
return counts;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export { ASTParser, SymbolExtractor, DependencyGraphBuilder };
|
|
124
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ASTNode, Symbol } from '../types/index.js';
|
|
2
|
+
export declare class SymbolExtractor {
|
|
3
|
+
extractSymbols(asts: Map<string, ASTNode>): Map<string, Symbol>;
|
|
4
|
+
private extractFromNode;
|
|
5
|
+
private getSymbolKind;
|
|
6
|
+
private extractImports;
|
|
7
|
+
private parseImportNode;
|
|
8
|
+
private extractImportSpecifiers;
|
|
9
|
+
extractReferences(symbols: Map<string, Symbol>, asts: Map<string, ASTNode>): void;
|
|
10
|
+
private findReferences;
|
|
11
|
+
private inferReferenceKind;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=symbol-extractor.d.ts.map
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { SymbolKind } from '../types/index.js';
|
|
2
|
+
import { Logger } from '../utils/logger.js';
|
|
3
|
+
export class SymbolExtractor {
|
|
4
|
+
extractSymbols(asts) {
|
|
5
|
+
const symbols = new Map();
|
|
6
|
+
Logger.progress('Extracting symbols from AST...');
|
|
7
|
+
for (const [filePath, ast] of asts) {
|
|
8
|
+
this.extractFromNode(ast, filePath, symbols);
|
|
9
|
+
}
|
|
10
|
+
Logger.success(`Extracted ${symbols.size} symbols`);
|
|
11
|
+
return symbols;
|
|
12
|
+
}
|
|
13
|
+
extractFromNode(node, filePath, symbols) {
|
|
14
|
+
const symbolKind = this.getSymbolKind(node.type);
|
|
15
|
+
if (symbolKind && node.name) {
|
|
16
|
+
const symbol = {
|
|
17
|
+
id: `${filePath}:${node.name}:${node.startLine}`,
|
|
18
|
+
name: node.name,
|
|
19
|
+
kind: symbolKind,
|
|
20
|
+
filePath,
|
|
21
|
+
location: {
|
|
22
|
+
filePath,
|
|
23
|
+
startLine: node.startLine,
|
|
24
|
+
endLine: node.endLine,
|
|
25
|
+
startColumn: 0,
|
|
26
|
+
endColumn: 0
|
|
27
|
+
},
|
|
28
|
+
references: [],
|
|
29
|
+
imports: this.extractImports(node)
|
|
30
|
+
};
|
|
31
|
+
symbols.set(symbol.id, symbol);
|
|
32
|
+
}
|
|
33
|
+
for (const child of node.children) {
|
|
34
|
+
this.extractFromNode(child, filePath, symbols);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
getSymbolKind(nodeType) {
|
|
38
|
+
const mapping = {
|
|
39
|
+
// JavaScript/TypeScript
|
|
40
|
+
'function_declaration': SymbolKind.Function,
|
|
41
|
+
'method_definition': SymbolKind.Function,
|
|
42
|
+
'arrow_function': SymbolKind.Function,
|
|
43
|
+
'class_declaration': SymbolKind.Class,
|
|
44
|
+
'interface_declaration': SymbolKind.Interface,
|
|
45
|
+
'type_alias_declaration': SymbolKind.Type,
|
|
46
|
+
'variable_declaration': SymbolKind.Variable,
|
|
47
|
+
'const_declaration': SymbolKind.Constant,
|
|
48
|
+
'lexical_declaration': SymbolKind.Variable,
|
|
49
|
+
// Python
|
|
50
|
+
'function_definition': SymbolKind.Function,
|
|
51
|
+
'class_definition': SymbolKind.Class,
|
|
52
|
+
'decorated_definition': SymbolKind.Function,
|
|
53
|
+
'async_function_definition': SymbolKind.Function,
|
|
54
|
+
// Go
|
|
55
|
+
'method_declaration': SymbolKind.Function,
|
|
56
|
+
'type_declaration': SymbolKind.Type,
|
|
57
|
+
// Rust
|
|
58
|
+
'function_item': SymbolKind.Function,
|
|
59
|
+
'impl_item': SymbolKind.Class,
|
|
60
|
+
'struct_item': SymbolKind.Class,
|
|
61
|
+
'enum_item': SymbolKind.Type,
|
|
62
|
+
'trait_item': SymbolKind.Interface
|
|
63
|
+
};
|
|
64
|
+
return mapping[nodeType] || null;
|
|
65
|
+
}
|
|
66
|
+
extractImports(node) {
|
|
67
|
+
const imports = [];
|
|
68
|
+
if (node.type === 'import_statement' || node.type === 'import_declaration') {
|
|
69
|
+
const importNode = this.parseImportNode(node);
|
|
70
|
+
if (importNode) {
|
|
71
|
+
imports.push(importNode);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const child of node.children) {
|
|
75
|
+
imports.push(...this.extractImports(child));
|
|
76
|
+
}
|
|
77
|
+
return imports;
|
|
78
|
+
}
|
|
79
|
+
parseImportNode(node) {
|
|
80
|
+
const sourceNode = node.children.find(c => c.type === 'string');
|
|
81
|
+
if (!sourceNode)
|
|
82
|
+
return null;
|
|
83
|
+
const source = sourceNode.metadata.text;
|
|
84
|
+
const specifiers = this.extractImportSpecifiers(node);
|
|
85
|
+
return {
|
|
86
|
+
source: source.replace(/['"]/g, ''),
|
|
87
|
+
specifiers,
|
|
88
|
+
location: {
|
|
89
|
+
filePath: node.filePath,
|
|
90
|
+
startLine: node.startLine,
|
|
91
|
+
endLine: node.endLine,
|
|
92
|
+
startColumn: 0,
|
|
93
|
+
endColumn: 0
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
extractImportSpecifiers(node) {
|
|
98
|
+
const specifiers = [];
|
|
99
|
+
const findSpecifiers = (n) => {
|
|
100
|
+
if (n.type === 'import_specifier' || n.type === 'identifier') {
|
|
101
|
+
if (n.name) {
|
|
102
|
+
specifiers.push(n.name);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
n.children.forEach(findSpecifiers);
|
|
106
|
+
};
|
|
107
|
+
findSpecifiers(node);
|
|
108
|
+
return specifiers;
|
|
109
|
+
}
|
|
110
|
+
extractReferences(symbols, asts) {
|
|
111
|
+
Logger.progress('Building reference graph...');
|
|
112
|
+
for (const [filePath, ast] of asts) {
|
|
113
|
+
this.findReferences(ast, symbols, filePath);
|
|
114
|
+
}
|
|
115
|
+
Logger.success('Reference graph built');
|
|
116
|
+
}
|
|
117
|
+
findReferences(node, symbols, currentFile) {
|
|
118
|
+
if (node.type === 'identifier' && node.name) {
|
|
119
|
+
for (const symbol of symbols.values()) {
|
|
120
|
+
if (symbol.name === node.name) {
|
|
121
|
+
const ref = {
|
|
122
|
+
location: {
|
|
123
|
+
filePath: currentFile,
|
|
124
|
+
startLine: node.startLine,
|
|
125
|
+
endLine: node.endLine,
|
|
126
|
+
startColumn: 0,
|
|
127
|
+
endColumn: 0
|
|
128
|
+
},
|
|
129
|
+
kind: this.inferReferenceKind(node)
|
|
130
|
+
};
|
|
131
|
+
symbol.references.push(ref);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const child of node.children) {
|
|
136
|
+
this.findReferences(child, symbols, currentFile);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
inferReferenceKind(node) {
|
|
140
|
+
const parent = node.metadata.parent;
|
|
141
|
+
if (parent?.includes('call'))
|
|
142
|
+
return 'call';
|
|
143
|
+
if (parent?.includes('assignment'))
|
|
144
|
+
return 'write';
|
|
145
|
+
if (parent?.includes('type'))
|
|
146
|
+
return 'type';
|
|
147
|
+
return 'read';
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=symbol-extractor.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export/Import System
|
|
3
|
+
*
|
|
4
|
+
* Форматы экспорта:
|
|
5
|
+
* - JSON (полный)
|
|
6
|
+
* - HTML отчёт
|
|
7
|
+
* - Markdown отчёт
|
|
8
|
+
* - PDF (через HTML)
|
|
9
|
+
* - CSV (метрики)
|
|
10
|
+
* - GraphML (граф зависимостей)
|
|
11
|
+
*/
|
|
12
|
+
import { DependencyGraph, Symbol } from '../types/index.js';
|
|
13
|
+
import { ProjectMetrics } from '../metrics/index.js';
|
|
14
|
+
import { RulesCheckResult } from '../rules-engine/index.js';
|
|
15
|
+
import { DeadCodeResult } from '../analyzers/dead-code.js';
|
|
16
|
+
import { DuplicationResult } from '../analyzers/duplication.js';
|
|
17
|
+
import { SecurityResult } from '../analyzers/security.js';
|
|
18
|
+
export interface ExportData {
|
|
19
|
+
projectName: string;
|
|
20
|
+
exportDate: string;
|
|
21
|
+
version: string;
|
|
22
|
+
graph?: DependencyGraph;
|
|
23
|
+
symbols?: Map<string, Symbol>;
|
|
24
|
+
metrics?: ProjectMetrics;
|
|
25
|
+
rules?: RulesCheckResult;
|
|
26
|
+
deadCode?: DeadCodeResult;
|
|
27
|
+
duplication?: DuplicationResult;
|
|
28
|
+
security?: SecurityResult;
|
|
29
|
+
}
|
|
30
|
+
export interface ExportOptions {
|
|
31
|
+
format: 'json' | 'html' | 'markdown' | 'csv' | 'graphml';
|
|
32
|
+
includeGraph?: boolean;
|
|
33
|
+
includeSymbols?: boolean;
|
|
34
|
+
includeMetrics?: boolean;
|
|
35
|
+
includeRules?: boolean;
|
|
36
|
+
includeDeadCode?: boolean;
|
|
37
|
+
includeDuplication?: boolean;
|
|
38
|
+
includeSecurity?: boolean;
|
|
39
|
+
language?: 'en' | 'ru';
|
|
40
|
+
}
|
|
41
|
+
export interface ImportResult {
|
|
42
|
+
success: boolean;
|
|
43
|
+
data?: ExportData;
|
|
44
|
+
errors?: string[];
|
|
45
|
+
}
|
|
46
|
+
export declare class ExportManager {
|
|
47
|
+
private version;
|
|
48
|
+
/**
|
|
49
|
+
* Экспорт данных в указанный формат
|
|
50
|
+
*/
|
|
51
|
+
export(data: ExportData, options: ExportOptions): Promise<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Импорт данных из JSON
|
|
54
|
+
*/
|
|
55
|
+
import(jsonString: string): Promise<ImportResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Экспорт в JSON
|
|
58
|
+
*/
|
|
59
|
+
private exportJSON;
|
|
60
|
+
/**
|
|
61
|
+
* Экспорт в HTML
|
|
62
|
+
*/
|
|
63
|
+
private exportHTML;
|
|
64
|
+
/**
|
|
65
|
+
* Экспорт в Markdown
|
|
66
|
+
*/
|
|
67
|
+
private exportMarkdown;
|
|
68
|
+
/**
|
|
69
|
+
* Экспорт метрик в CSV
|
|
70
|
+
*/
|
|
71
|
+
private exportCSV;
|
|
72
|
+
/**
|
|
73
|
+
* Экспорт графа в GraphML
|
|
74
|
+
*/
|
|
75
|
+
private exportGraphML;
|
|
76
|
+
/**
|
|
77
|
+
* Санитизация ID для GraphML
|
|
78
|
+
*/
|
|
79
|
+
private sanitizeId;
|
|
80
|
+
/**
|
|
81
|
+
* Экранирование XML
|
|
82
|
+
*/
|
|
83
|
+
private escapeXml;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Быстрые функции экспорта
|
|
87
|
+
*/
|
|
88
|
+
export declare function exportToJSON(data: ExportData): Promise<string>;
|
|
89
|
+
export declare function exportToHTML(data: ExportData, language?: 'en' | 'ru'): Promise<string>;
|
|
90
|
+
export declare function exportToMarkdown(data: ExportData, language?: 'en' | 'ru'): Promise<string>;
|
|
91
|
+
export declare function importFromJSON(jsonString: string): Promise<ImportResult>;
|
|
92
|
+
//# sourceMappingURL=index.d.ts.map
|