Source file src/cmd/vendor/golang.org/x/tools/internal/packagepath/packagepath.go
1 // Copyright 2025 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package packagepath provides metadata operations on package path 6 // strings. 7 package packagepath 8 9 // (This package should not depend on go/ast.) 10 import "strings" 11 12 // CanImport reports whether one package is allowed to import another. 13 // 14 // TODO(adonovan): allow customization of the accessibility relation 15 // (e.g. for Bazel). 16 func CanImport(from, to string) bool { 17 // TODO(adonovan): better segment hygiene. 18 if to == "internal" || strings.HasPrefix(to, "internal/") { 19 // Special case: only std packages may import internal/... 20 // We can't reliably know whether we're in std, so we 21 // use a heuristic on the first segment. 22 first, _, _ := strings.Cut(from, "/") 23 if strings.Contains(first, ".") { 24 return false // example.com/foo ∉ std 25 } 26 if first == "testdata" { 27 return false // testdata/foo ∉ std 28 } 29 } 30 if strings.HasSuffix(to, "/internal") { 31 return strings.HasPrefix(from, to[:len(to)-len("/internal")]) 32 } 33 if i := strings.LastIndex(to, "/internal/"); i >= 0 { 34 return strings.HasPrefix(from, to[:i]) 35 } 36 return true 37 } 38 39 // IsStdPackage reports whether the specified package path belongs to a 40 // package in the standard library (including internal dependencies). 41 func IsStdPackage(path string) bool { 42 // A standard package has no dot in its first segment. 43 // (It may yet have a dot, e.g. "vendor/golang.org/x/foo".) 44 slash := strings.IndexByte(path, '/') 45 if slash < 0 { 46 slash = len(path) 47 } 48 return !strings.Contains(path[:slash], ".") && path != "testdata" 49 } 50