1 | # Suggested Fixes in the Analysis Framework |
---|---|
2 | |
3 | ## The Purpose of Suggested Fixes |
4 | |
5 | The analysis framework is planned to add a facility to output |
6 | suggested fixes. Suggested fixes in the analysis framework |
7 | are meant to address two common use cases. The first is the |
8 | natural use case of allowing the user to quickly fix errors or issues |
9 | pointed out by analyzers through their editor or analysis tool. |
10 | An editor, when showing a diagnostic for an issue, can propose |
11 | code to fix that issue. Users can accept the proposal and have |
12 | the editor apply the fix for them. The second case is to allow |
13 | for defining refactorings. An analyzer meant to perform a |
14 | refactoring can produce suggested fixes equivalent to the diff |
15 | of the refactoring. Then, an analysis driver meant to apply |
16 | refactorings can automatically apply all the diffs that |
17 | are produced by the analysis as suggested fixes. |
18 | |
19 | ## Proposed Suggested Fix API |
20 | |
21 | Suggested fixes will be defined using the following structs: |
22 | |
23 | ```go |
24 | // A SuggestedFix is a code change associated with a Diagnostic that a user can choose |
25 | // to apply to their code. Usually the SuggestedFix is meant to fix the issue flagged |
26 | // by the diagnostic. |
27 | type SuggestedFix struct { |
28 | // A description for this suggested fix to be shown to a user deciding |
29 | // whether to accept it. |
30 | Message string |
31 | TextEdits []TextEdit |
32 | } |
33 | |
34 | // A TextEdit represents the replacement of the code between Pos and End with the new text. |
35 | type TextEdit struct { |
36 | // For a pure insertion, End can either be set to Pos or token.NoPos. |
37 | Pos token.Pos |
38 | End token.Pos |
39 | NewText []byte |
40 | } |
41 | ``` |
42 | |
43 | A suggested fix needs a message field so it can specify what it will do. |
44 | Some analyses may not have clear cut fixes, and a suggested fix may need |
45 | to provide additional information to help users specify whether they |
46 | should be added. |
47 | |
48 | Suggested fixes are allowed to make multiple |
49 | edits in a file, because some logical changes may affect otherwise |
50 | unrelated parts of the AST. |
51 | |
52 | A TextEdit specifies a Pos and End: these will usually be the Pos |
53 | and End of an AST node that will be replaced. |
54 | |
55 | Finally, the replacements themselves are represented as []bytes. |
56 | |
57 | |
58 | Suggested fixes themselves will be added as a field in the |
59 | Diagnostic struct: |
60 | |
61 | ```go |
62 | |
63 | type Diagnostic struct { |
64 | ... |
65 | SuggestedFixes []SuggestedFix // this is an optional field |
66 | } |
67 | |
68 | ``` |
69 | |
70 | ### Requirements for SuggestedFixes |
71 | |
72 | SuggestedFixes will be required to conform to several requirements: |
73 | |
74 | * TextEdits for a SuggestedFix should not overlap. |
75 | * TextEdits for SuggestedFixes should not contain edits for other packages. |
76 | * Each TextEdit should apply to a single file. |
77 | |
78 | These requirements guarantee that suggested fixes can be cleanly applied. |
79 | Because a driver may only analyze, or be able to modify, the current package, |
80 | we restrict edits to the current package. In general this restriction should |
81 | not be a big problem for users because other packages might not belong to the |
82 | same module and so will not be safe to modify in a singe change. |
83 | |
84 | On the other hand, analyzers will not be required to produce gofmt-compliant |
85 | code. Analysis drivers will be expected to apply gofmt to the results of |
86 | a SuggestedFix application. |
87 | |
88 | ## SuggestedFix integration points |
89 | |
90 | ### ```checker -fix``` |
91 | |
92 | Singlechecker and multichecker have the ```-fix``` flag, which will automatically |
93 | apply all fixes suggested by their analysis or analyses. This is intended to |
94 | be used primarily by refactoring tools, because in general, like diagnostics, |
95 | suggested fixes will need to be examined by a human who can decide whether |
96 | they are relevant. |
97 | |
98 | ### gopls |
99 | |
100 | Suggested fixes have been integrated into ```gopls```, and editors can choose |
101 | to display the suggested fixes to the user as they type, so that they can be |
102 | accepted to fix diagnostics immediately. |
103 | |
104 | ### Code Review Tools (Future Work) |
105 | |
106 | Suggested fixes can be integrated into programs that are integrated with |
107 | code review systems to suggest fixes that users can apply from their code review tools. |
108 | |
109 | ## Alternatives |
110 | |
111 | ### Performing transformations directly on the AST |
112 | |
113 | Even though it may be more convenient |
114 | for authors of refactorings to perform transformations directly on |
115 | the AST, allowing mutations on the AST would mean that a copy of the AST |
116 | would need to be made every time a transformation was produced, to avoid |
117 | having transformations interfere with each other. |
118 | |
119 | This is primarily an issue with the current design of the Go AST and |
120 | it's possible that a new future version of the AST might make this a more |
121 | viable option. |
122 | |
123 | ### Supplying AST nodes directly |
124 | |
125 | Another possibility would be for SuggestedFixes to supply the replacement |
126 | ASTs directly. There is one primary limitation to this: that because |
127 | comments to ASTs specify their location using token.Pos values, it's very |
128 | difficult to place any comments in the right place. |
129 | |
130 | In general, it's also more difficult to generate the AST structures for |
131 | some code than to generate the text for that code. So we prefer to allow |
132 | the flexibility to do the latter. |
133 | |
134 | Because users can call ```format.Node``` to produce the text for any |
135 | AST node, users will always be able to produce a SuggestedFix from AST |
136 | nodes. In future, we may choose to add a convenience method that does this for users. |
137 |
Members