package rule import ( "fmt" "go/token" "regexp" "strings" "github.com/mgechev/revive/lint" ) // exitFunctions is a map of std packages and functions that are considered as exit functions. var exitFunctions = map[string]map[string]bool{ "os": {"Exit": true}, "syscall": {"Exit": true}, "log": { "Fatal": true, "Fatalf": true, "Fatalln": true, "Panic": true, "Panicf": true, "Panicln": true, }, } func srcLine(src []byte, p token.Position) string { // Run to end of line in both directions if not at line start/end. lo, hi := p.Offset, p.Offset+1 for lo > 0 && src[lo-1] != '\n' { lo-- } for hi < len(src) && src[hi-1] != '\n' { hi++ } return string(src[lo:hi]) } // checkNumberOfArguments fails if the given number of arguments is not, at least, the expected one. func checkNumberOfArguments(expected int, args lint.Arguments, ruleName string) error { if len(args) < expected { return fmt.Errorf("not enough arguments for %s rule, expected %d, got %d. Please check the rule's documentation", ruleName, expected, len(args)) } return nil } // isRuleOption returns true if arg and name are the same after normalization. func isRuleOption(arg, name string) bool { return normalizeRuleOption(arg) == normalizeRuleOption(name) } // normalizeRuleOption returns an option name from the argument. It is lowercased and without hyphens. // // Example: normalizeRuleOption("allowTypesBefore"), normalizeRuleOption("allow-types-before") -> "allowtypesbefore". func normalizeRuleOption(arg string) string { return strings.ToLower(strings.ReplaceAll(arg, "-", "")) } var directiveCommentRE = regexp.MustCompile("^//(line |extern |export |[a-z0-9]+:[a-z0-9])") // see https://go-review.googlesource.com/c/website/+/442516/1..2/_content/doc/comment.md#494 func isDirectiveComment(line string) bool { return directiveCommentRE.MatchString(line) } // isCallToExitFunction checks if the function call is a call to an exit function. func isCallToExitFunction(pkgName, functionName string) bool { return exitFunctions[pkgName] != nil && exitFunctions[pkgName][functionName] } // newInternalFailureError returns a slice of Failure with a single internal failure in it. func newInternalFailureError(e error) []lint.Failure { return []lint.Failure{lint.NewInternalFailure(e.Error())} }