WIP
diff --git a/MODULE.bazel b/MODULE.bazel
index c1af060..aa90b0b 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -24,6 +24,7 @@
     # This name is ugly on purpose to avoid a conflict with a user-named SDK.
     "io_bazel_rules_nogo",
 )
+
 register_toolchains("@go_toolchains//:all")
 
 bazel_dep(name = "gazelle", version = "0.36.0")
@@ -35,6 +36,7 @@
     "com_github_gogo_protobuf",
     "com_github_golang_mock",
     "com_github_golang_protobuf",
+    "com_github_pmezard_go_difflib",
     "org_golang_google_genproto",
     "org_golang_google_grpc",
     "org_golang_google_grpc_cmd_protoc_gen_go_grpc",
diff --git a/go.mod b/go.mod
index 776305b..cbd908c 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@
 	github.com/gogo/protobuf v1.3.2
 	github.com/golang/mock v1.7.0-rc.1
 	github.com/golang/protobuf v1.5.3
+	github.com/pmezard/go-difflib v1.0.0
 	golang.org/x/net v0.18.0
 	golang.org/x/tools v0.15.0
 	google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013
diff --git a/go.sum b/go.sum
index 629573b..d55bd2f 100644
--- a/go.sum
+++ b/go.sum
@@ -48,6 +48,7 @@
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
diff --git a/go/private/rules/nogo.bzl b/go/private/rules/nogo.bzl
index 9d6b1f9..fe5b8c6 100644
--- a/go/private/rules/nogo.bzl
+++ b/go/private/rules/nogo.bzl
@@ -76,7 +76,7 @@
     nogo_source = go.library_to_source(go, struct(
         srcs = [struct(files = [nogo_main])],
         embed = [ctx.attr._nogo_srcs],
-        deps = analyzer_archives,
+        deps = analyzer_archives + [get_archive(ctx.attr._go_difflib)],
     ), nogo_library, False)
     _, executable, runfiles = go.binary(
         go,
@@ -106,6 +106,7 @@
         ),
         "_cgo_context_data": attr.label(default = "//:cgo_context_data_proxy"),
         "_go_config": attr.label(default = "//:go_config"),
+        "_go_difflib": attr.label(default = "@com_github_pmezard_go_difflib//difflib:go_default_library"),
         "_stdlib": attr.label(default = "//:stdlib"),
         "_allowlist_function_transition": attr.label(
             default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
diff --git a/go/tools/builders/nogo_main.go b/go/tools/builders/nogo_main.go
index 9cf558b..b940e91 100644
--- a/go/tools/builders/nogo_main.go
+++ b/go/tools/builders/nogo_main.go
@@ -39,6 +39,7 @@
 	"strings"
 	"sync"
 
+	"github.com/pmezard/go-difflib/difflib"
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/go/gcexportdata"
 	"golang.org/x/tools/internal/facts"
@@ -545,10 +546,70 @@
 		errMsg.WriteString(sep)
 		sep = "\n"
 		fmt.Fprintf(errMsg, "%s: %s (%s)", pkg.fset.Position(d.Pos), d.Message, d.Name)
+		for _, fix := range d.SuggestedFixes {
+			diff, err := calculateDiff(pkg.fset.File(d.Pos), fix.TextEdits)
+			if err != nil {
+				fmt.Fprintf(errMsg, "\nerror calculating diff: %v", err)
+				continue
+			}
+			println(diff)
+		}
 	}
 	return errMsg.String()
 }
 
