diff --git a/switch.go b/switch.go index dcf3b6d..5e81bc6 100644 --- a/switch.go +++ b/switch.go @@ -5,7 +5,6 @@ import ( "go/ast" "go/types" "regexp" - "sort" "strings" "golang.org/x/tools/go/analysis" @@ -262,19 +261,30 @@ func analyzeCaseClauseExpr(e ast.Expr, info *types.Info, found func(val constant // diagnosticMissingMembers constructs the list of missing enum members, // suitable for use in a reported diagnostic message. +// Order is the same as in enumMembers.Names. func diagnosticMissingMembers(missingMembers map[string]struct{}, em enumMembers) []string { - missingByConstVal := make(map[constantValue][]string) // missing members, keyed by constant value. - for m := range missingMembers { - val := em.NameToValue[m] - missingByConstVal[val] = append(missingByConstVal[val], m) + missingNamesGroupedByValue := make([][]string, len(em.Names)) // empty groups will be filtered out later + firstIndex := make(map[constantValue]int, len(em.ValueToNames)) + for i, name := range em.Names { + value := em.NameToValue[name] + j, ok := firstIndex[value] + if !ok { + firstIndex[value] = i + j = i + } + + if _, missing := missingMembers[name]; missing { + missingNamesGroupedByValue[j] = append(missingNamesGroupedByValue[j], name) + } } - var out []string - for _, names := range missingByConstVal { - sort.Strings(names) + out := make([]string, 0, len(missingMembers)) + for _, names := range missingNamesGroupedByValue { + if len(names) == 0 { + continue + } out = append(out, strings.Join(names, "|")) } - sort.Strings(out) return out } diff --git a/switch_test.go b/switch_test.go index f2d3dbf..622bb2f 100644 --- a/switch_test.go +++ b/switch_test.go @@ -60,7 +60,7 @@ func TestDiagnosticMissingMembers(t *testing.T) { t.Run("missing some: unique or unknown values", func(t *testing.T) { got := diagnosticMissingMembers(map[string]struct{}{"Yamuna": {}, "Kaveri": {}}, em) - want := []string{"Kaveri", "Yamuna"} + want := []string{"Yamuna", "Kaveri"} if !reflect.DeepEqual(want, got) { t.Errorf("want %v, got %v", want, got) } @@ -75,7 +75,7 @@ func TestDiagnosticMissingMembers(t *testing.T) { t.Run("missing all", func(t *testing.T) { got := diagnosticMissingMembers(map[string]struct{}{"Ganga": {}, "Kaveri": {}, "Yamuna": {}, "Unspecified": {}}, em) - want := []string{"Ganga|Unspecified", "Kaveri", "Yamuna"} + want := []string{"Ganga|Unspecified", "Yamuna", "Kaveri"} if !reflect.DeepEqual(want, got) { t.Errorf("want %v, got %v", want, got) } @@ -114,7 +114,7 @@ func TestMakeDiagnostic(t *testing.T) { want := analysis.Diagnostic{ Pos: 1, End: 11, - Message: "missing cases in switch of type enumpkg.Biome: Desert, Savanna", + Message: "missing cases in switch of type enumpkg.Biome: Savanna, Desert", } if !reflect.DeepEqual(want, got) { t.Errorf("want %+v, got %+v", want, got) diff --git a/testdata/src/duplicate-enum-value/otherpkg/otherpkg.go b/testdata/src/duplicate-enum-value/otherpkg/otherpkg.go index be243f7..f60a7c8 100644 --- a/testdata/src/duplicate-enum-value/otherpkg/otherpkg.go +++ b/testdata/src/duplicate-enum-value/otherpkg/otherpkg.go @@ -37,7 +37,7 @@ func _r() { } var s d.State - switch s { // want "^missing cases in switch of type duplicateenumvalue.State: DefaultState\\|TamilNadu, Kerala$" + switch s { // want "^missing cases in switch of type duplicateenumvalue.State: TamilNadu\\|DefaultState, Kerala$" case d.Karnataka: } } diff --git a/testdata/src/general/x/general.go b/testdata/src/general/x/general.go index c398594..6455311 100644 --- a/testdata/src/general/x/general.go +++ b/testdata/src/general/x/general.go @@ -162,7 +162,7 @@ func _q() { fi, err := os.Lstat(".") fmt.Println(err) - switch fi.Mode() { // want "^missing cases in switch of type fs.FileMode: ModeDevice, ModePerm, ModeSetgid, ModeSetuid, ModeType$" + switch fi.Mode() { // want "^missing cases in switch of type fs.FileMode: ModeDevice, ModeSetuid, ModeSetgid, ModeType, ModePerm$" case os.ModeDir: case os.ModeAppend: case os.ModeExclusive: diff --git a/testdata/src/ignore-enum-member/same_value.go b/testdata/src/ignore-enum-member/same_value.go index d07b337..e66473c 100644 --- a/testdata/src/ignore-enum-member/same_value.go +++ b/testdata/src/ignore-enum-member/same_value.go @@ -13,6 +13,6 @@ const ( // The member Standard, though it has the same constant value as User, must // still be reported in the diagnostic. func _c(a Access) { - switch a { // want "^missing cases in switch of type Access: Group, Standard$" + switch a { // want "^missing cases in switch of type Access: Standard, Group$" } }