Skip to content

Commit 18628d1

Browse files
committed
internal/lsp: error handling
1 parent 8dcb7bc commit 18628d1

13 files changed

+218
-75
lines changed

internal/lsp/cache/file.go

+24-19
Original file line numberDiff line numberDiff line change
@@ -25,63 +25,68 @@ type File struct {
2525
}
2626

2727
// GetContent returns the contents of the file, reading it from file system if needed.
28-
func (f *File) GetContent() []byte {
28+
func (f *File) GetContent() ([]byte, error) {
2929
f.view.mu.Lock()
3030
defer f.view.mu.Unlock()
31-
f.read()
32-
return f.content
31+
if f.content != nil {
32+
return f.content, nil
33+
}
34+
content, err := f.read()
35+
if err != nil {
36+
return nil, err
37+
}
38+
f.content = content
39+
return f.content, nil
3340
}
3441

3542
func (f *File) GetFileSet() *token.FileSet {
3643
return f.view.Config.Fset
3744
}
3845

39-
func (f *File) GetToken() *token.File {
46+
func (f *File) GetToken() (*token.File, error) {
4047
f.view.mu.Lock()
4148
defer f.view.mu.Unlock()
4249
if f.token == nil {
4350
if err := f.view.parse(f.URI); err != nil {
44-
return nil
51+
return nil, err
4552
}
4653
}
47-
return f.token
54+
return f.token, nil
4855
}
4956

50-
func (f *File) GetAST() *ast.File {
57+
func (f *File) GetAST() (*ast.File, error) {
5158
f.view.mu.Lock()
5259
defer f.view.mu.Unlock()
5360
if f.ast == nil {
5461
if err := f.view.parse(f.URI); err != nil {
55-
return nil
62+
return nil, err
5663
}
5764
}
58-
return f.ast
65+
return f.ast, nil
5966
}
6067

61-
func (f *File) GetPackage() *packages.Package {
68+
func (f *File) GetPackage() (*packages.Package, error) {
6269
f.view.mu.Lock()
6370
defer f.view.mu.Unlock()
6471
if f.pkg == nil {
6572
if err := f.view.parse(f.URI); err != nil {
66-
return nil
73+
return nil, err
6774
}
6875
}
69-
return f.pkg
76+
return f.pkg, nil
7077
}
7178

7279
// read is the internal part of Read that presumes the lock is already held
73-
func (f *File) read() {
74-
if f.content != nil {
75-
return
76-
}
80+
func (f *File) read() ([]byte, error) {
7781
// we don't know the content yet, so read it
7882
filename, err := f.URI.Filename()
7983
if err != nil {
80-
return
84+
return nil, err
8185
}
8286
content, err := ioutil.ReadFile(filename)
8387
if err != nil {
84-
return
88+
return nil, err
8589
}
86-
f.content = content
90+
// f.content = content
91+
return content, nil
8792
}

internal/lsp/cmd/definition.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ func (d *definition) Run(ctx context.Context, args ...string) error {
6565
if err != nil {
6666
return err
6767
}
68-
tok := f.GetToken()
68+
tok, err := f.GetToken()
69+
if err != nil {
70+
return err
71+
}
6972
pos := tok.Pos(from.Start.Offset)
7073
ident, err := source.Identifier(ctx, view, f, pos)
7174
if err != nil {
@@ -115,7 +118,10 @@ func buildDefinition(view source.View, ident *source.IdentifierInfo) (*Definitio
115118

116119
func buildGuruDefinition(view source.View, ident *source.IdentifierInfo) (*guru.Definition, error) {
117120
loc := newLocation(view.FileSet(), ident.Declaration.Range)
118-
pkg := ident.File.GetPackage()
121+
pkg, err := ident.File.GetPackage()
122+
if err != nil {
123+
return nil, err
124+
}
119125
// guru does not support ranges
120126
loc.End = loc.Start
121127
// Behavior that attempts to match the expected output for guru. For an example

internal/lsp/format.go

+22-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package lsp
22

33
import (
44
"context"
5+
"errors"
56

67
"golang.org/x/tools/internal/lsp/protocol"
78
"golang.org/x/tools/internal/lsp/source"
@@ -17,7 +18,10 @@ func formatRange(ctx context.Context, v source.View, uri protocol.DocumentURI, r
1718
if err != nil {
1819
return nil, err
1920
}
20-
tok := f.GetToken()
21+
tok, err := f.GetToken()
22+
if err != nil {
23+
return nil, err
24+
}
2125
var r source.Range
2226
if rng == nil {
2327
r.Start = tok.Pos(0)
@@ -29,15 +33,26 @@ func formatRange(ctx context.Context, v source.View, uri protocol.DocumentURI, r
2933
if err != nil {
3034
return nil, err
3135
}
32-
return toProtocolEdits(f, edits), nil
36+
37+
protocolEdits, err := toProtocolEdits(f, edits)
38+
if err != nil {
39+
return nil, err
40+
}
41+
return protocolEdits, nil
3342
}
3443

35-
func toProtocolEdits(f source.File, edits []source.TextEdit) []protocol.TextEdit {
44+
func toProtocolEdits(f source.File, edits []source.TextEdit) ([]protocol.TextEdit, error) {
3645
if edits == nil {
37-
return nil
46+
return nil, errors.New("toProtocolEdits, edits == nil")
47+
}
48+
tok, err := f.GetToken()
49+
if err != nil {
50+
return nil, err
51+
}
52+
content, err := f.GetContent()
53+
if err != nil {
54+
return nil, err
3855
}
39-
tok := f.GetToken()
40-
content := f.GetContent()
4156
// When a file ends with an empty line, the newline character is counted
4257
// as part of the previous line. This causes the formatter to insert
4358
// another unnecessary newline on each formatting. We handle this case by
@@ -56,5 +71,5 @@ func toProtocolEdits(f source.File, edits []source.TextEdit) []protocol.TextEdit
5671
NewText: edit.NewText,
5772
}
5873
}
59-
return result
74+
return result, nil
6075
}

internal/lsp/imports.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ func organizeImports(ctx context.Context, v source.View, uri protocol.DocumentUR
2020
if err != nil {
2121
return nil, err
2222
}
23-
tok := f.GetToken()
23+
tok, err := f.GetToken()
24+
if err != nil {
25+
return nil, err
26+
}
2427
r := source.Range{
2528
Start: tok.Pos(0),
2629
End: tok.Pos(tok.Size()),
@@ -29,5 +32,9 @@ func organizeImports(ctx context.Context, v source.View, uri protocol.DocumentUR
2932
if err != nil {
3033
return nil, err
3134
}
32-
return toProtocolEdits(f, edits), nil
35+
protocolEdits, err := toProtocolEdits(f, edits)
36+
if err != nil {
37+
return nil, err
38+
}
39+
return protocolEdits, nil
3340
}

internal/lsp/lsp_test.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,11 @@ func (f formats) test(t *testing.T, s *server) {
396396
})
397397
}
398398
}
399-
split := strings.SplitAfter(string(f.GetContent()), "\n")
399+
contents, err := f.GetContent()
400+
if err != nil {
401+
t.Error(err)
402+
}
403+
split := strings.SplitAfter(string(contents), "\n")
400404
got := strings.Join(diff.ApplyEdits(split, ops), "")
401405
if gofmted != got {
402406
t.Errorf("format failed for %s: expected '%v', got '%v'", filename, gofmted, got)
@@ -440,6 +444,11 @@ func (d definitions) test(t *testing.T, s *server, typ bool) {
440444
}
441445

442446
func (d definitions) collect(fset *token.FileSet, src, target packagestest.Range) {
443-
loc := toProtocolLocation(fset, source.Range(src))
444-
d[loc] = toProtocolLocation(fset, source.Range(target))
447+
srcLocation, err := toProtocolLocation(fset, source.Range(src))
448+
if err == nil {
449+
targetLocation, err := toProtocolLocation(fset, source.Range(target))
450+
if err == nil {
451+
d[*srcLocation] = *targetLocation
452+
}
453+
}
445454
}

internal/lsp/position.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package lsp
66

77
import (
88
"context"
9+
"fmt"
910
"go/token"
1011
"net/url"
1112

@@ -36,18 +37,24 @@ func fromProtocolLocation(ctx context.Context, v *cache.View, loc protocol.Locat
3637
if err != nil {
3738
return source.Range{}, err
3839
}
39-
tok := f.GetToken()
40+
tok, err := f.GetToken()
41+
if err != nil {
42+
return source.Range{}, err
43+
}
4044
return fromProtocolRange(tok, loc.Range), nil
4145
}
4246

4347
// toProtocolLocation converts from a source range back to a protocol location.
44-
func toProtocolLocation(fset *token.FileSet, r source.Range) protocol.Location {
48+
func toProtocolLocation(fset *token.FileSet, r source.Range) (*protocol.Location, error) {
4549
tok := fset.File(r.Start)
50+
if tok == nil {
51+
return nil, fmt.Errorf("cannot get File for position=%+v", r.Start)
52+
}
4653
uri := source.ToURI(tok.Name())
47-
return protocol.Location{
54+
return &protocol.Location{
4855
URI: protocol.DocumentURI(uri),
4956
Range: toProtocolRange(tok, r),
50-
}
57+
}, nil
5158
}
5259

5360
// fromProtocolRange converts a protocol range to a source range.

internal/lsp/server.go

+41-11
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ func (s *server) Initialize(ctx context.Context, params *protocol.InitializePara
7979
}
8080
s.initialized = true // mark server as initialized now
8181

82+
if params.Trace != "verbose" {
83+
params.Trace = "verbose"
84+
}
85+
8286
// Check if the client supports snippets in completion items.
8387
s.snippetsSupported = params.Capabilities.TextDocument.Completion.CompletionItem.SnippetSupport
8488
s.signatureHelpEnabled = true
@@ -108,7 +112,7 @@ func (s *server) Initialize(ctx context.Context, params *protocol.InitializePara
108112
Tests: true,
109113
})
110114

111-
return &protocol.InitializeResult{
115+
initializeResult := &protocol.InitializeResult{
112116
Capabilities: protocol.ServerCapabilities{
113117
CodeActionProvider: true,
114118
CompletionProvider: protocol.CompletionOptions{
@@ -127,7 +131,9 @@ func (s *server) Initialize(ctx context.Context, params *protocol.InitializePara
127131
},
128132
TypeDefinitionProvider: true,
129133
},
130-
}, nil
134+
}
135+
136+
return initializeResult, nil
131137
}
132138

133139
func (s *server) Initialized(context.Context, *protocol.InitializedParams) error {
@@ -220,7 +226,10 @@ func (s *server) Completion(ctx context.Context, params *protocol.CompletionPara
220226
if err != nil {
221227
return nil, err
222228
}
223-
tok := f.GetToken()
229+
tok, err := f.GetToken()
230+
if err != nil {
231+
return nil, err
232+
}
224233
pos := fromProtocolPosition(tok, params.Position)
225234
items, prefix, err := source.Completion(ctx, f, pos)
226235
if err != nil {
@@ -245,7 +254,10 @@ func (s *server) Hover(ctx context.Context, params *protocol.TextDocumentPositio
245254
if err != nil {
246255
return nil, err
247256
}
248-
tok := f.GetToken()
257+
tok, err := f.GetToken()
258+
if err != nil {
259+
return nil, err
260+
}
249261
pos := fromProtocolPosition(tok, params.Position)
250262
ident, err := source.Identifier(ctx, s.view, f, pos)
251263
if err != nil {
@@ -256,13 +268,14 @@ func (s *server) Hover(ctx context.Context, params *protocol.TextDocumentPositio
256268
return nil, err
257269
}
258270
markdown := "```go\n" + content + "\n```"
259-
return &protocol.Hover{
271+
hover := &protocol.Hover{
260272
Contents: protocol.MarkupContent{
261273
Kind: protocol.Markdown,
262274
Value: markdown,
263275
},
264276
Range: toProtocolRange(tok, ident.Range),
265-
}, nil
277+
}
278+
return hover, nil
266279
}
267280

268281
func (s *server) SignatureHelp(ctx context.Context, params *protocol.TextDocumentPositionParams) (*protocol.SignatureHelp, error) {
@@ -274,7 +287,10 @@ func (s *server) SignatureHelp(ctx context.Context, params *protocol.TextDocumen
274287
if err != nil {
275288
return nil, err
276289
}
277-
tok := f.GetToken()
290+
tok, err := f.GetToken()
291+
if err != nil {
292+
return nil, err
293+
}
278294
pos := fromProtocolPosition(tok, params.Position)
279295
info, err := source.SignatureHelp(ctx, f, pos)
280296
if err != nil {
@@ -292,13 +308,20 @@ func (s *server) Definition(ctx context.Context, params *protocol.TextDocumentPo
292308
if err != nil {
293309
return nil, err
294310
}
295-
tok := f.GetToken()
311+
tok, err := f.GetToken()
312+
if err != nil {
313+
return nil, err
314+
}
296315
pos := fromProtocolPosition(tok, params.Position)
297316
ident, err := source.Identifier(ctx, s.view, f, pos)
298317
if err != nil {
299318
return nil, err
300319
}
301-
return []protocol.Location{toProtocolLocation(s.view.FileSet(), ident.Declaration.Range)}, nil
320+
protocolLocation, err := toProtocolLocation(s.view.FileSet(), ident.Declaration.Range)
321+
if err != nil {
322+
return nil, err
323+
}
324+
return []protocol.Location{*protocolLocation}, nil
302325
}
303326

304327
func (s *server) TypeDefinition(ctx context.Context, params *protocol.TextDocumentPositionParams) ([]protocol.Location, error) {
@@ -310,13 +333,20 @@ func (s *server) TypeDefinition(ctx context.Context, params *protocol.TextDocume
310333
if err != nil {
311334
return nil, err
312335
}
313-
tok := f.GetToken()
336+
tok, err := f.GetToken()
337+
if err != nil {
338+
return nil, err
339+
}
314340
pos := fromProtocolPosition(tok, params.Position)
315341
ident, err := source.Identifier(ctx, s.view, f, pos)
316342
if err != nil {
317343
return nil, err
318344
}
319-
return []protocol.Location{toProtocolLocation(s.view.FileSet(), ident.Type.Range)}, nil
345+
protocolLocation, err := toProtocolLocation(s.view.FileSet(), ident.Type.Range)
346+
if err != nil {
347+
return nil, err
348+
}
349+
return []protocol.Location{*protocolLocation}, nil
320350
}
321351

322352
func (s *server) Implementation(context.Context, *protocol.TextDocumentPositionParams) ([]protocol.Location, error) {

0 commit comments

Comments
 (0)