package format import ( "strings" "git.warky.dev/wdevs/pgtidy/pkg/lexer" ) // SemanticallyEqual reports whether a and b have the same non-trivia token // stream, i.e. formatting may only ever change whitespace/comment trivia and // layout — it must never add, remove, or alter a token of actual code. // Unquoted identifiers/keywords compare case-insensitively (casing is a // style choice); everything else (strings, numbers, operators, punctuation) // must match exactly. Dollar-quoted body tokens are compared recursively so // that independent body reformatting doesn't trigger a false failure. // // The CLI and LSP must call this before ever writing or emitting formatted // output: if it returns false, the formatter has a bug and the original // source must be kept, never the (corrupting) formatted output. func SemanticallyEqual(a, b string) bool { ta := significantTokens(a) tb := significantTokens(b) if len(ta) != len(tb) { return false } for i := range ta { if ta[i].Kind != tb[i].Kind { return false } switch ta[i].Kind { case lexer.Ident: if !strings.EqualFold(ta[i].Text, tb[i].Text) { return false } case lexer.DollarString: _, innerA, _, okA := splitDollarQuote(ta[i].Text) _, innerB, _, okB := splitDollarQuote(tb[i].Text) if okA != okB || (okA && !SemanticallyEqual(innerA, innerB)) { return false } default: if ta[i].Text != tb[i].Text { return false } } } return true } // significantTokens lexes src and returns its tokens excluding EOF and trivia // (whitespace/comments). func significantTokens(src string) []lexer.Token { var out []lexer.Token for _, t := range lexer.Lex(src) { if t.Kind == lexer.EOF || t.IsTrivia() { continue } out = append(out, t) } return out }