Skip to content

Commit 96d2e44

Browse files
committed
go/packages/internal/linecount: add -nonblank flag
Change-Id: I2c2b63dd090dcbefb81a28e9c84c13c1356bcbd3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/692635 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
1 parent d507345 commit 96d2e44

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

go/packages/internal/linecount/linecount.go

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
//
99
// Example: show gopls' total source line count, and its breakdown
1010
// between gopls, x/tools, and the std go/* packages. (The balance
11-
// comes from other std packages.)
11+
// comes from other std packages, other x/ repos, and external
12+
// dependencies.)
1213
//
1314
// $ linecount -mode=total ./gopls
1415
// 752124
@@ -41,6 +42,8 @@ import (
4142
"cmp"
4243
"flag"
4344
"fmt"
45+
"go/scanner"
46+
"go/token"
4447
"log"
4548
"os"
4649
"path"
@@ -53,7 +56,6 @@ import (
5356
)
5457

5558
// TODO(adonovan): filters:
56-
// - exclude comment and blank lines (-nonblank)
5759
// - exclude generated files (-generated=false)
5860
// - exclude non-CompiledGoFiles
5961
// - include OtherFiles (asm, etc)
@@ -75,8 +77,9 @@ func main() {
7577
log.SetFlags(0)
7678
var (
7779
mode = flag.String("mode", "file", "group lines by 'module', 'package', or 'file', or show only 'total'")
78-
prefix = flag.String("prefix", "", "only count files in packages whose path has the specified prefix")
79-
onlyModule = flag.String("module", "", "only count files in the specified module")
80+
prefix = flag.String("prefix", "", "count files only in packages whose path has the specified prefix")
81+
onlyModule = flag.String("module", "", "count files only in the specified module")
82+
nonblank = flag.Bool("nonblank", false, "count only non-comment, non-blank lines")
8083
)
8184
flag.Usage = usage
8285
flag.Parse()
@@ -128,7 +131,8 @@ func main() {
128131
if err != nil {
129132
return err
130133
}
131-
n := bytes.Count(data, []byte("\n"))
134+
135+
n := count(*nonblank, data)
132136

133137
mu.Lock()
134138
byFile[f] = n
@@ -187,3 +191,35 @@ func within(file, dir string) bool {
187191
return file == dir ||
188192
strings.HasPrefix(file, dir) && file[len(dir)] == os.PathSeparator
189193
}
194+
195+
// count counts lines, or non-comment non-blank lines.
196+
func count(nonblank bool, src []byte) int {
197+
if nonblank {
198+
// Count distinct lines containing tokens.
199+
var (
200+
fset = token.NewFileSet()
201+
f = fset.AddFile("", fset.Base(), len(src))
202+
prevLine = 0
203+
count = 0
204+
scan scanner.Scanner
205+
)
206+
scan.Init(f, src, nil, 0)
207+
for {
208+
pos, tok, _ := scan.Scan()
209+
if tok == token.EOF {
210+
break
211+
}
212+
// This may be slow because it binary
213+
// searches the newline offset table.
214+
line := f.PositionFor(pos, false).Line // ignore //line directives
215+
if line > prevLine {
216+
prevLine = line
217+
count++
218+
}
219+
}
220+
return count
221+
}
222+
223+
// Count all lines.
224+
return bytes.Count(src, []byte("\n"))
225+
}

0 commit comments

Comments
 (0)