Skip to content

Commit 3c6e8b7

Browse files
committed
fix: analysis package
1 parent b3466d9 commit 3c6e8b7

35 files changed

+5719
-5456
lines changed

.coderabbit.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
language: "en"
2+
early_access: true
3+
4+
reviews:
5+
request_changes_workflow: true
6+
high_level_summary: true
7+
poem: false
8+
review_status: true
9+
collapse_walkthrough: false
10+
sequence_diagrams: true
11+
profile: "chill"
12+
path_filters:
13+
- "!**/*.md"
14+
- "!**/*.yaml"
15+
- "!**/*.yml"
16+
- "!**/*.json"
17+
- "!**/*.toml"
18+
- "!**/*.xml"
19+
- "!**/*.mdc"
20+
- "!**/*.mdx"
21+
- "!.cursor/**"
22+
- "!.git/**"
23+
- "!.claude/**"
24+
- "!.vscode/**"
25+
- "!.taskmaster/**"
26+
- "!docs/swagger.*"
27+
- "!**/mock_*.go"
28+
- "!**/*.pb.go"
29+
- "!**/*.pb.gw.go"
30+
- "!**/fixtures/**"
31+
- "!test/testdata/**"

README.md

Lines changed: 33 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -184,59 +184,27 @@ gograph analyze . \
184184

185185
### 3. Essential Graph Visualization Queries
186186

187-
Once connected, try these queries to explore your codebase:
187+
Once connected to Neo4j Browser, you can explore your codebase using Cypher queries.
188188

189-
#### **Complete Project Overview**
189+
**📚 For a comprehensive collection of queries, see [docs/QUERIES.md](docs/QUERIES.md)**
190+
191+
Here are a few essential queries to get you started:
190192

191193
```cypher
192194
// View the entire project structure
193195
MATCH (n)
194196
WHERE n.project_id = 'my-awesome-project'
195197
RETURN n
196198
LIMIT 500
197-
```
198-
199-
#### **Package Dependencies**
200-
201-
```cypher
202-
// Visualize package import relationships
203-
MATCH (p1:Package)-[:IMPORTS]->(p2:Package)
204-
WHERE p1.project_id = 'my-awesome-project'
205-
RETURN p1, p2
206-
```
207-
208-
#### **Function Call Graph**
209-
210-
```cypher
211-
// See function call relationships
212-
MATCH (f1:Function)-[:CALLS]->(f2:Function)
213-
WHERE f1.project_id = 'my-awesome-project'
214-
RETURN f1, f2
215-
LIMIT 100
216-
```
217199
218-
#### **Architecture Overview**
219-
220-
```cypher
221-
// High-level architecture view (packages and their relationships)
222-
MATCH path = (p1:Package)-[:IMPORTS*1..2]->(p2:Package)
223-
WHERE p1.project_id = 'my-awesome-project'
224-
AND p2.project_id = 'my-awesome-project'
225-
RETURN path
226-
LIMIT 50
227-
```
228-
229-
#### **Code Complexity Hotspots**
230-
231-
```cypher
232-
// Find the most connected functions (potential complexity hotspots)
200+
// Find the most connected functions
233201
MATCH (f:Function)
234202
WHERE f.project_id = 'my-awesome-project'
235-
WITH f,
236-
size((f)-[:CALLS]->()) as outgoing_calls,
237-
size((f)<-[:CALLS]-()) as incoming_calls
238-
RETURN f.name, f.package, outgoing_calls, incoming_calls,
239-
(outgoing_calls + incoming_calls) as total_connections
203+
OPTIONAL MATCH (f)-[:CALLS]->(called)
204+
WITH f, count(called) as outgoing_calls
205+
OPTIONAL MATCH (f)<-[:CALLS]-(caller)
206+
RETURN f.name, f.package, outgoing_calls, count(caller) as incoming_calls,
207+
(outgoing_calls + count(caller)) as total_connections
240208
ORDER BY total_connections DESC
241209
LIMIT 20
242210
```
@@ -253,63 +221,22 @@ LIMIT 20
253221

254222
**Useful Browser Commands:**
255223

256-
```cypher
257-
// Show node labels and relationship types
258-
CALL db.labels()
259-
CALL db.relationshipTypes()
260-
261-
// Count nodes by type
262-
MATCH (n)
263-
WHERE n.project_id = 'my-awesome-project'
264-
RETURN labels(n)[0] as NodeType, count(n) as Count
265-
ORDER BY Count DESC
266-
267-
// Find circular dependencies
268-
MATCH path = (p:Package)-[:IMPORTS*2..]->(p)
269-
WHERE p.project_id = 'my-awesome-project'
270-
RETURN path
271-
LIMIT 10
272-
```
224+
See [docs/QUERIES.md](docs/QUERIES.md) for more queries including:
225+
- Node and relationship type discovery
226+
- Circular dependency detection
227+
- Package dependency analysis
228+
- Test coverage analysis
229+
- And many more!
273230

274231
### 5. Advanced Analysis Examples
275232

276-
```bash
277-
# Find unused functions
278-
gograph query "
279-
MATCH (f:Function)
280-
WHERE f.project_id = 'my-awesome-project'
281-
AND NOT (f)<-[:CALLS]-()
282-
AND NOT f.name = 'main'
283-
RETURN f.name, f.package, f.file
284-
ORDER BY f.package, f.name
285-
"
286-
287-
# Analyze test coverage by package
288-
gograph query "
289-
MATCH (p:Package)
290-
WHERE p.project_id = 'my-awesome-project'
291-
OPTIONAL MATCH (p)-[:CONTAINS]->(f:File)
292-
WHERE f.name ENDS WITH '_test.go'
293-
WITH p, count(f) as test_files
294-
OPTIONAL MATCH (p)-[:CONTAINS]->(f2:File)
295-
WHERE NOT f2.name ENDS WITH '_test.go'
296-
RETURN p.name, count(f2) as source_files, test_files,
297-
CASE WHEN count(f2) > 0
298-
THEN round(100.0 * test_files / count(f2), 2)
299-
ELSE 0 END as test_ratio
300-
ORDER BY test_ratio DESC
301-
"
302-
303-
# Find interface implementations
304-
gograph query "
305-
MATCH (s:Struct)-[:IMPLEMENTS]->(i:Interface)
306-
WHERE s.project_id = 'my-awesome-project'
307-
RETURN i.name as Interface,
308-
collect(s.name) as Implementations,
309-
count(s) as ImplementationCount
310-
ORDER BY ImplementationCount DESC
311-
"
312-
```
233+
For advanced analysis queries, see [docs/QUERIES.md](docs/QUERIES.md) which includes:
234+
- Finding unused functions
235+
- Analyzing test coverage by package
236+
- Finding interface implementations
237+
- Detecting circular dependencies
238+
- Identifying code complexity hotspots
239+
- And many more analysis patterns!
313240

314241
### 6. Export and Share Results
315242

@@ -569,33 +496,26 @@ export GOGRAPH_MCP_PORT=8080
569496
| `IMPLEMENTS` | Struct implements interface |
570497
| `HAS_METHOD` | Struct/interface has method |
571498
| `DEPENDS_ON` | File depends on another file |
572-
| `DECLARES` | File declares function/struct/interface |
499+
| `DEFINES` | File defines function/struct/interface |
573500
| `USES` | Function uses variable/constant |
574501

575502
### Example Queries
576503

