Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 57 additions & 25 deletions called.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,39 +57,71 @@ func run(pass *analysis.Pass) (interface{}, error) {
func restrictedFuncs(pass *analysis.Pass, names string) []*types.Func {
var fs []*types.Func
for _, fn := range strings.Split(names, ",") {
ss := strings.Split(strings.TrimSpace(fn), ".")

// package function: pkgname.Func
if len(ss) < 2 {
continue
}
f, _ := analysisutil.ObjectOf(pass, ss[0], ss[1]).(*types.Func)
if f != nil {
fs = append(fs, f)
fn = strings.TrimSpace(fn)
if len(fn) == 0 {
continue
}

// method: (*pkgname.Type).Method
if len(ss) < 3 {
continue
}
pkgname := strings.TrimLeft(ss[0], "(")
typename := strings.TrimRight(ss[1], ")")
if pkgname != "" && pkgname[0] == '*' {
pkgname = pkgname[1:]
typename = "*" + typename
if fn[0] == '(' {
// method: (*pkgname.Type).Method
ss := splitLastN(fn, ".", 3)
if len(ss) < 3 {
continue
}
pkgname := strings.TrimLeft(ss[0], "(")
typename := strings.TrimRight(ss[1], ")")
if pkgname != "" && pkgname[0] == '*' {
pkgname = pkgname[1:]
typename = "*" + typename
}

typ := analysisutil.TypeOf(pass, pkgname, typename)
if typ == nil {
continue
}

m := analysisutil.MethodOf(typ, ss[2])
if m != nil {
fs = append(fs, m)
}
} else {
// package function: pkgname.Func
ss := splitLastN(fn, ".", 2)
if len(ss) < 2 {
continue
}
f, _ := analysisutil.ObjectOf(pass, ss[0], ss[1]).(*types.Func)
if f != nil {
fs = append(fs, f)
continue
}
}
}

typ := analysisutil.TypeOf(pass, pkgname, typename)
if typ == nil {
continue
return fs
}

func splitLastN(s, sep string, n int) []string {
ret := make([]string, 0)
for i := 0; i < n-1; i++ {
li := strings.LastIndex(s, sep)
if li < 0 {
break
}

m := analysisutil.MethodOf(typ, ss[2])
if m != nil {
fs = append(fs, m)
if li+1 < len(s) {
ret = append(ret, s[li+1:])
} else {
ret = append(ret, "")
}
s = s[:li]
}
ret = append(ret, s)

return fs
// reverse
for i, j := 0, len(ret)-1; i < j; i, j = i+1, j-1 {
ret[i], ret[j] = ret[j], ret[i]
}

return ret
}
2 changes: 1 addition & 1 deletion called_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ import (

func Test(t *testing.T) {
testdata := analysistest.TestData()
defer called.ExportSetFlagFuncs("b.Func,(*b.Type).Method, b/bsub.Type.Method")()
defer called.ExportSetFlagFuncs("b.Func,(*b.Type).Method, (b/bsub.Type).Method,github.com/gostaticanalysis/c.Func,(*github.com/gostaticanalysis/c.Type).Method,(github.com/gostaticanalysis/c/csub.Type).Method")()
analysistest.Run(t, testdata, called.Analyzer, "a")
}
24 changes: 24 additions & 0 deletions testdata/src/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package a
import (
"b"
"b/bsub"

"github.com/gostaticanalysis/c"
"github.com/gostaticanalysis/c/csub"
)

func afunc() {
Expand Down Expand Up @@ -53,5 +56,26 @@ func main() {
//lint:ignore called OK
m4(bsub.Type{}) // OK

c.Func() // want `github\.com/gostaticanalysis/c\.Func must not be called`
_ = c.Func // OK
g := c.Func // OK
g() // want `github\.com/gostaticanalysis/c\.Func must not be called`

new(c.Type).Method() // want `\(\*github\.com/gostaticanalysis/c\.Type\)\.Method must not be called`
_ = new(c.Type).Method // OK
m5 := new(c.Type).Method // OK
m5() // want `\(\*github\.com/gostaticanalysis/c\.Type\)\.Method must not be called`
(*c.Type).Method(new(c.Type)) // want `\(\*github\.com/gostaticanalysis/c\.Type\)\.Method must not be called`
m6 := (*c.Type).Method // OK
m6(new(c.Type)) // want `\(\*github\.com/gostaticanalysis/c\.Type\)\.Method must not be called`

csub.Type{}.Method() // want `\(github\.com/gostaticanalysis/c/csub\.Type\)\.Method must not be called`
_ = csub.Type{}.Method // OK
m7 := csub.Type{}.Method // OK
m7() // want `\(github\.com/gostaticanalysis/c/csub\.Type\)\.Method must not be called`
(csub.Type).Method(csub.Type{}) // want `\(github\.com/gostaticanalysis/c/csub\.Type\)\.Method must not be called`
m8 := (csub.Type).Method // OK
m8(csub.Type{}) // want `\(github\.com/gostaticanalysis/c/csub\.Type\)\.Method must not be called`

afunc() // OK
}
7 changes: 7 additions & 0 deletions testdata/src/github.com/gostaticanalysis/c/c.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package c

func Func() {}

type Type struct{}

func (*Type) Method() {}
5 changes: 5 additions & 0 deletions testdata/src/github.com/gostaticanalysis/c/csub/csub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package csub

type Type struct{}

func (Type) Method() {}