Skip to content

Commit 1a7ca93

Browse files
marwan-at-workstamblerre
authored andcommitted
internal/lsp/source: update SuggestedFixFunc to accept source.Snapshot
As part of the work for implementing method-stub code generation, this CL updates the function signature of source/command.go's SuggestedFixFunc so that a command can operate on the entire source.Snapshot to analyze and change multiple packages and their files. Updates golang/go#37537 Change-Id: I8430b2189ce7d91d37ab991f87ba368245293e56 Reviewed-on: https://go-review.googlesource.com/c/tools/+/279412 Reviewed-by: Rebecca Stambler <[email protected]> Trust: Rebecca Stambler <[email protected]> Trust: Robert Findley <[email protected]> Run-TryBot: Rebecca Stambler <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent 76d4494 commit 1a7ca93

File tree

1 file changed

+62
-37
lines changed

1 file changed

+62
-37
lines changed

internal/lsp/source/fix.go

+62-37
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ import (
1919
errors "golang.org/x/xerrors"
2020
)
2121

22-
// SuggestedFixFunc is a function used to get the suggested fixes for a given
23-
// gopls command, some of which are provided by go/analysis.Analyzers. Some of
24-
// the analyzers in internal/lsp/analysis are not efficient enough to include
25-
// suggested fixes with their diagnostics, so we have to compute them
26-
// separately. Such analyzers should provide a function with a signature of
27-
// SuggestedFixFunc.
28-
type SuggestedFixFunc func(fset *token.FileSet, rng span.Range, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error)
22+
type (
23+
// SuggestedFixFunc is a function used to get the suggested fixes for a given
24+
// gopls command, some of which are provided by go/analysis.Analyzers. Some of
25+
// the analyzers in internal/lsp/analysis are not efficient enough to include
26+
// suggested fixes with their diagnostics, so we have to compute them
27+
// separately. Such analyzers should provide a function with a signature of
28+
// SuggestedFixFunc.
29+
SuggestedFixFunc func(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, pRng protocol.Range) (*analysis.SuggestedFix, error)
30+
singleFileFixFunc func(fset *token.FileSet, rng span.Range, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error)
31+
)
2932

