diff --git a/README.rst b/README.rst index 3101dbc53..ba48ffdb6 100644 --- a/README.rst +++ b/README.rst @@ -1008,7 +1008,9 @@ The following directives are recognized: | ``import-lang`` may be omitted if it is the same as ``source-lang``. | | * ``import-string-regex`` is the regex applied to the import in the source code. | | If it matches, that import will be resolved to the label specified below. | -| * ``label`` is the Bazel label that Gazelle should write in ``deps``. | +| * ``label`` is the Bazel label that Gazelle should write in ``deps``. The label | +| can be constructed using captured strings from the subpattern matching in | +| import-string-regex | | | | For example: | | | @@ -1016,6 +1018,7 @@ The following directives are recognized: | | | # gazelle:resolve_regexp go example.com/.* //foo:go_default_library | | # gazelle:resolve_regexp proto go foo/.*\.proto //foo:foo_go_proto | +| # gazelle:resolve_regexp proto go foo/(.*)\.proto //foo/$1:foo_rule_proto | | | +---------------------------------------------------+----------------------------------------+ | :direc:`# gazelle:go_visibility label` | n/a | diff --git a/resolve/config.go b/resolve/config.go index d5eba0259..cc2b15d05 100644 --- a/resolve/config.go +++ b/resolve/config.go @@ -38,7 +38,8 @@ func FindRuleWithOverride(c *config.Config, imp ImportSpec, lang string) (label. for i := len(rc.regexpOverrides) - 1; i >= 0; i-- { o := rc.regexpOverrides[i] if o.matches(imp, lang) { - return o.dep, true + dep := o.resolveRegexpDep(imp) + return dep, true } } return label.NoLabel, false @@ -62,6 +63,17 @@ func (o regexpOverrideSpec) matches(imp ImportSpec, lang string) bool { (o.lang == "" || o.lang == lang) } +func (o regexpOverrideSpec) resolveRegexpDep(imp ImportSpec) label.Label { + + resolvedDepWithRegex := o.ImpRegex.ReplaceAllString(imp.Imp, o.dep.String()) + resolvedLabel, err := label.Parse(resolvedDepWithRegex) + if err != nil { + return o.dep + } + + return resolvedLabel +} + type resolveConfig struct { overrides map[overrideKey]label.Label regexpOverrides []regexpOverrideSpec diff --git a/resolve/resolve_test.go b/resolve/resolve_test.go index c3e87f1cb..653075e58 100644 --- a/resolve/resolve_test.go +++ b/resolve/resolve_test.go @@ -3,9 +3,9 @@ package resolve import ( "testing" - "github.com/bazelbuild/bazel-gazelle/rule" "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/label" + "github.com/bazelbuild/bazel-gazelle/rule" "github.com/google/go-cmp/cmp" ) @@ -22,6 +22,14 @@ func TestFindRuleWithOverride_ParentTraversal(t *testing.T) { secondChildCfg := getConfig(t, "second/child/rel", nil, rootCfg) + dualResolveRegexpCfg := getConfig(t, "dual/resolve/regexp", []rule.Directive{ + {Key: "resolve_regexp", Value: "go ^github.com/foo/(.*)$ @com_example//$1:replacement"}, + }, rootCfg) + + multipleExpDualResolveRegexpCfg := getConfig(t, "multi/dual/resolve/regexp", []rule.Directive{ + {Key: "resolve_regexp", Value: "go ^github.com/foo/(.*)/(.*)$ @com_example//$1/bar_sub_dir/$2:replacement"}, + }, rootCfg) + tests := []struct { name string cfg *config.Config @@ -86,6 +94,22 @@ func TestFindRuleWithOverride_ParentTraversal(t *testing.T) { want: getTestLabel(t, "@com_example//root:replacement"), wantFound: true, }, + { + name: "Target resolves to label populated by regexp", + cfg: dualResolveRegexpCfg, + importSpec: ImportSpec{Lang: "go", Imp: "github.com/foo/foo_package"}, + lang: "go", + want: getTestLabel(t, "@com_example//foo_package:replacement"), + wantFound: true, + }, + { + name: "Target resolves to label populated by multipe captured regexp", + cfg: multipleExpDualResolveRegexpCfg, + importSpec: ImportSpec{Lang: "go", Imp: "github.com/foo/foo_package/baz"}, + lang: "go", + want: getTestLabel(t, "@com_example//foo_package/bar_sub_dir/baz:replacement"), + wantFound: true, + }, } for _, tt := range tests {