Skip to content

Instantly share code, notes, and snippets.

@Merovius
Created August 20, 2019 13:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Merovius/53c774e11ad90675d6f184ccc18b4a24 to your computer and use it in GitHub Desktop.
Save Merovius/53c774e11ad90675d6f184ccc18b4a24 to your computer and use it in GitHub Desktop.
break label experiment
// Copyright 2019 Axel Wagner
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package breaklabel defines an Analyzer that checks for
// break statements that should have a label.
package breaklabel
import (
"go/ast"
"go/token"
"math/bits"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)
const Doc = `check for break statements that should have a label
A break inside a switch nested inside a loop (or vice versa) could benefit from
a label to disambiguate.`
var Analyzer = &analysis.Analyzer{
Name: "breaklabel",
Doc: Doc,
Run: run,
Requires: []*analysis.Analyzer{
inspect.Analyzer,
},
}
func run(pass *analysis.Pass) (interface{}, error) {
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
types := []ast.Node{
new(ast.BranchStmt),
}
insp.WithStack(types, func(n ast.Node, push bool, stack []ast.Node) bool {
branch := n.(*ast.BranchStmt)
if branch.Tok != token.BREAK || branch.Label != nil {
return false
}
var nestedIn uint
const (
nestFor = (1 << iota)
nestSwitch
nestSelect
)
AncestorLoop:
for i := len(stack) - 2; i >= 0; i-- {
switch stack[i].(type) {
case *ast.FuncDecl, *ast.FuncLit:
break AncestorLoop
case *ast.ForStmt, *ast.RangeStmt:
nestedIn |= nestFor
case *ast.SwitchStmt, *ast.TypeSwitchStmt:
nestedIn |= nestSwitch
case *ast.SelectStmt:
nestedIn |= nestSelect
}
}
if bits.OnesCount(nestedIn) > 1 {
pass.Reportf(branch.Pos(), "naked break could use a label")
}
return false
})
return nil, nil
}
$GOROOT/src/bytes/bytes_test.go:1554:5: naked break could use a label
$GOROOT/src/compress/flate/huffman_bit_writer.go:390:4: naked break could use a label
$GOROOT/src/compress/flate/huffman_bit_writer.go:394:4: naked break could use a label
$GOROOT/src/compress/flate/huffman_bit_writer.go:398:4: naked break could use a label
$GOROOT/src/compress/flate/huffman_code.go:76:4: naked break could use a label
$GOROOT/src/compress/flate/huffman_code.go:81:4: naked break could use a label
$GOROOT/src/compress/flate/huffman_code.go:86:4: naked break could use a label
$GOROOT/src/database/sql/example_service_test.go:107:5: naked break could use a label
$GOROOT/src/debug/elf/file.go:996:4: naked break could use a label
$GOROOT/src/debug/elf/file.go:1045:4: naked break could use a label
$GOROOT/src/debug/gosym/pclntab.go:72:5: naked break could use a label
$GOROOT/src/debug/gosym/symtab.go:251:6: naked break could use a label
$GOROOT/src/debug/gosym/symtab.go:369:5: naked break could use a label
$GOROOT/src/debug/gosym/symtab.go:386:6: naked break could use a label
$GOROOT/src/debug/plan9obj/file.go:239:6: naked break could use a label
$GOROOT/src/encoding/asn1/marshal.go:602:6: naked break could use a label
$GOROOT/src/encoding/json/decode.go:789:7: naked break could use a label
$GOROOT/src/encoding/json/decode.go:797:7: naked break could use a label
$GOROOT/src/encoding/json/decode.go:1266:7: naked break could use a label
$GOROOT/src/encoding/xml/xml.go:619:5: naked break could use a label
$GOROOT/src/encoding/xml/xml.go:681:6: naked break could use a label
$GOROOT/src/encoding/xml/xml.go:720:5: naked break could use a label
$GOROOT/src/encoding/xml/xml.go:763:7: naked break could use a label
$GOROOT/src/encoding/xml/xml.go:1927:5: naked break could use a label
$GOROOT/src/encoding/xml/xml.go:1971:5: naked break could use a label
$GOROOT/src/encoding/xml/xml_test.go:312:5: naked break could use a label
$GOROOT/src/fmt/scan.go:827:5: naked break could use a label
$GOROOT/src/fmt/scan.go:844:5: naked break could use a label
$GOROOT/src/go/build/read.go:159:5: naked break could use a label
$GOROOT/src/go/build/read.go:173:5: naked break could use a label
$GOROOT/src/go/doc/reader.go:535:6: naked break could use a label
$GOROOT/src/go/parser/error_test.go:97:5: naked break could use a label
$GOROOT/src/go/types/decl.go:655:8: naked break could use a label
$GOROOT/src/go/types/expr.go:1143:7: naked break could use a label
$GOROOT/src/go/types/expr.go:1227:9: naked break could use a label
$GOROOT/src/go/types/stdlib_test.go:125:7: naked break could use a label
$GOROOT/src/math/rand/regress_test.go:57:7: naked break could use a label
$GOROOT/src/mime/quotedprintable/reader.go:119:6: naked break could use a label
$GOROOT/src/mime/quotedprintable/reader.go:125:4: naked break could use a label
$GOROOT/src/mime/quotedprintable/reader.go:129:4: naked break could use a label
$GOROOT/src/net/interface_linux.go:82:6: naked break could use a label
$GOROOT/src/net/dnsclient_unix_test.go:496:6: naked break could use a label
$GOROOT/src/net/dnsclient_unix_test.go:515:6: naked break could use a label
$GOROOT/src/net/timeout_test.go:52:5: naked break could use a label
$GOROOT/src/net/http/cookie.go:124:6: naked break could use a label
$GOROOT/src/net/http/cookie.go:138:7: naked break could use a label
$GOROOT/src/net/http/h2_bundle.go:4391:5: naked break could use a label
$GOROOT/src/net/http/transport.go:891:4: naked break could use a label
$GOROOT/src/net/textproto/reader.go:368:5: naked break could use a label
$GOROOT/src/os/exec/exec_test.go:789:5: naked break could use a label
$GOROOT/src/path/match.go:139:6: naked break could use a label
$GOROOT/src/path/filepath/match.go:152:6: naked break could use a label
$GOROOT/src/reflect/value.go:2123:5: naked break could use a label
$GOROOT/src/reflect/value.go:2151:5: naked break could use a label
$GOROOT/src/regexp/syntax/parse.go:737:5: naked break could use a label
$GOROOT/src/regexp/syntax/parse.go:801:5: naked break could use a label
$GOROOT/src/regexp/syntax/parse.go:1277:5: naked break could use a label
$GOROOT/src/regexp/syntax/parse.go:1307:6: naked break could use a label
$GOROOT/src/regexp/syntax/parse_test.go:337:7: naked break could use a label
$GOROOT/src/runtime/mgc.go:1914:8: naked break could use a label
$GOROOT/src/runtime/proc.go:503:5: naked break could use a label
$GOROOT/src/runtime/proc.go:905:5: naked break could use a label
$GOROOT/src/strings/strings_test.go:1577:5: naked break could use a label
$GOROOT/src/text/template/exec.go:378:5: naked break could use a label
$GOROOT/src/text/template/parse/lex.go:531:5: naked break could use a label
$GOROOT/src/text/template/parse/lex.go:597:5: naked break could use a label
$GOROOT/src/time/format.go:604:5: naked break could use a label
$GOROOT/src/time/format.go:634:5: naked break could use a label
$GOROOT/src/time/format.go:827:5: naked break could use a label
$GOROOT/src/time/format.go:839:5: naked break could use a label
$GOROOT/src/time/format.go:887:5: naked break could use a label
$GOROOT/src/time/format.go:896:6: naked break could use a label
$GOROOT/src/time/format.go:908:5: naked break could use a label
$GOROOT/src/time/format.go:922:5: naked break could use a label
$GOROOT/src/time/format.go:937:5: naked break could use a label
$GOROOT/src/time/format.go:943:6: naked break could use a label
$GOROOT/src/time/format.go:947:6: naked break could use a label
$GOROOT/src/time/format.go:953:6: naked break could use a label
$GOROOT/src/time/format.go:959:6: naked break could use a label
$GOROOT/src/time/format.go:963:6: naked break could use a label
$GOROOT/src/time/format.go:969:6: naked break could use a label
$GOROOT/src/time/format.go:975:6: naked break could use a label
$GOROOT/src/time/format.go:1000:5: naked break could use a label
$GOROOT/src/time/format.go:1005:5: naked break could use a label
$GOROOT/src/time/format.go:1015:5: naked break could use a label
$GOROOT/src/time/format.go:1023:5: naked break could use a label
$GOROOT/src/time/time.go:1539:5: naked break could use a label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment