github.com/nya3jp/tast@v0.0.0-20230601000426-85c8e4d83a9b/src/go.chromium.org/tast/core/cmd/tast-lint/internal/check/forbidden_bundle_imports.go (about) 1 // Copyright 2019 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package check 6 7 import ( 8 "fmt" 9 "go/ast" 10 "go/token" 11 "path" 12 "path/filepath" 13 "regexp" 14 "strconv" 15 "strings" 16 ) 17 18 var bundleCategoryRegex = regexp.MustCompile(`^(go.chromium.org/tast-tests/cros/(?:local|remote)/bundles/\w+)/(\w+)`) 19 20 // parseBundlePackage analyzes full package path and returns matching bundle prefix and the category name. 21 // Returns ok=false if it's not a bundle (sub)package. 22 // 23 // Example: 24 // 25 // "go.chromium.org/tast-tests/cros/local/bundles/cros/foo" -> "go.chromium.org/tast-tests/cros/local/bundles/cros", "foo", true 26 // "go.chromium.org/tast-tests/cros/remote/bundles/crosint/foo/bar" -> "go.chromium.org/tast-tests/cros/remote/bundles/crosint", "foo", true 27 // "go.chromium.org/tast-tests/cros/local/foo" -> "", "", false 28 func parseBundlePackage(p string) (bundlePkg, category string, ok bool) { 29 m := bundleCategoryRegex.FindStringSubmatch(p) 30 if len(m) == 0 { 31 return "", "", false 32 } 33 return m[1], m[2], true 34 } 35 36 // ForbiddenBundleImports makes sure libraries in another package under bundles/ are not imported. 37 func ForbiddenBundleImports(fs *token.FileSet, f *ast.File) []*Issue { 38 filename := fs.Position(f.Package).Filename 39 mypkg := strings.TrimPrefix(filepath.Dir(filename), "src/") 40 myBundlePkg, myCategory, isBundle := parseBundlePackage(mypkg) 41 myBundlePath := path.Dir(myBundlePkg) 42 43 var issues []*Issue 44 for _, im := range f.Imports { 45 p, err := strconv.Unquote(im.Path.Value) 46 if err != nil { 47 continue 48 } 49 50 bundlePkg, category, ok := parseBundlePackage(p) 51 if !ok { 52 continue 53 } 54 55 // Allow import from main.go . 56 if mypkg == bundlePkg { 57 continue 58 } 59 60 // Allow import from package category across bundles. 61 bundlePath := path.Dir(bundlePkg) 62 if isBundle && myBundlePath == bundlePath && myCategory == category { 63 continue 64 } 65 66 categoryPkg := path.Join(bundlePath, "*", category) 67 68 issues = append(issues, &Issue{ 69 Pos: fs.Position(im.Pos()), 70 Msg: fmt.Sprintf("import of %s is only allowed from %s or its descendant", p, categoryPkg), 71 Link: "https://chromium.googlesource.com/chromiumos/platform/tast/+/HEAD/docs/writing_tests.md#Scoping-and-shared-code", 72 }) 73 } 74 75 return issues 76 }