--- /dev/null
+pkg go/build, type Directive struct #56986
+pkg go/build, type Directive struct, Pos token.Position #56986
+pkg go/build, type Directive struct, Text string #56986
+pkg go/build, type Package struct, Directives []Directive #56986
+pkg go/build, type Package struct, TestDirectives []Directive #56986
+pkg go/build, type Package struct, XTestDirectives []Directive #56986
TestmainGo *[]byte // content for _testmain.go
Embed map[string][]string // //go:embed comment mapping
OrigImportPath string // original import path before adding '_test' suffix
+ Directives []build.Directive
+ TestDirectives []build.Directive
+ XTestDirectives []build.Directive
Asmflags []string // -asmflags for this package
Gcflags []string // -gcflags for this package
p.TestEmbedPatterns = pp.TestEmbedPatterns
p.XTestEmbedPatterns = pp.XTestEmbedPatterns
p.Internal.OrigImportPath = pp.ImportPath
+ p.Internal.Directives = pp.Directives
+ p.Internal.TestDirectives = pp.TestDirectives
+ p.Internal.XTestDirectives = pp.XTestDirectives
}
// A PackageError describes an error loading information about a package.
// fileInfo records information learned about a file included in a build.
type fileInfo struct {
- name string // full name including dir
- header []byte
- fset *token.FileSet
- parsed *ast.File
- parseErr error
- imports []fileImport
- embeds []fileEmbed
+ name string // full name including dir
+ header []byte
+ fset *token.FileSet
+ parsed *ast.File
+ parseErr error
+ imports []fileImport
+ embeds []fileEmbed
+ directives []build.Directive
// Additional fields added to go/build's fileinfo for the purposes of the modindex package.
binaryOnly bool
"errors"
"fmt"
"go/ast"
+ "go/build"
"go/parser"
"go/token"
"io"
}
}
+ // Extract directives.
+ for _, group := range info.parsed.Comments {
+ if group.Pos() >= info.parsed.Package {
+ break
+ }
+ for _, c := range group.List {
+ if strings.HasPrefix(c.Text, "//go:") {
+ info.directives = append(info.directives, build.Directive{Text: c.Text, Pos: info.fset.Position(c.Slash)})
+ }
+ }
+ }
+
// If the file imports "embed",
// we have to look for //go:embed comments
// in the remainder of the file.
var fileList *[]string
var importMap, embedMap map[string][]token.Position
+ var directives *[]build.Directive
switch {
case isCgo:
allTags["cgo"] = true
fileList = &p.CgoFiles
importMap = importPos
embedMap = embedPos
+ directives = &p.Directives
} else {
// Ignore Imports and Embeds from cgo files if cgo is disabled.
fileList = &p.IgnoredGoFiles
fileList = &p.XTestGoFiles
importMap = xTestImportPos
embedMap = xTestEmbedPos
+ directives = &p.XTestDirectives
case isTest:
fileList = &p.TestGoFiles
importMap = testImportPos
embedMap = testEmbedPos
+ directives = &p.TestDirectives
default:
fileList = &p.GoFiles
importMap = importPos
embedMap = embedPos
+ directives = &p.Directives
}
*fileList = append(*fileList, name)
if importMap != nil {
embedMap[e.pattern] = append(embedMap[e.pattern], e.position)
}
}
+ if directives != nil {
+ *directives = append(*directives, tf.directives()...)
+ }
}
p.EmbedPatterns, p.EmbedPatternPos = cleanDecls(embedPos)
return pos + 4 + n*(4*5)
}
+func (sf *sourceFile) directivesOffset() int {
+ pos := sf.embedsOffset()
+ n := sf.d.intAt(pos)
+ // each import is 5 uint32s (string + tokpos)
+ return pos + 4 + n*(4*5)
+}
+
func (sf *sourceFile) imports() []rawImport {
sf.onceReadImports.Do(func() {
importsOffset := sf.importsOffset()
return ret
}
+func (sf *sourceFile) directives() []build.Directive {
+ directivesOffset := sf.directivesOffset()
+ r := sf.d.readAt(directivesOffset)
+ numDirectives := r.int()
+ ret := make([]build.Directive, numDirectives)
+ for i := range ret {
+ ret[i] = build.Directive{Text: r.string(), Pos: r.tokpos()}
+ }
+ return ret
+}
+
func asString(b []byte) string {
return unsafe.String(unsafe.SliceData(b), len(b))
}
"encoding/json"
"errors"
"fmt"
+ "go/build"
"go/doc"
"go/scanner"
"go/token"
plusBuildConstraints []string
imports []rawImport
embeds []embed
+ directives []build.Directive
}
type rawImport struct {
goBuildConstraint: info.goBuildConstraint,
plusBuildConstraints: info.plusBuildConstraints,
binaryOnly: info.binaryOnly,
+ directives: info.directives,
}
if info.parsed != nil {
rf.pkgName = info.parsed.Name.Name
"sort"
)
-const indexVersion = "go index v1" // 11 bytes (plus \n), to align uint32s in index
+const indexVersion = "go index v2" // 11 bytes (plus \n), to align uint32s in index
// encodeModuleBytes produces the encoded representation of the module index.
// encodeModuleBytes may modify the packages slice.
e.String(embed.pattern)
e.Position(embed.position)
}
+
+ e.Int(len(f.directives))
+ for _, d := range f.directives {
+ e.String(d.Text)
+ e.Position(d.Pos)
+ }
}
func newEncoder() *encoder {
TestGoFiles []string // _test.go files in package
XTestGoFiles []string // _test.go files outside package
+ // Go directive comments (//go:zzz...) found in source files.
+ Directives []Directive
+ TestDirectives []Directive
+ XTestDirectives []Directive
+
// Dependency information
Imports []string // import paths from GoFiles, CgoFiles
ImportPos map[string][]token.Position // line information for Imports
XTestEmbedPatternPos map[string][]token.Position // line information for XTestEmbedPatternPos
}
+// A Directive is a Go directive comment (//go:zzz...) found in a source file.
+type Directive struct {
+ Text string // full line comment including leading slashes
+ Pos token.Position // position of comment
+}
+
// IsCommand reports whether the package is considered a
// command to be installed (not just a library).
// Packages named "main" are treated as commands.
var fileList *[]string
var importMap, embedMap map[string][]token.Position
+ var directives *[]Directive
switch {
case isCgo:
allTags["cgo"] = true
fileList = &p.CgoFiles
importMap = importPos
embedMap = embedPos
+ directives = &p.Directives
} else {
// Ignore imports and embeds from cgo files if cgo is disabled.
fileList = &p.IgnoredGoFiles
fileList = &p.XTestGoFiles
importMap = xTestImportPos
embedMap = xTestEmbedPos
+ directives = &p.XTestDirectives
case isTest:
fileList = &p.TestGoFiles
importMap = testImportPos
embedMap = testEmbedPos
+ directives = &p.TestDirectives
default:
fileList = &p.GoFiles
importMap = importPos
embedMap = embedPos
+ directives = &p.Directives
}
*fileList = append(*fileList, name)
if importMap != nil {
embedMap[emb.pattern] = append(embedMap[emb.pattern], emb.pos)
}
}
+ if directives != nil {
+ *directives = append(*directives, info.directives...)
+ }
}
for tag := range allTags {
// fileInfo records information learned about a file included in a build.
type fileInfo struct {
- name string // full name including dir
- header []byte
- fset *token.FileSet
- parsed *ast.File
- parseErr error
- imports []fileImport
- embeds []fileEmbed
+ name string // full name including dir
+ header []byte
+ fset *token.FileSet
+ parsed *ast.File
+ parseErr error
+ imports []fileImport
+ embeds []fileEmbed
+ directives []Directive
}
type fileImport struct {
package build
import (
+ "fmt"
"internal/testenv"
"io"
"os"
t.Errorf("AllTags = %v, want empty", p.AllTags)
}
}
+
+func TestDirectives(t *testing.T) {
+ p, err := ImportDir("testdata/directives", 0)
+ if err != nil {
+ t.Fatalf("could not import testdata: %v", err)
+ }
+
+ check := func(name string, list []Directive, want string) {
+ if runtime.GOOS == "windows" {
+ want = strings.ReplaceAll(want, "testdata/directives/", `testdata\\directives\\`)
+ }
+ t.Helper()
+ s := fmt.Sprintf("%q", list)
+ if s != want {
+ t.Errorf("%s = %s, want %s", name, s, want)
+ }
+ }
+ check("Directives", p.Directives,
+ `[{"//go:main1" "testdata/directives/a.go:1:1"} {"//go:plant" "testdata/directives/eve.go:1:1"}]`)
+ check("TestDirectives", p.TestDirectives,
+ `[{"//go:test1" "testdata/directives/a_test.go:1:1"} {"//go:test2" "testdata/directives/b_test.go:1:1"}]`)
+ check("XTestDirectives", p.XTestDirectives,
+ `[{"//go:xtest1" "testdata/directives/c_test.go:1:1"} {"//go:xtest2" "testdata/directives/d_test.go:1:1"} {"//go:xtest3" "testdata/directives/d_test.go:2:1"}]`)
+}
}
}
+ // Extract directives.
+ for _, group := range info.parsed.Comments {
+ if group.Pos() >= info.parsed.Package {
+ break
+ }
+ for _, c := range group.List {
+ if strings.HasPrefix(c.Text, "//go:") {
+ info.directives = append(info.directives, Directive{c.Text, info.fset.Position(c.Slash)})
+ }
+ }
+ }
+
// If the file imports "embed",
// we have to look for //go:embed comments
// in the remainder of the file.
--- /dev/null
+//go:main1
+
+package p
--- /dev/null
+//go:test1
+
+package p
--- /dev/null
+//go:test2
+
+package p
+
+//go:ignored
--- /dev/null
+//go:xtest1
+
+package p_test
+
+//go:ignored
--- /dev/null
+//go:xtest2
+//go:xtest3
+
+package p_test
--- /dev/null
+//go:plant
+//axiom:plant
+
+package p