ucn 3.7.46 → 3.8.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/.claude/skills/ucn/SKILL.md +34 -4
- package/README.md +16 -13
- package/cli/index.js +112 -15
- package/core/cache.js +176 -51
- package/core/callers.js +350 -52
- package/core/deadcode.js +143 -17
- package/core/discovery.js +1 -1
- package/core/execute.js +245 -11
- package/core/output.js +423 -4
- package/core/project.js +1204 -94
- package/core/registry.js +18 -7
- package/core/shared.js +1 -1
- package/core/stacktrace.js +31 -2
- package/core/verify.js +11 -0
- package/languages/go.js +338 -24
- package/languages/index.js +20 -1
- package/languages/java.js +145 -6
- package/languages/javascript.js +199 -8
- package/languages/python.js +8 -2
- package/languages/rust.js +168 -8
- package/mcp/server.js +79 -17
- package/package.json +1 -1
|
@@ -49,7 +49,17 @@ ucn impact score_trend --exclude=test # Only production callers
|
|
|
49
49
|
|
|
50
50
|
Replaces: grep for the function name → manually filtering definitions vs calls vs imports → reading context around each match.
|
|
51
51
|
|
|
52
|
-
### 3. `
|
|
52
|
+
### 3. `blast` — Transitive blast radius
|
|
53
|
+
|
|
54
|
+
Walks UP the caller chain recursively. Shows the full tree of functions affected transitively if you change something. Like `impact` but recursive — answers "what breaks if I change this, including indirect callers?"
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
ucn blast helper # callers of callers (depth 3)
|
|
58
|
+
ucn blast helper --depth=5 # deeper chain
|
|
59
|
+
ucn blast helper --exclude=test # skip test callers
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 4. `trace` — Understand execution flow (downward)
|
|
53
63
|
|
|
54
64
|
Draws the call tree downward from any function. Compact by default; setting `--depth=N` shows the full tree to that depth with all children expanded.
|
|
55
65
|
|
|
@@ -61,7 +71,7 @@ ucn trace generate_report --all # all children at default depth
|
|
|
61
71
|
|
|
62
72
|
Shows the entire pipeline — what `generate_report` calls, what those functions call, etc. — as an indented tree. No file reading needed. Invaluable for understanding orchestrator functions or entry points.
|
|
63
73
|
|
|
64
|
-
###
|
|
74
|
+
### 5. `fn` / `class` — Extract without reading the whole file
|
|
65
75
|
|
|
66
76
|
Pull one or more functions out of a large file. Supports comma-separated names for bulk extraction.
|
|
67
77
|
|
|
@@ -71,7 +81,7 @@ ucn fn parse,format,validate # Extract multiple functions in one call
|
|
|
71
81
|
ucn class MarketDataFetcher
|
|
72
82
|
```
|
|
73
83
|
|
|
74
|
-
###
|
|
84
|
+
### 6. `deadcode` — Find unused code
|
|
75
85
|
|
|
76
86
|
Lists all functions and classes with zero callers across the project.
|
|
77
87
|
|
|
@@ -86,6 +96,9 @@ ucn deadcode --exclude=test # Skip test files (most useful)
|
|
|
86
96
|
|-----------|---------|-------------|
|
|
87
97
|
| Quick callers + callees list | `ucn context <name>` | Who calls it and what it calls. Results are numbered for `expand`. Use instead of `about` when you just need the call graph, not source code |
|
|
88
98
|
| Need function + all its helpers inline | `ucn smart <name>` | Returns function source with every helper it calls expanded below it. Use instead of `about` when you need code, not metadata |
|
|
99
|
+
| Full transitive blast radius | `ucn blast <name> --depth=5` | Callers of callers — the full chain of what breaks if you change something |
|
|
100
|
+
| How execution reaches a function | `ucn reverse-trace <name>` | Walk UP callers to entry points (★ marked). Shows how code flows to this function. Default depth=5 |
|
|
101
|
+
| Which tests to run after a change | `ucn affected-tests <name>` | Blast + test detection: shows test files, coverage %, uncovered functions. Use `--depth=N` to control depth |
|
|
89
102
|
| What changed and who's affected | `ucn diff-impact --base=main` | Shows changed functions + their callers from git diff |
|
|
90
103
|
| Checking if a refactor broke signatures | `ucn verify <name>` | Validates all call sites match the function's parameter count |
|
|
91
104
|
| Understanding a file's role in the project | `ucn imports <file>` | What it depends on |
|
|
@@ -97,10 +110,16 @@ ucn deadcode --exclude=test # Skip test files (most useful)
|
|
|
97
110
|
| Text search with context | `ucn search term --context=3` | Like grep -C 3, shows surrounding lines |
|
|
98
111
|
| Regex search (default) | `ucn search '\d+'` | Search supports regex by default (alternation, character classes, etc.) |
|
|
99
112
|
| Text search filtered | `ucn search term --exclude=test` | Search only in matching files |
|
|
113
|
+
| Structural search (index) | `ucn search --type=function --param=Request` | Query the symbol table, not text. Finds functions by param, return type, decorator, etc. |
|
|
114
|
+
| Find all db.* calls | `ucn search --type=call --receiver=db` | Search call sites by receiver — something grep can't do |
|
|
115
|
+
| Find exported functions | `ucn search --type=function --exported` | Only exported/public symbols |
|
|
116
|
+
| Find unused symbols | `ucn search --type=function --unused` | Mini deadcode: zero callers |
|
|
117
|
+
| Find decorated functions | `ucn search --decorator=Route` | Functions/classes with a specific decorator/annotation |
|
|
100
118
|
| Finding all usages (not just calls) | `ucn usages <name>` | Groups into: definitions, calls, imports, type references |
|
|
101
119
|
| Finding sibling/related functions | `ucn related <name>` | Name-based + structural matching (same file, shared deps). Not semantic — best for parse/format pairs |
|
|
102
120
|
| Preview a rename or param change | `ucn plan <name> --rename-to=new_name` | Shows what would change without doing it |
|
|
103
121
|
| File-level dependency tree | `ucn graph <file> --depth=1` | Visual import tree. Setting `--depth=N` expands all children. Can be noisy — use depth=1 for large projects. For function-level flow, use `trace` instead |
|
|
122
|
+
| Are there circular dependencies? | `ucn circular-deps` | Detect circular import chains. `--file=<pattern>` filters to cycles involving a file. `--exclude=test` skips test files |
|
|
104
123
|
| Find which tests cover a function | `ucn tests <name>` | Test files and test function names |
|
|
105
124
|
| Extract specific lines from a file | `ucn lines --file=<file> --range=10-20` | Pull a line range without reading the whole file |
|
|
106
125
|
| Find type definitions | `ucn typedef <name>` | Interfaces, enums, structs, traits, type aliases |
|
|
@@ -145,12 +164,21 @@ ucn [target] <command> [name] [--flags]
|
|
|
145
164
|
| `--detailed` | Show full symbol listing per file in `toc` |
|
|
146
165
|
| `--top-level` | Show only top-level functions in `toc` (exclude nested/indented) |
|
|
147
166
|
| `--top=N` | Limit result count (default: 10 for most commands) |
|
|
167
|
+
| `--limit=N` | Limit result count for `find`, `usages`, `search`, `deadcode`, `api`, `toc` |
|
|
168
|
+
| `--max-files=N` | Max files to index (for large projects with 10K+ files) |
|
|
148
169
|
| `--max-lines=N` | Max source lines for `class` (large classes show summary by default) |
|
|
149
170
|
| `--case-sensitive` | Case-sensitive text search (default: case-insensitive) |
|
|
150
171
|
| `--exact` | Exact name match only in `find`/`typedef` (no substring) |
|
|
151
172
|
| `--include-uncertain` | Include ambiguous/uncertain matches in `context`/`smart`/`about` |
|
|
152
173
|
| `--include-exported` | Include exported symbols in `deadcode` results |
|
|
153
174
|
| `--include-decorated` | Include decorated/annotated symbols in `deadcode` results |
|
|
175
|
+
| `--type=<kind>` | Structural search: `function`, `class`, `call`, `method`, `type`. Triggers index query instead of text grep |
|
|
176
|
+
| `--param=<name>` | Structural search: filter by parameter name or type (e.g., `--param=Request`) |
|
|
177
|
+
| `--receiver=<name>` | Structural search: filter calls by receiver (e.g., `--receiver=db` for all db.* calls) |
|
|
178
|
+
| `--returns=<type>` | Structural search: filter by return type (e.g., `--returns=error`) |
|
|
179
|
+
| `--decorator=<name>` | Structural search: filter by decorator/annotation (e.g., `--decorator=Route`) |
|
|
180
|
+
| `--exported` | Structural search: only exported/public symbols |
|
|
181
|
+
| `--unused` | Structural search: only symbols with zero callers |
|
|
154
182
|
|
|
155
183
|
## Workflow Integration
|
|
156
184
|
|
|
@@ -162,7 +190,9 @@ ucn trace problematic_function --depth=2 # See what it calls
|
|
|
162
190
|
|
|
163
191
|
**Before modifying a function:**
|
|
164
192
|
```bash
|
|
165
|
-
ucn impact the_function # Who will break?
|
|
193
|
+
ucn impact the_function # Who will break? (direct callers)
|
|
194
|
+
ucn blast the_function # Who will break? (full transitive chain)
|
|
195
|
+
ucn affected-tests the_function # Which tests to run after the change?
|
|
166
196
|
ucn smart the_function # See it + its helpers
|
|
167
197
|
# ... make changes ...
|
|
168
198
|
ucn verify the_function # Did all call sites survive?
|
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ Supports JS/TS, Python, Go, Rust, Java, and HTML. Runs locally.
|
|
|
38
38
|
│
|
|
39
39
|
┌──────┴──────┐
|
|
40
40
|
│ UCN Engine │
|
|
41
|
-
│
|
|
41
|
+
│ commands │
|
|
42
42
|
│ tree-sitter │
|
|
43
43
|
└─────────────┘
|
|
44
44
|
```
|
|
@@ -138,7 +138,7 @@ VS Code uses `.vscode/mcp.json`:
|
|
|
138
138
|
|
|
139
139
|
</details>
|
|
140
140
|
|
|
141
|
-
All
|
|
141
|
+
All commands ship as a single MCP tool - under 2KB of context.
|
|
142
142
|
|
|
143
143
|
### Agent Skill (no server needed)
|
|
144
144
|
|
|
@@ -265,28 +265,31 @@ ucn deadcode --exclude=test # what can be deleted?
|
|
|
265
265
|
|
|
266
266
|
---
|
|
267
267
|
|
|
268
|
-
## All
|
|
268
|
+
## All commands
|
|
269
269
|
|
|
270
270
|
```
|
|
271
271
|
UNDERSTAND MODIFY SAFELY
|
|
272
272
|
───────────────────── ─────────────────────
|
|
273
273
|
about full picture impact all call sites
|
|
274
|
-
context callers + callees
|
|
275
|
-
smart function + helpers
|
|
276
|
-
trace call tree
|
|
274
|
+
context callers + callees blast transitive impact
|
|
275
|
+
smart function + helpers diff-impact git diff + callers
|
|
276
|
+
trace call tree verify signature check
|
|
277
|
+
reverse-trace callers → root plan refactor preview
|
|
277
278
|
|
|
278
279
|
FIND & EXTRACT ARCHITECTURE
|
|
279
280
|
───────────────────── ─────────────────────
|
|
280
281
|
find locate definitions imports file dependencies
|
|
281
282
|
usages all occurrences exporters reverse dependencies
|
|
282
283
|
fn extract function graph dependency tree
|
|
283
|
-
class extract class
|
|
284
|
-
toc project overview
|
|
285
|
-
deadcode unused code
|
|
286
|
-
search text search
|
|
287
|
-
example best usage example
|
|
288
|
-
lines extract line range
|
|
289
|
-
expand drill into context
|
|
284
|
+
class extract class circular-deps import cycles
|
|
285
|
+
toc project overview related sibling functions
|
|
286
|
+
deadcode unused code tests find test coverage
|
|
287
|
+
search text search affected-tests tests for changes
|
|
288
|
+
example best usage example stacktrace error trace context
|
|
289
|
+
lines extract line range api public API surface
|
|
290
|
+
expand drill into context typedef type definitions
|
|
291
|
+
file-exports file's exports
|
|
292
|
+
stats project stats
|
|
290
293
|
```
|
|
291
294
|
|
|
292
295
|
---
|
package/cli/index.js
CHANGED
|
@@ -102,6 +102,16 @@ function parseFlags(tokens) {
|
|
|
102
102
|
regex: tokens.includes('--no-regex') ? false : undefined,
|
|
103
103
|
functions: tokens.includes('--functions'),
|
|
104
104
|
className: getValueFlag('--class-name'),
|
|
105
|
+
limit: parseInt(getValueFlag('--limit') || '0') || undefined,
|
|
106
|
+
maxFiles: parseInt(getValueFlag('--max-files') || '0') || undefined,
|
|
107
|
+
// Structural search flags
|
|
108
|
+
type: getValueFlag('--type'),
|
|
109
|
+
param: getValueFlag('--param'),
|
|
110
|
+
receiver: getValueFlag('--receiver'),
|
|
111
|
+
returns: getValueFlag('--returns'),
|
|
112
|
+
decorator: getValueFlag('--decorator'),
|
|
113
|
+
exported: tokens.includes('--exported'),
|
|
114
|
+
unused: tokens.includes('--unused'),
|
|
105
115
|
};
|
|
106
116
|
}
|
|
107
117
|
|
|
@@ -126,7 +136,8 @@ const knownFlags = new Set([
|
|
|
126
136
|
'--default', '--top', '--no-follow-symlinks',
|
|
127
137
|
'--base', '--staged', '--stack',
|
|
128
138
|
'--regex', '--no-regex', '--functions',
|
|
129
|
-
'--max-lines', '--class-name'
|
|
139
|
+
'--max-lines', '--class-name', '--limit', '--max-files',
|
|
140
|
+
'--type', '--param', '--receiver', '--returns', '--decorator', '--exported', '--unused'
|
|
130
141
|
]);
|
|
131
142
|
|
|
132
143
|
// Handle help flag
|
|
@@ -285,7 +296,9 @@ function runFileCommand(filePath, command, arg) {
|
|
|
285
296
|
|
|
286
297
|
// Require arg for commands that need it
|
|
287
298
|
const needsArg = { fn: 'fn <name>', class: 'class <name>', find: 'find <name>', usages: 'usages <name>', search: 'search <term>', lines: 'lines <start-end>', typedef: 'typedef <name>' };
|
|
288
|
-
|
|
299
|
+
// Structural search doesn't require term
|
|
300
|
+
const isStructural = flags.type || flags.param || flags.receiver || flags.returns || flags.decorator || flags.exported || flags.unused;
|
|
301
|
+
if (needsArg[canonical] && !(canonical === 'search' && isStructural)) {
|
|
289
302
|
requireArg(arg, `Usage: ucn <file> ${needsArg[canonical]}`);
|
|
290
303
|
}
|
|
291
304
|
|
|
@@ -340,7 +353,11 @@ function runFileCommand(filePath, command, arg) {
|
|
|
340
353
|
printOutput(result, r => output.formatUsagesJson(r, arg), r => output.formatUsages(r, arg));
|
|
341
354
|
break;
|
|
342
355
|
case 'search':
|
|
343
|
-
|
|
356
|
+
if (result && result.meta && result.meta.mode === 'structural') {
|
|
357
|
+
printOutput(result, output.formatStructuralSearchJson, output.formatStructuralSearch);
|
|
358
|
+
} else {
|
|
359
|
+
printOutput(result, r => output.formatSearchJson(r, arg), r => output.formatSearch(r, arg));
|
|
360
|
+
}
|
|
344
361
|
break;
|
|
345
362
|
case 'typedef':
|
|
346
363
|
printOutput(result, r => output.formatTypedefJson(r, arg), r => output.formatTypedef(r, arg));
|
|
@@ -396,7 +413,7 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
396
413
|
// If cache was loaded but stale, force rebuild to avoid duplicates
|
|
397
414
|
let needsCacheSave = false;
|
|
398
415
|
if (!usedCache) {
|
|
399
|
-
index.build(null, { quiet: flags.quiet, forceRebuild: cacheWasLoaded, followSymlinks: flags.followSymlinks });
|
|
416
|
+
index.build(null, { quiet: flags.quiet, forceRebuild: cacheWasLoaded, followSymlinks: flags.followSymlinks, maxFiles: flags.maxFiles });
|
|
400
417
|
needsCacheSave = flags.cache;
|
|
401
418
|
}
|
|
402
419
|
|
|
@@ -408,8 +425,9 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
408
425
|
// ── Commands using shared executor ───────────────────────────────
|
|
409
426
|
|
|
410
427
|
case 'toc': {
|
|
411
|
-
const { ok, result, error } = execute(index, 'toc', flags);
|
|
428
|
+
const { ok, result, error, note } = execute(index, 'toc', flags);
|
|
412
429
|
if (!ok) fail(error);
|
|
430
|
+
if (note) console.error(note);
|
|
413
431
|
printOutput(result, output.formatTocJson, r => output.formatToc(r, {
|
|
414
432
|
detailedHint: 'Add --detailed to list all functions, or "ucn . about <name>" for full details on a symbol',
|
|
415
433
|
uncertainHint: 'use --include-uncertain to include all'
|
|
@@ -429,8 +447,9 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
429
447
|
}
|
|
430
448
|
|
|
431
449
|
case 'usages': {
|
|
432
|
-
const { ok, result, error } = execute(index, 'usages', { name: arg, ...flags });
|
|
450
|
+
const { ok, result, error, note } = execute(index, 'usages', { name: arg, ...flags });
|
|
433
451
|
if (!ok) fail(error);
|
|
452
|
+
if (note) console.error(note);
|
|
434
453
|
printOutput(result,
|
|
435
454
|
r => output.formatUsagesJson(r, arg),
|
|
436
455
|
r => output.formatUsages(r, arg)
|
|
@@ -533,6 +552,13 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
533
552
|
break;
|
|
534
553
|
}
|
|
535
554
|
|
|
555
|
+
case 'blast': {
|
|
556
|
+
const { ok, result, error } = execute(index, 'blast', { name: arg, ...flags });
|
|
557
|
+
if (!ok) fail(error);
|
|
558
|
+
printOutput(result, output.formatBlastJson, output.formatBlast);
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
|
|
536
562
|
case 'plan': {
|
|
537
563
|
const { ok, result, error } = execute(index, 'plan', { name: arg, ...flags });
|
|
538
564
|
if (!ok) fail(error);
|
|
@@ -547,6 +573,13 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
547
573
|
break;
|
|
548
574
|
}
|
|
549
575
|
|
|
576
|
+
case 'reverseTrace': {
|
|
577
|
+
const { ok, result, error } = execute(index, 'reverseTrace', { name: arg, ...flags });
|
|
578
|
+
if (!ok) fail(error);
|
|
579
|
+
printOutput(result, output.formatReverseTraceJson, output.formatReverseTrace);
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
|
|
550
583
|
case 'stacktrace': {
|
|
551
584
|
const { ok, result, error } = execute(index, 'stacktrace', { stack: arg });
|
|
552
585
|
if (!ok) fail(error);
|
|
@@ -642,6 +675,13 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
642
675
|
break;
|
|
643
676
|
}
|
|
644
677
|
|
|
678
|
+
case 'circularDeps': {
|
|
679
|
+
const { ok, result, error } = execute(index, 'circularDeps', { file: flags.file, exclude: flags.exclude });
|
|
680
|
+
if (!ok) fail(error);
|
|
681
|
+
printOutput(result, output.formatCircularDepsJson, output.formatCircularDeps);
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
|
|
645
685
|
// ── Remaining commands ──────────────────────────────────────────
|
|
646
686
|
|
|
647
687
|
case 'typedef': {
|
|
@@ -664,9 +704,17 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
664
704
|
break;
|
|
665
705
|
}
|
|
666
706
|
|
|
707
|
+
case 'affectedTests': {
|
|
708
|
+
const { ok, result, error } = execute(index, 'affectedTests', { name: arg, ...flags });
|
|
709
|
+
if (!ok) fail(error);
|
|
710
|
+
printOutput(result, output.formatAffectedTestsJson, output.formatAffectedTests);
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
|
|
667
714
|
case 'api': {
|
|
668
|
-
const { ok, result, error } = execute(index, 'api', { file: arg });
|
|
715
|
+
const { ok, result, error, note } = execute(index, 'api', { file: arg || flags.file, limit: flags.limit });
|
|
669
716
|
if (!ok) fail(error);
|
|
717
|
+
if (note) console.error(note);
|
|
670
718
|
printOutput(result,
|
|
671
719
|
r => output.formatApiJson(r, arg),
|
|
672
720
|
r => output.formatApi(r, arg)
|
|
@@ -675,18 +723,23 @@ function runProjectCommand(rootDir, command, arg) {
|
|
|
675
723
|
}
|
|
676
724
|
|
|
677
725
|
case 'search': {
|
|
678
|
-
const { ok, result, error } = execute(index, 'search', { term: arg, ...flags });
|
|
726
|
+
const { ok, result, error, structural } = execute(index, 'search', { term: arg, ...flags });
|
|
679
727
|
if (!ok) fail(error);
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
728
|
+
if (structural) {
|
|
729
|
+
printOutput(result, output.formatStructuralSearchJson, output.formatStructuralSearch);
|
|
730
|
+
} else {
|
|
731
|
+
printOutput(result,
|
|
732
|
+
r => output.formatSearchJson(r, arg),
|
|
733
|
+
r => output.formatSearch(r, arg)
|
|
734
|
+
);
|
|
735
|
+
}
|
|
684
736
|
break;
|
|
685
737
|
}
|
|
686
738
|
|
|
687
739
|
case 'deadcode': {
|
|
688
|
-
const { ok, result, error } = execute(index, 'deadcode', { ...flags, in: flags.in || subdirScope });
|
|
740
|
+
const { ok, result, error, note } = execute(index, 'deadcode', { ...flags, in: flags.in || subdirScope });
|
|
689
741
|
if (!ok) fail(error);
|
|
742
|
+
if (note) console.error(note);
|
|
690
743
|
printOutput(result,
|
|
691
744
|
output.formatDeadcodeJson,
|
|
692
745
|
r => output.formatDeadcode(r, {
|
|
@@ -987,7 +1040,9 @@ UNDERSTAND CODE (UCN's strength - semantic analysis)
|
|
|
987
1040
|
context <name> Who calls this + what it calls (numbered for expand)
|
|
988
1041
|
smart <name> Function + all dependencies inline
|
|
989
1042
|
impact <name> What breaks if changed (call sites grouped by file)
|
|
1043
|
+
blast <name> Transitive blast radius (callers of callers, --depth=N)
|
|
990
1044
|
trace <name> Call tree visualization (--depth=N expands all children)
|
|
1045
|
+
reverse-trace <name> Upward call chain to entry points (--depth=N, default 5)
|
|
991
1046
|
related <name> Find similar functions (same file, shared deps)
|
|
992
1047
|
example <name> Best usage example with context
|
|
993
1048
|
|
|
@@ -998,7 +1053,9 @@ FIND CODE
|
|
|
998
1053
|
usages <name> All usages grouped: definitions, calls, imports, references
|
|
999
1054
|
toc Table of contents (compact; --detailed lists all symbols)
|
|
1000
1055
|
search <term> Text search (regex default, --context=N, --exclude=, --in=)
|
|
1056
|
+
Structural: --type=function|class|call --param= --returns= --decorator= --exported --unused
|
|
1001
1057
|
tests <name> Find test files for a function
|
|
1058
|
+
affected-tests <n> Tests affected by a change (blast + test detection, --depth=N)
|
|
1002
1059
|
|
|
1003
1060
|
═══════════════════════════════════════════════════════════════════════════════
|
|
1004
1061
|
EXTRACT CODE
|
|
@@ -1015,6 +1072,7 @@ FILE DEPENDENCIES
|
|
|
1015
1072
|
exporters <file> Who imports this file
|
|
1016
1073
|
file-exports <file> What does file export
|
|
1017
1074
|
graph <file> Full dependency tree (--depth=N, --direction=imports|importers|both)
|
|
1075
|
+
circular-deps Detect circular import chains (--file=, --exclude=)
|
|
1018
1076
|
|
|
1019
1077
|
═══════════════════════════════════════════════════════════════════════════════
|
|
1020
1078
|
REFACTORING HELPERS
|
|
@@ -1040,6 +1098,8 @@ Common Flags:
|
|
|
1040
1098
|
--direction=X Graph direction: imports, importers, or both (default: both)
|
|
1041
1099
|
--all Expand truncated sections (about, trace, graph, related)
|
|
1042
1100
|
--top=N Limit results (find, deadcode)
|
|
1101
|
+
--limit=N Limit result count (find, usages, search, deadcode, api, toc)
|
|
1102
|
+
--max-files=N Max files to index (large projects)
|
|
1043
1103
|
--context=N Lines of context around matches
|
|
1044
1104
|
--json Machine-readable output
|
|
1045
1105
|
--code-only Filter out comments and strings
|
|
@@ -1120,18 +1180,23 @@ Commands:
|
|
|
1120
1180
|
expand <N> Show code for item N from context
|
|
1121
1181
|
smart <name> Function + dependencies
|
|
1122
1182
|
impact <name> What breaks if changed
|
|
1183
|
+
blast <name> Transitive blast radius (--depth=N)
|
|
1123
1184
|
trace <name> Call tree (--depth=N)
|
|
1185
|
+
reverse-trace <name> Upward to entry points (--depth=N)
|
|
1124
1186
|
example <name> Best usage example
|
|
1125
1187
|
related <name> Sibling functions
|
|
1126
1188
|
fn <name>[,n2,...] Extract function(s) (--file=)
|
|
1127
1189
|
class <name> Extract class code (--file=)
|
|
1128
1190
|
lines <range> Extract lines (--file= required)
|
|
1129
1191
|
graph <file> File dependency tree (--direction=, --depth=)
|
|
1192
|
+
circular-deps Circular import chains (--file=, --exclude=)
|
|
1130
1193
|
file-exports <file> File's exported symbols
|
|
1131
1194
|
imports <file> What file imports
|
|
1132
1195
|
exporters <file> Who imports file
|
|
1133
1196
|
tests <name> Find tests (--calls-only)
|
|
1197
|
+
affected-tests <n> Tests affected by a change (--depth=N)
|
|
1134
1198
|
search <term> Text search (--context=N, --exclude=, --in=)
|
|
1199
|
+
Structural: --type= --param= --returns= --decorator= --exported --unused
|
|
1135
1200
|
typedef <name> Find type definitions
|
|
1136
1201
|
deadcode Find unused functions/classes
|
|
1137
1202
|
verify <name> Check call sites match signature
|
|
@@ -1341,6 +1406,13 @@ function executeInteractiveCommand(index, command, arg, iflags = {}, cache = nul
|
|
|
1341
1406
|
break;
|
|
1342
1407
|
}
|
|
1343
1408
|
|
|
1409
|
+
case 'blast': {
|
|
1410
|
+
const { ok, result, error } = execute(index, 'blast', { name: arg, ...iflags });
|
|
1411
|
+
if (!ok) { console.log(error); return; }
|
|
1412
|
+
console.log(output.formatBlast(result));
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1344
1416
|
case 'trace': {
|
|
1345
1417
|
const { ok, result, error } = execute(index, 'trace', { name: arg, ...iflags });
|
|
1346
1418
|
if (!ok) { console.log(error); return; }
|
|
@@ -1348,6 +1420,13 @@ function executeInteractiveCommand(index, command, arg, iflags = {}, cache = nul
|
|
|
1348
1420
|
break;
|
|
1349
1421
|
}
|
|
1350
1422
|
|
|
1423
|
+
case 'reverseTrace': {
|
|
1424
|
+
const { ok, result, error } = execute(index, 'reverseTrace', { name: arg, ...iflags });
|
|
1425
|
+
if (!ok) { console.log(error); return; }
|
|
1426
|
+
console.log(output.formatReverseTrace(result));
|
|
1427
|
+
break;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1351
1430
|
case 'graph': {
|
|
1352
1431
|
const { ok, result, error } = execute(index, 'graph', { file: arg, ...iflags });
|
|
1353
1432
|
if (!ok) { console.log(error); return; }
|
|
@@ -1356,6 +1435,13 @@ function executeInteractiveCommand(index, command, arg, iflags = {}, cache = nul
|
|
|
1356
1435
|
break;
|
|
1357
1436
|
}
|
|
1358
1437
|
|
|
1438
|
+
case 'circularDeps': {
|
|
1439
|
+
const { ok, result, error } = execute(index, 'circularDeps', { file: iflags.file, exclude: iflags.exclude });
|
|
1440
|
+
if (!ok) { console.log(error); return; }
|
|
1441
|
+
console.log(output.formatCircularDeps(result));
|
|
1442
|
+
break;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1359
1445
|
case 'fileExports': {
|
|
1360
1446
|
const { ok, result, error } = execute(index, 'fileExports', { file: arg });
|
|
1361
1447
|
if (!ok) { console.log(error); return; }
|
|
@@ -1384,10 +1470,21 @@ function executeInteractiveCommand(index, command, arg, iflags = {}, cache = nul
|
|
|
1384
1470
|
break;
|
|
1385
1471
|
}
|
|
1386
1472
|
|
|
1473
|
+
case 'affectedTests': {
|
|
1474
|
+
const { ok, result, error } = execute(index, 'affectedTests', { name: arg, ...iflags });
|
|
1475
|
+
if (!ok) { console.log(error); return; }
|
|
1476
|
+
console.log(output.formatAffectedTests(result));
|
|
1477
|
+
break;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1387
1480
|
case 'search': {
|
|
1388
|
-
const { ok, result, error } = execute(index, 'search', { term: arg, ...iflags });
|
|
1481
|
+
const { ok, result, error, structural } = execute(index, 'search', { term: arg, ...iflags });
|
|
1389
1482
|
if (!ok) { console.log(error); return; }
|
|
1390
|
-
|
|
1483
|
+
if (structural) {
|
|
1484
|
+
console.log(output.formatStructuralSearch(result));
|
|
1485
|
+
} else {
|
|
1486
|
+
console.log(output.formatSearch(result, arg));
|
|
1487
|
+
}
|
|
1391
1488
|
break;
|
|
1392
1489
|
}
|
|
1393
1490
|
|