Suppress underscore warning for cgo functions
This change suppresses the warning for functions which are:
1. exported to C via a cgo "//export" comment, and
2. not exported in the Go package.
That allows functions exported to C to use idiomatic C names, but
still requires that they not pollute the exported Go API.
Fixes #144
diff --git a/lint.go b/lint.go
index 22c60c4..a13129c 100644
--- a/lint.go
+++ b/lint.go
@@ -544,6 +544,7 @@
if id.Name == should {
return
}
+
if len(id.Name) > 2 && strings.Contains(id.Name[1:], "_") {
f.errorf(id, 0.9, link("http://golang.org/doc/effective_go.html#mixed-caps"), category("naming"), "don't use underscores in Go names; %s %s should be %s", thing, id.Name, should)
return
@@ -581,7 +582,12 @@
thing = "method"
}
- check(v.Name, thing)
+ // Exclude naming warnings for functions that are exported to C but
+ // not exported in the Go API.
+ // See https://github.com/golang/lint/issues/144.
+ if ast.IsExported(v.Name.Name) || !isCgoExported(v) {
+ check(v.Name, thing)
+ }
checkList(v.Type.Params, thing+" parameter")
checkList(v.Type.Results, thing+" result")
@@ -1508,6 +1514,20 @@
return ok && lit.Kind == token.INT && lit.Value == "1"
}
+func isCgoExported(f *ast.FuncDecl) bool {
+ if f.Recv != nil || f.Doc == nil {
+ return false
+ }
+
+ cgoExport := regexp.MustCompile(fmt.Sprintf("(?m)^//export %s$", regexp.QuoteMeta(f.Name.Name)))
+ for _, c := range f.Doc.List {
+ if cgoExport.MatchString(c.Text) {
+ return true
+ }
+ }
+ return false
+}
+
var basicTypeKinds = map[types.BasicKind]string{
types.UntypedBool: "bool",
types.UntypedInt: "int",
diff --git a/testdata/names.go b/testdata/names.go
index f884fab..0ec1520 100644
--- a/testdata/names.go
+++ b/testdata/names.go
@@ -10,6 +10,8 @@
"net/url"
)
+import "C"
+
var var_name int // MATCH /underscore.*var.*var_name/
type t_wow struct { // MATCH /underscore.*type.*t_wow/
@@ -89,3 +91,26 @@
type t struct{}
func (t) LastInsertId() (int64, error) { return 0, nil } // okay because it matches a known style violation
+
+//export exported_to_c
+func exported_to_c() {} // okay: https://github.com/golang/lint/issues/144
+
+//export exported_to_c_with_arg
+func exported_to_c_with_arg(but_use_go_param_names int) // MATCH /underscore.*func parameter.*but_use_go_param_names/
+
+// This is an exported C function with a leading doc comment.
+//
+//export exported_to_c_with_comment
+func exported_to_c_with_comment() {} // okay: https://github.com/golang/lint/issues/144
+
+//export maybe_exported_to_CPlusPlusWithCamelCase
+func maybe_exported_to_CPlusPlusWithCamelCase() {} // okay: https://github.com/golang/lint/issues/144
+
+// WhyAreYouUsingCapitalLetters_InACFunctionName is a Go-exported function that
+// is also exported to C as a name with underscores.
+//
+// Don't do that. If you want to use a C-style name for a C export, make it
+// lower-case and leave it out of the Go-exported API.
+//
+//export WhyAreYouUsingCapitalLetters_InACFunctionName
+func WhyAreYouUsingCapitalLetters_InACFunctionName() {} // MATCH /underscore.*func.*Why.*CFunctionName/