577-
```cypher
578-
-- Find all functions in a package
579-
MATCH (p:Package {name: "main"})-[:CONTAINS]->(f:File)-[:DECLARES]->(fn:Function)
580-
RETURN fn.name, fn.signature
581-
582-
-- Find circular dependencies
583-
MATCH path=(p1:Package)-[:IMPORTS*]->(p1)
584-
RETURN path
504+
For a comprehensive collection of Cypher queries organized by use case, see [docs/QUERIES.md](docs/QUERIES.md).
585505

506+
Quick examples:
507+
```cypher
586508
-- Find most called functions
587509
MATCH (f:Function)<-[:CALLS]-(caller)
510+
WHERE f.project_id = 'my-project'
588511
RETURN f.name, count(caller) as call_count
589512
ORDER BY call_count DESC
513+
LIMIT 10
590514
591-
-- Find unused functions
592-
MATCH (f:Function)
593-
WHERE NOT (f)<-[:CALLS]-()
594-
RETURN f.name, f.package
595-
596-
-- Find interface implementations
515+
-- Find interface implementations
597516
MATCH (s:Struct)-[:IMPLEMENTS]->(i:Interface)
598-
RETURN s.name, i.name
517+
WHERE s.project_id = 'my-project'
518+
RETURN i.name as Interface, collect(s.name) as Implementations
599519
```
600520

601521
## 🤖 MCP Integration
@@ -817,6 +737,7 @@ Inspired by:
817737
## 🔗 Links
818738

819739
- [Documentation](docs/)
740+
- [Query Reference Guide](docs/QUERIES.md)
820741
- [MCP Integration Guide](docs/MCP_INTEGRATION.md)
821742
- [Issue Tracker](https://github.com/compozy/gograph/issues)
822743
- [Discussions](https://github.com/compozy/gograph/discussions)

cmd/gograph/commands/analyze.go

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,12 @@ The resulting graph allows you to:
8080

8181
// Initialize parser configuration from config
8282
parserConfig := &parser.Config{
83-
IgnoreDirs: cfg.Analysis.IgnoreDirs,
84-
IgnoreFiles: cfg.Analysis.IgnoreFiles,
85-
IncludeTests: cfg.Analysis.IncludeTests,
86-
IncludeVendor: cfg.Analysis.IncludeVendor,
87-
MaxConcurrency: cfg.Analysis.MaxConcurrency,
83+
IgnoreDirs: cfg.Analysis.IgnoreDirs,
84+
IgnoreFiles: cfg.Analysis.IgnoreFiles,
85+
IncludeTests: cfg.Analysis.IncludeTests,
86+
IncludeVendor: cfg.Analysis.IncludeVendor,
87+
EnableSSA: true,
88+
EnableCallGraph: true,
8889
}
8990

9091
// Initialize analyzer configuration with defaults
@@ -150,8 +151,16 @@ func runAnalysisWithoutProgress(
150151
if err != nil {
151152
return fmt.Errorf("failed to parse project: %w", err)
152153
}
154+
155+
// Count total files from packages
156+
totalFiles := 0
157+
for _, pkg := range parseResult.Packages {
158+
totalFiles += len(pkg.Files)
159+
}
160+
153161
logger.Info("parsing completed",
154-
"files", len(parseResult.Files),
162+
"packages", len(parseResult.Packages),
163+
"files", totalFiles,
155164
"duration_ms", parseResult.ParseTime)
156165

157166
// -----
@@ -160,8 +169,8 @@ func runAnalysisWithoutProgress(
160169
logger.Info("analyzing project structure")
161170
analyzerService := analyzer.NewAnalyzer(analyzerConfig)
162171
analysisInput := &analyzer.AnalysisInput{
163-
ProjectID: projectID.String(),
164-
Files: parseResult.Files,
172+
ProjectID: projectID.String(),
173+
ParseResult: parseResult,
165174
}
166175
report, err := analyzerService.AnalyzeProject(ctx, analysisInput)
167176
if err != nil {
@@ -255,9 +264,15 @@ func runAnalysisWithProgress(
255264
// Success with detailed statistics
256265
successMsg := "Analysis completed successfully!"
257266

267+
// Count total files from packages
268+
totalFiles := 0
269+
for _, pkg := range parseResult.Packages {
270+
totalFiles += len(pkg.Files)
271+
}
272+
258273
// Create detailed statistics
259274
stats := progress.AnalysisStats{
260-
Files: len(parseResult.Files),
275+
Files: totalFiles,
261276
Nodes: len(graphResult.Nodes),
262277
Relationships: len(graphResult.Relationships),
263278
Interfaces: len(report.InterfaceImplementations),
@@ -289,7 +304,17 @@ func runParsingPhase(
289304
progressIndicator.Error(fmt.Errorf("failed to parse project: %w", err))
290305
return nil, fmt.Errorf("failed to parse project: %w", err)
291306
}
292-
progressIndicator.UpdateProgress(0.25, fmt.Sprintf("Parsed %d files", len(parseResult.Files)))
307+
308+
// Count total files from packages
309+
totalFiles := 0
310+
for _, pkg := range parseResult.Packages {
311+
totalFiles += len(pkg.Files)
312+
}
313+
314+
progressIndicator.UpdateProgress(
315+
0.25,
316+
fmt.Sprintf("Parsed %d files in %d packages", totalFiles, len(parseResult.Packages)),
317+
)
293318
return parseResult, nil
294319
}
295320

@@ -305,8 +330,8 @@ func runAnalysisPhase(
305330

306331
analyzerService := analyzer.NewAnalyzer(analyzerConfig)
307332
analysisInput := &analyzer.AnalysisInput{
308-
ProjectID: projectID.String(),
309-
Files: parseResult.Files,
333+
ProjectID: projectID.String(),
334+
ParseResult: parseResult,
310335
}
311336
progressIndicator.UpdateProgress(0.4, "Analyzing structure and dependencies")
312337

0 commit comments

Comments
 (0)