xref: /aosp_15_r20/external/go-cmp/cmp/internal/value/name.go (revision 88d15eac089d7f20c739ff1001d56b91872b21a1)
1*88d15eacSSasha Smundak// Copyright 2020, The Go Authors. All rights reserved.
2*88d15eacSSasha Smundak// Use of this source code is governed by a BSD-style
3*88d15eacSSasha Smundak// license that can be found in the LICENSE file.
4*88d15eacSSasha Smundak
5*88d15eacSSasha Smundakpackage value
6*88d15eacSSasha Smundak
7*88d15eacSSasha Smundakimport (
8*88d15eacSSasha Smundak	"reflect"
9*88d15eacSSasha Smundak	"strconv"
10*88d15eacSSasha Smundak)
11*88d15eacSSasha Smundak
12*88d15eacSSasha Smundakvar anyType = reflect.TypeOf((*interface{})(nil)).Elem()
13*88d15eacSSasha Smundak
14*88d15eacSSasha Smundak// TypeString is nearly identical to reflect.Type.String,
15*88d15eacSSasha Smundak// but has an additional option to specify that full type names be used.
16*88d15eacSSasha Smundakfunc TypeString(t reflect.Type, qualified bool) string {
17*88d15eacSSasha Smundak	return string(appendTypeName(nil, t, qualified, false))
18*88d15eacSSasha Smundak}
19*88d15eacSSasha Smundak
20*88d15eacSSasha Smundakfunc appendTypeName(b []byte, t reflect.Type, qualified, elideFunc bool) []byte {
21*88d15eacSSasha Smundak	// BUG: Go reflection provides no way to disambiguate two named types
22*88d15eacSSasha Smundak	// of the same name and within the same package,
23*88d15eacSSasha Smundak	// but declared within the namespace of different functions.
24*88d15eacSSasha Smundak
25*88d15eacSSasha Smundak	// Use the "any" alias instead of "interface{}" for better readability.
26*88d15eacSSasha Smundak	if t == anyType {
27*88d15eacSSasha Smundak		return append(b, "any"...)
28*88d15eacSSasha Smundak	}
29*88d15eacSSasha Smundak
30*88d15eacSSasha Smundak	// Named type.
31*88d15eacSSasha Smundak	if t.Name() != "" {
32*88d15eacSSasha Smundak		if qualified && t.PkgPath() != "" {
33*88d15eacSSasha Smundak			b = append(b, '"')
34*88d15eacSSasha Smundak			b = append(b, t.PkgPath()...)
35*88d15eacSSasha Smundak			b = append(b, '"')
36*88d15eacSSasha Smundak			b = append(b, '.')
37*88d15eacSSasha Smundak			b = append(b, t.Name()...)
38*88d15eacSSasha Smundak		} else {
39*88d15eacSSasha Smundak			b = append(b, t.String()...)
40*88d15eacSSasha Smundak		}
41*88d15eacSSasha Smundak		return b
42*88d15eacSSasha Smundak	}
43*88d15eacSSasha Smundak
44*88d15eacSSasha Smundak	// Unnamed type.
45*88d15eacSSasha Smundak	switch k := t.Kind(); k {
46*88d15eacSSasha Smundak	case reflect.Bool, reflect.String, reflect.UnsafePointer,
47*88d15eacSSasha Smundak		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
48*88d15eacSSasha Smundak		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
49*88d15eacSSasha Smundak		reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
50*88d15eacSSasha Smundak		b = append(b, k.String()...)
51*88d15eacSSasha Smundak	case reflect.Chan:
52*88d15eacSSasha Smundak		if t.ChanDir() == reflect.RecvDir {
53*88d15eacSSasha Smundak			b = append(b, "<-"...)
54*88d15eacSSasha Smundak		}
55*88d15eacSSasha Smundak		b = append(b, "chan"...)
56*88d15eacSSasha Smundak		if t.ChanDir() == reflect.SendDir {
57*88d15eacSSasha Smundak			b = append(b, "<-"...)
58*88d15eacSSasha Smundak		}
59*88d15eacSSasha Smundak		b = append(b, ' ')
60*88d15eacSSasha Smundak		b = appendTypeName(b, t.Elem(), qualified, false)
61*88d15eacSSasha Smundak	case reflect.Func:
62*88d15eacSSasha Smundak		if !elideFunc {
63*88d15eacSSasha Smundak			b = append(b, "func"...)
64*88d15eacSSasha Smundak		}
65*88d15eacSSasha Smundak		b = append(b, '(')
66*88d15eacSSasha Smundak		for i := 0; i < t.NumIn(); i++ {
67*88d15eacSSasha Smundak			if i > 0 {
68*88d15eacSSasha Smundak				b = append(b, ", "...)
69*88d15eacSSasha Smundak			}
70*88d15eacSSasha Smundak			if i == t.NumIn()-1 && t.IsVariadic() {
71*88d15eacSSasha Smundak				b = append(b, "..."...)
72*88d15eacSSasha Smundak				b = appendTypeName(b, t.In(i).Elem(), qualified, false)
73*88d15eacSSasha Smundak			} else {
74*88d15eacSSasha Smundak				b = appendTypeName(b, t.In(i), qualified, false)
75*88d15eacSSasha Smundak			}
76*88d15eacSSasha Smundak		}
77*88d15eacSSasha Smundak		b = append(b, ')')
78*88d15eacSSasha Smundak		switch t.NumOut() {
79*88d15eacSSasha Smundak		case 0:
80*88d15eacSSasha Smundak			// Do nothing
81*88d15eacSSasha Smundak		case 1:
82*88d15eacSSasha Smundak			b = append(b, ' ')
83*88d15eacSSasha Smundak			b = appendTypeName(b, t.Out(0), qualified, false)
84*88d15eacSSasha Smundak		default:
85*88d15eacSSasha Smundak			b = append(b, " ("...)
86*88d15eacSSasha Smundak			for i := 0; i < t.NumOut(); i++ {
87*88d15eacSSasha Smundak				if i > 0 {
88*88d15eacSSasha Smundak					b = append(b, ", "...)
89*88d15eacSSasha Smundak				}
90*88d15eacSSasha Smundak				b = appendTypeName(b, t.Out(i), qualified, false)
91*88d15eacSSasha Smundak			}
92*88d15eacSSasha Smundak			b = append(b, ')')
93*88d15eacSSasha Smundak		}
94*88d15eacSSasha Smundak	case reflect.Struct:
95*88d15eacSSasha Smundak		b = append(b, "struct{ "...)
96*88d15eacSSasha Smundak		for i := 0; i < t.NumField(); i++ {
97*88d15eacSSasha Smundak			if i > 0 {
98*88d15eacSSasha Smundak				b = append(b, "; "...)
99*88d15eacSSasha Smundak			}
100*88d15eacSSasha Smundak			sf := t.Field(i)
101*88d15eacSSasha Smundak			if !sf.Anonymous {
102*88d15eacSSasha Smundak				if qualified && sf.PkgPath != "" {
103*88d15eacSSasha Smundak					b = append(b, '"')
104*88d15eacSSasha Smundak					b = append(b, sf.PkgPath...)
105*88d15eacSSasha Smundak					b = append(b, '"')
106*88d15eacSSasha Smundak					b = append(b, '.')
107*88d15eacSSasha Smundak				}
108*88d15eacSSasha Smundak				b = append(b, sf.Name...)
109*88d15eacSSasha Smundak				b = append(b, ' ')
110*88d15eacSSasha Smundak			}
111*88d15eacSSasha Smundak			b = appendTypeName(b, sf.Type, qualified, false)
112*88d15eacSSasha Smundak			if sf.Tag != "" {
113*88d15eacSSasha Smundak				b = append(b, ' ')
114*88d15eacSSasha Smundak				b = strconv.AppendQuote(b, string(sf.Tag))
115*88d15eacSSasha Smundak			}
116*88d15eacSSasha Smundak		}
117*88d15eacSSasha Smundak		if b[len(b)-1] == ' ' {
118*88d15eacSSasha Smundak			b = b[:len(b)-1]
119*88d15eacSSasha Smundak		} else {
120*88d15eacSSasha Smundak			b = append(b, ' ')
121*88d15eacSSasha Smundak		}
122*88d15eacSSasha Smundak		b = append(b, '}')
123*88d15eacSSasha Smundak	case reflect.Slice, reflect.Array:
124*88d15eacSSasha Smundak		b = append(b, '[')
125*88d15eacSSasha Smundak		if k == reflect.Array {
126*88d15eacSSasha Smundak			b = strconv.AppendUint(b, uint64(t.Len()), 10)
127*88d15eacSSasha Smundak		}
128*88d15eacSSasha Smundak		b = append(b, ']')
129*88d15eacSSasha Smundak		b = appendTypeName(b, t.Elem(), qualified, false)
130*88d15eacSSasha Smundak	case reflect.Map:
131*88d15eacSSasha Smundak		b = append(b, "map["...)
132*88d15eacSSasha Smundak		b = appendTypeName(b, t.Key(), qualified, false)
133*88d15eacSSasha Smundak		b = append(b, ']')
134*88d15eacSSasha Smundak		b = appendTypeName(b, t.Elem(), qualified, false)
135*88d15eacSSasha Smundak	case reflect.Ptr:
136*88d15eacSSasha Smundak		b = append(b, '*')
137*88d15eacSSasha Smundak		b = appendTypeName(b, t.Elem(), qualified, false)
138*88d15eacSSasha Smundak	case reflect.Interface:
139*88d15eacSSasha Smundak		b = append(b, "interface{ "...)
140*88d15eacSSasha Smundak		for i := 0; i < t.NumMethod(); i++ {
141*88d15eacSSasha Smundak			if i > 0 {
142*88d15eacSSasha Smundak				b = append(b, "; "...)
143*88d15eacSSasha Smundak			}
144*88d15eacSSasha Smundak			m := t.Method(i)
145*88d15eacSSasha Smundak			if qualified && m.PkgPath != "" {
146*88d15eacSSasha Smundak				b = append(b, '"')
147*88d15eacSSasha Smundak				b = append(b, m.PkgPath...)
148*88d15eacSSasha Smundak				b = append(b, '"')
149*88d15eacSSasha Smundak				b = append(b, '.')
150*88d15eacSSasha Smundak			}
151*88d15eacSSasha Smundak			b = append(b, m.Name...)
152*88d15eacSSasha Smundak			b = appendTypeName(b, m.Type, qualified, true)
153*88d15eacSSasha Smundak		}
154*88d15eacSSasha Smundak		if b[len(b)-1] == ' ' {
155*88d15eacSSasha Smundak			b = b[:len(b)-1]
156*88d15eacSSasha Smundak		} else {
157*88d15eacSSasha Smundak			b = append(b, ' ')
158*88d15eacSSasha Smundak		}
159*88d15eacSSasha Smundak		b = append(b, '}')
160*88d15eacSSasha Smundak	default:
161*88d15eacSSasha Smundak		panic("invalid kind: " + k.String())
162*88d15eacSSasha Smundak	}
163*88d15eacSSasha Smundak	return b
164*88d15eacSSasha Smundak}
165