Skip to content

Commit 1e56d3e

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

File tree

14 files changed

+222
-76
lines changed

14 files changed

+222
-76
lines changed

internal/lsp/cache/file.go

Lines changed: 24 additions & 19 deletions
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/cache/view.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ func (v *View) FileSet() *token.FileSet {
4646
}
4747

4848
func (v *View) GetAnalysisCache() *source.AnalysisCache {
49+
v.mu.Lock()
50+
defer v.mu.Unlock()
51+
4952
if v.analysisCache == nil {
5053
v.analysisCache = source.NewAnalysisCache()
5154
}
@@ -91,8 +94,8 @@ func (v *View) SetContent(ctx context.Context, uri source.URI, content []byte) (
9194
// adds the file to the managed set if needed.
9295
func (v *View) GetFile(ctx context.Context, uri source.URI) (source.File, error) {
9396
v.mu.Lock()
97+
defer v.mu.Unlock()
9498
f := v.getFile(uri)
95-
v.mu.Unlock()
9699
return f, nil
97100
}
98101

internal/lsp/cmd/definition.go

Lines changed: 8 additions & 2 deletions
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

Lines changed: 22 additions & 7 deletions
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

Lines changed: 9 additions & 2 deletions
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

Lines changed: 12 additions & 3 deletions
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

Lines changed: 11 additions & 4 deletions
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.

0 commit comments

Comments
 (0)