- pkg/lsp: JSON-RPC 2.0 LSP server (formatting, diagnostics, codeAction quick-fixes) - cmd/pgtidy: lsp and config subcommands - pkg/diagnostics: TextFix struct for byte-range autofixes - pkg/lint: MIG001/MIG003 autofixes, ApplyFixes helper, --fix flag on lint command - editors/vscode: TypeScript extension with LanguageClient, showVersion/showConfig/formatDocument commands, logo - editors/datagrip: Gradle JetBrains plugin via LSP4IJ, pluginIcon - .goreleaser.yaml, .github/workflows: CI + release pipeline - Makefile: snapshot, release, vscode-compile, vscode-package targets - go.mod + all imports: module path updated to git.warky.dev/wdevs/pgtidy - assets: logo files (256px, 128px, 1024px, ico)
40 lines
979 B
Go
40 lines
979 B
Go
package lint
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"git.warky.dev/wdevs/pgtidy/pkg/diagnostics"
|
|
)
|
|
|
|
// ApplyFixes applies all autofixes from diags to src and returns the result.
|
|
// Fixes are applied in reverse-offset order so earlier edits do not shift the
|
|
// byte positions of later ones. Overlapping fixes are skipped.
|
|
func ApplyFixes(src string, diags []diagnostics.Diagnostic) string {
|
|
type fix struct {
|
|
offset, end int
|
|
new string
|
|
}
|
|
var fixes []fix
|
|
for _, d := range diags {
|
|
if d.Fix != nil {
|
|
fixes = append(fixes, fix{d.Fix.Offset, d.Fix.End, d.Fix.New})
|
|
}
|
|
}
|
|
if len(fixes) == 0 {
|
|
return src
|
|
}
|
|
sort.Slice(fixes, func(i, j int) bool {
|
|
return fixes[i].offset > fixes[j].offset
|
|
})
|
|
b := []byte(src)
|
|
last := len(b) + 1 // sentinel: no fix applied yet
|
|
for _, f := range fixes {
|
|
if f.end > last {
|
|
continue // overlaps a previously applied fix; skip
|
|
}
|
|
last = f.offset
|
|
b = append(b[:f.offset], append([]byte(f.new), b[f.end:]...)...)
|
|
}
|
|
return string(b)
|
|
}
|