Skip to content

Commit

Permalink
passes/schemavalidatefunc: Support *ast.FuncLit declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
bflad committed Jan 15, 2020
1 parent eb22c67 commit 0b7b138
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 19 deletions.
41 changes: 41 additions & 0 deletions helper/terraformtype/helper_schema_schemavalidatefunc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package terraformtype

import (
"go/ast"
"go/token"
"go/types"
)

// HelperSchemaSchemaValidateFuncInfo represents all gathered SchemaValidateFunc data for easier access
type HelperSchemaSchemaValidateFuncInfo struct {
AstFuncDecl *ast.FuncDecl
AstFuncLit *ast.FuncLit
Body *ast.BlockStmt
Node ast.Node
Pos token.Pos
Type *ast.FuncType
TypesInfo *types.Info
}

// NewHelperSchemaSchemaValidateFuncInfo instantiates a HelperSchemaSchemaValidateFuncInfo
func NewHelperSchemaSchemaValidateFuncInfo(funcDecl *ast.FuncDecl, funcLit *ast.FuncLit, info *types.Info) *HelperSchemaSchemaValidateFuncInfo {
result := &HelperSchemaSchemaValidateFuncInfo{
AstFuncDecl: funcDecl,
AstFuncLit: funcLit,
TypesInfo: info,
}

if funcDecl != nil {
result.Body = funcDecl.Body
result.Node = funcDecl
result.Pos = funcDecl.Pos()
result.Type = funcDecl.Type
} else if funcLit != nil {
result.Body = funcLit.Body
result.Node = funcLit
result.Pos = funcLit.Pos()
result.Type = funcLit.Type
}

return result
}
11 changes: 6 additions & 5 deletions passes/V001/V001.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"go/ast"

