Skip to content

Commit

Permalink
Merge pull request #1 from ldez/feat/improve
Browse files Browse the repository at this point in the history
  • Loading branch information
sashamelentyev authored Aug 20, 2022
2 parents fde710e + cf16515 commit 1702936
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 66 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
run:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Install Go
uses: actions/setup-go@v3
with:
go-version: 1.19

- name: Lint
uses: golangci/[email protected]
with:
version: latest
args: --timeout 5m

- name: Go Format
run: gofmt -s -w . && git diff --exit-code

- name: Go Tidy
run: go mod tidy && git diff --exit-code

- name: Go Mod
run: go mod download

- name: Go Build
run: go build -v ./...

- name: Go Test
run: go test -v -race ./...
5 changes: 1 addition & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ module github.com/sashamelentyev/interfacebloat

go 1.18

require (
github.com/sashamelentyev/usestdlibvars v1.7.0
golang.org/x/tools v0.1.12
)
require golang.org/x/tools v0.1.12

require (
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
github.com/sashamelentyev/usestdlibvars v1.7.0 h1:jjDzfl4RjcUWer1EwhNyipT+f+LL0HmcuGF0jDhb7sM=
github.com/sashamelentyev/usestdlibvars v1.7.0/go.mod h1:BFt7b5mSVHaaa26ZupiNRV2ODViQBxZZVhtAxAJRrjs=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"golang.org/x/tools/go/analysis/singlechecker"

"github.com/sashamelentyev/usestdlibvars/pkg/analyzer"
"github.com/sashamelentyev/interfacebloat/pkg/analyzer"
)

func main() {
Expand Down
32 changes: 12 additions & 20 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@ package analyzer
import (
"flag"
"go/ast"
"go/token"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
)

const InterfaceLenFlag = "interface-len"
const InterfaceMaxMethodsFlag = "max"

const defaultInterfaceLen = 10
const defaultMaxMethods = 10

// New returns new interfacebloat analyzer.
func New() *analysis.Analyzer {
return &analysis.Analyzer{
Name: "interfacebloat",
Doc: "A linter that checks length of interface.",
Doc: "A linter that checks the number of methods inside an interface.",
Run: run,
Flags: flags(),
Requires: []*analysis.Analyzer{inspect.Analyzer},
Expand All @@ -27,11 +26,16 @@ func New() *analysis.Analyzer {

func flags() flag.FlagSet {
flags := flag.NewFlagSet("", flag.ExitOnError)
flags.Int(InterfaceLenFlag, 10, "length of interface")
flags.Int(InterfaceMaxMethodsFlag, 10, "maximum number of methods")
return *flags
}

func run(pass *analysis.Pass) (interface{}, error) {
maxMethods, ok := pass.Analyzer.Flags.Lookup(InterfaceMaxMethodsFlag).Value.(flag.Getter).Get().(int)
if !ok {
maxMethods = defaultMaxMethods
}

insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)

filter := []ast.Node{
Expand All @@ -43,23 +47,11 @@ func run(pass *analysis.Pass) (interface{}, error) {
if !ok {
return
}
interfaceLen := interfaceLen(pass, InterfaceLenFlag)
if len(i.Methods.List) > interfaceLen {
report(pass, node.Pos(), interfaceLen)

if len(i.Methods.List) > maxMethods {
pass.Reportf(node.Pos(), `the interface has more than %d methods: %d`, maxMethods, len(i.Methods.List))
}
})

return nil, nil
}

func interfaceLen(pass *analysis.Pass, name string) (interfaceLen int) {
interfaceLen, ok := pass.Analyzer.Flags.Lookup(name).Value.(flag.Getter).Get().(int)
if !ok {
interfaceLen = defaultInterfaceLen
}
return
}

func report(pass *analysis.Pass, pos token.Pos, interfaceLen int) {
pass.Reportf(pos, `length of interface greater than %d`, interfaceLen)
}
154 changes: 115 additions & 39 deletions pkg/analyzer/testdata/src/a/a.go
Original file line number Diff line number Diff line change
@@ -1,47 +1,123 @@
package a

type _ interface { // want "length of interface greater than 10"
a()
b()
c()
d()
f()
g()
h()
i()
j()
k()
l()
}

func _() {
var _ interface { // want "length of interface greater than 10"
a()
b()
c()
d()
f()
g()
h()
i()
j()
k()
l()
type Example01 interface { // want "the interface has more than 10 methods: 11"
a01()
a02()
a03()
a04()
a05()
a06()
a07()
a08()
a09()
a10()
a11()
}

func Example02() {
var _ interface { // want "the interface has more than 10 methods: 11"
a01()
a02()
a03()
a04()
a05()
a06()
a07()
a08()
a09()
a10()
a11()
}
}

func Example03() interface { // want "the interface has more than 10 methods: 11"
a01()
a02()
a03()
a04()
a05()
a06()
a07()
a08()
a09()
a10()
a11()
} {
return nil
}

type Example04 struct {
Foo interface { // want "the interface has more than 10 methods: 11"
a01()
a02()
a03()
a04()
a05()
a06()
a07()
a08()
a09()
a10()
a11()
}
}

type Small01 interface {
a01()
a02()
a03()
a04()
a05()
}

type Small02 interface {
a06()
a07()
a08()
a09()
a10()
a11()
}

type Example05 interface {
Small01
Small02
}

type Example06 interface {
interface { // want "the interface has more than 10 methods: 11"
a01()
a02()
a03()
a04()
a05()
a06()
a07()
a08()
a09()
a10()
a11()
}
}

func __() interface { // want "length of interface greater than 10"
a()
b()
c()
d()
f()
g()
h()
i()
j()
k()
l()
type TypeGeneric interface {
~uint8 | ~uint16 | ~uint32 | ~uint64 | uint |
~int8 | ~int16 | ~int32 | ~int64 | int |
~float32 | ~float64 |
~string
}

func ExampleNoProblem() interface {
a01()
a02()
a03()
a04()
a05()
a06()
a07()
a08()
a09()
a10()
} {
return nil
}

0 comments on commit 1702936

Please sign in to comment.