mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
go.tools/cover: split parsing code out from cmd/cover
Split the profile parsing code out of cmd/cover into a reusable package, to support third-party coverage tools. R=golang-dev, r, adg CC=golang-dev https://golang.org/cl/36050045
This commit is contained in:
parent
ff84d756df
commit
df34f98521
@ -83,7 +83,7 @@ func main() {
|
|||||||
|
|
||||||
// Generate coverage-annotated source.
|
// Generate coverage-annotated source.
|
||||||
if *mode != "" {
|
if *mode != "" {
|
||||||
cover(flag.Arg(0))
|
annotate(flag.Arg(0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +319,7 @@ func initialComments(content []byte) []byte {
|
|||||||
return content[:end]
|
return content[:end]
|
||||||
}
|
}
|
||||||
|
|
||||||
func cover(name string) {
|
func annotate(name string) {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
content, err := ioutil.ReadFile(name)
|
content, err := ioutil.ReadFile(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,10 +10,14 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"go/build"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"code.google.com/p/go.tools/cover"
|
||||||
)
|
)
|
||||||
|
|
||||||
// funcOutput takes two file names as arguments, a coverage profile to read as input and an output
|
// funcOutput takes two file names as arguments, a coverage profile to read as input and an output
|
||||||
@ -29,7 +33,7 @@ import (
|
|||||||
// total: (statements) 91.4%
|
// total: (statements) 91.4%
|
||||||
|
|
||||||
func funcOutput(profile, outputFile string) error {
|
func funcOutput(profile, outputFile string) error {
|
||||||
profiles, err := ParseProfiles(profile)
|
profiles, err := cover.ParseProfiles(profile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -126,7 +130,7 @@ func (v *FuncVisitor) Visit(node ast.Node) ast.Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// coverage returns the fraction of the statements in the function that were covered, as a numerator and denominator.
|
// coverage returns the fraction of the statements in the function that were covered, as a numerator and denominator.
|
||||||
func (f *FuncExtent) coverage(profile *Profile) (num, den int64) {
|
func (f *FuncExtent) coverage(profile *cover.Profile) (num, den int64) {
|
||||||
// We could avoid making this n^2 overall by doing a single scan and annotating the functions,
|
// We could avoid making this n^2 overall by doing a single scan and annotating the functions,
|
||||||
// but the sizes of the data structures is never very large and the scan is almost instantaneous.
|
// but the sizes of the data structures is never very large and the scan is almost instantaneous.
|
||||||
var covered, total int64
|
var covered, total int64
|
||||||
@ -150,3 +154,13 @@ func (f *FuncExtent) coverage(profile *Profile) (num, den int64) {
|
|||||||
}
|
}
|
||||||
return covered, total
|
return covered, total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findFile finds the location of the named file in GOROOT, GOPATH etc.
|
||||||
|
func findFile(file string) (string, error) {
|
||||||
|
dir, file := filepath.Split(file)
|
||||||
|
pkg, err := build.Import(dir, ".", build.FindOnly)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("can't find %q: %v", file, err)
|
||||||
|
}
|
||||||
|
return filepath.Join(pkg.Dir, file), nil
|
||||||
|
}
|
||||||
|
@ -16,13 +16,15 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"code.google.com/p/go.tools/cover"
|
||||||
)
|
)
|
||||||
|
|
||||||
// htmlOutput reads the profile data from profile and generates an HTML
|
// htmlOutput reads the profile data from profile and generates an HTML
|
||||||
// coverage report, writing it to outfile. If outfile is empty,
|
// coverage report, writing it to outfile. If outfile is empty,
|
||||||
// it writes the report to a temporary file and opens it in a web browser.
|
// it writes the report to a temporary file and opens it in a web browser.
|
||||||
func htmlOutput(profile, outfile string) error {
|
func htmlOutput(profile, outfile string) error {
|
||||||
profiles, err := ParseProfiles(profile)
|
profiles, err := cover.ParseProfiles(profile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -83,7 +85,7 @@ func htmlOutput(profile, outfile string) error {
|
|||||||
|
|
||||||
// htmlGen generates an HTML coverage report with the provided filename,
|
// htmlGen generates an HTML coverage report with the provided filename,
|
||||||
// source code, and tokens, and writes it to the given Writer.
|
// source code, and tokens, and writes it to the given Writer.
|
||||||
func htmlGen(w io.Writer, src []byte, boundaries []Boundary) error {
|
func htmlGen(w io.Writer, src []byte, boundaries []cover.Boundary) error {
|
||||||
dst := bufio.NewWriter(w)
|
dst := bufio.NewWriter(w)
|
||||||
for i := range src {
|
for i := range src {
|
||||||
for len(boundaries) > 0 && boundaries[0].Offset == i {
|
for len(boundaries) > 0 && boundaries[0].Offset == i {
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package main
|
// Package cover provides support for parsing coverage profiles
|
||||||
|
// generated by "go test -coverprofile=cover.out".
|
||||||
|
package cover
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -37,10 +37,10 @@ func (p byFileName) Len() int { return len(p) }
|
|||||||
func (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName }
|
func (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName }
|
||||||
func (p byFileName) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
func (p byFileName) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||||
|
|
||||||
// ParseProfiles parses profile data from the given Reader and returns a
|
// ParseProfiles parses profile data in the specified file and returns a
|
||||||
// Profile for each file.
|
// Profile for each source file described therein.
|
||||||
func ParseProfiles(fileName string) ([]*Profile, error) {
|
func ParseProfiles(fileName string) ([]*Profile, error) {
|
||||||
pf, err := os.Open(profile)
|
pf, err := os.Open(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -188,13 +188,3 @@ func (b boundariesByPos) Less(i, j int) bool {
|
|||||||
}
|
}
|
||||||
return b[i].Offset < b[j].Offset
|
return b[i].Offset < b[j].Offset
|
||||||
}
|
}
|
||||||
|
|
||||||
// findFile finds the location of the named file in GOROOT, GOPATH etc.
|
|
||||||
func findFile(file string) (string, error) {
|
|
||||||
dir, file := filepath.Split(file)
|
|
||||||
pkg, err := build.Import(dir, ".", build.FindOnly)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("can't find %q: %v", file, err)
|
|
||||||
}
|
|
||||||
return filepath.Join(pkg.Dir, file), nil
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user