"github.com/bflad/tfproviderlint/helper/astutils"
"github.com/bflad/tfproviderlint/helper/terraformtype"
"github.com/bflad/tfproviderlint/passes/commentignore"
"github.com/bflad/tfproviderlint/passes/schemavalidatefunc"
"golang.org/x/tools/go/analysis"
Expand All @@ -30,14 +31,14 @@ var Analyzer = &analysis.Analyzer{

func run(pass *analysis.Pass) (interface{}, error) {
ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer)
funcDecls := pass.ResultOf[schemavalidatefunc.Analyzer].([]*ast.FuncDecl)
schemaValidateFuncs := pass.ResultOf[schemavalidatefunc.Analyzer].([]*terraformtype.HelperSchemaSchemaValidateFuncInfo)

for _, funcDecl := range funcDecls {
if ignorer.ShouldIgnore(analyzerName, funcDecl) {
for _, schemaValidateFunc := range schemaValidateFuncs {
if ignorer.ShouldIgnore(analyzerName, schemaValidateFunc.Node) {
continue
}

ast.Inspect(funcDecl.Body, func(n ast.Node) bool {
ast.Inspect(schemaValidateFunc.Body, func(n ast.Node) bool {
callExpr, ok := n.(*ast.CallExpr)

if !ok {
Expand All @@ -48,7 +49,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
return true
}

pass.Reportf(funcDecl.Pos(), "%s: custom SchemaValidateFunc should be replaced with validation.StringMatch() or validation.StringDoesNotMatch()", analyzerName)
pass.Reportf(schemaValidateFunc.Pos, "%s: custom SchemaValidateFunc should be replaced with validation.StringMatch() or validation.StringDoesNotMatch()", analyzerName)
return false
})
}
Expand Down
22 changes: 20 additions & 2 deletions passes/V001/testdata/src/a/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,19 @@ func commentIgnore(v interface{}, k string) (warns []string, errs []error) {
return
}

func failingInline(v interface{}, k string) (warns []string, errs []error) { // want "custom SchemaValidateFunc should be replaced with validation.StringMatch\\(\\) or validation.StringDoesNotMatch\\(\\)"
func failingAnonymousFunction() {
_ = func(v interface{}, k string) (warns []string, errs []error) { // want "custom SchemaValidateFunc should be replaced with validation.StringMatch\\(\\) or validation.StringDoesNotMatch\\(\\)"
value := v.(string)

if !regexp.MustCompile(`example`).MatchString(value) {
errs = append(errs, errors.New("example"))
}

return
}
}

func failingInlineRegexp(v interface{}, k string) (warns []string, errs []error) { // want "custom SchemaValidateFunc should be replaced with validation.StringMatch\\(\\) or validation.StringDoesNotMatch\\(\\)"
value := v.(string)

if !regexp.MustCompile(`example`).MatchString(value) {
Expand All @@ -26,7 +38,7 @@ func failingInline(v interface{}, k string) (warns []string, errs []error) { //
return
}

func failingVariable(v interface{}, k string) (warns []string, errs []error) { // want "custom SchemaValidateFunc should be replaced with validation.StringMatch\\(\\) or validation.StringDoesNotMatch\\(\\)"
func failingVariableRegexp(v interface{}, k string) (warns []string, errs []error) { // want "custom SchemaValidateFunc should be replaced with validation.StringMatch\\(\\) or validation.StringDoesNotMatch\\(\\)"
value := v.(string)

re := regexp.MustCompile(`example`)
Expand All @@ -38,6 +50,12 @@ func failingVariable(v interface{}, k string) (warns []string, errs []error) { /
return
}

func passingAnonymousFunction() {
_ = func(v interface{}, k string) (warns []string, errs []error) {
return
}
}

func passingRegexpMatchString() {
_ = regexp.MustCompile(`example`).MatchString("")
}
Expand Down
37 changes: 25 additions & 12 deletions passes/schemavalidatefunc/schemavalidatefunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"reflect"

"github.com/bflad/tfproviderlint/helper/astutils"
"github.com/bflad/tfproviderlint/helper/terraformtype"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
Expand All @@ -17,48 +18,60 @@ var Analyzer = &analysis.Analyzer{
inspect.Analyzer,
},
Run: run,
ResultType: reflect.TypeOf([]*ast.FuncDecl{}),
ResultType: reflect.TypeOf([]*terraformtype.HelperSchemaSchemaValidateFuncInfo{}),
}

func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.FuncDecl)(nil),
(*ast.FuncLit)(nil),
}
var result []*ast.FuncDecl
var result []*terraformtype.HelperSchemaSchemaValidateFuncInfo

inspect.Preorder(nodeFilter, func(n ast.Node) {
funcDecl := n.(*ast.FuncDecl)
funcDecl, funcDeclOk := n.(*ast.FuncDecl)
funcLit, funcLitOk := n.(*ast.FuncLit)

params := funcDecl.Type.Params.List
var funcType *ast.FuncType

if len(params) != 2 {
if funcDeclOk && funcDecl != nil {
funcType = funcDecl.Type
} else if funcLitOk && funcLit != nil {
funcType = funcLit.Type
} else {
return
}

if !astutils.IsFunctionParameterTypeInterface(params[0].Type) {
params := funcType.Params

if params == nil || len(params.List) != 2 {
return
}

if !astutils.IsFunctionParameterTypeInterface(params.List[0].Type) {
return
}

if !astutils.IsFunctionParameterTypeString(params[1].Type) {
if !astutils.IsFunctionParameterTypeString(params.List[1].Type) {
return
}

results := funcDecl.Type.Results.List
results := funcType.Results

if len(results) != 2 {
if results == nil || len(results.List) != 2 {
return
}

if !astutils.IsFunctionParameterTypeArrayString(results[0].Type) {
if !astutils.IsFunctionParameterTypeArrayString(results.List[0].Type) {
return
}

if !astutils.IsFunctionParameterTypeArrayError(results[1].Type) {
if !astutils.IsFunctionParameterTypeArrayError(results.List[1].Type) {
return
}

result = append(result, funcDecl)
result = append(result, terraformtype.NewHelperSchemaSchemaValidateFuncInfo(funcDecl, funcLit, pass.TypesInfo))
})

return result, nil
Expand Down

0 comments on commit 0b7b138

Please sign in to comment.