+func calculateDiff(f *token.File, edits []analysis.TextEdit) (string, error) {
+	sort.SliceStable(edits, func(i, j int) bool {
+		return edits[i].Pos < edits[j].Pos || edits[i].End < edits[j].End
+		// Some edits are purely insertion. They should be prioritised.
+	})
+
+	beforeBytes, err := os.ReadFile(f.Name())
+	if err != nil {
+		return "", err
+	}
+	before := string(beforeBytes)
+
+	after := applyEdits(f, edits, before)
+	// The epoch timestamp is assumed to represent file creation/deletion events
+	// by some tools, so use a dummy timestamp that is one ns past the epoch.
+	// See https://github.com/bazelbuild/bazel-gazelle/issues/1528.
+	date := "1970-01-01 00:00:00.000000001 +0000"
+	diff := difflib.UnifiedDiff{
+		Context:  3,
+		FromDate: date,
+		ToDate:   date,
+		FromFile: f.Name(),
+		ToFile:   f.Name(),
+		A: 	      difflib.SplitLines(before),
+		B: 	      difflib.SplitLines(after),
+	}
+
+	return difflib.GetUnifiedDiffString(diff)
+}
+
+func applyEdits(f *token.File, edits []analysis.TextEdit, before string) string {
+	var b strings.Builder
+	var currentOffset int
+	for _, edit := range edits {
+		off := f.Offset(edit.Pos)
+		b.WriteString(before[currentOffset:off])
+		if len(edit.NewText) > 0 {
+			b.Write(edit.NewText)
+		}
+
+		end := off
+		if edit.End.IsValid() {
+			// The end pos for text edits may be token.NoPos to represent pure
+			// insertion.
+			end = f.Offset(edit.End)
+		}
+		currentOffset = end
+	}
+	b.WriteString(before[currentOffset:])
+	return b.String()
+}
+
 // config determines which source files an analyzer will emit diagnostics for.
 // config values are generated in another file that is compiled with
 // nogo_main.go by the nogo rule.
@@ -578,7 +639,7 @@
 	factMap      map[string]string         // map import path in source code to file containing serialized facts
 }
 
-func newImporter(importMap, packageFile map[string]string, factMap map[string]string) *importer {
+func newImporter(importMap, packageFile, factMap map[string]string) *importer {
 	return &importer{
 		fset:         token.NewFileSet(),
 		importMap:    importMap,
diff --git a/tests/bcr/BUILD.bazel b/tests/bcr/BUILD.bazel
index 3426c21..493e3d0 100644
--- a/tests/bcr/BUILD.bazel
+++ b/tests/bcr/BUILD.bazel
@@ -12,6 +12,7 @@
     name = "my_nogo",
     visibility = ["//visibility:public"],
     deps = TOOLS_NOGO,
+    debug = True,
 )
 
 go_library(
diff --git a/tests/bcr/go.mod b/tests/bcr/go.mod
new file mode 100644
index 0000000..cb298eb
--- /dev/null
+++ b/tests/bcr/go.mod
@@ -0,0 +1,17 @@
+module example.com
+
+go 1.22.0
+
+require github.com/shirou/gopsutil/v3 v3.24.5
+
+require (
+	github.com/go-ole/go-ole v1.2.6 // indirect
+	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
+	github.com/shoenig/go-m1cpu v0.1.6 // indirect
+	github.com/tklauser/go-sysconf v0.3.12 // indirect
+	github.com/tklauser/numcpus v0.6.1 // indirect
+	github.com/yusufpapurcu/wmi v1.2.4 // indirect
+	golang.org/x/sys v0.22.0 // indirect
+	golang.org/x/tools v0.23.0
+)
diff --git a/tests/bcr/go.sum b/tests/bcr/go.sum
new file mode 100644
index 0000000..6848a10
--- /dev/null
+++ b/tests/bcr/go.sum
@@ -0,0 +1,28 @@
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
+github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
+github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
+github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
+github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
+golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tests/bcr/main.go b/tests/bcr/main.go
index 46c058e..73868bc 100644
--- a/tests/bcr/main.go
+++ b/tests/bcr/main.go
@@ -2,10 +2,25 @@
 
 import (
 	"fmt"
+	"log"
 
 	"example.com/lib"
 )
 
+type basicStruct struct {
+	foo int
+}
+
+var _ = basicStruct{}
+
 func main() {
-	fmt.Printf("Hello %s!", lib.Name())
+	if main != nil {
+		fmt.Printf("Hello %s!", lib.Name())
+	}
+	_ = !(true && false)
+	maps := make(map[string]string)
+	for k, _ := range maps {
+		log.Println(k)
+	}
+	maps = maps
 }