...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package main
16
17 import (
18 "bytes"
19 "fmt"
20 "go/parser"
21 "go/token"
22 "io/ioutil"
23 "os"
24 "strconv"
25 )
26
27
28
29
30 func instrumentForCoverage(goenv *env, srcPath, srcName, coverVar, mode, outPath string) error {
31 goargs := goenv.goTool("cover", "-var", coverVar, "-mode", mode, "-o", outPath, srcPath)
32 if err := goenv.runCommand(goargs); err != nil {
33 return err
34 }
35
36 return registerCoverage(outPath, coverVar, srcName)
37 }
38
39
40
41
42
43 func registerCoverage(coverSrcFilename, varName, srcName string) error {
44 coverSrc, err := os.ReadFile(coverSrcFilename)
45 if err != nil {
46 return fmt.Errorf("instrumentForCoverage: reading instrumented source: %w", err)
47 }
48
49
50 fset := token.NewFileSet()
51 f, err := parser.ParseFile(fset, coverSrcFilename, coverSrc, parser.ParseComments)
52 if err != nil {
53 return nil
54 }
55
56
57
58
59 editor := NewBuffer(coverSrc)
60
61
62
63 const coverdataPath = "github.com/bazelbuild/rules_go/go/tools/coverdata"
64 var coverdataName string
65 for _, imp := range f.Imports {
66 path, err := strconv.Unquote(imp.Path.Value)
67 if err != nil {
68 return nil
69 }
70 if path == coverdataPath {
71 if imp.Name != nil {
72
73 if imp.Name.Name == "_" {
74
75 editor.Replace(
76 fset.Position(imp.Name.Pos()).Offset,
77 fset.Position(imp.Name.End()).Offset,
78 "coverdata")
79 coverdataName = "coverdata"
80 } else {
81 coverdataName = imp.Name.Name
82 }
83 } else {
84
85 coverdataName = "coverdata"
86 }
87 break
88 }
89 }
90 if coverdataName == "" {
91
92 coverdataName = "coverdata"
93 editor.Insert(fset.Position(f.Name.End()).Offset, fmt.Sprintf("; import %q", coverdataPath))
94 }
95
96
97 var buf = bytes.NewBuffer(editor.Bytes())
98 fmt.Fprintf(buf, `
99 func init() {
100 %s.RegisterFile(%q,
101 %[3]s.Count[:],
102 %[3]s.Pos[:],
103 %[3]s.NumStmt[:])
104 }
105 `, coverdataName, srcName, varName)
106 if err := ioutil.WriteFile(coverSrcFilename, buf.Bytes(), 0666); err != nil {
107 return fmt.Errorf("registerCoverage: %v", err)
108 }
109 return nil
110 }
111
View as plain text