| 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