Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 14 additions & 62 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,20 @@
"panel": "new"
}
},
{
"label": "Run pgcov",
"type": "shell",
"command": "${workspaceFolder}/pgcov${command:pickString,values,.exe,}",
"args": [
"run",
"./testdata/simple",
"--verbose"
],
"group": "none",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"dependsOn": ["Build pgcov"],
"problemMatcher": []
},
{
"label": "Lint",
"type": "shell",
"command": "golangci-lint run",
"problemMatcher": [
"$go"
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "new"
}
},

{
"label": "Clean Build Cache",
"type": "shell",
Expand All @@ -88,51 +85,6 @@
"panel": "shared"
},
"problemMatcher": []
},
{
"label": "Go Mod Tidy",
"type": "shell",
"command": "go",
"args": [
"mod",
"tidy"
],
"group": "none",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"problemMatcher": []
},
{
"label": "Format Code",
"type": "shell",
"command": "go",
"args": [
"fmt",
"./..."
],
"group": "none",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"problemMatcher": []
},
{
"label": "Go Vet",
"type": "shell",
"command": "go",
"args": [
"vet",
"./..."
],
"group": "none",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"problemMatcher": ["$go"]
}
]
}
12 changes: 6 additions & 6 deletions internal/cli/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,21 @@ func ReportSummary(coverageFile string) error {
}

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

// Print per-file coverage
fmt.Println("File Coverage:")
for file, hits := range cov.Files {
for file, posHits := range cov.Positions {
covered := 0
for _, count := range hits {
for _, count := range posHits {
if count > 0 {
covered++
}
}
total := len(hits)
percent := cov.LineCoveragePercent(file)
total := len(posHits)
percent := cov.PositionCoveragePercent(file)

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

return nil
Expand Down
3 changes: 2 additions & 1 deletion internal/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func Run(ctx context.Context, config *Config, searchPath string) (int, error) {

// Step 7: Collect coverage
collector := coverage.NewCollector()

if err := collector.CollectFromRuns(testRuns); err != nil {
return 1, fmt.Errorf("coverage collection failed: %w", err)
}
Expand Down Expand Up @@ -125,7 +126,7 @@ func Run(ctx context.Context, config *Config, searchPath string) (int, error) {
}

// PrintVerbose prints a message if verbose mode is enabled
func PrintVerbose(config *Config, format string, args ...interface{}) {
func PrintVerbose(config *Config, format string, args ...any) {
if config.Verbose {
fmt.Printf(format+"\n", args...)
}
Expand Down
48 changes: 29 additions & 19 deletions internal/coverage/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,24 @@ func (c *Collector) AddSignal(signal runner.CoverageSignal) error {

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

// Add line or branch coverage
// Add position-based coverage only
if branch == "" {
// Line coverage - increment hit count
if existingCount, exists := c.coverage.Files[file][line]; exists {
c.coverage.AddLine(file, line, existingCount+1)
// Position coverage - increment hit count
posKey := fmt.Sprintf("%d:%d", startPos, length)
if existingCount, exists := c.coverage.Positions[file][posKey]; exists {
c.coverage.AddPosition(file, startPos, length, existingCount+1)
} else {
c.coverage.AddLine(file, line, 1)
c.coverage.AddPosition(file, startPos, length, 1)
}
} else {
// Branch coverage (placeholder for future)
branchKey := fmt.Sprintf("%d:%s", line, branch)
branchKey := fmt.Sprintf("%d:%d:%s", startPos, length, branch)
c.coverage.AddBranch(file, branchKey, 1)
}

Expand Down Expand Up @@ -97,32 +98,41 @@ func (c *Collector) Merge(other *Collector) error {
other.mu.Lock()
defer other.mu.Unlock()

for file, otherHits := range other.coverage.Files {
// Merge line hit counts
for line, count := range otherHits {
if existingCount, exists := c.coverage.Files[file][line]; exists {
c.coverage.AddLine(file, line, existingCount+count)
// Merge position hit counts only
for file, otherPosHits := range other.coverage.Positions {
for posKey, count := range otherPosHits {
// Parse position key to get startPos and length
var startPos, length int
_, err := fmt.Sscanf(posKey, "%d:%d", &startPos, &length)
if err != nil {
continue // Skip invalid keys
}

if existingCount, exists := c.coverage.Positions[file][posKey]; exists {
c.coverage.AddPosition(file, startPos, length, existingCount+count)
} else {
c.coverage.AddLine(file, line, count)
c.coverage.AddPosition(file, startPos, length, count)
}
}
}

return nil
}

// GetFileCoverage returns coverage data for a specific file (simplified)
func (c *Collector) GetFileCoverage(filePath string) FileHits {
// GetFilePositionCoverage returns position coverage data for a specific file
func (c *Collector) GetFilePositionCoverage(filePath string) PositionHits {
c.mu.Lock()
defer c.mu.Unlock()
return c.coverage.Files[filePath]
return c.coverage.Positions[filePath]
}

// GetFileList returns a list of all files with coverage data
func (c *Collector) GetFileList() []string {
c.mu.Lock()
defer c.mu.Unlock()

var files []string
for file := range c.coverage.Files {
for file := range c.coverage.Positions {
files = append(files, file)
}
return files
Expand All @@ -132,5 +142,5 @@ func (c *Collector) GetFileList() []string {
func (c *Collector) TotalCoveragePercent() float64 {
c.mu.Lock()
defer c.mu.Unlock()
return c.coverage.TotalLineCoveragePercent()
return c.coverage.TotalPositionCoveragePercent()
}
Loading