Coverage Analysis Visitor: Class Diagram Explained
Hey guys! Let's dive into the class diagram for the updated coverage analysis visitor. This pull request (PR) brings some significant changes, including deprecating the redundant verify flag on ProjectCompiler, revamping Solidity coverage analysis with the Solar AST/HIR pipeline, and updating the coverage test CLI and reporter. It also touches on simplifying test fixtures and patching ancillary tooling. So, buckle up, and let’s get started!
Understanding the Updated Coverage Analysis Visitor
In this section, we will deeply discuss the class diagram for the updated coverage analysis visitor.
classDiagram
class SourceVisitor {
+source_id: u32
+gcx: Gcx
+contract_name: Arc<str>
+branch_id: u32
+items: Vec<CoverageItem>
+all_lines: Vec<u32>
+function_calls: Vec<Span>
+function_calls_set: FxHashSet<Span>
+new(source_id: u32, gcx: Gcx)
+checkpoint() SourceVisitorCheckpoint
+restore_checkpoint(checkpoint: SourceVisitorCheckpoint)
+visit_contract(contract: ast::ItemContract)
+has_tests(checkpoint: SourceVisitorCheckpoint) bool
+disambiguate_functions()
+resolve_function_calls(hir_source_id: hir::SourceId)
+sort()
+push_lines()
+push_stmt(span: Span)
+push_item_kind(kind: CoverageItemKind, span: Span)
+source_location_for(span: Span) SourceLocation
+byte_range(span: Span) Range<u32>
+line_range(span: Span) Range<u32>
+next_branch_id() u32
}
class SourceVisitorCheckpoint {
+items: usize
+all_lines: usize
+function_calls: usize
}
class CoverageItem {
+kind: CoverageItemKind
+loc: SourceLocation
+hits: u32
+ord_key()
+fmt_with_source(src: Option<str>)
}
class CoverageItemKind {
<<enum>>
Line
Statement
Branch
Function
+ord_key()
}
class SourceLocation {
+source_id: usize
+contract_name: Arc<str>
+bytes: Range<u32>
+lines: Range<u32>
+bytes() Range<usize>
+len() u32
}
SourceVisitor --> SourceVisitorCheckpoint
SourceVisitor --> CoverageItem
CoverageItem --> CoverageItemKind
CoverageItem --> SourceLocation
At the heart of the update is the SourceVisitor class. Think of it as the detective in our coverage analysis story. This class is responsible for traversing the source code and collecting information about what lines, statements, branches, and functions have been covered during testing.
-
Key Attributes:
source_id
: A unique identifier for the source file. It's like the case file number for our detective.gcx
: Short for “Global Context,” this holds the global compilation context. It’s the detective's headquarters, containing all the necessary resources.contract_name
: The name of the contract being analyzed. This is the name of our suspect in the case.branch_id
: An identifier for tracking branches in the code. Think of it as marking different paths in a maze.items
: A collection ofCoverageItem
objects. These are the clues our detective collects – each item represents a covered line, statement, or branch.all_lines
: A list of all line numbers in the source file. This is the complete map of the territory.function_calls
: A list of function call spans. These are important events our detective notes down.function_calls_set
: A set of function call spans for quick lookup. It’s the detective’s quick reference list.
-
Key Methods:
new(source_id: u32, gcx: Gcx)
: Constructor for creating a newSourceVisitor
. It's like hiring a new detective and giving them their first case.checkpoint() SourceVisitorCheckpoint
: Creates a checkpoint of the current state. This is like the detective taking notes at a crucial point in the investigation.restore_checkpoint(checkpoint: SourceVisitorCheckpoint)
: Restores the state from a checkpoint. It’s like the detective revisiting their notes to reconsider their path.visit_contract(contract: ast::ItemContract)
: Visits a contract node in the AST (Abstract Syntax Tree). This is the detective entering the crime scene.has_tests(checkpoint: SourceVisitorCheckpoint) bool
: Checks if there are tests associated with the current state. It’s like asking, “Do we have enough evidence to proceed?”disambiguate_functions()
: Resolves function calls to their definitions. It’s like connecting the dots between different pieces of evidence.resolve_function_calls(hir_source_id: hir::SourceId)
: Resolves function calls using the HIR (High-Level Intermediate Representation). This is like using advanced tools to analyze the evidence.sort()
: Sorts the coverage items. It’s like organizing the clues in order of importance.push_lines()
: Pushes line coverage items. It’s like marking the path the suspect took.push_stmt(span: Span)
: Pushes statement coverage items. It’s like noting each action the suspect performed.push_item_kind(kind: CoverageItemKind, span: Span)
: Pushes coverage items of a specific kind. It’s like categorizing the evidence.source_location_for(span: Span) SourceLocation
: Gets the source location for a given span. It’s like pinpointing the exact spot where an event occurred.byte_range(span: Span) Range<u32>
: Gets the byte range for a span. It’s like measuring the size of the footprint.line_range(span: Span) Range<u32>
: Gets the line range for a span. It’s like noting the line numbers where the event took place.next_branch_id() u32
: Generates the next unique branch ID. It’s like labeling different paths in a decision tree.
SourceVisitorCheckpoint
The SourceVisitorCheckpoint class is a helper class that allows the SourceVisitor
to save and restore its state. It's like the detective taking a snapshot of their progress so they can backtrack if needed.
- Key Attributes:
items
: The number of coverage items at the checkpoint.all_lines
: The number of lines covered at the checkpoint.function_calls
: The number of function calls recorded at the checkpoint.
CoverageItem
The CoverageItem class represents a single covered item, such as a line, statement, or branch. It's one of the crucial clues that our detective collects.
-
Key Attributes:
kind
: The kind of coverage item (CoverageItemKind
). Is it a line, statement, branch, or function?loc
: The source location of the item (SourceLocation
). Where did this item occur in the code?hits
: The number of times this item was hit during testing. How many times did this event occur?
-
Key Methods:
ord_key()
: Generates a key for sorting coverage items. It’s like prioritizing the clues.fmt_with_source(src: Option<str>)
: Formats the coverage item with source code context. It’s like presenting the clue with its surrounding environment for better understanding.
CoverageItemKind
The CoverageItemKind enum defines the types of coverage items. It’s the categorization system our detective uses to classify the clues.
-
Enum Variants:
Line
: Represents a covered line.Statement
: Represents a covered statement.Branch
: Represents a covered branch.Function
: Represents a covered function.
-
Key Methods:
ord_key()
: Generates a key for sorting coverage item kinds. It’s like prioritizing the categories of clues.
SourceLocation
The SourceLocation class represents the location of a coverage item in the source code. It's like the detective pinpointing the exact spot where a clue was found.
-
Key Attributes:
source_id
: The ID of the source file.contract_name
: The name of the contract.bytes
: The range of bytes in the source file. It’s like measuring the exact footprint size.lines
: The range of lines in the source file. It’s like noting the specific lines of code involved.
-
Key Methods:
bytes() Range<usize>
: Returns the byte range.len() u32
: Returns the length of the location.
Deprecated ProjectCompiler::verify
Next up, let's talk about the deprecated ProjectCompiler::verify
field and method. This change simplifies the compiler by removing a redundant flag. Here's the class diagram:
classDiagram
class ProjectCompiler {
+project_root: PathBuf
-verify: Option<bool> (removed)
+print_names: Option<bool>
+print_sizes: Option<bool>
+quiet: Option<bool>
+new()
-verify(yes: bool) (removed)
+print_names(yes: bool)
+print_sizes(yes: bool)
+quiet(yes: bool)
}
The ProjectCompiler class is responsible for compiling the Solidity code. The verify
field and its setter method have been removed to simplify the compiler’s logic.
- Key Changes:
-verify: Option<bool> (removed)
: Theverify
field, which was an option to enable or disable verification, has been removed.-verify(yes: bool) (removed)
: The setter method for theverify
field has also been removed.
Updated SourceFiles and SourceAnalysis
Moving on, let’s discuss the updates to SourceFiles
and SourceAnalysis
. These changes enhance how source files are managed and analyzed.
classDiagram
class SourceFiles {
+sources: HashMap<u32, PathBuf>
}
class SourceAnalysis {
+new(data: SourceFiles, output: ProjectCompileOutput)
}
SourceAnalysis --> SourceFiles
SourceFiles
The SourceFiles class now maintains a map of source IDs to file paths. It’s like having a well-organized directory of all the case files.
- Key Attributes:
sources
: AHashMap
that maps au32
source ID to aPathBuf
file path. This allows quick lookup of file paths by their ID.
SourceAnalysis
The SourceAnalysis class is responsible for analyzing the source code and generating coverage data.
- Key Attributes:
new(data: SourceFiles, output: ProjectCompileOutput)
: The constructor now takesSourceFiles
andProjectCompileOutput
as arguments. This provides the analysis class with the necessary data for coverage analysis.
Updated CoverageItem and CoverageItemKind
Now, let's explore the updates to CoverageItem
and CoverageItemKind
. These changes focus on improving ordering and formatting.
classDiagram
class CoverageItemKind {
<<enum>>
Line
Statement
Branch
Function
+ord_key()
+PartialEq
+Eq
+PartialOrd
+Ord
}
class CoverageItem {
+kind: CoverageItemKind
+loc: SourceLocation
+hits: u32
+ord_key()
+PartialEq
+Eq
+PartialOrd
+Ord
+fmt_with_source(src: Option<str>)
}
CoverageItem --> CoverageItemKind
CoverageItemKind
The CoverageItemKind enum now derives PartialEq
, Eq
, PartialOrd
, and Ord
, allowing for easy comparison and sorting.
- Key Methods:
ord_key()
: Generates a key for sorting coverage item kinds. This helps in prioritizing different types of coverage items.
CoverageItem
The CoverageItem class also derives PartialEq
, Eq
, PartialOrd
, and Ord
for sorting. Additionally, the fmt_with_source
method is enhanced to include source code snippets.
- Key Methods:
ord_key()
: Generates a key for sorting coverage items.fmt_with_source(src: Option<str>)
: Formats the coverage item with source code context, making it easier to understand the coverage results.
Updated Display Implementations
Finally, let's cover the updated display implementations for ContractId
, ItemAnchor
, CoverageItem
, and SourceLocation
. These changes improve how these objects are displayed, making the output more readable.
classDiagram
class ContractId {
+contract_name: Arc<str>
+fmt(f: &mut fmt::Formatter)
}
class ItemAnchor {
+instruction: u32
+item_id: u32
+fmt(f: &mut fmt::Formatter)
}
class CoverageItem {
+fmt(f: &mut fmt::Formatter)
+fmt_with_source(src: Option<str>)
}
class SourceLocation {
+fmt(f: &mut fmt::Formatter)
}
The fmt
methods for these classes are updated to provide more detailed and readable output. For example, CoverageItem
now uses fmt_with_source
to include source code snippets, making it easier to see what part of the code is being covered.
File-Level Changes
To give you a bird's-eye view, here's a summary of the file-level changes:
Change | Details | Files |
---|---|---|
Overhaul coverage AST visitor to use Solar |
|
crates/evm/coverage/src/analysis.rs |
Adapt SourceAnalysis to new ProjectCompileOutput and SourceFiles |
|
crates/evm/coverage/src/analysis.rs crates/forge/src/cmd/coverage.rs |
Deprecate ProjectCompiler::verify and fix compile_target signature |
|
crates/common/src/compile.rs crates/forge/src/cmd/coverage.rs |
Simplify coverage test fixtures |
|
crates/forge/tests/cli/coverage.rs |
Enhance coverage reporter to include source snippets |
|
crates/forge/src/coverage.rs |
Implement ordering and improved Display for coverage items |
|
crates/evm/coverage/src/lib.rs |
Patch anvil tracing, workflows, and hardfork mapping |
|
crates/anvil/src/lib.rs .github/workflows/docker-publish.yml .github/workflows/release.yml crates/anvil/src/hardfork.rs |
Ensure state touch in cheatcodes broadcasts |
|
crates/cheatcodes/src/inspector.rs |
Bump and reorganize dependencies |
|
Cargo.toml crates/evm/coverage/Cargo.toml |
Conclusion
So, guys, that’s a wrap on the class diagram and updates for the coverage analysis visitor! These changes collectively enhance the accuracy, readability, and efficiency of our coverage analysis. By adopting the Solar AST/HIR pipeline, simplifying the compiler, and improving the display of coverage items, we’re making significant strides in our testing and analysis capabilities.
Keep an eye out for more updates, and happy coding!