Skip to content

Commit

Permalink
Support regular expression (#3)
Browse files Browse the repository at this point in the history
* Add test

* Support regexp path

* Add README about regexp support

* Copy test directry to run paralley

* Fix regular expression

* Rename to d

* Fix bug

* Use pointer receiver for consistency

* Use errors.New
  • Loading branch information
sachaos authored Apr 5, 2021
1 parent d0bf5cb commit a22c8f7
Show file tree
Hide file tree
Showing 8 changed files with 1,327 additions and 7 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,18 @@ importas \
-alias knative.dev/serving/pkg/apis/serving/v1:servingv1 \
./...
~~~~

### Use regular expression

You can specify the package path by regular expression, and alias by regular expression replacement syntax like following snippet.

~~~~
importas -alias 'knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+):$1$2'
~~~~

`$1` represents the text of the first submatch. See [detail](https://golang.org/pkg/regexp/#Regexp.Expand).

So it will enforce that

"knative.dev/serving/pkg/apis/autoscaling/v1alpha1" is aliased by "autoscalingv1alpha1", and
"knative.dev/serving/pkg/apis/serving/v1" is aliased by "servingv1"
14 changes: 7 additions & 7 deletions analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ import (
"golang.org/x/tools/go/ast/inspector"
)

type Config struct {
RequiredAlias map[string]string // path -> alias.
}

var Analyzer = &analysis.Analyzer{
Name: "importas",
Doc: "Enforces consistent import aliases",
Expand All @@ -26,15 +22,19 @@ var Analyzer = &analysis.Analyzer{
Requires: []*analysis.Analyzer{inspect.Analyzer},
}

var config = Config{
var config = &Config{
RequiredAlias: make(map[string]string),
}

func run(pass *analysis.Pass) (interface{}, error) {
return runWithConfig(config, pass)
}

func runWithConfig(config Config, pass *analysis.Pass) (interface{}, error) {
func runWithConfig(config *Config, pass *analysis.Pass) (interface{}, error) {
if err := config.CompileRegexp(); err != nil {
return nil, err
}

inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
inspect.Preorder([]ast.Node{(*ast.ImportSpec)(nil)}, func(n ast.Node) {
visitImportSpecNode(n.(*ast.ImportSpec), pass)
Expand Down Expand Up @@ -62,7 +62,7 @@ func visitImportSpecNode(node *ast.ImportSpec, pass *analysis.Pass) {
pass.Reportf(node.Pos(), "import not quoted")
}

if required, exists := config.RequiredAlias[path]; exists && required != alias {
if required, exists := config.AliasFor(path); exists && required != alias {
pass.Report(analysis.Diagnostic{
Pos: node.Pos(),
End: node.End(),
Expand Down
7 changes: 7 additions & 0 deletions analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ func TestAnalyzer(t *testing.T) {
"knative.dev/serving/pkg/apis/serving/v1": "servingv1",
},
},
{
desc: "regexp",
pkg: "d",
aliases: stringMap{
"knative.dev/serving/pkg/apis/(\\w+)/(v[\\w\\d]+)": "$1$2",
},
},
}

for _, test := range testCases {
Expand Down
68 changes: 68 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package importas

import (
"errors"
"fmt"
"regexp"
)

type Config struct {
RequiredAlias map[string]string
Rules []*Rule
}

func (c *Config) CompileRegexp() error {
rules := make([]*Rule, 0, len(c.RequiredAlias))
for path, alias := range c.RequiredAlias {
reg, err := regexp.Compile(fmt.Sprintf("^%s$", path))
if err != nil {
return err
}

rules = append(rules, &Rule{
Regexp: reg,
Alias: alias,
})
}

c.Rules = rules
return nil
}

func (c *Config) findRule(path string) *Rule {
for _, rule := range c.Rules {
if rule.Regexp.MatchString(path) {
return rule
}
}

return nil
}

func (c *Config) AliasFor(path string) (string, bool) {
rule := c.findRule(path)
if rule == nil {
return "", false
}

alias, err := rule.aliasFor(path)
if err != nil {
return "", false
}

return alias, true
}

type Rule struct {
Alias string
Regexp *regexp.Regexp
}

func (r *Rule) aliasFor(path string) (string, error) {
str := r.Regexp.FindString(path)
if len(str) > 0 {
return r.Regexp.ReplaceAllString(str, r.Alias), nil
}

return "", errors.New("mismatch rule")
}
11 changes: 11 additions & 0 deletions testdata/src/d/d.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package c

import (
v1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" // want `import "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" imported as "v1alpha1" but must be "autoscalingv1alpha1" according to config`
v1 "knative.dev/serving/pkg/apis/serving/v1" // want `import "knative.dev/serving/pkg/apis/serving/v1" imported as "v1" but must be "servingv1" according to config`
)

func foo() {
v1alpha1.Resource("")
v1.Resource("")
}
11 changes: 11 additions & 0 deletions testdata/src/d/d.go.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package c

import (
autoscalingv1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" // want `import "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" imported as "v1alpha1" but must be "autoscalingv1alpha1" according to config`
servingv1 "knative.dev/serving/pkg/apis/serving/v1" // want `import "knative.dev/serving/pkg/apis/serving/v1" imported as "v1" but must be "servingv1" according to config`
)

func foo() {
autoscalingv1alpha1.Resource("")
servingv1.Resource("")
}
5 changes: 5 additions & 0 deletions testdata/src/d/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/julz/importas/testdata/src/c

go 1.15

require knative.dev/serving v0.21.0
Loading

0 comments on commit a22c8f7

Please sign in to comment.