Skip to content

Commit 5c69b51

Browse files
author
Nishanth Shanmugham
committed
also suggest fix if default case exists
1 parent b86543f commit 5c69b51

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

exhaustive.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,8 @@
5656
//
5757
// Fixes
5858
//
59-
// The analyzer suggests fixes for a switch statement if it is not exhaustive
60-
// and does not have a 'default' case. The suggested fix always adds a single
61-
// case clause for the missing enum members.
59+
// The analyzer suggests fixes for a switch statement if it is not exhaustive.
60+
// The suggested fix always adds a single case clause for the missing enum members.
6261
//
6362
// case MissingA, MissingB, MissingC:
6463
// panic(fmt.Sprintf("unhandled value: %v", v))

switch.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,11 @@ func checkSwitchStatements_(
123123
return true
124124
}
125125

126-
defaultCaseExists := false
126+
var defaultCase *ast.CaseClause
127127
for _, stmt := range sw.Body.List {
128128
caseCl := stmt.(*ast.CaseClause)
129129
if isDefaultCase(caseCl) {
130-
defaultCaseExists = true
130+
defaultCase = caseCl
131131
continue // nothing more to do if it's the default case
132132
}
133133
for _, e := range caseCl.List {
@@ -158,11 +158,11 @@ func checkSwitchStatements_(
158158
}
159159
}
160160

161-
defaultSuffices := fDefaultSignifiesExhaustive && defaultCaseExists
161+
defaultSuffices := fDefaultSignifiesExhaustive && defaultCase != nil
162162
shouldReport := len(hitlist) > 0 && !defaultSuffices
163163

164164
if shouldReport {
165-
reportSwitch(pass, sw, samePkg, tagType, em, hitlist, defaultCaseExists, file)
165+
reportSwitch(pass, sw, defaultCase, samePkg, tagType, em, hitlist, file)
166166
}
167167
return true
168168
})
@@ -237,20 +237,18 @@ func determineMissingOutput(missingMembers map[string]struct{}, em *enumMembers)
237237
func reportSwitch(
238238
pass *analysis.Pass,
239239
sw *ast.SwitchStmt,
240+
defaultCase *ast.CaseClause,
240241
samePkg bool,
241242
enumType *types.Named,
242243
em *enumMembers,
243244
missingMembers map[string]struct{},
244-
defaultCaseExists bool,
245245
f *ast.File,
246246
) {
247247
missingOutput := determineMissingOutput(missingMembers, em)
248248

249249
var fixes []analysis.SuggestedFix
250-
if !defaultCaseExists {
251-
if fix, ok := computeFix(pass, pass.Fset, f, sw, enumType, samePkg, missingMembers); ok {
252-
fixes = append(fixes, fix)
253-
}
250+
if fix, ok := computeFix(pass, pass.Fset, f, sw, defaultCase, enumType, samePkg, missingMembers); ok {
251+
fixes = append(fixes, fix)
254252
}
255253

256254
pass.Report(analysis.Diagnostic{
@@ -261,7 +259,7 @@ func reportSwitch(
261259
})
262260
}
263261

264-
func computeFix(pass *analysis.Pass, fset *token.FileSet, f *ast.File, sw *ast.SwitchStmt, enumType *types.Named, samePkg bool, missingMembers map[string]struct{}) (analysis.SuggestedFix, bool) {
262+
func computeFix(pass *analysis.Pass, fset *token.FileSet, f *ast.File, sw *ast.SwitchStmt, defaultCase *ast.CaseClause, enumType *types.Named, samePkg bool, missingMembers map[string]struct{}) (analysis.SuggestedFix, bool) {
265263
// Function and method calls may be mutative, so we don't want to reuse the
266264
// call expression in the about-to-be-inserted case clause body. So we just
267265
// don't suggest a fix in such situations.
@@ -275,7 +273,7 @@ func computeFix(pass *analysis.Pass, fset *token.FileSet, f *ast.File, sw *ast.S
275273
return analysis.SuggestedFix{}, false
276274
}
277275

278-
textEdits := []analysis.TextEdit{missingCasesTextEdit(fset, f, samePkg, sw, enumType, missingMembers)}
276+
textEdits := []analysis.TextEdit{missingCasesTextEdit(fset, f, samePkg, sw, defaultCase, enumType, missingMembers)}
279277

280278
// need to add "fmt" import if "fmt" import doesn't already exist
281279
if !hasImportWithPath(fset, f, `"fmt"`) {
@@ -396,7 +394,7 @@ func fmtImportTextEdit(fset *token.FileSet, f *ast.File) analysis.TextEdit {
396394
}
397395
}
398396

399-
func missingCasesTextEdit(fset *token.FileSet, f *ast.File, samePkg bool, sw *ast.SwitchStmt, enumType *types.Named, missingMembers map[string]struct{}) analysis.TextEdit {
397+
func missingCasesTextEdit(fset *token.FileSet, f *ast.File, samePkg bool, sw *ast.SwitchStmt, defaultCase *ast.CaseClause, enumType *types.Named, missingMembers map[string]struct{}) analysis.TextEdit {
400398
// ... Construct insertion text for case clause and its body ...
401399

402400
var tag bytes.Buffer
@@ -443,9 +441,14 @@ func missingCasesTextEdit(fset *token.FileSet, f *ast.File, samePkg bool, sw *as
443441

444442
// ... Create the text edit ...
445443

444+
pos := sw.Body.Rbrace - 1 // put it as last case
445+
if defaultCase != nil {
446+
pos = defaultCase.Case - 2 // put it before the default case (why -2?)
447+
}
448+
446449
return analysis.TextEdit{
447-
Pos: sw.Body.Rbrace - 1,
448-
End: sw.Body.Rbrace - 1,
450+
Pos: pos,
451+
End: pos,
449452
NewText: []byte(insert),
450453
}
451454
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package switchfix
22

3+
import (
4+
"fmt"
5+
)
6+
37
func _caseclause_defaultexists() {
48
var d Direction
59
switch d { // want "missing cases in switch of type Direction: E, directionInvalid"
610
case N:
711
case S:
812
case W:
13+
case E, directionInvalid:
14+
panic(fmt.Sprintf("unhandled value: %v", d))
915
default:
1016
}
1117
}

0 commit comments

Comments
 (0)