golang.org/x/tools/gopls@v0.15.3/internal/cache/errors_test.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cache 6 7 import ( 8 "encoding/json" 9 "strings" 10 "testing" 11 12 "github.com/google/go-cmp/cmp" 13 "golang.org/x/tools/go/packages" 14 "golang.org/x/tools/gopls/internal/protocol" 15 ) 16 17 func TestParseErrorMessage(t *testing.T) { 18 tests := []struct { 19 name string 20 in string 21 expectedFileName string 22 expectedLine int 23 expectedColumn int 24 }{ 25 { 26 name: "from go list output", 27 in: "\nattributes.go:13:1: expected 'package', found 'type'", 28 expectedFileName: "attributes.go", 29 expectedLine: 13, 30 expectedColumn: 1, 31 }, 32 { 33 name: "windows driver letter", 34 in: "C:\\foo\\bar.go:13: message", 35 expectedFileName: "bar.go", 36 expectedLine: 13, 37 expectedColumn: 0, 38 }, 39 } 40 41 for _, tt := range tests { 42 t.Run(tt.name, func(t *testing.T) { 43 fn, line, col8 := parseGoListError(packages.Error{Msg: tt.in}, ".") 44 45 if !strings.HasSuffix(fn, tt.expectedFileName) { 46 t.Errorf("expected filename with suffix %v but got %v", tt.expectedFileName, fn) 47 } 48 if line != tt.expectedLine { 49 t.Errorf("expected line %v but got %v", tt.expectedLine, line) 50 } 51 if col8 != tt.expectedColumn { 52 t.Errorf("expected col %v but got %v", tt.expectedLine, col8) 53 } 54 }) 55 } 56 } 57 58 func TestDiagnosticEncoding(t *testing.T) { 59 diags := []*Diagnostic{ 60 {}, // empty 61 { 62 URI: "file///foo", 63 Range: protocol.Range{ 64 Start: protocol.Position{Line: 4, Character: 2}, 65 End: protocol.Position{Line: 6, Character: 7}, 66 }, 67 Severity: protocol.SeverityWarning, 68 Code: "red", 69 CodeHref: "https://go.dev", 70 Source: "test", 71 Message: "something bad happened", 72 Tags: []protocol.DiagnosticTag{81}, 73 Related: []protocol.DiagnosticRelatedInformation{ 74 { 75 Location: protocol.Location{ 76 URI: "file:///other", 77 Range: protocol.Range{ 78 Start: protocol.Position{Line: 3, Character: 6}, 79 End: protocol.Position{Line: 4, Character: 9}, 80 }, 81 }, 82 Message: "psst, over here", 83 }, 84 }, 85 86 // Fields below are used internally to generate quick fixes. They aren't 87 // part of the LSP spec and don't leave the server. 88 SuggestedFixes: []SuggestedFix{ 89 { 90 Title: "fix it!", 91 Edits: map[protocol.DocumentURI][]protocol.TextEdit{ 92 "file:///foo": {{ 93 Range: protocol.Range{ 94 Start: protocol.Position{Line: 4, Character: 2}, 95 End: protocol.Position{Line: 6, Character: 7}, 96 }, 97 NewText: "abc", 98 }}, 99 "file:///other": {{ 100 Range: protocol.Range{ 101 Start: protocol.Position{Line: 4, Character: 2}, 102 End: protocol.Position{Line: 6, Character: 7}, 103 }, 104 NewText: "!@#!", 105 }}, 106 }, 107 Command: &protocol.Command{ 108 Title: "run a command", 109 Command: "gopls.fix", 110 Arguments: []json.RawMessage{json.RawMessage(`{"a":1}`)}, 111 }, 112 ActionKind: protocol.QuickFix, 113 }, 114 }, 115 }, 116 { 117 URI: "file//bar", 118 // other fields tested above 119 }, 120 } 121 122 data := encodeDiagnostics(diags) 123 diags2 := decodeDiagnostics(data) 124 125 if diff := cmp.Diff(diags, diags2); diff != "" { 126 t.Errorf("decoded diagnostics do not match (-original +decoded):\n%s", diff) 127 } 128 }