Skip to content

Commit

Permalink
New Check: AT009: Check for acctest.RandStringFromCharSet that can be…
Browse files Browse the repository at this point in the history
… acctest.RandString (#211)

Reference: #175

Includes new helper/terraformtype/helper/acctest package and passes/helper/acctest/randstringfromcharsetcallexpr.
  • Loading branch information
bflad authored Oct 29, 2020
1 parent 062a421 commit 36f478c
Show file tree
Hide file tree
Showing 104 changed files with 21,656 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# v0.20.0

FEATURES

* **New Check:** `AT009`: check for `acctest.RandStringFromCharSet()` calls that can be `acctest.RandString`

ENHANCEMENTS

* passes/helper/acctest: Pass for collecting `acctest.RandStringFromCharSet()` calls
* passes/АТ001: Add optional `-ignored-filename-suffixes` and `-ignored-filename-prefixes` flags (#210)

# v0.19.0
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Standard lint checks are enabled by default in the `tfproviderlint` tool. Opt-in
| [AT006](passes/AT006/README.md) | check for acceptance test functions containing multiple `resource.Test()` invocations | AST |
| [AT007](passes/AT007/README.md) | check for acceptance test functions containing multiple `resource.ParallelTest()` invocations | AST |
| [AT008](passes/AT008/README.md) | check for acceptance test function declaration `*testing.T` parameter naming | AST |
| [AT009](passes/AT009/README.md) | check for `acctest.RandStringFromCharSet()` calls that can be simplified to `acctest.RandString()` | AST |

### Standard Resource Checks

Expand Down
6 changes: 6 additions & 0 deletions helper/terraformtype/helper/acctest/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package acctest

const (
ConstNameCharSetAlpha = "CharSetAlpha"
ConstNameCharSetAlphaNum = "CharSetAlphaNum"
)
12 changes: 12 additions & 0 deletions helper/terraformtype/helper/acctest/funcs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package acctest

const (
FuncNameRandInt = `RandInt`
FuncNameRandIntRange = `RandIntRange`
FuncNameRandIpAddress = `RandIpAddress`
FuncNameRandSSHKeyPair = `RandSSHKeyPair`
FuncNameRandString = `RandString`
FuncNameRandStringFromCharSet = `RandStringFromCharSet`
FuncNameRandTLSCert = `RandTLSCert`
FuncNameRandomWithPrefix = `RandomWithPrefix`
)
43 changes: 43 additions & 0 deletions helper/terraformtype/helper/acctest/package.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package acctest

import (
"fmt"
"go/ast"
"go/types"

"github.com/bflad/tfproviderlint/helper/astutils"
"github.com/bflad/tfproviderlint/helper/terraformtype"
)

const (
PackageModule = terraformtype.ModuleTerraformPluginSdk
PackageModulePath = `helper/acctest`
PackageName = `acctest`
PackagePath = PackageModule + `/` + PackageModulePath
)

// IsConst returns if the expr is a constant in the acctest package
func IsConst(e ast.Expr, info *types.Info, constName string) bool {
// IsModulePackageFunc can handle any SelectorExpr name
return astutils.IsModulePackageFunc(e, info, PackageModule, PackageModulePath, constName)
}

// IsFunc returns if the function call is in the acctest package
func IsFunc(e ast.Expr, info *types.Info, funcName string) bool {
return astutils.IsModulePackageFunc(e, info, PackageModule, PackageModulePath, funcName)
}

// IsNamedType returns if the type name matches and is from the helper/acctest package
func IsNamedType(t *types.Named, typeName string) bool {
return astutils.IsModulePackageNamedType(t, PackageModule, PackageModulePath, typeName)
}

// PackagePathVersion returns the import path for a module version
func PackagePathVersion(moduleVersion int) string {
switch moduleVersion {
case 0, 1:
return PackagePath
default:
return fmt.Sprintf("%s/v%d/%s", PackageModule, moduleVersion, PackageModulePath)
}
}
50 changes: 50 additions & 0 deletions passes/AT009/AT009.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package AT009

import (
"go/ast"

"github.com/bflad/tfproviderlint/helper/terraformtype/helper/acctest"
"github.com/bflad/tfproviderlint/passes/commentignore"
"github.com/bflad/tfproviderlint/passes/helper/acctest/randstringfromcharsetcallexpr"
"golang.org/x/tools/go/analysis"
)

const Doc = `check for acctest.RandStringFromCharSet() calls that can be acctest.RandString()
The AT009 analyzer reports where the second parameter of a
RandStringFromCharSet call is acctest.CharSetAlpha, which is equivalent to
calling RandString.`

const analyzerName = "AT009"

var Analyzer = &analysis.Analyzer{
Name: analyzerName,
Doc: Doc,
Requires: []*analysis.Analyzer{
commentignore.Analyzer,
randstringfromcharsetcallexpr.Analyzer,
},
Run: run,
}

func run(pass *analysis.Pass) (interface{}, error) {
ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer)
callExprs := pass.ResultOf[randstringfromcharsetcallexpr.Analyzer].([]*ast.CallExpr)
for _, callExpr := range callExprs {
if ignorer.ShouldIgnore(analyzerName, callExpr) {
continue
}

if len(callExpr.Args) < 2 {
continue
}

if !acctest.IsConst(callExpr.Args[1], pass.TypesInfo, acctest.ConstNameCharSetAlpha) {
continue
}

pass.Reportf(callExpr.Pos(), "%s: should use RandString call instead", analyzerName)
}

return nil, nil
}
12 changes: 12 additions & 0 deletions passes/AT009/AT009_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package AT009

import (
"testing"

"golang.org/x/tools/go/analysis/analysistest"
)

func TestAT009(t *testing.T) {
testdata := analysistest.TestData()
analysistest.Run(t, testdata, Analyzer, "a")
}
24 changes: 24 additions & 0 deletions passes/AT009/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# AT009

The AT009 analyzer reports where `acctest.RandStringFromCharSet()` calls can be simplified to `acctest.RandString()`.

## Flagged Code

```go
rString := acctest.RandStringFromCharSet(8, acctest.CharSetAlphaNum)
```

## Passing Code

```go
rString := acctest.RandString(8)
```

## Ignoring Reports

Singular reports can be ignored by adding the a `//lintignore:AT009` Go code comment at the end of the offending line or on the line immediately proceding, e.g.

```go
//lintignore:AT009
rString := acctest.RandStringFromCharSet(8, acctest.CharSetAlphaNum)
```
26 changes: 26 additions & 0 deletions passes/AT009/testdata/src/a/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package a

import (
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
)

const (
ConstKey = "ConstValue"
)

func f() {
// Comment ignored

//lintignore:AT009
_ = acctest.RandStringFromCharSet(1, acctest.CharSetAlpha)

// Failing

_ = acctest.RandStringFromCharSet(1, acctest.CharSetAlpha) // want "should use RandString call instead"

// Passing

_ = acctest.RandStringFromCharSet(1, acctest.CharSetAlphaNum)
_ = acctest.RandStringFromCharSet(1, "abc123")
_ = acctest.RandString(1)
}
1 change: 1 addition & 0 deletions passes/AT009/testdata/src/a/vendor
2 changes: 2 additions & 0 deletions passes/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/bflad/tfproviderlint/passes/AT006"
"github.com/bflad/tfproviderlint/passes/AT007"
"github.com/bflad/tfproviderlint/passes/AT008"
"github.com/bflad/tfproviderlint/passes/AT009"
"github.com/bflad/tfproviderlint/passes/R001"
"github.com/bflad/tfproviderlint/passes/R002"
"github.com/bflad/tfproviderlint/passes/R003"
Expand Down Expand Up @@ -87,6 +88,7 @@ var AllChecks = []*analysis.Analyzer{
AT006.Analyzer,
AT007.Analyzer,
AT008.Analyzer,
AT009.Analyzer,
R001.Analyzer,
R002.Analyzer,
R003.Analyzer,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package randstringfromcharsetcallexpr

import (
"github.com/bflad/tfproviderlint/helper/analysisutils"
"github.com/bflad/tfproviderlint/helper/terraformtype/helper/acctest"
)

var Analyzer = analysisutils.FunctionCallExprAnalyzer(
"randstringfromcharsetcallexpr",
acctest.IsFunc,
acctest.PackagePath,
acctest.FuncNameRandStringFromCharSet,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package randstringfromcharsetcallexpr

import (
"testing"

"golang.org/x/tools/go/analysis"
)

func TestValidateAnalyzer(t *testing.T) {
err := analysis.Validate([]*analysis.Analyzer{Analyzer})

if err != nil {
t.Fatal(err)
}
}
2 changes: 2 additions & 0 deletions tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ package main

import (
// analysistest does not work with Go Modules yet
_ "github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
_ "github.com/hashicorp/terraform-plugin-sdk/helper/resource"
_ "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
_ "github.com/hashicorp/terraform-plugin-sdk/helper/validation"
_ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
_ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
_ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
_ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 36f478c

Please sign in to comment.