Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rule.exported: add feature to disable selected warnings for rule (const,method,function) #1047

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 2 additions & 1 deletion RULES_DESCRIPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,13 @@ Available flags are:
* _disableStutteringCheck_ disables checking for method names that stutter with the package name (i.e. avoid failure messages of the form _type name will be used as x.XY by other packages, and that stutters; consider calling this Y_)
* _sayRepetitiveInsteadOfStutters_ replaces the use of the term _stutters_ by _repetitive_ in failure messages
* _checkPublicInterface_ enabled checking public method definitions in public interface types
* []string list of code types to ignore warnings, avaliable options: function, method, type and var

Example:

```toml
[rule.exported]
arguments = ["checkPrivateReceivers", "disableStutteringCheck", "checkPublicInterface"]
arguments = ["checkPrivateReceivers", "disableStutteringCheck", "checkPublicInterface", ["function","method","type","var"]]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the configuration entry gives no clue about the "ignore" nature of the list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok i try struct with dedicated fields but in toml there is problem with notation like:

IgnoredWarnings{field:true,field2:true}

you can only use like this:

{field:true,field2:true} or list ["val","val2","val3"]

but there is no option to name/prefix that (or maybe I dont know the magic yet :()

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what @chavacava is asking is to have a better naming of the setting, e.g. disableFunctionDocumentationCheck instead of function...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what @chavacava is asking is to have a better naming of the setting, e.g. disableFunctionDocumentationCheck instead of function...

ok so each element of ["function","method","type","var"] as dedicated flag

arguments = ["disableFunctionCheck", "disableMethodCheck", "disableTypeCheck", "disableVarCheck"]

that was my first idea, but thinks using array/slice will be simpler (one place to modify) :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok maybe we can walk that way:

arguments = ["disableFunctionCheck", "disableMethodCheck", "disableTypeCheck", "disableVarCheck"]

and of course modify my commited code to use that flags insted of additional array in config what you think @chavacava ?

```

## file-header
Expand Down
99 changes: 80 additions & 19 deletions rule/exported.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"go/ast"
"go/token"
"reflect"
"strings"
"sync"
"unicode"
Expand All @@ -13,38 +14,96 @@ import (
"github.com/mgechev/revive/lint"
)

// IgnoredWarnings store ignored warnings types
type IgnoredWarnings struct {
mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
Const bool
Function bool
Method bool
Type bool
Var bool
}

// Name returns the rule name.
mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
func (i *IgnoredWarnings) isDisabled(t string) bool {
mfederowicz marked this conversation as resolved.
Show resolved Hide resolved

mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
switch t {
case "var":
return i.Var
case "const":
return i.Const
case "function":
return i.Function
case "method":
return i.Method
case "type":
return i.Type
default:
panic(fmt.Sprintf("Unknown ignore warning flag %s", t))
}

mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
}

// ExportedRule lints given else constructs.
type ExportedRule struct {
configured bool
checkPrivateReceivers bool
disableStutteringCheck bool
checkPublicInterface bool
stuttersMsg string
disabledWarningsTypes IgnoredWarnings
sync.Mutex
}

