Skip to content

Commit

Permalink
templates: remove LineCount, SourceSize, AllFiles, DeclCount, TokenCount
Browse files Browse the repository at this point in the history
They have been superseded by faster and more extensive code.

  LineCount  -> .Go.Lines
  SourceSize -> .All.Size
  DeclCount  -> .Decls
  TokenCount -> .Tokens
  • Loading branch information
egonelbre committed Dec 29, 2020
1 parent beef85e commit e60504f
Showing 1 changed file with 1 addition and 227 deletions.
228 changes: 1 addition & 227 deletions templates/templates.go
Original file line number Diff line number Diff line change
@@ -1,235 +1,9 @@
package templates

import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io"
"io/ioutil"
"os"
"sort"
"text/template"

"golang.org/x/tools/go/packages"

"github.com/loov/goda/memory"
)

func Parse(t string) (*template.Template, error) {
return template.New("").Funcs(template.FuncMap{
"LineCount": LineCount,
"SourceSize": SourceSize,
"AllFiles": AllFiles,
"DeclCount": CountDecls,
"TokenCount": CountTokens,
}).Funcs(numeric()).Parse(t)
}

func LineCount(vs ...interface{}) int64 {
var count int64

for _, filename := range filesFromInterface(vs...) {
r, err := os.Open(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "%v open failed: %v\n", filename, err)
continue
}
count += countLines(r)

if err := r.Close(); err != nil {
fmt.Fprintf(os.Stderr, "%v close failed: %v\n", filename, err)
continue
}
}

return count
}

func SourceSize(vs ...interface{}) memory.Bytes {
var size int64

for _, filename := range filesFromInterface(vs...) {
stat, err := os.Stat(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "%v stat failed: %v", filename, err)
continue
}
size += stat.Size()
}

return memory.Bytes(size)
}

func AllFiles(vs ...interface{}) (files []string) {
for _, v := range vs {
switch v := v.(type) {
case []string:
files = append(files, v...)
case *packages.Package:
files = append(files, allFiles(v)...)
case interface{ Pkg() *packages.Package }:
files = append(files, allFiles(v.Pkg())...)
}
}
return files
}

type DeclCount struct {
Func int64
Type int64
Const int64
Var int64
Other int64
}

func (decl DeclCount) Total() int64 {
return decl.Func + decl.Type + decl.Const + decl.Var + decl.Other
}

func CountDecls(vs ...interface{}) DeclCount {
var count DeclCount

for _, v := range vs {
fset := token.NewFileSet() // positions are relative to fset

for _, filename := range filesFromInterface(v) {
src, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "%q reading failed: %v\n", filename, err)
continue
}

f, err := parser.ParseFile(fset, filename, src, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "%q parsing failed: %v\n", filename, err)
continue
}

for _, decl := range f.Decls {
switch decl := decl.(type) {
case *ast.GenDecl:
switch decl.Tok {
case token.TYPE:
count.Type++
case token.VAR:
count.Var++
case token.CONST:
count.Const++
default:
count.Other++
}
case *ast.FuncDecl:
count.Func++
default:
count.Other++
}
}
}
}

return count
}

type TokenCount struct {
Code int64
Comment int64
Basic int64
}

func CountTokens(vs ...interface{}) TokenCount {
var count TokenCount
for _, v := range vs {
fset := token.NewFileSet() // positions are relative to fset
for _, filename := range filesFromInterface(v) {
src, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "%q reading failed: %v\n", filename, err)
continue
}

f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
if err != nil {
fmt.Fprintf(os.Stderr, "%q parsing failed: %v\n", filename, err)
continue
}

ast.Inspect(f, func(n ast.Node) bool {
if n == nil {
return true
}

switch n.(type) {
default:
count.Code++
case *ast.BasicLit:
count.Basic++
case *ast.CommentGroup, *ast.Comment:
count.Comment++
return false
}

return true
})
}
}

return count
}

func filesFromInterface(vs ...interface{}) []string {
var files []string
for _, v := range vs {
switch v := v.(type) {
// assume we want the list of files
case []string:
files = append(files, v...)
// assume we want the all files in package directories
case *packages.Package:
files = append(files, v.GoFiles...)
// assume we want the all files in package directories
case interface{ Pkg() *packages.Package }:
files = append(files, v.Pkg().GoFiles...)
}
}
return files
}

func allFiles(p *packages.Package) []string {
files := map[string]bool{}
for _, filename := range p.GoFiles {
files[filename] = true
}
for _, filename := range p.OtherFiles {
files[filename] = true
}

var list []string
for file := range files {
list = append(list, file)
}
sort.Strings(list)

return list
}

func countLines(r io.Reader) int64 {
var count int64
var buffer [1 << 20]byte
for {
n, err := r.Read(buffer[:])

for _, r := range buffer[:n] {
if r == 0 { // probably a binary file
return 0
}
if r == '\n' {
count++
}
}

if err != nil || n == 0 {
return count
}
}
return template.New("").Funcs(numeric()).Parse(t)
}

0 comments on commit e60504f

Please sign in to comment.