-
Notifications
You must be signed in to change notification settings - Fork 43
/
irprint.go
106 lines (89 loc) · 2.29 KB
/
irprint.go
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package irprint
import (
"bytes"
"fmt"
"go/format"
"io"
"reflect"
"github.com/quasilyte/go-ruleguard/ruleguard/ir"
)
func File(w io.Writer, f *ir.File) {
p := printer{}
p.printFile(f)
pretty, err := format.Source(p.buf.Bytes())
if err != nil {
fmt.Println(p.buf.String())
panic(err)
}
_, _ = w.Write(pretty)
}
type printer struct {
buf bytes.Buffer
}
func (p *printer) writef(format string, args ...interface{}) {
fmt.Fprintf(&p.buf, format, args...)
}
func (p *printer) printFile(f *ir.File) {
p.writef("ir.File{\n")
p.writef("PkgPath: %q,\n", f.PkgPath)
p.writef("CustomDecls: []string{\n")
for _, src := range f.CustomDecls {
p.writef("%q,\n", src)
}
p.writef("},\n")
p.writef("BundleImports: []ir.BundleImport{\n")
for _, imp := range f.BundleImports {
p.writef("Line: %d,\n", imp.Line)
p.writef("PkgPath: %q,\n", imp.PkgPath)
p.writef("Prefix: %q,\n", imp.PkgPath)
}
p.writef("},\n")
p.printReflectElem("RuleGroups", reflect.ValueOf(f.RuleGroups))
p.writef("}\n")
}
func (p *printer) printReflectElem(key string, v reflect.Value) {
if v.IsZero() {
return
}
if key != "" {
p.writef("%s: ", key)
}
if v.Type().Name() == "FilterOp" {
p.writef("ir.Filter%sOp,\n", v.Interface().(ir.FilterOp).String())
return
}
// There are tons of this, print it in a compact way.
if v.Type().Name() == "PatternString" {
v := v.Interface().(ir.PatternString)
p.writef("ir.PatternString{Line: %d, Value: %#v},\n", v.Line, v.Value)
return
}
if v.Type().Name() == "FilterExpr" {
v := v.Interface().(ir.FilterExpr)
if v.Op == ir.FilterStringOp || v.Op == ir.FilterVarPureOp || v.Op == ir.FilterVarTextOp {
p.writef("ir.FilterExpr{Line: %d, Op: ir.Filter%sOp, Src: %#v, Value: %#v},\n",
v.Line, v.Op.String(), v.Src, v.Value.(string))
return
}
}
if v.Type().Kind() == reflect.Struct {
p.writef("%s{\n", v.Type().String())
for i := 0; i < v.NumField(); i++ {
p.printReflectElem(v.Type().Field(i).Name, v.Field(i))
}
p.writef("},\n")
} else if v.Type().Kind() == reflect.Slice {
p.writef("%s{\n", v.Type().String())
for j := 0; j < v.Len(); j++ {
p.printReflectElem("", v.Index(j))
}
p.writef("},\n")
} else {
switch val := v.Interface().(type) {
case int64:
p.writef("int64(%v),\n", val)
default:
p.writef("%#v,\n", val)
}
}
}