3033
const (
3134
FillStruct = "fill_struct"
@@ -37,11 +40,22 @@ const (
3740

3841
// suggestedFixes maps a suggested fix command id to its handler.
3942
var suggestedFixes = map[string]SuggestedFixFunc{
40-
FillStruct: fillstruct.SuggestedFix,
41-
UndeclaredName: undeclaredname.SuggestedFix,
42-
ExtractVariable: extractVariable,
43-
ExtractFunction: extractFunction,
44-
ExtractMethod: extractMethod,
43+
FillStruct: singleFile(fillstruct.SuggestedFix),
44+
UndeclaredName: singleFile(undeclaredname.SuggestedFix),
45+
ExtractVariable: singleFile(extractVariable),
46+
ExtractFunction: singleFile(extractFunction),
47+
ExtractMethod: singleFile(extractMethod),
48+
}
49+
50+
// singleFile calls analyzers that expect inputs for a single file
51+
func singleFile(sf singleFileFixFunc) SuggestedFixFunc {
52+
return func(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, pRng protocol.Range) (*analysis.SuggestedFix, error) {
53+
fset, rng, src, file, pkg, info, err := getAllSuggestedFixInputs(ctx, snapshot, fh, pRng)
54+
if err != nil {
55+
return nil, err
56+
}
57+
return sf(fset, rng, src, file, pkg, info)
58+
}
4559
}
4660

4761
func SuggestedFixFromCommand(cmd protocol.Command, kind protocol.CodeActionKind) SuggestedFix {
@@ -59,55 +73,66 @@ func ApplyFix(ctx context.Context, fix string, snapshot Snapshot, fh VersionedFi
5973
if !ok {
6074
return nil, fmt.Errorf("no suggested fix function for %s", fix)
6175
}
62-
fset, rng, src, file, m, pkg, info, err := getAllSuggestedFixInputs(ctx, snapshot, fh, pRng)
63-
if err != nil {
64-
return nil, err
65-
}
66-
suggestion, err := handler(fset, rng, src, file, pkg, info)
76+
suggestion, err := handler(ctx, snapshot, fh, pRng)
6777
if err != nil {
6878
return nil, err
6979
}
7080
if suggestion == nil {
7181
return nil, nil
7282
}
73-
74-
var edits []protocol.TextEdit
83+
fset := snapshot.FileSet()
84+
editsPerFile := map[span.URI]*protocol.TextDocumentEdit{}
7585
for _, edit := range suggestion.TextEdits {
76-
rng := span.NewRange(fset, edit.Pos, edit.End)
77-
spn, err := rng.Span()
86+
spn, err := span.NewRange(fset, edit.Pos, edit.End).Span()
7887
if err != nil {
7988
return nil, err
8089
}
81-
clRng, err := m.Range(spn)
90+
fh, err := snapshot.GetVersionedFile(ctx, spn.URI())
91+
if err != nil {
92+
return nil, err
93+
}
94+
te, ok := editsPerFile[spn.URI()]
95+
if !ok {
96+
te = &protocol.TextDocumentEdit{
97+
TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
98+
Version: fh.Version(),
99+
TextDocumentIdentifier: protocol.TextDocumentIdentifier{
100+
URI: protocol.URIFromSpanURI(fh.URI()),
101+
},
102+
},
103+
}
104+
editsPerFile[spn.URI()] = te
105+
}
106+
_, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
82107
if err != nil {
83108
return nil, err
84109
}
85-
edits = append(edits, protocol.TextEdit{
86-
Range: clRng,
110+
rng, err := pgf.Mapper.Range(spn)
111+
if err != nil {
112+
return nil, err
113+
}
114+
te.Edits = append(te.Edits, protocol.TextEdit{
115+
Range: rng,
87116
NewText: string(edit.NewText),
88117
})
89118
}
90-
return []protocol.TextDocumentEdit{{
91-
TextDocument: protocol.OptionalVersionedTextDocumentIdentifier{
92-
Version: fh.Version(),
93-
TextDocumentIdentifier: protocol.TextDocumentIdentifier{
94-
URI: protocol.URIFromSpanURI(fh.URI()),
95-
},
96-
},
97-
Edits: edits,
98-
}}, nil
119+
var edits []protocol.TextDocumentEdit
120+
for _, edit := range editsPerFile {
121+
edits = append(edits, *edit)
122+
}
123+
return edits, nil
99124
}
100125

101126
// getAllSuggestedFixInputs is a helper function to collect all possible needed
102127
// inputs for an AppliesFunc or SuggestedFixFunc.
103-
func getAllSuggestedFixInputs(ctx context.Context, snapshot Snapshot, fh FileHandle, pRng protocol.Range) (*token.FileSet, span.Range, []byte, *ast.File, *protocol.ColumnMapper, *types.Package, *types.Info, error) {
128+
func getAllSuggestedFixInputs(ctx context.Context, snapshot Snapshot, fh FileHandle, pRng protocol.Range) (*token.FileSet, span.Range, []byte, *ast.File, *types.Package, *types.Info, error) {
104129
pkg, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
105130
if err != nil {
106-
return nil, span.Range{}, nil, nil, nil, nil, nil, errors.Errorf("getting file for Identifier: %w", err)
131+
return nil, span.Range{}, nil, nil, nil, nil, errors.Errorf("getting file for Identifier: %w", err)
107132
}
108133
rng, err := pgf.Mapper.RangeToSpanRange(pRng)
109134
if err != nil {
110-
return nil, span.Range{}, nil, nil, nil, nil, nil, err
135+
return nil, span.Range{}, nil, nil, nil, nil, err
111136
}
112-
return snapshot.FileSet(), rng, pgf.Src, pgf.File, pgf.Mapper, pkg.GetTypes(), pkg.GetTypesInfo(), nil
137+
return snapshot.FileSet(), rng, pgf.Src, pgf.File, pkg.GetTypes(), pkg.GetTypesInfo(), nil
113138
}

0 commit comments

Comments
 (0)