Thank you for your interest, it's amazing 🥰. Here is some information to help you contribute to this project.
I hope these informations will help you:
- How to contribute?
- I have never programmed in Go, but I would love to learn
- How to run automated tests?
- How is the source code organized?
- I want to add or modify a report
- My contribution is about supporting a new programming language
- My contribution involves updating the data structure (protobuf)
- How to release new version?
- How to improve the website?
No problem! Golang is accessible and easy to learn. Here are some resources to get you started:
- A Tour of Go: an interactive tour that will help you get started with Go.
- Go by Example: a hands-on introduction to Go using annotated example programs.
- Go in 5 minutes: a series of short videos that will help you get started with Go.
You will need Go 1.21+
to contribute to the source code. Please follow the official installation guide to install Go on your machine.
To run automated tests, use the following command:
go test ./...
The main directories of the application are as follows:
src/Analyzer
: contains everything related to AST analysis (complexity, volume, etc.)src/Configuration
: manages configuration (loading files, validation, etc.)src/Engine
: contains various engines that convert source code (Python, Golang, PHP...) into an ASTsrc/Report
: generates reports (HTML, markdown, etc.)
The NodeType
structure is the most important part of the project. It's the data structure that will be used to store the AST of the source code, and analysis results. This structure is automatically generated from the proto/NodeType.proto
file.
[!INFO]
An AST (Abstract Syntax Tree) is a tree representation of the source code. It's used to represent the structure of the source code in a way that is easy to analyze.
A Statement is a node in the AST. It represents a part of the source code, like a function, a class, an if statement, etc.
Each statement in the AST can have another statements as children, recursively. For example, the StmtClass
statement can have StmtFunction
as children, which can have StmtDecisionIf
as children, etc.
In all case, each statement has at least the following properties:
Name
: the structured name of the statementStmts
: a list of children statementsAnalyze
: a list of analysis results (Volume, complexity, etc.)- (optional)
StmtLocationInFile
: tracks the location of the statement in the source code
The role of each Engine
consists in parsing the source code, and creating the corresponding Stmt*
statement(s).
Then, each Analyzer
will then traverse the AST, and compute analysis results (like cyclomatic complexity, volume, etc.) filling the Analyze
property of each statement.
Do not hesitate to look at the existing analyzers to understand how to use the Analyze
property. An analyzer is a structure that implements the Visitor
interface, and will be used to traverse the AST.
This visitor pattern is used to traverse the AST, and compute analysis results.
type Visitor interface {
Visit(stmts *pb.Stmts, parents *pb.Stmts)
LeaveNode(stmts *pb.Stmts)
}
You'll find an example of an analyzer in the src/Analyzer/Complexity/CyclomaticVisitor.go
file.
[!INFO]
If you want to discover protobuf, you can read the official documentation.
Reports can be generated in formats like HTML, markdown, etc.
To add a new report, you need to create a structure that implements the Reporter
interface defined in src/Report/Reporter.go
.
type Reporter interface {
// generates a report based on the files and the project aggregated data
Generate(files []*pb.File, projectAggregated Analyzer.ProjectAggregated) ([]GeneratedReport, error)
}
Then, register this new Reporter
in the list of available reporters in the file src/Report/ReportersFactory.go
.
Finally, add a CLI option (e.g., --report-myreport=file1.foo
) to activate this report by modifying the main.go
file.
Language agnosticism in the analysis is achieved by using protobuf files that act as intermediaries between the parsed file (an AST) and the analysis engine.
To add support for a new programming language, you need to declare a new Engine that implements the Engine
interface defined in src/Engine/Engine.go
.
type Engine interface {
// Returns true when analyzed files are concerned by the programming language
IsRequired() bool
// Prepare the engine for the analysis. For example, in order to prepare caches
Ensure() error
// First step of analysis. Parse all files, and generate protobuff compatible AST files
DumpAST()
// Cleanups the engine. For example, to remove caches
Finish() error
// Give a UI progress bar to the engine
SetProgressbar(progressbar *pterm.SpinnerPrinter)
// Give the configuration to the engine
SetConfiguration(configuration *Configuration.Configuration)
// Parse a file and return a protobuff compatible AST object
Parse(filepath string) (*pb.File, error)
}
The protobuf file is defined in the proto directory, and a corresponding Go file is generated with the make build-protobuff
command. This file is versioned as src/NodeType.NodeType.go.
The data structure is defined in protobuf files located in the proto directory.
You need to install protobuf by running:
make install-protobuf
Once you've finished editing the protobuf files, you can generate the corresponding Go code with the command:
make build-protobuff
This will also verify that the protobuf files are well-formed.
First ensure tests pass:
make test
Then release new version:
make build
The website is hosted on Github, using the documentation
branch.
When the documentation
branch is updated, the website is automatically updated. You just need to create a pull request on the documentation
branch.
You'll need mkdocs to build the website locally. Once installed, you can run the following command to build the website:
mkdocs serve