Source file
src/go/types/format.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "bytes"
11 "fmt"
12 "go/ast"
13 "go/token"
14 "strconv"
15 "strings"
16 )
17
18 func sprintf(fset *token.FileSet, qf Qualifier, tpSubscripts bool, format string, args ...any) string {
19 for i, arg := range args {
20 switch a := arg.(type) {
21 case nil:
22 arg = "<nil>"
23 case operand:
24 panic("got operand instead of *operand")
25 case *operand:
26 arg = operandString(a, qf)
27 case []*operand:
28 var buf strings.Builder
29 buf.WriteByte('[')
30 for i, x := range a {
31 if i > 0 {
32 buf.WriteString(", ")
33 }
34 buf.WriteString(operandString(x, qf))
35 }
36 buf.WriteByte(']')
37 arg = buf.String()
38 case token.Pos:
39 if fset != nil {
40 arg = fset.Position(a).String()
41 }
42 case ast.Expr:
43 arg = ExprString(a)
44 case []ast.Expr:
45 var buf bytes.Buffer
46 buf.WriteByte('[')
47 writeExprList(&buf, a)
48 buf.WriteByte(']')
49 arg = buf.String()
50 case Object:
51 arg = ObjectString(a, qf)
52 case Type:
53 var buf bytes.Buffer
54 w := newTypeWriter(&buf, qf)
55 w.tpSubscripts = tpSubscripts
56 w.typ(a)
57 arg = buf.String()
58 case []Type:
59 var buf bytes.Buffer
60 w := newTypeWriter(&buf, qf)
61 w.tpSubscripts = tpSubscripts
62 buf.WriteByte('[')
63 for i, x := range a {
64 if i > 0 {
65 buf.WriteString(", ")
66 }
67 w.typ(x)
68 }
69 buf.WriteByte(']')
70 arg = buf.String()
71 case []*TypeParam:
72 var buf bytes.Buffer
73 w := newTypeWriter(&buf, qf)
74 w.tpSubscripts = tpSubscripts
75 buf.WriteByte('[')
76 for i, x := range a {
77 if i > 0 {
78 buf.WriteString(", ")
79 }
80 w.typ(x)
81 }
82 buf.WriteByte(']')
83 arg = buf.String()
84 }
85 args[i] = arg
86 }
87 return fmt.Sprintf(format, args...)
88 }
89
90
91 func (check *Checker) sprintf(format string, args ...any) string {
92 var fset *token.FileSet
93 var qf Qualifier
94 if check != nil {
95 fset = check.fset
96 qf = check.qualifier
97 }
98 return sprintf(fset, qf, false, format, args...)
99 }
100
101 func (check *Checker) trace(pos token.Pos, format string, args ...any) {
102 pos1 := check.fset.Position(pos)
103
104
105
106 w := ndigits(pos1.Line) + ndigits(pos1.Column)
107 pad := " "[:max(5-w, 0)]
108 fmt.Printf("%s%s: %s%s\n",
109 pos1,
110 pad,
111 strings.Repeat(". ", check.indent),
112 sprintf(check.fset, check.qualifier, true, format, args...),
113 )
114 }
115
116
117
118
119 func ndigits(x int) int {
120 switch {
121 case x < 10:
122 return 1
123 case x < 100:
124 return 2
125 default:
126 return 3
127 }
128 }
129
130
131 func (check *Checker) dump(format string, args ...any) {
132 fmt.Println(sprintf(check.fset, check.qualifier, true, format, args...))
133 }
134
135 func (check *Checker) qualifier(pkg *Package) string {
136
137 if pkg != check.pkg {
138 if check.pkgPathMap == nil {
139 check.pkgPathMap = make(map[string]map[string]bool)
140 check.seenPkgMap = make(map[*Package]bool)
141 check.markImports(check.pkg)
142 }
143
144 if len(check.pkgPathMap[pkg.name]) > 1 {
145 return strconv.Quote(pkg.path)
146 }
147 return pkg.name
148 }
149 return ""
150 }
151
152
153
154 func (check *Checker) markImports(pkg *Package) {
155 if check.seenPkgMap[pkg] {
156 return
157 }
158 check.seenPkgMap[pkg] = true
159
160 forName, ok := check.pkgPathMap[pkg.name]
161 if !ok {
162 forName = make(map[string]bool)
163 check.pkgPathMap[pkg.name] = forName
164 }
165 forName[pkg.path] = true
166
167 for _, imp := range pkg.imports {
168 check.markImports(imp)
169 }
170 }
171
172
173 func stripAnnotations(s string) string {
174 var buf strings.Builder
175 for _, r := range s {
176
177 if r < '₀' || '₀'+10 <= r {
178 buf.WriteRune(r)
179 }
180 }
181 if buf.Len() < len(s) {
182 return buf.String()
183 }
184 return s
185 }
186
View as plain text