Documentation
¶
Overview ¶
Package coupling computes Robert C. Martin's package-coupling metrics — afferent coupling (Ca), efferent coupling (Ce), and instability (I = Ce/(Ca+Ce)) — and detects circular dependencies, across many language ecosystems.
It works on a first-party import graph it builds from per-file data the caller supplies (path, language, imports, declared package). The package itself does no parsing; pair it with a symbol extractor such as github.com/richardwooding/treesitter-symbols to obtain the imports and package for each file.
The ecosystem is detected from the build manifest at the project root — go.mod (Go packages), Cargo.toml (Rust crates), Package.swift (SwiftPM target modules), Maven/Gradle/sbt (JVM packages), .sln/.csproj (C# namespaces), a Python manifest (packages), package.json/tsconfig.json (JS/TS directory modules), a Perl dist manifest (:: packages), Gemfile/*.gemspec (Ruby directory modules), and CMake/autotools/meson (C/C++ #include directory modules). The first-party boundary and the file→node / import→node mappings are per-ecosystem; the graph math is language-agnostic.
g := coupling.Build(root, files)
for _, c := range g.Coupling() { ... } // Ca / Ce / I per package
for _, c := range g.Cycles() { ... } // circular dependencies
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Coupling ¶
type Coupling struct {
Package string `json:"package"` // node id (import path / crate / namespace / dir)
Afferent int `json:"afferent"` // Ca: distinct first-party nodes that import this one
Efferent int `json:"efferent"` // Ce: distinct first-party nodes this one imports
Instability float64 `json:"instability"` // I = Ce / (Ca + Ce); 0 when isolated
}
Coupling is the afferent/efferent coupling profile of one first-party node (package / crate / namespace / directory module).
type Cycle ¶
Cycle is one circular dependency: a strongly-connected component of size > 1 in the first-party import graph. Nodes is the sorted member set (not an edge-ordered path).
func FindCycles ¶
FindCycles is a convenience wrapper: Build(root, files).Cycles().
type File ¶
type File struct {
// Path is the file's location on disk (absolute or cwd-relative). Used by
// path-based ecosystems (Go/Rust/Python/JS-TS/Ruby/C-C++) to map a file to
// its node.
Path string
// Language is the canonical language id ("go", "rust", "java", …).
Language string
// Imports are the file's import paths (absolute form).
Imports []string
// RelativeImports are dotted-relative imports with leading dots preserved
// (Python); empty for other languages.
RelativeImports []string
// Package is the file's declared package / namespace, for the
// declaration-based ecosystems (Java/Kotlin/Scala/C#/PHP/Perl). Ignored by
// the path-based ones.
Package string
}
File is the per-file input to Build: the data a caller has already extracted for one source file. Path may be absolute or relative to the current working directory.
type Graph ¶
type Graph struct {
// contains filtered or unexported fields
}
Graph is a first-party import graph built by Build. Query it with Graph.Coupling and Graph.Cycles; both are pure reads, so a Graph may be queried repeatedly and concurrently.
func Build ¶
Build constructs the first-party import graph for the project rooted at root from files. root selects the ecosystem (via its build manifest) and anchors first-party resolution; each File carries the imports / package the caller already extracted.
When root carries no recognised manifest, the returned graph is non-analysable (Graph.Analysable is false) and its queries return empty — mirroring the "unknown ecosystem" case rather than erroring.
func (*Graph) Analysable ¶
Analysable reports whether root carried a recognised build manifest. When false, Coupling and Cycles return empty.
func (*Graph) Coupling ¶
Coupling returns the per-node Ca/Ce/I profile, ranked most-depended-upon first (high Ca), then most unstable (high I), then by name — the "fragile hub" seams where a refactor is riskiest.
func (*Graph) Cycles ¶
Cycles returns the circular dependencies — strongly-connected components of size > 1 — ranked largest-first, then alphabetically by first member.
func (*Graph) FileCoupling ¶ added in v0.3.0
FileCoupling returns the coupling profile of each first-party file's node, keyed by the File.Path that was passed to Build. Files that mapped to no first-party node — an unmatched language, an empty/external node, or a file under a non-analysable root — are absent from the map.
It lets a caller attribute node-level Ca/Ce/instability back to individual files (many files may share one node's profile) without reproducing the ecosystem's node rule. Use the same Path form (absolute or relative) you gave Build; the returned keys echo it verbatim.