spec-gen-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1078 -0
- package/dist/api/analyze.d.ts +17 -0
- package/dist/api/analyze.d.ts.map +1 -0
- package/dist/api/analyze.js +109 -0
- package/dist/api/analyze.js.map +1 -0
- package/dist/api/drift.d.ts +21 -0
- package/dist/api/drift.d.ts.map +1 -0
- package/dist/api/drift.js +145 -0
- package/dist/api/drift.js.map +1 -0
- package/dist/api/generate.d.ts +18 -0
- package/dist/api/generate.d.ts.map +1 -0
- package/dist/api/generate.js +251 -0
- package/dist/api/generate.js.map +1 -0
- package/dist/api/index.d.ts +39 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +32 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/init.d.ts +18 -0
- package/dist/api/init.d.ts.map +1 -0
- package/dist/api/init.js +82 -0
- package/dist/api/init.js.map +1 -0
- package/dist/api/run.d.ts +19 -0
- package/dist/api/run.d.ts.map +1 -0
- package/dist/api/run.js +291 -0
- package/dist/api/run.js.map +1 -0
- package/dist/api/specs.d.ts +49 -0
- package/dist/api/specs.d.ts.map +1 -0
- package/dist/api/specs.js +136 -0
- package/dist/api/specs.js.map +1 -0
- package/dist/api/types.d.ts +176 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +9 -0
- package/dist/api/types.js.map +1 -0
- package/dist/api/verify.d.ts +20 -0
- package/dist/api/verify.d.ts.map +1 -0
- package/dist/api/verify.js +117 -0
- package/dist/api/verify.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +27 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +485 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/drift.d.ts +9 -0
- package/dist/cli/commands/drift.d.ts.map +1 -0
- package/dist/cli/commands/drift.js +540 -0
- package/dist/cli/commands/drift.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +9 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +633 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +171 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +638 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +574 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/run.d.ts +24 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +546 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +9 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +417 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/commands/view.d.ts +9 -0
- package/dist/cli/commands/view.d.ts.map +1 -0
- package/dist/cli/commands/view.js +511 -0
- package/dist/cli/commands/view.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +83 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/analyzer/architecture-writer.d.ts +67 -0
- package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
- package/dist/core/analyzer/architecture-writer.js +209 -0
- package/dist/core/analyzer/architecture-writer.js.map +1 -0
- package/dist/core/analyzer/artifact-generator.d.ts +222 -0
- package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
- package/dist/core/analyzer/artifact-generator.js +726 -0
- package/dist/core/analyzer/artifact-generator.js.map +1 -0
- package/dist/core/analyzer/call-graph.d.ts +83 -0
- package/dist/core/analyzer/call-graph.d.ts.map +1 -0
- package/dist/core/analyzer/call-graph.js +827 -0
- package/dist/core/analyzer/call-graph.js.map +1 -0
- package/dist/core/analyzer/code-shaper.d.ts +33 -0
- package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
- package/dist/core/analyzer/code-shaper.js +149 -0
- package/dist/core/analyzer/code-shaper.js.map +1 -0
- package/dist/core/analyzer/dependency-graph.d.ts +179 -0
- package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
- package/dist/core/analyzer/dependency-graph.js +574 -0
- package/dist/core/analyzer/dependency-graph.js.map +1 -0
- package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
- package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
- package/dist/core/analyzer/duplicate-detector.js +279 -0
- package/dist/core/analyzer/duplicate-detector.js.map +1 -0
- package/dist/core/analyzer/embedding-service.d.ts +50 -0
- package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
- package/dist/core/analyzer/embedding-service.js +104 -0
- package/dist/core/analyzer/embedding-service.js.map +1 -0
- package/dist/core/analyzer/file-walker.d.ts +78 -0
- package/dist/core/analyzer/file-walker.d.ts.map +1 -0
- package/dist/core/analyzer/file-walker.js +531 -0
- package/dist/core/analyzer/file-walker.js.map +1 -0
- package/dist/core/analyzer/import-parser.d.ts +91 -0
- package/dist/core/analyzer/import-parser.d.ts.map +1 -0
- package/dist/core/analyzer/import-parser.js +720 -0
- package/dist/core/analyzer/import-parser.js.map +1 -0
- package/dist/core/analyzer/index.d.ts +10 -0
- package/dist/core/analyzer/index.d.ts.map +1 -0
- package/dist/core/analyzer/index.js +10 -0
- package/dist/core/analyzer/index.js.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts +80 -0
- package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
- package/dist/core/analyzer/refactor-analyzer.js +339 -0
- package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
- package/dist/core/analyzer/repository-mapper.d.ts +150 -0
- package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
- package/dist/core/analyzer/repository-mapper.js +731 -0
- package/dist/core/analyzer/repository-mapper.js.map +1 -0
- package/dist/core/analyzer/signature-extractor.d.ts +31 -0
- package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/signature-extractor.js +387 -0
- package/dist/core/analyzer/signature-extractor.js.map +1 -0
- package/dist/core/analyzer/significance-scorer.d.ts +79 -0
- package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
- package/dist/core/analyzer/significance-scorer.js +407 -0
- package/dist/core/analyzer/significance-scorer.js.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts +43 -0
- package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
- package/dist/core/analyzer/subgraph-extractor.js +129 -0
- package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
- package/dist/core/analyzer/vector-index.d.ts +63 -0
- package/dist/core/analyzer/vector-index.d.ts.map +1 -0
- package/dist/core/analyzer/vector-index.js +169 -0
- package/dist/core/analyzer/vector-index.js.map +1 -0
- package/dist/core/drift/drift-detector.d.ts +102 -0
- package/dist/core/drift/drift-detector.d.ts.map +1 -0
- package/dist/core/drift/drift-detector.js +597 -0
- package/dist/core/drift/drift-detector.js.map +1 -0
- package/dist/core/drift/git-diff.d.ts +55 -0
- package/dist/core/drift/git-diff.d.ts.map +1 -0
- package/dist/core/drift/git-diff.js +356 -0
- package/dist/core/drift/git-diff.js.map +1 -0
- package/dist/core/drift/index.d.ts +12 -0
- package/dist/core/drift/index.d.ts.map +1 -0
- package/dist/core/drift/index.js +9 -0
- package/dist/core/drift/index.js.map +1 -0
- package/dist/core/drift/spec-mapper.d.ts +73 -0
- package/dist/core/drift/spec-mapper.d.ts.map +1 -0
- package/dist/core/drift/spec-mapper.js +353 -0
- package/dist/core/drift/spec-mapper.js.map +1 -0
- package/dist/core/generator/adr-generator.d.ts +32 -0
- package/dist/core/generator/adr-generator.d.ts.map +1 -0
- package/dist/core/generator/adr-generator.js +192 -0
- package/dist/core/generator/adr-generator.js.map +1 -0
- package/dist/core/generator/index.d.ts +9 -0
- package/dist/core/generator/index.d.ts.map +1 -0
- package/dist/core/generator/index.js +12 -0
- package/dist/core/generator/index.js.map +1 -0
- package/dist/core/generator/mapping-generator.d.ts +54 -0
- package/dist/core/generator/mapping-generator.d.ts.map +1 -0
- package/dist/core/generator/mapping-generator.js +239 -0
- package/dist/core/generator/mapping-generator.js.map +1 -0
- package/dist/core/generator/openspec-compat.d.ts +160 -0
- package/dist/core/generator/openspec-compat.d.ts.map +1 -0
- package/dist/core/generator/openspec-compat.js +523 -0
- package/dist/core/generator/openspec-compat.js.map +1 -0
- package/dist/core/generator/openspec-format-generator.d.ts +111 -0
- package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
- package/dist/core/generator/openspec-format-generator.js +817 -0
- package/dist/core/generator/openspec-format-generator.js.map +1 -0
- package/dist/core/generator/openspec-writer.d.ts +131 -0
- package/dist/core/generator/openspec-writer.d.ts.map +1 -0
- package/dist/core/generator/openspec-writer.js +379 -0
- package/dist/core/generator/openspec-writer.js.map +1 -0
- package/dist/core/generator/prompts.d.ts +35 -0
- package/dist/core/generator/prompts.d.ts.map +1 -0
- package/dist/core/generator/prompts.js +212 -0
- package/dist/core/generator/prompts.js.map +1 -0
- package/dist/core/generator/spec-pipeline.d.ts +94 -0
- package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
- package/dist/core/generator/spec-pipeline.js +474 -0
- package/dist/core/generator/spec-pipeline.js.map +1 -0
- package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
- package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
- package/dist/core/generator/stages/stage1-survey.js +105 -0
- package/dist/core/generator/stages/stage1-survey.js.map +1 -0
- package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
- package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
- package/dist/core/generator/stages/stage2-entities.js +67 -0
- package/dist/core/generator/stages/stage2-entities.js.map +1 -0
- package/dist/core/generator/stages/stage3-services.d.ts +11 -0
- package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
- package/dist/core/generator/stages/stage3-services.js +75 -0
- package/dist/core/generator/stages/stage3-services.js.map +1 -0
- package/dist/core/generator/stages/stage4-api.d.ts +11 -0
- package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
- package/dist/core/generator/stages/stage4-api.js +65 -0
- package/dist/core/generator/stages/stage4-api.js.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts +10 -0
- package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
- package/dist/core/generator/stages/stage5-architecture.js +62 -0
- package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
- package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
- package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
- package/dist/core/generator/stages/stage6-adr.js +41 -0
- package/dist/core/generator/stages/stage6-adr.js.map +1 -0
- package/dist/core/services/chat-agent.d.ts +45 -0
- package/dist/core/services/chat-agent.d.ts.map +1 -0
- package/dist/core/services/chat-agent.js +310 -0
- package/dist/core/services/chat-agent.js.map +1 -0
- package/dist/core/services/chat-tools.d.ts +32 -0
- package/dist/core/services/chat-tools.d.ts.map +1 -0
- package/dist/core/services/chat-tools.js +270 -0
- package/dist/core/services/chat-tools.js.map +1 -0
- package/dist/core/services/config-manager.d.ts +61 -0
- package/dist/core/services/config-manager.d.ts.map +1 -0
- package/dist/core/services/config-manager.js +143 -0
- package/dist/core/services/config-manager.js.map +1 -0
- package/dist/core/services/gitignore-manager.d.ts +29 -0
- package/dist/core/services/gitignore-manager.d.ts.map +1 -0
- package/dist/core/services/gitignore-manager.js +106 -0
- package/dist/core/services/gitignore-manager.js.map +1 -0
- package/dist/core/services/index.d.ts +8 -0
- package/dist/core/services/index.d.ts.map +1 -0
- package/dist/core/services/index.js +8 -0
- package/dist/core/services/index.js.map +1 -0
- package/dist/core/services/llm-service.d.ts +336 -0
- package/dist/core/services/llm-service.d.ts.map +1 -0
- package/dist/core/services/llm-service.js +1155 -0
- package/dist/core/services/llm-service.js.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts +42 -0
- package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/analysis.js +300 -0
- package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
- package/dist/core/services/mcp-handlers/graph.d.ts +65 -0
- package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/graph.js +509 -0
- package/dist/core/services/mcp-handlers/graph.js.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts +38 -0
- package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/semantic.js +172 -0
- package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
- package/dist/core/services/mcp-handlers/utils.d.ts +21 -0
- package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
- package/dist/core/services/mcp-handlers/utils.js +62 -0
- package/dist/core/services/mcp-handlers/utils.js.map +1 -0
- package/dist/core/services/project-detector.d.ts +32 -0
- package/dist/core/services/project-detector.d.ts.map +1 -0
- package/dist/core/services/project-detector.js +111 -0
- package/dist/core/services/project-detector.js.map +1 -0
- package/dist/core/verifier/index.d.ts +5 -0
- package/dist/core/verifier/index.d.ts.map +1 -0
- package/dist/core/verifier/index.js +5 -0
- package/dist/core/verifier/index.js.map +1 -0
- package/dist/core/verifier/verification-engine.d.ts +226 -0
- package/dist/core/verifier/verification-engine.d.ts.map +1 -0
- package/dist/core/verifier/verification-engine.js +681 -0
- package/dist/core/verifier/verification-engine.js.map +1 -0
- package/dist/types/index.d.ts +252 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/pipeline.d.ts +148 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +5 -0
- package/dist/types/pipeline.js.map +1 -0
- package/dist/utils/errors.d.ts +51 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +128 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +149 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +331 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/progress.d.ts +142 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +280 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/prompts.d.ts +53 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +199 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/shutdown.d.ts +89 -0
- package/dist/utils/shutdown.d.ts.map +1 -0
- package/dist/utils/shutdown.js +237 -0
- package/dist/utils/shutdown.js.map +1 -0
- package/package.json +114 -0
- package/src/viewer/InteractiveGraphViewer.jsx +1486 -0
- package/src/viewer/app/index.html +17 -0
- package/src/viewer/app/main.jsx +13 -0
- package/src/viewer/components/ArchitectureView.jsx +177 -0
- package/src/viewer/components/ChatPanel.jsx +448 -0
- package/src/viewer/components/ClusterGraph.jsx +441 -0
- package/src/viewer/components/FilterBar.jsx +179 -0
- package/src/viewer/components/FlatGraph.jsx +275 -0
- package/src/viewer/components/MicroComponents.jsx +83 -0
- package/src/viewer/hooks/usePanZoom.js +79 -0
- package/src/viewer/utils/constants.js +47 -0
- package/src/viewer/utils/graph-helpers.js +291 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Graph Service
|
|
3
|
+
*
|
|
4
|
+
* Builds a complete graph of how files relate to each other through imports.
|
|
5
|
+
* Provides metrics like in-degree, out-degree, betweenness centrality, and PageRank.
|
|
6
|
+
* Detects clusters, cycles, and special nodes (centers, leaves, bridges, orphans).
|
|
7
|
+
*/
|
|
8
|
+
import { ImportExportParser, resolveImport } from './import-parser.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// DEPENDENCY GRAPH BUILDER
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Builds and analyzes a dependency graph from scored files
|
|
14
|
+
*/
|
|
15
|
+
export class DependencyGraphBuilder {
|
|
16
|
+
nodes = new Map();
|
|
17
|
+
edges = [];
|
|
18
|
+
adjacencyList = new Map();
|
|
19
|
+
reverseAdjacencyList = new Map();
|
|
20
|
+
parser;
|
|
21
|
+
options;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.parser = new ImportExportParser();
|
|
24
|
+
this.options = {
|
|
25
|
+
rootDir: options.rootDir,
|
|
26
|
+
extensions: options.extensions ?? [], // empty = auto-detect per file in resolveImport
|
|
27
|
+
minClusterSize: options.minClusterSize ?? 2,
|
|
28
|
+
dampingFactor: options.dampingFactor ?? 0.85,
|
|
29
|
+
maxIterations: options.maxIterations ?? 100,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build the dependency graph from scored files
|
|
34
|
+
*/
|
|
35
|
+
async build(files) {
|
|
36
|
+
// Clear any previous state
|
|
37
|
+
this.nodes.clear();
|
|
38
|
+
this.edges = [];
|
|
39
|
+
this.adjacencyList.clear();
|
|
40
|
+
this.reverseAdjacencyList.clear();
|
|
41
|
+
// Parse all files and create nodes
|
|
42
|
+
const analyses = await this.parseFiles(files);
|
|
43
|
+
// Create nodes for each file
|
|
44
|
+
for (const file of files) {
|
|
45
|
+
const analysis = analyses.get(file.absolutePath);
|
|
46
|
+
this.nodes.set(file.absolutePath, {
|
|
47
|
+
id: file.absolutePath,
|
|
48
|
+
file,
|
|
49
|
+
exports: analysis?.exports ?? [],
|
|
50
|
+
metrics: {
|
|
51
|
+
inDegree: 0,
|
|
52
|
+
outDegree: 0,
|
|
53
|
+
betweenness: 0,
|
|
54
|
+
pageRank: 1 / files.length,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
this.adjacencyList.set(file.absolutePath, new Set());
|
|
58
|
+
this.reverseAdjacencyList.set(file.absolutePath, new Set());
|
|
59
|
+
}
|
|
60
|
+
// Create edges from imports
|
|
61
|
+
await this.buildEdges(files, analyses);
|
|
62
|
+
// Calculate metrics
|
|
63
|
+
this.calculateDegrees();
|
|
64
|
+
this.calculateBetweenness();
|
|
65
|
+
this.calculatePageRank();
|
|
66
|
+
// Detect clusters
|
|
67
|
+
const clusters = this.detectClusters();
|
|
68
|
+
// Detect cycles
|
|
69
|
+
const cycles = this.detectCycles();
|
|
70
|
+
// Generate rankings
|
|
71
|
+
const rankings = this.generateRankings(clusters);
|
|
72
|
+
// Calculate statistics
|
|
73
|
+
const statistics = this.calculateStatistics(clusters, cycles);
|
|
74
|
+
return {
|
|
75
|
+
nodes: Array.from(this.nodes.values()),
|
|
76
|
+
edges: this.edges,
|
|
77
|
+
clusters,
|
|
78
|
+
rankings,
|
|
79
|
+
cycles,
|
|
80
|
+
statistics,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Parse all files to extract imports/exports
|
|
85
|
+
*/
|
|
86
|
+
async parseFiles(files) {
|
|
87
|
+
const analyses = new Map();
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
try {
|
|
90
|
+
const analysis = await this.parser.parseFile(file.absolutePath);
|
|
91
|
+
analyses.set(file.absolutePath, analysis);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// File couldn't be parsed, skip it
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return analyses;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Build edges from import relationships
|
|
101
|
+
*/
|
|
102
|
+
async buildEdges(files, analyses) {
|
|
103
|
+
const fileSet = new Set(files.map(f => f.absolutePath));
|
|
104
|
+
for (const file of files) {
|
|
105
|
+
const analysis = analyses.get(file.absolutePath);
|
|
106
|
+
if (!analysis)
|
|
107
|
+
continue;
|
|
108
|
+
for (const imp of analysis.imports) {
|
|
109
|
+
// Skip non-relative imports (packages, builtins)
|
|
110
|
+
if (!imp.isRelative)
|
|
111
|
+
continue;
|
|
112
|
+
// Resolve the import to an absolute path
|
|
113
|
+
const resolvedPath = await resolveImport(imp.source, file.absolutePath, {
|
|
114
|
+
baseDir: this.options.rootDir,
|
|
115
|
+
extensions: this.options.extensions.length > 0 ? this.options.extensions : undefined,
|
|
116
|
+
});
|
|
117
|
+
// Skip if not resolved or not in our file set
|
|
118
|
+
if (!resolvedPath || !fileSet.has(resolvedPath))
|
|
119
|
+
continue;
|
|
120
|
+
// Create edge
|
|
121
|
+
const edge = {
|
|
122
|
+
source: file.absolutePath,
|
|
123
|
+
target: resolvedPath,
|
|
124
|
+
importedNames: imp.importedNames,
|
|
125
|
+
isTypeOnly: imp.isTypeOnly,
|
|
126
|
+
weight: imp.isTypeOnly ? 0.5 : 1,
|
|
127
|
+
};
|
|
128
|
+
this.edges.push(edge);
|
|
129
|
+
// Update adjacency lists
|
|
130
|
+
this.adjacencyList.get(file.absolutePath)?.add(resolvedPath);
|
|
131
|
+
this.reverseAdjacencyList.get(resolvedPath)?.add(file.absolutePath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Calculate in-degree and out-degree for each node
|
|
137
|
+
*/
|
|
138
|
+
calculateDegrees() {
|
|
139
|
+
for (const [nodeId, node] of this.nodes) {
|
|
140
|
+
node.metrics.outDegree = this.adjacencyList.get(nodeId)?.size ?? 0;
|
|
141
|
+
node.metrics.inDegree = this.reverseAdjacencyList.get(nodeId)?.size ?? 0;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Calculate betweenness centrality using Brandes' algorithm
|
|
146
|
+
*/
|
|
147
|
+
calculateBetweenness() {
|
|
148
|
+
const nodeIds = Array.from(this.nodes.keys());
|
|
149
|
+
const betweenness = new Map();
|
|
150
|
+
// Initialize betweenness to 0
|
|
151
|
+
for (const id of nodeIds) {
|
|
152
|
+
betweenness.set(id, 0);
|
|
153
|
+
}
|
|
154
|
+
// Brandes' algorithm
|
|
155
|
+
for (const source of nodeIds) {
|
|
156
|
+
const stack = [];
|
|
157
|
+
const predecessors = new Map();
|
|
158
|
+
const sigma = new Map();
|
|
159
|
+
const distance = new Map();
|
|
160
|
+
const delta = new Map();
|
|
161
|
+
// Initialize
|
|
162
|
+
for (const v of nodeIds) {
|
|
163
|
+
predecessors.set(v, []);
|
|
164
|
+
sigma.set(v, 0);
|
|
165
|
+
distance.set(v, -1);
|
|
166
|
+
delta.set(v, 0);
|
|
167
|
+
}
|
|
168
|
+
sigma.set(source, 1);
|
|
169
|
+
distance.set(source, 0);
|
|
170
|
+
// BFS
|
|
171
|
+
const queue = [source];
|
|
172
|
+
while (queue.length > 0) {
|
|
173
|
+
const v = queue.shift();
|
|
174
|
+
stack.push(v);
|
|
175
|
+
const neighbors = this.adjacencyList.get(v) ?? new Set();
|
|
176
|
+
for (const w of neighbors) {
|
|
177
|
+
// First visit?
|
|
178
|
+
if (distance.get(w) < 0) {
|
|
179
|
+
queue.push(w);
|
|
180
|
+
distance.set(w, distance.get(v) + 1);
|
|
181
|
+
}
|
|
182
|
+
// Shortest path to w via v?
|
|
183
|
+
if (distance.get(w) === distance.get(v) + 1) {
|
|
184
|
+
sigma.set(w, sigma.get(w) + sigma.get(v));
|
|
185
|
+
predecessors.get(w).push(v);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Back-propagation
|
|
190
|
+
while (stack.length > 0) {
|
|
191
|
+
const w = stack.pop();
|
|
192
|
+
for (const v of predecessors.get(w)) {
|
|
193
|
+
delta.set(v, delta.get(v) + (sigma.get(v) / sigma.get(w)) * (1 + delta.get(w)));
|
|
194
|
+
}
|
|
195
|
+
if (w !== source) {
|
|
196
|
+
betweenness.set(w, betweenness.get(w) + delta.get(w));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Normalize and update nodes
|
|
201
|
+
const maxBetweenness = Math.max(...Array.from(betweenness.values()), 1);
|
|
202
|
+
for (const [nodeId, node] of this.nodes) {
|
|
203
|
+
node.metrics.betweenness = betweenness.get(nodeId) / maxBetweenness;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Calculate PageRank-style importance scores
|
|
208
|
+
*/
|
|
209
|
+
calculatePageRank() {
|
|
210
|
+
const nodeIds = Array.from(this.nodes.keys());
|
|
211
|
+
const n = nodeIds.length;
|
|
212
|
+
if (n === 0)
|
|
213
|
+
return;
|
|
214
|
+
const d = this.options.dampingFactor;
|
|
215
|
+
let pageRank = new Map();
|
|
216
|
+
let newPageRank = new Map();
|
|
217
|
+
// Initialize
|
|
218
|
+
for (const id of nodeIds) {
|
|
219
|
+
pageRank.set(id, 1 / n);
|
|
220
|
+
}
|
|
221
|
+
// Iterate until convergence
|
|
222
|
+
for (let iter = 0; iter < this.options.maxIterations; iter++) {
|
|
223
|
+
let maxDiff = 0;
|
|
224
|
+
for (const id of nodeIds) {
|
|
225
|
+
// Sum contributions from nodes that link to this one
|
|
226
|
+
let sum = 0;
|
|
227
|
+
const incomingNodes = this.reverseAdjacencyList.get(id) ?? new Set();
|
|
228
|
+
for (const source of incomingNodes) {
|
|
229
|
+
const outDegree = this.adjacencyList.get(source)?.size ?? 1;
|
|
230
|
+
sum += pageRank.get(source) / outDegree;
|
|
231
|
+
}
|
|
232
|
+
const newRank = (1 - d) / n + d * sum;
|
|
233
|
+
newPageRank.set(id, newRank);
|
|
234
|
+
maxDiff = Math.max(maxDiff, Math.abs(newRank - pageRank.get(id)));
|
|
235
|
+
}
|
|
236
|
+
// Swap
|
|
237
|
+
[pageRank, newPageRank] = [newPageRank, pageRank];
|
|
238
|
+
// Check convergence
|
|
239
|
+
if (maxDiff < 1e-6)
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
// Normalize and update nodes
|
|
243
|
+
const maxPageRank = Math.max(...Array.from(pageRank.values()), 0.001);
|
|
244
|
+
for (const [nodeId, node] of this.nodes) {
|
|
245
|
+
node.metrics.pageRank = pageRank.get(nodeId) / maxPageRank;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Detect clusters using a simple community detection approach
|
|
250
|
+
* Groups files by their common directory prefix and connectivity
|
|
251
|
+
*/
|
|
252
|
+
detectClusters() {
|
|
253
|
+
const clusters = [];
|
|
254
|
+
const nodeIds = Array.from(this.nodes.keys());
|
|
255
|
+
// Group by directory
|
|
256
|
+
const dirGroups = new Map();
|
|
257
|
+
for (const nodeId of nodeIds) {
|
|
258
|
+
const node = this.nodes.get(nodeId);
|
|
259
|
+
const dir = node.file.directory || '(root)';
|
|
260
|
+
if (!dirGroups.has(dir)) {
|
|
261
|
+
dirGroups.set(dir, []);
|
|
262
|
+
}
|
|
263
|
+
dirGroups.get(dir).push(nodeId);
|
|
264
|
+
}
|
|
265
|
+
// Create clusters from directory groups
|
|
266
|
+
let clusterId = 0;
|
|
267
|
+
for (const [dir, files] of dirGroups) {
|
|
268
|
+
if (files.length < this.options.minClusterSize)
|
|
269
|
+
continue;
|
|
270
|
+
// Calculate internal and external edges
|
|
271
|
+
let internalEdges = 0;
|
|
272
|
+
let externalEdges = 0;
|
|
273
|
+
const fileSet = new Set(files);
|
|
274
|
+
for (const edge of this.edges) {
|
|
275
|
+
const sourceInCluster = fileSet.has(edge.source);
|
|
276
|
+
const targetInCluster = fileSet.has(edge.target);
|
|
277
|
+
if (sourceInCluster && targetInCluster) {
|
|
278
|
+
internalEdges++;
|
|
279
|
+
}
|
|
280
|
+
else if (sourceInCluster || targetInCluster) {
|
|
281
|
+
externalEdges++;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// Calculate cohesion (internal density)
|
|
285
|
+
const possibleInternalEdges = files.length * (files.length - 1);
|
|
286
|
+
const cohesion = possibleInternalEdges > 0 ? internalEdges / possibleInternalEdges : 0;
|
|
287
|
+
// Calculate coupling (external connections)
|
|
288
|
+
const totalEdges = internalEdges + externalEdges;
|
|
289
|
+
const coupling = totalEdges > 0 ? externalEdges / totalEdges : 0;
|
|
290
|
+
// Generate suggested domain name
|
|
291
|
+
const suggestedDomain = this.suggestDomainName(dir, files);
|
|
292
|
+
clusters.push({
|
|
293
|
+
id: `cluster-${clusterId++}`,
|
|
294
|
+
name: dir,
|
|
295
|
+
files,
|
|
296
|
+
internalEdges,
|
|
297
|
+
externalEdges,
|
|
298
|
+
cohesion,
|
|
299
|
+
coupling,
|
|
300
|
+
suggestedDomain,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
return clusters;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Suggest a domain name based on directory and file contents
|
|
307
|
+
*/
|
|
308
|
+
suggestDomainName(dir, files) {
|
|
309
|
+
// Extract meaningful name from directory
|
|
310
|
+
const parts = dir.split('/').filter(p => p && p !== '(root)');
|
|
311
|
+
// Common patterns to convert
|
|
312
|
+
const patterns = [
|
|
313
|
+
[/^src$/i, ''],
|
|
314
|
+
[/^lib$/i, ''],
|
|
315
|
+
[/^app$/i, ''],
|
|
316
|
+
[/^(api|routes|endpoints?)$/i, 'api'],
|
|
317
|
+
[/^(models?|entities|schemas?)$/i, 'domain'],
|
|
318
|
+
[/^(services?)$/i, 'services'],
|
|
319
|
+
[/^(controllers?)$/i, 'controllers'],
|
|
320
|
+
[/^(utils?|helpers?|common)$/i, 'utilities'],
|
|
321
|
+
[/^(components?)$/i, 'components'],
|
|
322
|
+
[/^(hooks?)$/i, 'hooks'],
|
|
323
|
+
[/^(auth|authentication)$/i, 'authentication'],
|
|
324
|
+
[/^(users?)$/i, 'users'],
|
|
325
|
+
[/^(products?)$/i, 'products'],
|
|
326
|
+
[/^(orders?)$/i, 'orders'],
|
|
327
|
+
[/^(payments?)$/i, 'payments'],
|
|
328
|
+
[/^(core)$/i, 'core'],
|
|
329
|
+
];
|
|
330
|
+
// Try to find a meaningful name
|
|
331
|
+
for (const part of parts.reverse()) {
|
|
332
|
+
for (const [pattern, replacement] of patterns) {
|
|
333
|
+
if (pattern.test(part)) {
|
|
334
|
+
return replacement || part.toLowerCase();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// If no pattern matches, use the part as-is
|
|
338
|
+
if (!/^(src|lib|app)$/i.test(part)) {
|
|
339
|
+
return part.toLowerCase().replace(/[^a-z0-9]/g, '-');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// Fallback: use first file's name pattern
|
|
343
|
+
if (files.length > 0) {
|
|
344
|
+
const firstFile = this.nodes.get(files[0])?.file.name ?? 'unknown';
|
|
345
|
+
return firstFile.replace(/\.(ts|js|tsx|jsx|py)x?$/, '').toLowerCase();
|
|
346
|
+
}
|
|
347
|
+
return 'misc';
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Detect cycles in the dependency graph using DFS
|
|
351
|
+
*/
|
|
352
|
+
detectCycles() {
|
|
353
|
+
const cycles = [];
|
|
354
|
+
const visited = new Set();
|
|
355
|
+
const recursionStack = new Set();
|
|
356
|
+
const path = [];
|
|
357
|
+
const dfs = (node) => {
|
|
358
|
+
visited.add(node);
|
|
359
|
+
recursionStack.add(node);
|
|
360
|
+
path.push(node);
|
|
361
|
+
const neighbors = this.adjacencyList.get(node) ?? new Set();
|
|
362
|
+
for (const neighbor of neighbors) {
|
|
363
|
+
if (!visited.has(neighbor)) {
|
|
364
|
+
dfs(neighbor);
|
|
365
|
+
}
|
|
366
|
+
else if (recursionStack.has(neighbor)) {
|
|
367
|
+
// Found a cycle
|
|
368
|
+
const cycleStart = path.indexOf(neighbor);
|
|
369
|
+
const cycle = path.slice(cycleStart);
|
|
370
|
+
cycle.push(neighbor); // Complete the cycle
|
|
371
|
+
// Check if this cycle is not a duplicate (or rotation of existing)
|
|
372
|
+
if (!this.isDuplicateCycle(cycles, cycle)) {
|
|
373
|
+
cycles.push(cycle);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
path.pop();
|
|
378
|
+
recursionStack.delete(node);
|
|
379
|
+
};
|
|
380
|
+
for (const nodeId of this.nodes.keys()) {
|
|
381
|
+
if (!visited.has(nodeId)) {
|
|
382
|
+
dfs(nodeId);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return cycles;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Check if a cycle is a duplicate or rotation of an existing cycle
|
|
389
|
+
*/
|
|
390
|
+
isDuplicateCycle(existingCycles, newCycle) {
|
|
391
|
+
const normalizedNew = this.normalizeCycle(newCycle);
|
|
392
|
+
for (const existing of existingCycles) {
|
|
393
|
+
const normalizedExisting = this.normalizeCycle(existing);
|
|
394
|
+
if (normalizedNew === normalizedExisting) {
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Normalize a cycle for comparison (smallest element first, then compare)
|
|
402
|
+
*/
|
|
403
|
+
normalizeCycle(cycle) {
|
|
404
|
+
// Remove the duplicate closing element
|
|
405
|
+
const clean = cycle.slice(0, -1);
|
|
406
|
+
if (clean.length === 0)
|
|
407
|
+
return '';
|
|
408
|
+
// Find the smallest element
|
|
409
|
+
const minIdx = clean.indexOf(clean.reduce((min, curr) => (curr < min ? curr : min)));
|
|
410
|
+
// Rotate so smallest is first
|
|
411
|
+
const rotated = [...clean.slice(minIdx), ...clean.slice(0, minIdx)];
|
|
412
|
+
return rotated.join('|');
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Generate various rankings of nodes
|
|
416
|
+
*/
|
|
417
|
+
generateRankings(clusters) {
|
|
418
|
+
const nodes = Array.from(this.nodes.values());
|
|
419
|
+
// By PageRank importance
|
|
420
|
+
const byImportance = nodes
|
|
421
|
+
.sort((a, b) => b.metrics.pageRank - a.metrics.pageRank)
|
|
422
|
+
.map(n => n.id);
|
|
423
|
+
// By total connectivity (in + out degree)
|
|
424
|
+
const byConnectivity = nodes
|
|
425
|
+
.sort((a, b) => (b.metrics.inDegree + b.metrics.outDegree) -
|
|
426
|
+
(a.metrics.inDegree + a.metrics.outDegree))
|
|
427
|
+
.map(n => n.id);
|
|
428
|
+
// Cluster centers (highest in-degree within each cluster)
|
|
429
|
+
const clusterCenters = [];
|
|
430
|
+
for (const cluster of clusters) {
|
|
431
|
+
const clusterNodes = cluster.files
|
|
432
|
+
.map(f => this.nodes.get(f))
|
|
433
|
+
.filter((n) => n !== undefined);
|
|
434
|
+
if (clusterNodes.length > 0) {
|
|
435
|
+
const center = clusterNodes.reduce((max, n) => n.metrics.inDegree > max.metrics.inDegree ? n : max);
|
|
436
|
+
clusterCenters.push(center.id);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
// Leaf nodes (high out-degree, low in-degree)
|
|
440
|
+
const leafNodes = nodes
|
|
441
|
+
.filter(n => n.metrics.outDegree > 0 && n.metrics.inDegree === 0)
|
|
442
|
+
.sort((a, b) => b.metrics.outDegree - a.metrics.outDegree)
|
|
443
|
+
.map(n => n.id);
|
|
444
|
+
// Bridge nodes (high betweenness)
|
|
445
|
+
const bridgeNodes = nodes
|
|
446
|
+
.filter(n => n.metrics.betweenness > 0.1)
|
|
447
|
+
.sort((a, b) => b.metrics.betweenness - a.metrics.betweenness)
|
|
448
|
+
.map(n => n.id);
|
|
449
|
+
// Orphan nodes (no connections)
|
|
450
|
+
const orphanNodes = nodes
|
|
451
|
+
.filter(n => n.metrics.inDegree === 0 && n.metrics.outDegree === 0)
|
|
452
|
+
.map(n => n.id);
|
|
453
|
+
return {
|
|
454
|
+
byImportance,
|
|
455
|
+
byConnectivity,
|
|
456
|
+
clusterCenters,
|
|
457
|
+
leafNodes,
|
|
458
|
+
bridgeNodes,
|
|
459
|
+
orphanNodes,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Calculate overall statistics
|
|
464
|
+
*/
|
|
465
|
+
calculateStatistics(clusters, cycles) {
|
|
466
|
+
const nodeCount = this.nodes.size;
|
|
467
|
+
const edgeCount = this.edges.length;
|
|
468
|
+
// Average degree
|
|
469
|
+
let totalDegree = 0;
|
|
470
|
+
for (const node of this.nodes.values()) {
|
|
471
|
+
totalDegree += node.metrics.inDegree + node.metrics.outDegree;
|
|
472
|
+
}
|
|
473
|
+
const avgDegree = nodeCount > 0 ? totalDegree / nodeCount : 0;
|
|
474
|
+
// Density: actual edges / possible edges
|
|
475
|
+
const possibleEdges = nodeCount * (nodeCount - 1);
|
|
476
|
+
const density = possibleEdges > 0 ? edgeCount / possibleEdges : 0;
|
|
477
|
+
return {
|
|
478
|
+
nodeCount,
|
|
479
|
+
edgeCount,
|
|
480
|
+
avgDegree,
|
|
481
|
+
density,
|
|
482
|
+
clusterCount: clusters.length,
|
|
483
|
+
cycleCount: cycles.length,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
// ============================================================================
|
|
488
|
+
// CONVENIENCE FUNCTIONS
|
|
489
|
+
// ============================================================================
|
|
490
|
+
/**
|
|
491
|
+
* Build a dependency graph from scored files
|
|
492
|
+
*/
|
|
493
|
+
export async function buildDependencyGraph(files, options) {
|
|
494
|
+
const builder = new DependencyGraphBuilder(options);
|
|
495
|
+
return builder.build(files);
|
|
496
|
+
}
|
|
497
|
+
// ============================================================================
|
|
498
|
+
// EXPORT FORMATS
|
|
499
|
+
// ============================================================================
|
|
500
|
+
/**
|
|
501
|
+
* Convert graph to D3.js force graph format
|
|
502
|
+
*/
|
|
503
|
+
export function toD3Format(result) {
|
|
504
|
+
// Create cluster index map
|
|
505
|
+
const clusterIndex = new Map();
|
|
506
|
+
result.clusters.forEach((cluster, idx) => {
|
|
507
|
+
for (const file of cluster.files) {
|
|
508
|
+
clusterIndex.set(file, idx);
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
return {
|
|
512
|
+
nodes: result.nodes.map(n => ({
|
|
513
|
+
id: n.file.path,
|
|
514
|
+
group: clusterIndex.get(n.id) ?? -1,
|
|
515
|
+
score: n.metrics.pageRank,
|
|
516
|
+
})),
|
|
517
|
+
links: result.edges.map(e => ({
|
|
518
|
+
source: result.nodes.find(n => n.id === e.source)?.file.path ?? e.source,
|
|
519
|
+
target: result.nodes.find(n => n.id === e.target)?.file.path ?? e.target,
|
|
520
|
+
value: e.weight,
|
|
521
|
+
})),
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Convert graph to Mermaid diagram syntax
|
|
526
|
+
*/
|
|
527
|
+
export function toMermaidFormat(result, maxNodes = 50) {
|
|
528
|
+
const lines = ['graph TD'];
|
|
529
|
+
// Take top nodes by importance
|
|
530
|
+
const topNodes = result.rankings.byImportance.slice(0, maxNodes);
|
|
531
|
+
const nodeSet = new Set(topNodes);
|
|
532
|
+
// Create node labels
|
|
533
|
+
const nodeLabels = new Map();
|
|
534
|
+
result.nodes
|
|
535
|
+
.filter(n => nodeSet.has(n.id))
|
|
536
|
+
.forEach((n, idx) => {
|
|
537
|
+
const label = `N${idx}`;
|
|
538
|
+
nodeLabels.set(n.id, label);
|
|
539
|
+
const name = n.file.name.replace(/["[\]]/g, '');
|
|
540
|
+
lines.push(` ${label}["${name}"]`);
|
|
541
|
+
});
|
|
542
|
+
// Create edges
|
|
543
|
+
for (const edge of result.edges) {
|
|
544
|
+
const sourceLabel = nodeLabels.get(edge.source);
|
|
545
|
+
const targetLabel = nodeLabels.get(edge.target);
|
|
546
|
+
if (sourceLabel && targetLabel) {
|
|
547
|
+
const style = edge.isTypeOnly ? '-.->' : '-->';
|
|
548
|
+
lines.push(` ${sourceLabel} ${style} ${targetLabel}`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return lines.join('\n');
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Convert graph to DOT format (Graphviz)
|
|
555
|
+
*/
|
|
556
|
+
export function toDotFormat(result) {
|
|
557
|
+
const lines = ['digraph Dependencies {'];
|
|
558
|
+
lines.push(' rankdir=LR;');
|
|
559
|
+
lines.push(' node [shape=box];');
|
|
560
|
+
// Create node definitions with labels
|
|
561
|
+
for (const node of result.nodes) {
|
|
562
|
+
const name = node.file.name.replace(/"/g, '\\"');
|
|
563
|
+
const color = node.metrics.pageRank > 0.5 ? 'lightblue' : 'white';
|
|
564
|
+
lines.push(` "${node.id}" [label="${name}" fillcolor="${color}" style="filled"];`);
|
|
565
|
+
}
|
|
566
|
+
// Create edges
|
|
567
|
+
for (const edge of result.edges) {
|
|
568
|
+
const style = edge.isTypeOnly ? 'dashed' : 'solid';
|
|
569
|
+
lines.push(` "${edge.source}" -> "${edge.target}" [style="${style}"];`);
|
|
570
|
+
}
|
|
571
|
+
lines.push('}');
|
|
572
|
+
return lines.join('\n');
|
|
573
|
+
}
|
|
574
|
+
//# sourceMappingURL=dependency-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../../../src/core/analyzer/dependency-graph.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAsC,MAAM,oBAAoB,CAAC;AAyF3G,+EAA+E;AAC/E,2BAA2B;AAC3B,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,sBAAsB;IACzB,KAAK,GAAgC,IAAI,GAAG,EAAE,CAAC;IAC/C,KAAK,GAAqB,EAAE,CAAC;IAC7B,aAAa,GAA6B,IAAI,GAAG,EAAE,CAAC;IACpD,oBAAoB,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC3D,MAAM,CAAqB;IAC3B,OAAO,CAAmC;IAElD,YAAY,OAA+B;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG;YACb,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,EAAE,EAAG,gDAAgD;YACvF,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,CAAC;YAC3C,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,IAAI;YAC5C,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,GAAG;SAC5C,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK,CAAC,KAAmB;QAC7B,2BAA2B;QAC3B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAElC,mCAAmC;QACnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAE9C,6BAA6B;QAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE;gBAChC,EAAE,EAAE,IAAI,CAAC,YAAY;gBACrB,IAAI;gBACJ,OAAO,EAAE,QAAQ,EAAE,OAAO,IAAI,EAAE;gBAChC,OAAO,EAAE;oBACP,QAAQ,EAAE,CAAC;oBACX,SAAS,EAAE,CAAC;oBACZ,WAAW,EAAE,CAAC;oBACd,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM;iBAC3B;aACF,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YACrD,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,4BAA4B;QAC5B,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAEvC,oBAAoB;QACpB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,kBAAkB;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAEvC,gBAAgB;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAEnC,oBAAoB;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAEjD,uBAAuB;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAE9D,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACtC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ;YACR,QAAQ;YACR,MAAM;YACN,UAAU;SACX,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,UAAU,CAAC,KAAmB;QAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;QAEjD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAChE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,mCAAmC;YACrC,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,UAAU,CACtB,KAAmB,EACnB,QAAmC;QAEnC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QAExD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjD,IAAI,CAAC,QAAQ;gBAAE,SAAS;YAExB,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACnC,iDAAiD;gBACjD,IAAI,CAAC,GAAG,CAAC,UAAU;oBAAE,SAAS;gBAE9B,yCAAyC;gBACzC,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE;oBACtE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;oBAC7B,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;iBACrF,CAAC,CAAC;gBAEH,8CAA8C;gBAC9C,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;oBAAE,SAAS;gBAE1D,cAAc;gBACd,MAAM,IAAI,GAAmB;oBAC3B,MAAM,EAAE,IAAI,CAAC,YAAY;oBACzB,MAAM,EAAE,YAAY;oBACpB,aAAa,EAAE,GAAG,CAAC,aAAa;oBAChC,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;iBACjC,CAAC;gBAEF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEtB,yBAAyB;gBACzB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC7D,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,gBAAgB;QACtB,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;YACnE,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED;;OAEG;IACK,oBAAoB;QAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE9C,8BAA8B;QAC9B,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACzB,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACzB,CAAC;QAED,qBAAqB;QACrB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;YACjD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;YACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC3C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;YAExC,aAAa;YACb,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACxB,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAChB,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACpB,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACrB,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAExB,MAAM;YACN,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,CAAC;YACjC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAEd,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;gBACzD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;oBAC1B,eAAe;oBACf,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,CAAC,EAAE,CAAC;wBACzB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;wBACd,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC;oBACxC,CAAC;oBACD,4BAA4B;oBAC5B,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,CAAC,EAAE,CAAC;wBAC7C,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC;wBAC5C,YAAY,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAC/B,CAAC;gBACH,CAAC;YACH,CAAC;YAED,mBAAmB;YACnB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;gBACvB,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAE,EAAE,CAAC;oBACrC,KAAK,CAAC,GAAG,CACP,CAAC,EACD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CACtE,CAAC;gBACJ,CAAC;gBACD,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;oBACjB,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC;gBAC1D,CAAC;YACH,CAAC;QACH,CAAC;QAED,6BAA6B;QAC7B,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAE,GAAG,cAAc,CAAC;QACvE,CAAC;IACH,CAAC;IAED;;OAEG;IACK,iBAAiB;QACvB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO;QAEpB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;QACrC,IAAI,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,IAAI,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE5C,aAAa;QACb,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,CAAC;QAED,4BAA4B;QAC5B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;YAC7D,IAAI,OAAO,GAAG,CAAC,CAAC;YAEhB,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;gBACzB,qDAAqD;gBACrD,IAAI,GAAG,GAAG,CAAC,CAAC;gBACZ,MAAM,aAAa,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;gBACrE,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;oBACnC,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;oBAC5D,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAE,GAAG,SAAS,CAAC;gBAC3C,CAAC;gBAED,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;gBACtC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBAC7B,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC;YACrE,CAAC;YAED,OAAO;YACP,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAElD,oBAAoB;YACpB,IAAI,OAAO,GAAG,IAAI;gBAAE,MAAM;QAC5B,CAAC;QAED,6BAA6B;QAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACtE,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAE,GAAG,WAAW,CAAC;QAC9D,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,cAAc;QACpB,MAAM,QAAQ,GAAkB,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAE9C,qBAAqB;QACrB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;QAC9C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC;YAE5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACzB,CAAC;YACD,SAAS,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,wCAAwC;QACxC,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;YACrC,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc;gBAAE,SAAS;YAEzD,wCAAwC;YACxC,IAAI,aAAa,GAAG,CAAC,CAAC;YACtB,IAAI,aAAa,GAAG,CAAC,CAAC;YACtB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YAE/B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACjD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAEjD,IAAI,eAAe,IAAI,eAAe,EAAE,CAAC;oBACvC,aAAa,EAAE,CAAC;gBAClB,CAAC;qBAAM,IAAI,eAAe,IAAI,eAAe,EAAE,CAAC;oBAC9C,aAAa,EAAE,CAAC;gBAClB,CAAC;YACH,CAAC;YAED,wCAAwC;YACxC,MAAM,qBAAqB,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,qBAAqB,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvF,4CAA4C;YAC5C,MAAM,UAAU,GAAG,aAAa,GAAG,aAAa,CAAC;YACjD,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YAEjE,iCAAiC;YACjC,MAAM,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAE3D,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,WAAW,SAAS,EAAE,EAAE;gBAC5B,IAAI,EAAE,GAAG;gBACT,KAAK;gBACL,aAAa;gBACb,aAAa;gBACb,QAAQ;gBACR,QAAQ;gBACR,eAAe;aAChB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,GAAW,EAAE,KAAe;QACpD,yCAAyC;QACzC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,CAAC;QAE9D,6BAA6B;QAC7B,MAAM,QAAQ,GAAuB;YACnC,CAAC,QAAQ,EAAE,EAAE,CAAC;YACd,CAAC,QAAQ,EAAE,EAAE,CAAC;YACd,CAAC,QAAQ,EAAE,EAAE,CAAC;YACd,CAAC,4BAA4B,EAAE,KAAK,CAAC;YACrC,CAAC,gCAAgC,EAAE,QAAQ,CAAC;YAC5C,CAAC,gBAAgB,EAAE,UAAU,CAAC;YAC9B,CAAC,mBAAmB,EAAE,aAAa,CAAC;YACpC,CAAC,6BAA6B,EAAE,WAAW,CAAC;YAC5C,CAAC,kBAAkB,EAAE,YAAY,CAAC;YAClC,CAAC,aAAa,EAAE,OAAO,CAAC;YACxB,CAAC,0BAA0B,EAAE,gBAAgB,CAAC;YAC9C,CAAC,aAAa,EAAE,OAAO,CAAC;YACxB,CAAC,gBAAgB,EAAE,UAAU,CAAC;YAC9B,CAAC,cAAc,EAAE,QAAQ,CAAC;YAC1B,CAAC,gBAAgB,EAAE,UAAU,CAAC;YAC9B,CAAC,WAAW,EAAE,MAAM,CAAC;SACtB,CAAC;QAEF,gCAAgC;QAChC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YACnC,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,QAAQ,EAAE,CAAC;gBAC9C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACvB,OAAO,WAAW,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC3C,CAAC;YACH,CAAC;YACD,4CAA4C;YAC5C,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC;YACnE,OAAO,SAAS,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACxE,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,MAAM,MAAM,GAAe,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;QACzC,MAAM,IAAI,GAAa,EAAE,CAAC;QAE1B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAQ,EAAE;YACjC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClB,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;YAC5D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC3B,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAChB,CAAC;qBAAM,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxC,gBAAgB;oBAChB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;oBAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;oBACrC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,qBAAqB;oBAE3C,mEAAmE;oBACnE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;wBAC1C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,GAAG,EAAE,CAAC;YACX,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,GAAG,CAAC,MAAM,CAAC,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,cAA0B,EAAE,QAAkB;QACrE,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAEpD,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;YACtC,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YACzD,IAAI,aAAa,KAAK,kBAAkB,EAAE,CAAC;gBACzC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,KAAe;QACpC,uCAAuC;QACvC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAElC,4BAA4B;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAC1B,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CACvD,CAAC;QAEF,8BAA8B;QAC9B,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACpE,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,QAAuB;QAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAE9C,yBAAyB;QACzB,MAAM,YAAY,GAAG,KAAK;aACvB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;aACvD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAElB,0CAA0C;QAC1C,MAAM,cAAc,GAAG,KAAK;aACzB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACb,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;YAC1C,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAC3C;aACA,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAElB,0DAA0D;QAC1D,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK;iBAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;iBAC3B,MAAM,CAAC,CAAC,CAAC,EAAuB,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;YAEvD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAC5C,CAAC,CAAC,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CACpD,CAAC;gBACF,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,8CAA8C;QAC9C,MAAM,SAAS,GAAG,KAAK;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,CAAC,CAAC;aAChE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;aACzD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAElB,kCAAkC;QAClC,MAAM,WAAW,GAAG,KAAK;aACtB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC;aACxC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;aAC7D,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAElB,gCAAgC;QAChC,MAAM,WAAW,GAAG,KAAK;aACtB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,KAAK,CAAC,CAAC;aAClE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAElB,OAAO;YACL,YAAY;YACZ,cAAc;YACd,cAAc;YACd,SAAS;YACT,WAAW;YACX,WAAW;SACZ,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,mBAAmB,CACzB,QAAuB,EACvB,MAAkB;QAElB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAEpC,iBAAiB;QACjB,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;QAChE,CAAC;QACD,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9D,yCAAyC;QACzC,MAAM,aAAa,GAAG,SAAS,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAElE,OAAO;YACL,SAAS;YACT,SAAS;YACT,SAAS;YACT,OAAO;YACP,YAAY,EAAE,QAAQ,CAAC,MAAM;YAC7B,UAAU,EAAE,MAAM,CAAC,MAAM;SAC1B,CAAC;IACJ,CAAC;CACF;AAED,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAmB,EACnB,OAA+B;IAE/B,MAAM,OAAO,GAAG,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAA6B;IAItD,2BAA2B;IAC3B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;QACvC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5B,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACnC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ;SAC1B,CAAC,CAAC;QACH,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM;YACxE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM;YACxE,KAAK,EAAE,CAAC,CAAC,MAAM;SAChB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAA6B,EAAE,QAAQ,GAAG,EAAE;IAC1E,MAAM,KAAK,GAAa,CAAC,UAAU,CAAC,CAAC;IAErC,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAElC,qBAAqB;IACrB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,CAAC,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC9B,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;QAClB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACxB,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEL,eAAe;IACf,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,WAAW,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,OAAO,WAAW,IAAI,KAAK,IAAI,WAAW,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAA6B;IACvD,MAAM,KAAK,GAAa,CAAC,wBAAwB,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC9B,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAEpC,sCAAsC;IACtC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,aAAa,IAAI,gBAAgB,KAAK,oBAAoB,CAAC,CAAC;IACxF,CAAC;IAED,eAAe;IACf,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,SAAS,IAAI,CAAC,MAAM,aAAa,KAAK,KAAK,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duplicate Code Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects code clones using pure static analysis — no LLM calls:
|
|
5
|
+
* - Type 1 (exact): identical code after whitespace/comment normalization
|
|
6
|
+
* - Type 2 (structural): same AST structure with renamed variables
|
|
7
|
+
* - Type 3 (near): high Jaccard similarity on token n-grams (≥ 0.7)
|
|
8
|
+
*
|
|
9
|
+
* Requires a CallGraphResult for precise function boundaries (byte ranges).
|
|
10
|
+
* Complexity: O(n) for Types 1-2, O(n²) for Type 3 (bounded by MAX_NEAR_FUNCTIONS).
|
|
11
|
+
*/
|
|
12
|
+
import type { CallGraphResult } from './call-graph.js';
|
|
13
|
+
export interface CloneInstance {
|
|
14
|
+
file: string;
|
|
15
|
+
functionName: string;
|
|
16
|
+
className?: string;
|
|
17
|
+
startLine: number;
|
|
18
|
+
endLine: number;
|
|
19
|
+
}
|
|
20
|
+
/** 'exact' = identical after normalization, 'structural' = same shape renamed, 'near' = high Jaccard */
|
|
21
|
+
export type CloneType = 'exact' | 'structural' | 'near';
|
|
22
|
+
export interface CloneGroup {
|
|
23
|
+
type: CloneType;
|
|
24
|
+
/** 1.0 for exact/structural; Jaccard similarity for near */
|
|
25
|
+
similarity: number;
|
|
26
|
+
instances: CloneInstance[];
|
|
27
|
+
/** Number of lines in the smallest instance of the cloned block */
|
|
28
|
+
lineCount: number;
|
|
29
|
+
}
|
|
30
|
+
export interface DuplicateDetectionResult {
|
|
31
|
+
cloneGroups: CloneGroup[];
|
|
32
|
+
stats: {
|
|
33
|
+
/** Functions analyzed (above minimum size threshold) */
|
|
34
|
+
totalFunctions: number;
|
|
35
|
+
/** Functions that appear in at least one clone group */
|
|
36
|
+
duplicatedFunctions: number;
|
|
37
|
+
/** duplicatedFunctions / totalFunctions */
|
|
38
|
+
duplicationRatio: number;
|
|
39
|
+
/** Number of distinct clone groups */
|
|
40
|
+
cloneGroupCount: number;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Detect duplicate functions across the codebase using the call graph's
|
|
45
|
+
* function nodes (which carry byte-range boundaries) and the original file
|
|
46
|
+
* contents.
|
|
47
|
+
*/
|
|
48
|
+
export declare function detectDuplicates(files: Array<{
|
|
49
|
+
path: string;
|
|
50
|
+
content: string;
|
|
51
|
+
}>, callGraph: CallGraphResult): DuplicateDetectionResult;
|
|
52
|
+
//# sourceMappingURL=duplicate-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-detector.d.ts","sourceRoot":"","sources":["../../../src/core/analyzer/duplicate-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAMvD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wGAAwG;AACxG,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,KAAK,EAAE;QACL,wDAAwD;QACxD,cAAc,EAAE,MAAM,CAAC;QACvB,wDAAwD;QACxD,mBAAmB,EAAE,MAAM,CAAC;QAC5B,2CAA2C;QAC3C,gBAAgB,EAAE,MAAM,CAAC;QACzB,sCAAsC;QACtC,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AA+ID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC/C,SAAS,EAAE,eAAe,GACzB,wBAAwB,CA2J1B"}
|