@titan-design/code-graph 0.7.0 → 0.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/README.md +19 -2
- package/dist/index.d.ts +14 -9
- package/dist/index.js +514 -79
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ const { snapshotId, files, nodes, edges, reused } = await indexPaths(store, {
|
|
|
18
18
|
ref: "head",
|
|
19
19
|
});
|
|
20
20
|
listNodes(store, snapshotId); // file / module / external nodes, symbols on request
|
|
21
|
-
listEdges(store, snapshotId); // imports / re-exports, references on request
|
|
21
|
+
listEdges(store, snapshotId); // imports / re-exports, references and calls on request
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
## What was extracted, and what was not
|
|
@@ -166,7 +166,7 @@ wrong time model for a population re-indexed all at once), `metric`, `id_alias`,
|
|
|
166
166
|
`file_fingerprint`.
|
|
167
167
|
|
|
168
168
|
The symbol layer is hidden by default. `listNodes` drops `symbol` nodes and `listEdges` drops
|
|
169
|
-
`references` edges unless you ask for them, so a caller reasoning about module structure sees
|
|
169
|
+
`references` and `calls` edges unless you ask for them (`includeReferences` covers both), so a caller reasoning about module structure sees
|
|
170
170
|
the graph it expects and does not have one import of thirty names read as thirty
|
|
171
171
|
dependencies.
|
|
172
172
|
|
|
@@ -342,6 +342,23 @@ Python, and are written on every function or file, zeros included:
|
|
|
342
342
|
`...`, `continue`, a bare or `None`/`null`/`undefined` return, or one call to a logger,
|
|
343
343
|
`print`, `warn` or `console`).
|
|
344
344
|
|
|
345
|
+
Call-graph metrics (TP-323) come from `calls` edges, one per caller and callee symbol, each
|
|
346
|
+
carrying the literal arguments of every call site in `attrs.sites`. TypeScript resolves a
|
|
347
|
+
call or `new` through the type checker to one in-repo declaration. Python resolves only a
|
|
348
|
+
bare name declared at module level in the same file, a bare name bound by `from <in-repo
|
|
349
|
+
module> import`, and `self.<name>()` to a method of the enclosing class or a base class
|
|
350
|
+
declared in the same file. Anything else is dropped, never guessed, and an edge whose target
|
|
351
|
+
has no symbol node is pruned. The caller is the enclosing function, method or class, or the
|
|
352
|
+
file for a module-level call. Each function, method and class gets `symbol_caller_count`
|
|
353
|
+
(distinct callers, recursion excluded) and `symbol_single_caller_helper` (1 when a
|
|
354
|
+
non-exported, non-dunder symbol has exactly one caller and it is a symbol). A callable with 2
|
|
355
|
+
or more resolved call sites also gets `symbol_constant_params`: parameters every site passes
|
|
356
|
+
the same literal, or none passes. Callers found only through unresolved calls are missing, so
|
|
357
|
+
a private method that tests call on an instance can read as a single-caller helper. These
|
|
358
|
+
metrics need edges from every file, so they are recomputed on each index. Under reuse, an
|
|
359
|
+
unchanged caller's edge to a callee that moved behind a re-export stays pruned until the
|
|
360
|
+
caller changes, as `references` edges do.
|
|
361
|
+
|
|
345
362
|
PageRank, relevance, and symbol coupling run at query time over one snapshot:
|
|
346
363
|
|
|
347
364
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -121,7 +121,7 @@ declare class CodeGraphStore {
|
|
|
121
121
|
listNodes(snapshotId: number, opts?: {
|
|
122
122
|
includeSymbols?: boolean;
|
|
123
123
|
}): GraphNode[];
|
|
124
|
-
/** See {@link listNodes}: `references` edges are the symbol layer, excluded by default. */
|
|
124
|
+
/** See {@link listNodes}: `references` and `calls` edges are the symbol layer, excluded by default. */
|
|
125
125
|
listEdges(snapshotId: number, opts?: {
|
|
126
126
|
includeReferences?: boolean;
|
|
127
127
|
}): GraphEdge[];
|
|
@@ -137,7 +137,7 @@ declare class CodeGraphStore {
|
|
|
137
137
|
limit?: number;
|
|
138
138
|
kind?: string;
|
|
139
139
|
}): TopMetricRow[];
|
|
140
|
-
/** Edges into or out of one node;
|
|
140
|
+
/** Edges into or out of one node; symbol-layer edges are excluded unless asked, as in {@link listEdges}. */
|
|
141
141
|
listEdgesTouching(snapshotId: number, nodeId: string, opts?: {
|
|
142
142
|
includeReferences?: boolean;
|
|
143
143
|
}): GraphEdge[];
|
|
@@ -205,7 +205,7 @@ declare function runPrune(store: CodeGraphStore, options?: PruneOptions & {
|
|
|
205
205
|
* index version is never reused, so a change to node/edge shape or to a metric's
|
|
206
206
|
* value for the same bytes can never be carried forward from an incompatible graph.
|
|
207
207
|
*/
|
|
208
|
-
declare const INDEX_VERSION = "0.
|
|
208
|
+
declare const INDEX_VERSION = "0.18.0";
|
|
209
209
|
interface IndexOptions {
|
|
210
210
|
/** Roots to walk. Node ids are still rooted at the git toplevel, so importers across roots share an id space. */
|
|
211
211
|
paths: string[];
|
|
@@ -448,7 +448,7 @@ declare function readSourceFiles(filePaths: readonly string[]): Promise<ReadFile
|
|
|
448
448
|
* Everything from a prior snapshot needed to rebuild an unchanged file's
|
|
449
449
|
* contribution to the graph without re-parsing it: its content fingerprint,
|
|
450
450
|
* the node table (to look up external-node names), outbound edges grouped by
|
|
451
|
-
* source, and the source-content metrics (loc, complexity, lcom4, ...).
|
|
451
|
+
* source file (a symbol's `calls` edges under the file declaring it), and the source-content metrics (loc, complexity, lcom4, ...).
|
|
452
452
|
*/
|
|
453
453
|
interface ReuseBasis {
|
|
454
454
|
snapshotId: number;
|
|
@@ -494,10 +494,11 @@ declare function edgeWeight(e: GraphEdge): number;
|
|
|
494
494
|
/**
|
|
495
495
|
* Drop `references` edges (C-53) whose target `symbol` node doesn't exist — an
|
|
496
496
|
* aliased re-export chain, or a barrel that changed under a reused file, can
|
|
497
|
-
* resolve a name to an origin that doesn't declare it.
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
497
|
+
* resolve a name to an origin that doesn't declare it. `calls` edges (TP-323)
|
|
498
|
+
* are dropped the same way, which is how a callee name that maps to no symbol
|
|
499
|
+
* node is discarded rather than guessed. Only these two can dangle
|
|
500
|
+
* (imports/re-exports resolve to always-emitted file/external nodes). Mutates
|
|
501
|
+
* `edges` in place.
|
|
501
502
|
*/
|
|
502
503
|
declare function pruneDanglingReferences(nodes: ReadonlyMap<string, GraphNode>, edges: Map<string, GraphEdge>): void;
|
|
503
504
|
/**
|
|
@@ -1120,7 +1121,7 @@ type MetricDirection = "higher-worse" | "lower-worse" | "neutral";
|
|
|
1120
1121
|
/** A missing row reads as zero (a sparse writer's floor) or is left out of means, percentiles, and ranks. */
|
|
1121
1122
|
type MetricAbsence = "zero" | "exclude";
|
|
1122
1123
|
/** The code-graph module that writes the metric, for provenance. */
|
|
1123
|
-
type MetricSource = "degree" | "source-metrics" | "lcom" | "exception-handling" | "dead-code" | "growth-risk" | "history" | "test-linker" | "coverage";
|
|
1124
|
+
type MetricSource = "degree" | "source-metrics" | "lcom" | "call-graph" | "exception-handling" | "dead-code" | "growth-risk" | "history" | "test-linker" | "coverage";
|
|
1124
1125
|
interface MetricDescriptor {
|
|
1125
1126
|
/** The stored name, or a template such as `churn_{w}` when {@link windowed} is set. */
|
|
1126
1127
|
name: string;
|
|
@@ -1190,6 +1191,10 @@ interface MetricOutlierRule {
|
|
|
1190
1191
|
percentile: number;
|
|
1191
1192
|
/** Fewest nodes that must carry the metric before any is judged; defaults to 20. */
|
|
1192
1193
|
minSample?: number;
|
|
1194
|
+
/** A node is flagged only if its value also exceeds this absolute floor, guarding sparse metrics whose percentile sits at or near zero. */
|
|
1195
|
+
floor?: number;
|
|
1196
|
+
/** When true, rank and gate on the pool of carriers with a non-zero value only; zero-valued nodes are never flagged. */
|
|
1197
|
+
rankNonZero?: boolean;
|
|
1193
1198
|
severity?: Severity;
|
|
1194
1199
|
}
|
|
1195
1200
|
interface ForbidImportRule {
|