/* Copyright 2021 Qiniu Cloud (qiniu.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package build import ( "crypto/sha256" "fmt" "path" "time" ) // declareCoverVars attaches the required cover variables names // to the files, to be used when annotating the files. func declareCoverVars(p *Package) map[string]*FileVar { coverVars := make(map[string]*FileVar) coverIndex := 0 // We create the cover counters as new top-level variables in the package. // We need to avoid collisions with user variables (GoCover_0 is unlikely but still) // and more importantly with dot imports of other covered packages, // so we append 12 hex digits from the SHA-256 of the import path. // The point is only to avoid accidents, not to defeat users determined to // break things. sum := sha256.Sum256([]byte(p.ImportPath)) h := fmt.Sprintf("%x", sum[:6]) for _, file := range p.GoFiles { // These names appear in the cmd/cover HTML interface. var longFile = path.Join(p.ImportPath, file) coverVars[file] = &FileVar{ File: longFile, Var: fmt.Sprintf("GoCover_%d_%x", coverIndex, h), } coverIndex++ } for _, file := range p.CgoFiles { // These names appear in the cmd/cover HTML interface. var longFile = path.Join(p.ImportPath, file) coverVars[file] = &FileVar{ File: longFile, Var: fmt.Sprintf("GoCover_%d_%x", coverIndex, h), } coverIndex++ } return coverVars } // PackageCover holds all the generate coverage variables of a package type PackageCover struct { Package *Package Vars map[string]*FileVar } // FileVar holds the name of the generated coverage variables targeting the named file. type FileVar struct { File string // 这里其实不是文件名,是 importpath + filename Var string } // Package map a package output by go list // this is subset of package struct in: https://github.com/golang/go/blob/master/src/cmd/go/internal/load/pkg.go#L58 type Package struct { Dir string `json:"Dir"` // directory containing package sources ImportPath string `json:"ImportPath"` // import path of package in dir Name string `json:"Name"` // package name Target string `json:",omitempty"` // installed target for this package (may be executable) Root string `json:",omitempty"` // Go root, Go path dir, or module root dir containing this package Module *ModulePublic `json:",omitempty"` // info about package's module, if any Goroot bool `json:"Goroot,omitempty"` // is this package in the Go root? Standard bool `json:"Standard,omitempty"` // is this package part of the standard Go library? DepOnly bool `json:"DepOnly,omitempty"` // package is only a dependency, not explicitly listed // Source files GoFiles []string `json:"GoFiles,omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) CgoFiles []string `json:"CgoFiles,omitempty"` // .go source files that import "C" // Dependency information Deps []string `json:"Deps,omitempty"` // all (recursively) imported dependencies Imports []string `json:",omitempty"` // import paths used by this package ImportMap map[string]string `json:",omitempty"` // map from source import to ImportPath (identity entries omitted) // Error information Incomplete bool `json:"Incomplete,omitempty"` // this package or a dependency has an error Error *PackageError `json:"Error,omitempty"` // error loading package DepsErrors []*PackageError `json:"DepsErrors,omitempty"` // errors loading dependencies } // ModulePublic represents the package info of a module type ModulePublic struct { Path string `json:",omitempty"` // module path Version string `json:",omitempty"` // module version Versions []string `json:",omitempty"` // available module versions Replace *ModulePublic `json:",omitempty"` // replaced by this module Time *time.Time `json:",omitempty"` // time version was created Update *ModulePublic `json:",omitempty"` // available update (with -u) Main bool `json:",omitempty"` // is this the main module? Indirect bool `json:",omitempty"` // module is only indirectly needed by main module Dir string `json:",omitempty"` // directory holding local copy of files, if any GoMod string `json:",omitempty"` // path to go.mod file describing module, if any GoVersion string `json:",omitempty"` // go version used in module Error *ModuleError `json:",omitempty"` // error loading module } // ModuleError represents the error loading module type ModuleError struct { Err string // error text } // PackageError is the error info for a package when list failed type PackageError struct { ImportStack []string // shortest path from package named on command line to this one Pos string // position of error (if present, file:line:col) Err string // the error itself }