This project is a Go code structure visualizer that analyzes Go source code to extract structs, interfaces, and their relationships. It then generates a visual representation of these relationships as a graph.
Example ouput ran on loglens/internal
- Green boxes represent interfaces.
- White boxes represent structs.
- An arrow from an interface to a struct means the struct implements that interface.
- An arrow from a struct to another struct or interface means the struct depends on it.
- Brown arrows indicate that a parent struct uses or returns the child struct.
- Parses Go source code to identify:
- Structs and their fields
- Interfaces and their methods
- Method implementations
- Embedded struct dependencies
- Determines which structs implement which interfaces
- Generates a directed graph visualization of the relationships using Graphviz
The project requires the following Python libraries:
tree_sitter(for parsing Go code)tree_sitter_go(Go language grammar fortree_sitter)pygraphviz(for visualizing the structure graph)
You can install the required dependencies using:
pip install tree_sitter tree_sitter_go pygraphvizRun the script with the path to the Go source directory:
python main.py /path/to/go/projectThis will analyze the Go project and generate a graph saved as type-graph.png.
- Code Parsing: Uses
tree_sitterto parse Go source files recursively from the given directory. - Data Extraction:
- Extracts struct definitions, including fields and embedded structs.
- Extracts interface definitions and methods.
- Matches struct methods to interfaces to determine implementation relationships.
- Graph Generation: Uses
pygraphvizto create a directed graph:- Nodes represent structs and interfaces.
- Edges represent struct dependencies and interface implementations.
While the project is useful for visualizing Go code structures, it has some limitations:
-
Cannot Parse Functions as Parameters
- If a method or function takes another function as a parameter (e.g.,
func f(callback func(int) int)), the parser does not handle this correctly. - This is because function types require deeper parsing of the Go AST.
- If a method or function takes another function as a parameter (e.g.,
-
Cannot Handle Grouped Parameters
- The parser does not correctly handle grouped parameters like:
func Example(x, y, z int)
- It assumes each parameter has an explicit type (e.g.,
func Example(x int, y int, z int)). - This means methods with grouped parameters might be incorrectly parsed or missed.
- The parser does not correctly handle grouped parameters like:
-
Limited Type Resolution for Fields
- It does not resolve field types beyond direct name extraction.
- Example:
type A struct { B *SomeType }
- It will capture
"*SomeType"but does not check ifSomeTypeis a struct, an alias, or an imported type.
- Example:
- It does not resolve field types beyond direct name extraction.
-
No Support for Package Imports or Aliases
- The parser does not track imported packages and type aliases, meaning it may misinterpret types from external packages.
- Example:
import "mypackage" type A struct { B mypackage.SomeType }
- It treats
"mypackage.SomeType"as a raw string without verifying its definition.
- It treats
-
No Support for Generics
- The script does not handle Go 1.18+ generics.
- Example:
type Box[T any] struct { value T }
- It does not extract
Tproperly.
-
Struct Method Parsing Might Fail on Receivers with Generics or Complex Types
- Example:
func (b Box[T]) GetValue() T { return b.value }
- The parser may struggle to extract
Tas a return type.
- Example: