From a00a1c99d573a6bf5ec39dbf9e40d599ac04f23d Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Wed, 7 Sep 2022 21:26:40 +0200 Subject: [PATCH] preferredimports: support regular expressions for the import path Having to list all packages isn't very manageable and requires constant maintenance that is easy to miss. For example, test/e2e/framework/daemonset was created without adding an entry for it. Promptly one file doesn't use the intended e2edaemonset alias. A simpler solution is to support matching the import path against a regular expression and deriving the intended alias by expanding placeholders (${name}, $1, etc.) with the corresponding submatches from the import path. Example: k8s.io/kubernetes/test/e2e/framework/([^/]*) -> e2e$1 This support is backwards compatible because normal import paths don't contain characters that are special in a regular expression and normal aliases don't contain placeholders. A regular expression must match the entire import path, otherwise it is skipped. --- cmd/preferredimports/preferredimports.go | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/cmd/preferredimports/preferredimports.go b/cmd/preferredimports/preferredimports.go index 0213bd7e72e..5397ab6e17e 100644 --- a/cmd/preferredimports/preferredimports.go +++ b/cmd/preferredimports/preferredimports.go @@ -43,7 +43,7 @@ var ( regex = flag.String("include-path", "(test/e2e/|test/e2e_node)", "only files with paths matching this regex is touched") isTerminal = term.IsTerminal(int(os.Stdout.Fd())) logPrefix = "" - aliases map[string]string + aliases = map[*regexp.Regexp]string{} ) type analyzer struct { @@ -95,7 +95,17 @@ func (a *analyzer) collect(dir string) { if imp.Name != nil { importName = imp.Name.Name } - if alias, ok := aliases[importPath]; ok { + for re, template := range aliases { + match := re.FindStringSubmatchIndex(importPath) + if match == nil { + // No match. + continue + } + if match[0] > 0 || match[1] < len(importPath) { + // Not a full match. + continue + } + alias := string(re.ExpandString(nil, template, importPath, match)) if alias != importName { if !*confirm { fmt.Fprintf(os.Stderr, "%sERROR wrong alias for import \"%s\" should be %s in file %s\n", logPrefix, importPath, alias, pathToFile) @@ -108,6 +118,7 @@ func (a *analyzer) collect(dir string) { imp.Name = ast.NewIdent(alias) } } + break } } @@ -238,10 +249,18 @@ func main() { if err != nil { log.Fatalf("Error reading import aliases: %v", err) } - err = json.Unmarshal(bytes, &aliases) + var stringAliases map[string]string + err = json.Unmarshal(bytes, &stringAliases) if err != nil { log.Fatalf("Error loading aliases: %v", err) } + for pattern, name := range stringAliases { + re, err := regexp.Compile(pattern) + if err != nil { + log.Fatalf("Error parsing import path pattern %q as regular expression: %v", pattern, err) + } + aliases[re] = name + } } if isTerminal { logPrefix = "\r" // clear status bar when printing