golang.org/x/tools@v0.21.0/go/packages/internal/nodecount/nodecount.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // The nodecount program illustrates the use of packages.Load to print 6 // the frequency of occurrence of each type of syntax node among the 7 // selected packages. 8 // 9 // Example usage: 10 // 11 // $ nodecount golang.org/x/tools/... std 12 // 13 // A typical distribution is 40% identifiers, 10% literals, 8% 14 // selectors, and 6% calls; around 3% each of BinaryExpr, BlockStmt, 15 // AssignStmt, Field, and Comment; and the rest accounting for 20%. 16 package main 17 18 import ( 19 "flag" 20 "fmt" 21 "go/ast" 22 "log" 23 "reflect" 24 "sort" 25 26 "golang.org/x/tools/go/packages" 27 ) 28 29 func main() { 30 flag.Parse() 31 32 // Parse specified packages. 33 config := packages.Config{ 34 Mode: packages.NeedSyntax | packages.NeedFiles, 35 Tests: true, 36 } 37 pkgs, err := packages.Load(&config, flag.Args()...) 38 if err != nil { 39 log.Fatal(err) 40 } 41 42 // Count each type of syntax node. 43 var ( 44 byType = make(map[reflect.Type]int) 45 total int 46 ) 47 packages.Visit(pkgs, nil, func(p *packages.Package) { 48 for _, f := range p.Syntax { 49 ast.Inspect(f, func(n ast.Node) bool { 50 if n != nil { 51 byType[reflect.TypeOf(n)]++ 52 total++ 53 } 54 return true 55 }) 56 } 57 }) 58 59 // Print results (percent, count, type) in descending order. 60 var types []reflect.Type 61 for t := range byType { 62 types = append(types, t) 63 } 64 sort.Slice(types, func(i, j int) bool { 65 return byType[types[i]] > byType[types[j]] 66 }) 67 for _, t := range types { 68 percent := 100 * float64(byType[t]) / float64(total) 69 fmt.Printf("%6.2f%%\t%8d\t%s\n", percent, byType[t], t) 70 } 71 }