@@ -4,8 +4,11 @@ import (
44 "bytes"
55 "encoding/json"
66 "fmt"
7+ "os"
8+ "path/filepath"
79 "sort"
810
11+ "github.com/bmatcuk/doublestar/v4"
912 "github.com/crytic/medusa-geth/core/vm"
1013 "github.com/crytic/medusa/compilation/types"
1114 "github.com/crytic/medusa/logging"
@@ -58,6 +61,52 @@ func (s *SourceAnalysis) CoveredLineCount() int {
5861 return count
5962}
6063
64+ // shouldExcludeFile checks if a file path matches any of the exclusion patterns
65+ func shouldExcludeFile (filePath string , exclusionPatterns []string ) bool {
66+ for _ , pattern := range exclusionPatterns {
67+ if matched , err := doublestar .Match (pattern , filePath ); err == nil && matched {
68+ return true
69+ }
70+ }
71+ return false
72+ }
73+
74+ // filterExcludedFiles removes files matching exclusion patterns from the source analysis.
75+ // Pattern matching is performed on relative paths (relative to current working directory)
76+ // to match the behavior of the coverage report display.
77+ func (s * SourceAnalysis ) filterExcludedFiles (exclusionPatterns []string ) {
78+ if len (exclusionPatterns ) == 0 {
79+ return
80+ }
81+
82+ // Get current working directory to convert absolute paths to relative paths
83+ // This ensures pattern matching works on the same relative paths shown in reports
84+ cwd , err := os .Getwd ()
85+ if err != nil {
86+ // If we can't get the working directory, skip filtering to avoid issues
87+ return
88+ }
89+
90+ // Create a new map without excluded files
91+ filteredFiles := make (map [string ]* SourceFileAnalysis )
92+
93+ for filePath , fileAnalysis := range s .Files {
94+ // Convert to relative path for pattern matching (same logic as in report template)
95+ relativePath := filePath
96+ if relPath , err := filepath .Rel (cwd , filePath ); err == nil {
97+ relativePath = relPath
98+ }
99+
100+ // Keep the file if it doesn't match any exclusion pattern
101+ if ! shouldExcludeFile (relativePath , exclusionPatterns ) {
102+ filteredFiles [filePath ] = fileAnalysis
103+ }
104+ }
105+
106+ // Replace the original files map with filtered results
107+ s .Files = filteredFiles
108+ }
109+
61110// GenerateLCOVReport generates an LCOV report from the source analysis.
62111// The spec of the format is here https://github.com/linux-test-project/lcov/blob/07a1127c2b4390abf4a516e9763fb28a956a9ce4/man/geninfo.1#L989
63112func (s * SourceAnalysis ) GenerateLCOVReport () string {
@@ -214,10 +263,10 @@ func GetUniquePCsCount(compilations []types.Compilation, coverageMaps *CoverageM
214263 return uniquePCs , nil
215264}
216265
217- // AnalyzeSourceCoverage takes a list of compilations and a set of coverage maps, and performs source analysis
218- // to determine source coverage information.
266+ // AnalyzeSourceCoverage takes a list of compilations, coverage maps, and exclusion patterns, then performs source analysis
267+ // to determine source coverage information. Files matching the exclusion patterns will be filtered out from the results.
219268// Returns a SourceAnalysis object, or an error if one occurs.
220- func AnalyzeSourceCoverage (compilations []types.Compilation , coverageMaps * CoverageMaps , logger * logging.Logger ) (* SourceAnalysis , error ) {
269+ func AnalyzeSourceCoverage (compilations []types.Compilation , coverageMaps * CoverageMaps , exclusionPatterns [] string , logger * logging.Logger ) (* SourceAnalysis , error ) {
221270 // Create a new source analysis object
222271 sourceAnalysis := & SourceAnalysis {
223272 Files : make (map [string ]* SourceFileAnalysis ),
@@ -323,6 +372,10 @@ func AnalyzeSourceCoverage(compilations []types.Compilation, coverageMaps *Cover
323372 }
324373 }
325374 }
375+
376+ // Apply exclusion filtering if patterns are provided
377+ sourceAnalysis .filterExcludedFiles (exclusionPatterns )
378+
326379 return sourceAnalysis , nil
327380}
328381
0 commit comments