From 092982e6eb3d9d06ae786255fab96bec88ce21ea Mon Sep 17 00:00:00 2001 From: Salman Shah Date: Sat, 9 Mar 2024 23:02:04 +0000 Subject: [PATCH 1/2] Switch statements handled in analyzer 1. checkswitch.go: Code added to handle switch statements 2. testdata.go: New test cases handled to ensure switch statements are accounted for --- tools/checkswitch/checkswitch.go | 64 ++++++++++++++++++++++++++ tools/checkswitch/testdata/testdata.go | 37 +++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/tools/checkswitch/checkswitch.go b/tools/checkswitch/checkswitch.go index ec4a1bdb28ab..42116b4f78c5 100644 --- a/tools/checkswitch/checkswitch.go +++ b/tools/checkswitch/checkswitch.go @@ -18,6 +18,7 @@ package main import ( "fmt" "go/ast" + "go/token" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/singlechecker" @@ -146,6 +147,69 @@ func run(pass *analysis.Pass) (any, error) { } } } + // Handle *ast.SwitchStmt, which represents a switch statement in Go. + case *ast.SwitchStmt: + // Declare a variable to hold the name of the case. + var name string + + // Iterate over each case in the switch statement. + for _, el := range n.Body.List { + // If a case has no expressions (i.e., it's a default case), skip to the next case. + if len(el.(*ast.CaseClause).List) < 1 { + continue + } + + // Get the first expression from the case clause. + firstTypeCase := el.(*ast.CaseClause).List[0] + + // Check if the first expression is a basic literal of type string. + switch firstTypeCase := firstTypeCase.(type) { + case *ast.BasicLit: + if firstTypeCase.Kind == token.STRING { + // If it is, assign the value of the literal to name. + name = firstTypeCase.Value + } + } + + // Check if the name is in the orderTypes map. + idxSl, ok := orderTypes[name] + if ok && (idxSl < idx) { + // If it is, and the current index is less than the previous index, + // report that the current case should go before the last case. + pass.Reportf(n.Pos(), "%s should go before %s in the switch", name, lastName) + } + + // Update the index and last name to the current index and name. + idx, lastName = idxSl, name + + // If a case has more than one expression (e.g., 'case "tag1", "tag2":'), + // check the order of each expression. + if len(el.(*ast.CaseClause).List) > 1 { + // Initialize subindex and sublastname with current index and name. + subidx, sublastName := idx, lastName + for i := 0; i < len(el.(*ast.CaseClause).List); i++ { + cs := el.(*ast.CaseClause).List[i] + switch cs := cs.(type) { + case *ast.BasicLit: + if cs.Kind == token.STRING { + // If it is, assign the value of the literal to name. + name = cs.Value + } + } + + // Check if the name is in the orderTypes map. + subidxSl, ok := orderTypes[name] + if ok && (subidxSl < subidx) { + // If it is, and the current subindex is less than the previous subindex, + // report that the current case should go before the last case. + pass.Reportf(n.Pos(), "%s should go before %s in the switch", name, sublastName) + } + + // Update the subindex and sublastname to the current subindex and name. + subidx, sublastName = subidxSl, name + } + } + } } return true diff --git a/tools/checkswitch/testdata/testdata.go b/tools/checkswitch/testdata/testdata.go index 1bee1a8a6304..9266d1138b10 100644 --- a/tools/checkswitch/testdata/testdata.go +++ b/tools/checkswitch/testdata/testdata.go @@ -57,3 +57,40 @@ func testIncorrectMultiple(v any) { case float64, int64, int32: } } + +func testCorrectOrderSwitch() { + tag := "tag1" + switch tag { + case "tag1": + case "tag2": + } +} + +func testSkipFirstOrderSwitch() { + tag := "tag1" + switch tag { + case "tag2": + case "tag1": + } +} + +func testMultipleCasesSwitch() { + tag := "tag1" + switch tag { + case "tag2", "tag3": + case "tag1": + } +} + +func testNoCasesSwitch() { + tag := "tag1" + switch tag { + } +} + +func testOneCaseSwitch() { + tag := "tag1" + switch tag { + case "tag1": + } +} \ No newline at end of file From 413d262b16973cb9b2baa70c8619cfe3ab09938e Mon Sep 17 00:00:00 2001 From: sbshah97 Date: Sat, 9 Mar 2024 23:11:42 +0000 Subject: [PATCH 2/2] go fmt changes for testdata file --- tools/checkswitch/testdata/testdata.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/checkswitch/testdata/testdata.go b/tools/checkswitch/testdata/testdata.go index 9266d1138b10..258466724407 100644 --- a/tools/checkswitch/testdata/testdata.go +++ b/tools/checkswitch/testdata/testdata.go @@ -67,11 +67,11 @@ func testCorrectOrderSwitch() { } func testSkipFirstOrderSwitch() { - tag := "tag1" - switch tag { - case "tag2": - case "tag1": - } + tag := "tag1" + switch tag { + case "tag2": + case "tag1": + } } func testMultipleCasesSwitch() { @@ -93,4 +93,4 @@ func testOneCaseSwitch() { switch tag { case "tag1": } -} \ No newline at end of file +}