package tests import ( "bytes" "fmt" "strings" "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/span" ) // DiffDiagnostics prints the diff between expected and actual diagnostics test // results. func DiffDiagnostics(uri span.URI, want, got []source.Diagnostic) string { source.SortDiagnostics(want) source.SortDiagnostics(got) if len(got) != len(want) { return summarizeDiagnostics(-1, uri, want, got, "different lengths got %v want %v", len(got), len(want)) } for i, w := range want { g := got[i] if w.Message != g.Message { return summarizeDiagnostics(i, uri, want, got, "incorrect Message got %v want %v", g.Message, w.Message) } if w.Severity != g.Severity { return summarizeDiagnostics(i, uri, want, got, "incorrect Severity got %v want %v", g.Severity, w.Severity) } if w.Source != g.Source { return summarizeDiagnostics(i, uri, want, got, "incorrect Source got %v want %v", g.Source, w.Source) } // Don't check the range on the badimport test. if strings.Contains(uri.Filename(), "badimport") { continue } if protocol.ComparePosition(w.Range.Start, g.Range.Start) != 0 { return summarizeDiagnostics(i, uri, want, got, "incorrect Start got %v want %v", g.Range.Start, w.Range.Start) } if !protocol.IsPoint(g.Range) { // Accept any 'want' range if the diagnostic returns a zero-length range. if protocol.ComparePosition(w.Range.End, g.Range.End) != 0 { return summarizeDiagnostics(i, uri, want, got, "incorrect End got %v want %v", g.Range.End, w.Range.End) } } } return "" } func summarizeDiagnostics(i int, uri span.URI, want []source.Diagnostic, got []source.Diagnostic, reason string, args ...interface{}) string { msg := &bytes.Buffer{} fmt.Fprint(msg, "diagnostics failed") if i >= 0 { fmt.Fprintf(msg, " at %d", i) } fmt.Fprint(msg, " because of ") fmt.Fprintf(msg, reason, args...) fmt.Fprint(msg, ":\nexpected:\n") for _, d := range want { fmt.Fprintf(msg, " %s:%v: %s\n", uri, d.Range, d.Message) } fmt.Fprintf(msg, "got:\n") for _, d := range got { fmt.Fprintf(msg, " %s:%v: %s\n", uri, d.Range, d.Message) } return msg.String() }