@@ -19,13 +19,16 @@ import (
19
19
errors "golang.org/x/xerrors"
20
20
)
21
21
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
+ )
29
32
30
33
const (
31
34
FillStruct = "fill_struct"
@@ -37,11 +40,22 @@ const (
37
40
38
41
// suggestedFixes maps a suggested fix command id to its handler.
39
42
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
+ }
45
59
}
46
60
47
61
func SuggestedFixFromCommand (cmd protocol.Command , kind protocol.CodeActionKind ) SuggestedFix {
@@ -59,55 +73,66 @@ func ApplyFix(ctx context.Context, fix string, snapshot Snapshot, fh VersionedFi
59
73
if ! ok {
60
74
return nil , fmt .Errorf ("no suggested fix function for %s" , fix )
61
75
}
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 )
67
77
if err != nil {
68
78
return nil , err
69
79
}
70
80
if suggestion == nil {
71
81
return nil , nil
72
82
}
73
-
74
- var edits [] protocol.TextEdit
83
+ fset := snapshot . FileSet ()
84
+ editsPerFile := map [span. URI ] * protocol.TextDocumentEdit {}
75
85
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 ()
78
87
if err != nil {
79
88
return nil , err
80
89
}
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 )
82
107
if err != nil {
83
108
return nil , err
84
109
}
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 ,
87
116
NewText : string (edit .NewText ),
88
117
})
89
118
}
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
99
124
}
100
125
101
126
// getAllSuggestedFixInputs is a helper function to collect all possible needed
102
127
// 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 ) {
104
129
pkg , pgf , err := GetParsedFile (ctx , snapshot , fh , NarrowestPackage )
105
130
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 )
107
132
}
108
133
rng , err := pgf .Mapper .RangeToSpanRange (pRng )
109
134
if err != nil {
110
- return nil , span.Range {}, nil , nil , nil , nil , nil , err
135
+ return nil , span.Range {}, nil , nil , nil , nil , err
111
136
}
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
113
138
}
0 commit comments