Skip to content

Commit 78cfd48

Browse files
author
Mathias M
authored
refac: remove pkg/types package (#55)
Fixes #51
1 parent 4b0625f commit 78cfd48

File tree

12 files changed

+236
-287
lines changed

12 files changed

+236
-287
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
v 1.4.0
2+
- refac: remove pkg/types package. #51
3+
- Add CLI support for coverage thresholds. #43
24
- refac: faster and cleaner code generator. #52
35

46
v 1.3.1

cmd/generator/main.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"strings"
1616
"text/template"
1717

18-
"github.com/matm/gocov-html/pkg/types"
18+
"github.com/matm/gocov-html/pkg/themes"
1919
)
2020

2121
const tmpl = `// Code generated by "go run generator.go". DO NOT EDIT.
@@ -25,14 +25,12 @@ package themes
2525
import (
2626
"text/template"
2727
"time"
28-
29-
"github.com/matm/gocov-html/pkg/types"
3028
)
3129
32-
func (t {{.Type}}) Data() *types.TemplateData {
33-
td:= &types.TemplateData{
30+
func (t {{.Type}}) Data() *templateData {
31+
td:= &templateData{
3432
When: time.Now().Format(time.RFC1123),
35-
ProjectURL: types.ProjectURL,
33+
ProjectURL: ProjectURL,
3634
}
3735
{{if .Style}}
3836
td.Style = "{{.Style}}"
@@ -159,7 +157,7 @@ type params struct {
159157
filename string
160158
rtype string // Receiver type.
161159
theme string
162-
assets types.StaticAssets
160+
assets themes.StaticAssets
163161
}
164162

165163
func main() {

cmd/gocov-html/main.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"runtime"
3030

3131
"github.com/matm/gocov-html/pkg/config"
32-
"github.com/matm/gocov-html/pkg/cov"
3332
"github.com/matm/gocov-html/pkg/themes"
3433
)
3534

@@ -94,13 +93,13 @@ func main() {
9493
log.Fatalf("Usage: %s data.json\n", os.Args[0])
9594
}
9695

97-
opts := cov.ReportOptions{
96+
opts := themes.ReportOptions{
9897
LowCoverageOnTop: *reverseOrder,
9998
Stylesheet: *css,
10099
CoverageMin: uint8(*minCoverage),
101100
CoverageMax: uint8(*maxCoverage),
102101
}
103-
if err := cov.HTMLReportCoverage(r, opts); err != nil {
102+
if err := themes.HTMLReportCoverage(r, opts); err != nil {
104103
log.Fatal(err)
105104
}
106105
}

pkg/themes/default.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@ package themes
22

33
//go:generate ../../generator
44

5-
import (
6-
"github.com/matm/gocov-html/pkg/types"
7-
)
8-
95
type defaultTheme struct{}
106

11-
func (t defaultTheme) Assets() types.StaticAssets {
12-
return types.StaticAssets{
7+
func (t defaultTheme) Assets() StaticAssets {
8+
return StaticAssets{
139
Stylesheets: []string{"style.css"},
1410
Index: "index.html",
1511
}

pkg/themes/default_gen.go

Lines changed: 3 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/themes/kit.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@ package themes
22

33
//go:generate ../../generator
44

5-
import (
6-
"github.com/matm/gocov-html/pkg/types"
7-
)
8-
95
type kitTheme struct{}
106

11-
func (t kitTheme) Assets() types.StaticAssets {
12-
return types.StaticAssets{
7+
func (t kitTheme) Assets() StaticAssets {
8+
return StaticAssets{
139
Stylesheets: []string{
1410
// From the official theme.
1511
"app.css",

pkg/themes/kit_gen.go

Lines changed: 3 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 163 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,20 @@
1-
// Copyright (c) 2012 The Gocov Authors.
2-
//
3-
// Permission is hereby granted, free of charge, to any person obtaining a copy
4-
// of this software and associated documentation files (the "Software"), to
5-
// deal in the Software without restriction, including without limitation the
6-
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7-
// sell copies of the Software, and to permit persons to whom the Software is
8-
// furnished to do so, subject to the following conditions:
9-
//
10-
// The above copyright notice and this permission notice shall be included in
11-
// all copies or substantial portions of the Software.
12-
//
13-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18-
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19-
// IN THE SOFTWARE.
20-
21-
package cov
1+
package themes
222

233
import (
244
"encoding/base64"
255
"encoding/json"
266
"fmt"
7+
"go/token"
8+
"html"
279
"io"
2810
"io/ioutil"
2911
"os"
12+
"path/filepath"
3013
"sort"
3114
"strings"
3215
"time"
3316

3417
"github.com/axw/gocov"
35-
"github.com/matm/gocov-html/pkg/themes"
36-
"github.com/matm/gocov-html/pkg/types"
3718
"github.com/rotisserie/eris"
3819
)
3920

@@ -97,10 +78,10 @@ func (r *report) clear() {
9778
r.packages = nil
9879
}
9980

100-
func buildReportPackage(pkg *gocov.Package, r *report) types.ReportPackage {
101-
rv := types.ReportPackage{
81+
func buildReportPackage(pkg *gocov.Package, r *report) reportPackage {
82+
rv := reportPackage{
10283
Pkg: pkg,
103-
Functions: make(types.ReportFunctionList, 0),
84+
Functions: make(reportFunctionList, 0),
10485
}
10586
for _, fn := range pkg.Functions {
10687
reached := 0
@@ -109,7 +90,7 @@ func buildReportPackage(pkg *gocov.Package, r *report) types.ReportPackage {
10990
reached++
11091
}
11192
}
112-
rf := types.ReportFunction{Function: fn, StatementsReached: reached}
93+
rf := reportFunction{Function: fn, StatementsReached: reached}
11394
covp := rf.CoveragePercent()
11495
if covp >= float64(r.CoverageMin) && covp <= float64(r.CoverageMax) {
11596
rv.Functions = append(rv.Functions, rf)
@@ -127,8 +108,7 @@ func buildReportPackage(pkg *gocov.Package, r *report) types.ReportPackage {
127108

128109
// printReport prints a coverage report to the given writer.
129110
func printReport(w io.Writer, r *report) error {
130-
theme := themes.Current()
131-
data := theme.Data()
111+
data := curTheme.Data()
132112

133113
// Base64 decoding of style data and script.
134114
s, err := base64.StdEncoding.DecodeString(data.Style)
@@ -154,7 +134,7 @@ func printReport(w io.Writer, r *report) error {
154134
}
155135
css = string(style)
156136
}
157-
reportPackages := make(types.ReportPackageList, len(r.packages))
137+
reportPackages := make(reportPackageList, len(r.packages))
158138
pkgNames := make([]string, len(r.packages))
159139
for i, pkg := range r.packages {
160140
reportPackages[i] = buildReportPackage(pkg, r)
@@ -170,7 +150,7 @@ func printReport(w io.Writer, r *report) error {
170150
)
171151

172152
if len(reportPackages) > 1 {
173-
rv := types.ReportPackage{
153+
rv := reportPackage{
174154
Pkg: &gocov.Package{Name: "Report Total"},
175155
}
176156
for _, rp := range reportPackages {
@@ -179,7 +159,7 @@ func printReport(w io.Writer, r *report) error {
179159
}
180160
data.Overview = &rv
181161
}
182-
err = theme.Template().Execute(w, data)
162+
err = curTheme.Template().Execute(w, data)
183163
return eris.Wrap(err, "execute template")
184164
}
185165

@@ -227,3 +207,154 @@ func HTMLReportCoverage(r io.Reader, opts ReportOptions) error {
227207
fmt.Fprintf(os.Stderr, "Took %v\n", time.Since(t0))
228208
return eris.Wrap(err, "HTML report")
229209
}
210+
211+
// ProjectURL is the project's site on GitHub.
212+
const ProjectURL = "https://github.com/matm/gocov-html"
213+
214+
const (
215+
hitPrefix = " "
216+
missPrefix = "MISS"
217+
)
218+
219+
type reportPackageList []reportPackage
220+
221+
type reportPackage struct {
222+
Pkg *gocov.Package
223+
Functions reportFunctionList
224+
TotalStatements int
225+
ReachedStatements int
226+
}
227+
228+
// PercentageReached computes the percentage of reached statements by the tests
229+
// for a package.
230+
func (rp *reportPackage) PercentageReached() float64 {
231+
var rv float64
232+
if rp.TotalStatements > 0 {
233+
rv = float64(rp.ReachedStatements) / float64(rp.TotalStatements) * 100
234+
}
235+
return rv
236+
}
237+
238+
// reportFunction is a gocov Function with some added stats.
239+
type reportFunction struct {
240+
*gocov.Function
241+
StatementsReached int
242+
}
243+
244+
// functionLine holds the line of code, its line number in the source file
245+
// and whether the tests reached it.
246+
type functionLine struct {
247+
Code string
248+
LineNumber int
249+
Missed bool
250+
}
251+
252+
// CoveragePercent is the percentage of code coverage for a function. Returns 100
253+
// if the function has no statement.
254+
func (f reportFunction) CoveragePercent() float64 {
255+
reached := f.StatementsReached
256+
var stmtPercent float64 = 0
257+
if len(f.Statements) > 0 {
258+
stmtPercent = float64(reached) / float64(len(f.Statements)) * 100
259+
} else if len(f.Statements) == 0 {
260+
stmtPercent = 100
261+
}
262+
return stmtPercent
263+
}
264+
265+
// ShortFileName returns the base path of the function's file name. Provided for
266+
// convenience to be used in the HTML template of the theme.
267+
func (f reportFunction) ShortFileName() string {
268+
return filepath.Base(f.File)
269+
}
270+
271+
// Lines returns information about all a function's Lines of code.
272+
func (f reportFunction) Lines() []functionLine {
273+
type annotator struct {
274+
fset *token.FileSet
275+
files map[string]*token.File
276+
}
277+
a := &annotator{}
278+
a.fset = token.NewFileSet()
279+
a.files = make(map[string]*token.File)
280+
281+
// Load the file for line information. Probably overkill, maybe
282+
// just compute the lines from offsets in here.
283+
setContent := false
284+
file := a.files[f.File]
285+
if file == nil {
286+
info, err := os.Stat(f.File)
287+
if err != nil {
288+
panic(err)
289+
}
290+
file = a.fset.AddFile(f.File, a.fset.Base(), int(info.Size()))
291+
setContent = true
292+
}
293+
294+
data, err := ioutil.ReadFile(f.File)
295+
if err != nil {
296+
panic(err)
297+
}
298+
299+
if setContent {
300+
// This processes the content and records line number info.
301+
file.SetLinesForContent(data)
302+
}
303+
304+
statements := f.Statements[:]
305+
lineno := file.Line(file.Pos(f.Start))
306+
lines := strings.Split(string(data)[f.Start:f.End], "\n")
307+
fls := make([]functionLine, len(lines))
308+
309+
for i, line := range lines {
310+
lineno := lineno + i
311+
statementFound := false
312+
hit := false
313+
for j := 0; j < len(statements); j++ {
314+
start := file.Line(file.Pos(statements[j].Start))
315+
if start == lineno {
316+
statementFound = true
317+
if !hit && statements[j].Reached > 0 {
318+
hit = true
319+
}
320+
statements = append(statements[:j], statements[j+1:]...)
321+
}
322+
}
323+
hitmiss := hitPrefix
324+
if statementFound && !hit {
325+
hitmiss = missPrefix
326+
}
327+
fls[i] = functionLine{
328+
Missed: hitmiss == missPrefix,
329+
LineNumber: lineno,
330+
Code: html.EscapeString(strings.Replace(line, "\t", " ", -1)),
331+
}
332+
}
333+
return fls
334+
}
335+
336+
// reportFunctionList is a list of functions for a report.
337+
type reportFunctionList []reportFunction
338+
339+
func (l reportFunctionList) Len() int {
340+
return len(l)
341+
}
342+
343+
// TODO make sort method configurable?
344+
func (l reportFunctionList) Less(i, j int) bool {
345+
var left, right float64
346+
if len(l[i].Statements) > 0 {
347+
left = float64(l[i].StatementsReached) / float64(len(l[i].Statements))
348+
}
349+
if len(l[j].Statements) > 0 {
350+
right = float64(l[j].StatementsReached) / float64(len(l[j].Statements))
351+
}
352+
if left < right {
353+
return true
354+
}
355+
return left == right && len(l[i].Statements) < len(l[j].Statements)
356+
}
357+
358+
func (l reportFunctionList) Swap(i, j int) {
359+
l[i], l[j] = l[j], l[i]
360+
}

0 commit comments

Comments
 (0)