CgoFiles []string `json:",omitempty"` // .go source files that import "C"
CompiledGoFiles []string `json:",omitempty"` // .go output from running cgo on CgoFiles
IgnoredGoFiles []string `json:",omitempty"` // .go source files ignored due to build constraints
+ InvalidGoFiles []string `json:",omitempty"` // .go source files with detected problems (parse error, wrong package name, and so on)
IgnoredOtherFiles []string `json:",omitempty"` // non-.go source files ignored due to build constraints
CFiles []string `json:",omitempty"` // .c source files
CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files
p.CgoFiles,
// no p.CompiledGoFiles, because they are from GoFiles or generated by us
p.IgnoredGoFiles,
+ // no p.InvalidGoFiles, because they are from GoFiles
p.IgnoredOtherFiles,
p.CFiles,
p.CXXFiles,
p.GoFiles = pp.GoFiles
p.CgoFiles = pp.CgoFiles
p.IgnoredGoFiles = pp.IgnoredGoFiles
+ p.InvalidGoFiles = pp.InvalidGoFiles
p.IgnoredOtherFiles = pp.IgnoredOtherFiles
p.CFiles = pp.CFiles
p.CXXFiles = pp.CXXFiles
}
if opts.MainOnly {
- pkgs = mainPackagesOnly(pkgs, patterns)
+ pkgs = mainPackagesOnly(pkgs, matches)
}
// Now that CmdlinePkg is set correctly,
// mainPackagesOnly filters out non-main packages matched only by arguments
// containing "..." and returns the remaining main packages.
//
+// Packages with missing, invalid, or ambiguous names may be treated as
+// possibly-main packages.
+//
// mainPackagesOnly sets a non-main package's Error field and returns it if it
// is named by a literal argument.
//
// mainPackagesOnly prints warnings for non-literal arguments that only match
// non-main packages.
-func mainPackagesOnly(pkgs []*Package, patterns []string) []*Package {
- matchers := make([]func(string) bool, len(patterns))
- for i, p := range patterns {
- if strings.Contains(p, "...") {
- matchers[i] = search.MatchPattern(p)
+func mainPackagesOnly(pkgs []*Package, matches []*search.Match) []*Package {
+ treatAsMain := map[string]bool{}
+ for _, m := range matches {
+ if m.IsLiteral() {
+ for _, path := range m.Pkgs {
+ treatAsMain[path] = true
+ }
}
}
- matchedPkgs := make([]*Package, 0, len(pkgs))
- mainCount := make([]int, len(patterns))
- nonMainCount := make([]int, len(patterns))
+ var mains []*Package
for _, pkg := range pkgs {
- if pkg.Name == "main" || (pkg.Incomplete && pkg.Name == "") {
- matchedPkgs = append(matchedPkgs, pkg)
- for i := range patterns {
- if matchers[i] != nil && matchers[i](pkg.ImportPath) {
- mainCount[i]++
- }
- }
- } else {
- for i := range patterns {
- if matchers[i] == nil && patterns[i] == pkg.ImportPath {
- if pkg.Error == nil {
- pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}}
- }
- matchedPkgs = append(matchedPkgs, pkg)
- } else if matchers[i] != nil && matchers[i](pkg.ImportPath) {
- nonMainCount[i]++
- }
+ if pkg.Name == "main" {
+ treatAsMain[pkg.ImportPath] = true
+ mains = append(mains, pkg)
+ continue
+ }
+
+ if len(pkg.InvalidGoFiles) > 0 { // TODO(#45999): && pkg.Name == "", but currently go/build sets pkg.Name arbitrarily if it is ambiguous.
+ // The package has (or may have) conflicting names, and we can't easily
+ // tell whether one of them is "main". So assume that it could be, and
+ // report an error for the package.
+ treatAsMain[pkg.ImportPath] = true
+ }
+ if treatAsMain[pkg.ImportPath] {
+ if pkg.Error == nil {
+ pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}}
}
+ mains = append(mains, pkg)
}
}
- for i, p := range patterns {
- if matchers[i] != nil && mainCount[i] == 0 && nonMainCount[i] > 0 {
- fmt.Fprintf(os.Stderr, "go: warning: %q matched no main packages\n", p)
+
+ for _, m := range matches {
+ if m.IsLiteral() || len(m.Pkgs) == 0 {
+ continue
+ }
+ foundMain := false
+ for _, path := range m.Pkgs {
+ if treatAsMain[path] {
+ foundMain = true
+ break
+ }
+ }
+ if !foundMain {
+ fmt.Fprintf(os.Stderr, "go: warning: %q matched only non-main packages\n", m.Pattern())
}
}
- return matchedPkgs
+ return mains
}
type mainPackageError struct {