func (r *ExportedRule) configure(arguments lint.Arguments) {
r.Lock()
defer r.Unlock()
if !r.configured {
mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
r.disabledWarningsTypes = IgnoredWarnings{}
r.stuttersMsg = "stutters"
for _, flag := range arguments {
flagStr, ok := flag.(string)
if !ok {
panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a string, got %T", r.Name(), flag))
}
switch flagStr {
case "checkPrivateReceivers":
r.checkPrivateReceivers = true
case "disableStutteringCheck":
r.disableStutteringCheck = true
case "sayRepetitiveInsteadOfStutters":
r.stuttersMsg = "is repetitive"
case "checkPublicInterface":
r.checkPublicInterface = true

switch flag.(type) {
case string:
flagStr, ok := flag.(string)
if !ok {
panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a string, got %T", r.Name(), flag))
}
switch flagStr {
case "checkPrivateReceivers":
r.checkPrivateReceivers = true
case "disableStutteringCheck":
r.disableStutteringCheck = true
case "sayRepetitiveInsteadOfStutters":
r.stuttersMsg = "is repetitive"
case "checkPublicInterface":
r.checkPublicInterface = true
default:
panic(fmt.Sprintf("Unknown configuration flag %s for %s rule", flagStr, r.Name()))
}
case []interface{}:
flagSlice, ok := flag.([]interface{})
if !ok {
panic(fmt.Sprintf("Invalid argument for the %s rule: expecting a []string, got %T", r.Name(), flag))
}
for _, val := range flagSlice {
switch val {
case "const":
r.disabledWarningsTypes.Const = true
case "function":
r.disabledWarningsTypes.Function = true
case "method":
r.disabledWarningsTypes.Method = true
case "type":
r.disabledWarningsTypes.Type = true
case "var":
r.disabledWarningsTypes.Var = true
}
}

default:
panic(fmt.Sprintf("Unknown configuration flag %s for %s rule", flagStr, r.Name()))
panic(fmt.Sprintf("Unknown configuration flag type %s for %s rule", reflect.TypeOf(flag), r.Name()))
}

}
r.configured = true
mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
}
Expand Down Expand Up @@ -72,6 +131,7 @@ func (r *ExportedRule) Apply(file *lint.File, args lint.Arguments) []lint.Failur
disableStutteringCheck: r.disableStutteringCheck,
checkPublicInterface: r.checkPublicInterface,
stuttersMsg: r.stuttersMsg,
disabledWarningsTypes: r.disabledWarningsTypes,
}

ast.Walk(&walker, fileAst)
Expand All @@ -94,6 +154,7 @@ type lintExported struct {
disableStutteringCheck bool
checkPublicInterface bool
stuttersMsg string
disabledWarningsTypes IgnoredWarnings
}

func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) {
Expand Down Expand Up @@ -134,7 +195,7 @@ func (w *lintExported) lintFuncDoc(fn *ast.FuncDecl) {
}
s := normalizeText(fn.Doc.Text())
prefix := fn.Name.Name + " "
if !strings.HasPrefix(s, prefix) {
if !strings.HasPrefix(s, prefix) && !w.disabledWarningsTypes.isDisabled(kind) {
w.onFailure(lint.Failure{
Node: fn.Doc,
Confidence: 0.8,
Expand Down Expand Up @@ -204,8 +265,8 @@ func (w *lintExported) lintTypeDoc(t *ast.TypeSpec, doc *ast.CommentGroup) {
}
}
// if comment starts with name of type and has some text after - it's ok
expectedPrefix := t.Name.Name+" "
if strings.HasPrefix(s, expectedPrefix){
expectedPrefix := t.Name.Name + " "
if strings.HasPrefix(s, expectedPrefix) || w.disabledWarningsTypes.isDisabled("type") {
return
}
w.onFailure(lint.Failure{
Expand Down Expand Up @@ -279,7 +340,7 @@ func (w *lintExported) lintValueSpecDoc(vs *ast.ValueSpec, gd *ast.GenDecl, genD

prefix := name + " "
s := normalizeText(doc.Text())
if !strings.HasPrefix(s, prefix) {
if !strings.HasPrefix(s, prefix) && !w.disabledWarningsTypes.isDisabled(kind) {
w.onFailure(lint.Failure{
Confidence: 1,
Node: doc,
Expand Down Expand Up @@ -348,7 +409,7 @@ func (w *lintExported) doCheckPublicInterface(typeName string, iface *ast.Interf

func (w *lintExported) lintInterfaceMethod(typeName string, m *ast.Field) {
if len(m.Names) == 0 {
return
return
}
if !ast.IsExported(m.Names[0].Name) {
return
Expand Down
7 changes: 7 additions & 0 deletions test/exported_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ func TestCheckPublicInterfaceOption(t *testing.T) {

testRule(t, "exported-issue-1002", &rule.ExportedRule{}, &lint.RuleConfig{Arguments: args})
}

func TestExportedDisableKindWarnings(t *testing.T) {

mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
args := []any{[]interface{}{"const", "function", "method", "type"}}
mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
testRule(t, "exported-issue-1045", &rule.ExportedRule{}, &lint.RuleConfig{Arguments: args})

mfederowicz marked this conversation as resolved.
Show resolved Hide resolved
}
25 changes: 25 additions & 0 deletions testdata/exported-issue-1045.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Package golint comment
package golint


// path separator defined by os.Separator.
const FilePath = "xyz"


// Rewrite string to remove non-standard path characters
func UnicodeSanitize(s string) string {}


// Tags returns a slice of tags. The order is the original tag order unless it
// was changed.
func (t *Tags) Keys() []string {}

// A value which may be passed to the which parameter for Getitimer and
type ItimerWhich int


/*
// PropertyBag
*/
// Rectangle An area within an image.
type Rectangle struct {}
Loading