Skip to content

Commit 98cc372

Browse files
committed
feat: switch to positional instrumenting from line-oriented
1 parent 83d4433 commit 98cc372

23 files changed

Lines changed: 924 additions & 593 deletions

internal/cli/report.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ func ReportSummary(coverageFile string) error {
7373
}
7474

7575
// Print overall coverage
76-
fmt.Printf("Overall Coverage: %.2f%%\n\n", cov.TotalLineCoveragePercent())
76+
fmt.Printf("Overall Coverage: %.2f%%\n\n", cov.TotalPositionCoveragePercent())
7777

7878
// Print per-file coverage
7979
fmt.Println("File Coverage:")
80-
for file, hits := range cov.Files {
80+
for file, posHits := range cov.Positions {
8181
covered := 0
82-
for _, count := range hits {
82+
for _, count := range posHits {
8383
if count > 0 {
8484
covered++
8585
}
8686
}
87-
total := len(hits)
88-
percent := cov.LineCoveragePercent(file)
87+
total := len(posHits)
88+
percent := cov.PositionCoveragePercent(file)
8989

90-
fmt.Printf(" %s: %.2f%% (%d/%d lines)\n", file, percent, covered, total)
90+
fmt.Printf(" %s: %.2f%% (%d/%d positions)\n", file, percent, covered, total)
9191
}
9292

9393
return nil

internal/cli/run.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ func Run(ctx context.Context, config *Config, searchPath string) (int, error) {
9898

9999
// Step 7: Collect coverage
100100
collector := coverage.NewCollector()
101+
101102
if err := collector.CollectFromRuns(testRuns); err != nil {
102103
return 1, fmt.Errorf("coverage collection failed: %w", err)
103104
}
@@ -125,7 +126,7 @@ func Run(ctx context.Context, config *Config, searchPath string) (int, error) {
125126
}
126127

127128
// PrintVerbose prints a message if verbose mode is enabled
128-
func PrintVerbose(config *Config, format string, args ...interface{}) {
129+
func PrintVerbose(config *Config, format string, args ...any) {
129130
if config.Verbose {
130131
fmt.Printf(format+"\n", args...)
131132
}

internal/coverage/collector.go

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,24 @@ func (c *Collector) AddSignal(signal runner.CoverageSignal) error {
5353

5454
// addSignalUnsafe adds a signal without locking (internal use when lock is already held)
5555
func (c *Collector) addSignalUnsafe(signal runner.CoverageSignal) error {
56-
// Parse signal ID to extract file, line, and branch
57-
file, line, branch, err := instrument.ParseSignalID(signal.SignalID)
56+
// Parse signal ID to extract file, startPos, length, and branch
57+
file, startPos, length, branch, err := instrument.ParseSignalID(signal.SignalID)
5858
if err != nil {
5959
return fmt.Errorf("invalid signal ID: %w", err)
6060
}
6161

62-
// Add line or branch coverage
62+
// Add position-based coverage only
6363
if branch == "" {
64-
// Line coverage - increment hit count
65-
if existingCount, exists := c.coverage.Files[file][line]; exists {
66-
c.coverage.AddLine(file, line, existingCount+1)
64+
// Position coverage - increment hit count
65+
posKey := fmt.Sprintf("%d:%d", startPos, length)
66+
if existingCount, exists := c.coverage.Positions[file][posKey]; exists {
67+
c.coverage.AddPosition(file, startPos, length, existingCount+1)
6768
} else {
68-
c.coverage.AddLine(file, line, 1)
69+
c.coverage.AddPosition(file, startPos, length, 1)
6970
}
7071
} else {
7172
// Branch coverage (placeholder for future)
72-
branchKey := fmt.Sprintf("%d:%s", line, branch)
73+
branchKey := fmt.Sprintf("%d:%d:%s", startPos, length, branch)
7374
c.coverage.AddBranch(file, branchKey, 1)
7475
}
7576

@@ -97,32 +98,41 @@ func (c *Collector) Merge(other *Collector) error {
9798
other.mu.Lock()
9899
defer other.mu.Unlock()
99100

100-
for file, otherHits := range other.coverage.Files {
101-
// Merge line hit counts
102-
for line, count := range otherHits {
103-
if existingCount, exists := c.coverage.Files[file][line]; exists {
104-
c.coverage.AddLine(file, line, existingCount+count)
101+
// Merge position hit counts only
102+
for file, otherPosHits := range other.coverage.Positions {
103+
for posKey, count := range otherPosHits {
104+
// Parse position key to get startPos and length
105+
var startPos, length int
106+
_, err := fmt.Sscanf(posKey, "%d:%d", &startPos, &length)
107+
if err != nil {
108+
continue // Skip invalid keys
109+
}
110+
111+
if existingCount, exists := c.coverage.Positions[file][posKey]; exists {
112+
c.coverage.AddPosition(file, startPos, length, existingCount+count)
105113
} else {
106-
c.coverage.AddLine(file, line, count)
114+
c.coverage.AddPosition(file, startPos, length, count)
107115
}
108116
}
109117
}
118+
110119
return nil
111120
}
112121

113-
// GetFileCoverage returns coverage data for a specific file (simplified)
114-
func (c *Collector) GetFileCoverage(filePath string) FileHits {
122+
// GetFilePositionCoverage returns position coverage data for a specific file
123+
func (c *Collector) GetFilePositionCoverage(filePath string) PositionHits {
115124
c.mu.Lock()
116125
defer c.mu.Unlock()
117-
return c.coverage.Files[filePath]
126+
return c.coverage.Positions[filePath]
118127
}
119128

120129
// GetFileList returns a list of all files with coverage data
121130
func (c *Collector) GetFileList() []string {
122131
c.mu.Lock()
123132
defer c.mu.Unlock()
133+
124134
var files []string
125-
for file := range c.coverage.Files {
135+
for file := range c.coverage.Positions {
126136
files = append(files, file)
127137
}
128138
return files
@@ -132,5 +142,5 @@ func (c *Collector) GetFileList() []string {
132142
func (c *Collector) TotalCoveragePercent() float64 {
133143
c.mu.Lock()
134144
defer c.mu.Unlock()
135-
return c.coverage.TotalLineCoveragePercent()
145+
return c.coverage.TotalPositionCoveragePercent()
136146
}

0 commit comments

Comments
 (0)