[engine] Use relative paths in `shac fmt` output

This is less verbose and repetitive than using absolute paths.

Change-Id: I2a12f097e41e4542f4f4416cfe9934bbaf0c86ee
Reviewed-on: https://fuchsia-review.googlesource.com/c/shac-project/shac/+/929013
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Fuchsia-Auto-Submit: Oliver Newman <olivernewman@google.com>
Reviewed-by: Ina Huh <ihuh@google.com>
diff --git a/internal/engine/fix.go b/internal/engine/fix.go
index 425c929..1e22bb6 100644
--- a/internal/engine/fix.go
+++ b/internal/engine/fix.go
@@ -15,6 +15,7 @@
 package engine
 
 import (
+	"cmp"
 	"context"
 	"errors"
 	"fmt"
@@ -31,8 +32,9 @@
 // in it, then applies suggested fixes to files on disk.
 func Fix(ctx context.Context, o *Options, quiet bool) error {
 	fc := findingCollector{
-		countsByCheck: map[string]int{},
-		quiet:         quiet,
+		countsByCheck:  map[string]int{},
+		quiet:          quiet,
+		findingsByFile: make(map[findingFile][]findingToFix),
 	}
 	if o.Report != nil {
 		return fmt.Errorf("cannot overwrite reporter")
@@ -42,21 +44,18 @@
 		return err
 	}
 
-	findingsByFile := make(map[string][]findingToFix)
-	for _, f := range fc.findings {
-		findingsByFile[f.file] = append(findingsByFile[f.file], f)
-	}
-
-	orderedFiles := make([]string, 0, len(findingsByFile))
-	for f := range findingsByFile {
+	orderedFiles := make([]findingFile, 0, len(fc.findingsByFile))
+	for f := range fc.findingsByFile {
 		orderedFiles = append(orderedFiles, f)
 	}
 	// Sort for determinism.
-	sort.Strings(orderedFiles)
+	slices.SortFunc(orderedFiles, func(a, b findingFile) int {
+		return cmp.Compare(a.path, b.path)
+	})
 
-	for _, path := range orderedFiles {
-		findings := findingsByFile[path]
-		numFixed, err := fixFindings(path, findings)
+	for _, f := range orderedFiles {
+		findings := fc.findingsByFile[f]
+		numFixed, err := fixFindings(filepath.Join(f.root, f.path), findings)
 		if err != nil {
 			return err
 		}
@@ -65,7 +64,7 @@
 			noun += "s"
 		}
 		if !quiet {
-			fmt.Fprintf(os.Stderr, "Fixed %d %s in %s\n", numFixed, noun, path)
+			fmt.Fprintf(os.Stderr, "Fixed %d %s in %s\n", numFixed, noun, f.path)
 		}
 	}
 	return nil
@@ -139,8 +138,12 @@
 	return numFixed, nil
 }
 
+type findingFile struct {
+	root string
+	path string
+}
+
 type findingToFix struct {
-	file        string
 	span        Span
 	replacement string
 }
@@ -170,10 +173,10 @@
 }
 
 type findingCollector struct {
-	mu            sync.Mutex
-	findings      []findingToFix
-	countsByCheck map[string]int
-	quiet         bool
+	mu             sync.Mutex
+	findingsByFile map[findingFile][]findingToFix
+	countsByCheck  map[string]int
+	quiet          bool
 }
 
 var _ Report = (*findingCollector)(nil)
@@ -188,8 +191,8 @@
 	if len(replacements) == 1 {
 		c.mu.Lock()
 		defer c.mu.Unlock()
-		c.findings = append(c.findings, findingToFix{
-			file:        filepath.Join(root, filepath.FromSlash(file)),
+		key := findingFile{root: root, path: filepath.FromSlash(file)}
+		c.findingsByFile[key] = append(c.findingsByFile[key], findingToFix{
 			span:        s,
 			replacement: replacements[0],
 		})
diff --git a/internal/engine/version.go b/internal/engine/version.go
index 554d94b..fbfe97f 100644
--- a/internal/engine/version.go
+++ b/internal/engine/version.go
@@ -26,7 +26,7 @@
 	// Version is the current tool version.
 	//
 	// TODO(maruel): Add proper version, preferably from git tag.
-	Version = shacVersion{0, 1, 12}
+	Version = shacVersion{0, 1, 13}
 )
 
 func (v shacVersion) String() string {