File: nodecount.go

package info (click to toggle)
golang-golang-x-tools 1%3A0.25.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 22,724 kB
  • sloc: javascript: 2,027; asm: 1,645; sh: 166; yacc: 155; makefile: 49; ansic: 8
file content (71 lines) | stat: -rw-r--r-- 1,654 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The nodecount program illustrates the use of packages.Load to print
// the frequency of occurrence of each type of syntax node among the
// selected packages.
//
// Example usage:
//
//	$ nodecount golang.org/x/tools/... std
//
// A typical distribution is 40% identifiers, 10% literals, 8%
// selectors, and 6% calls; around 3% each of BinaryExpr, BlockStmt,
// AssignStmt, Field, and Comment; and the rest accounting for 20%.
package main

import (
	"flag"
	"fmt"
	"go/ast"
	"log"
	"reflect"
	"sort"

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

func main() {
	flag.Parse()

	// Parse specified packages.
	config := packages.Config{
		Mode:  packages.NeedSyntax | packages.NeedFiles,
		Tests: true,
	}
	pkgs, err := packages.Load(&config, flag.Args()...)
	if err != nil {
		log.Fatal(err)
	}

	// Count each type of syntax node.
	var (
		byType = make(map[reflect.Type]int)
		total  int
	)
	packages.Visit(pkgs, nil, func(p *packages.Package) {
		for _, f := range p.Syntax {
			ast.Inspect(f, func(n ast.Node) bool {
				if n != nil {
					byType[reflect.TypeOf(n)]++
					total++
				}
				return true
			})
		}
	})

	// Print results (percent, count, type) in descending order.
	var types []reflect.Type
	for t := range byType {
		types = append(types, t)
	}
	sort.Slice(types, func(i, j int) bool {
		return byType[types[i]] > byType[types[j]]
	})
	for _, t := range types {
		percent := 100 * float64(byType[t]) / float64(total)
		fmt.Printf("%6.2f%%\t%8d\t%s\n", percent, byType[t], t)
	}
}