...

Source file src/go/types/selection.go

Documentation: go/types

		 1  // Copyright 2013 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  // This file implements Selections.
		 6  
		 7  package types
		 8  
		 9  import (
		10  	"bytes"
		11  	"fmt"
		12  )
		13  
		14  // SelectionKind describes the kind of a selector expression x.f
		15  // (excluding qualified identifiers).
		16  type SelectionKind int
		17  
		18  const (
		19  	FieldVal	 SelectionKind = iota // x.f is a struct field selector
		20  	MethodVal											 // x.f is a method selector
		21  	MethodExpr											// x.f is a method expression
		22  )
		23  
		24  // A Selection describes a selector expression x.f.
		25  // For the declarations:
		26  //
		27  //	type T struct{ x int; E }
		28  //	type E struct{}
		29  //	func (e E) m() {}
		30  //	var p *T
		31  //
		32  // the following relations exist:
		33  //
		34  //	Selector		Kind					Recv		Obj		Type			 Index		 Indirect
		35  //
		36  //	p.x				 FieldVal			T			 x			int				{0}			 true
		37  //	p.m				 MethodVal		 *T			m			func()		 {1, 0}		true
		38  //	T.m				 MethodExpr		T			 m			func(T)		{1, 0}		false
		39  //
		40  type Selection struct {
		41  	kind		 SelectionKind
		42  	recv		 Type	 // type of x
		43  	obj			Object // object denoted by x.f
		44  	index		[]int	// path from x to x.f
		45  	indirect bool	 // set if there was any pointer indirection on the path
		46  }
		47  
		48  // Kind returns the selection kind.
		49  func (s *Selection) Kind() SelectionKind { return s.kind }
		50  
		51  // Recv returns the type of x in x.f.
		52  func (s *Selection) Recv() Type { return s.recv }
		53  
		54  // Obj returns the object denoted by x.f; a *Var for
		55  // a field selection, and a *Func in all other cases.
		56  func (s *Selection) Obj() Object { return s.obj }
		57  
		58  // Type returns the type of x.f, which may be different from the type of f.
		59  // See Selection for more information.
		60  func (s *Selection) Type() Type {
		61  	switch s.kind {
		62  	case MethodVal:
		63  		// The type of x.f is a method with its receiver type set
		64  		// to the type of x.
		65  		sig := *s.obj.(*Func).typ.(*Signature)
		66  		recv := *sig.recv
		67  		recv.typ = s.recv
		68  		sig.recv = &recv
		69  		return &sig
		70  
		71  	case MethodExpr:
		72  		// The type of x.f is a function (without receiver)
		73  		// and an additional first argument with the same type as x.
		74  		// TODO(gri) Similar code is already in call.go - factor!
		75  		// TODO(gri) Compute this eagerly to avoid allocations.
		76  		sig := *s.obj.(*Func).typ.(*Signature)
		77  		arg0 := *sig.recv
		78  		sig.recv = nil
		79  		arg0.typ = s.recv
		80  		var params []*Var
		81  		if sig.params != nil {
		82  			params = sig.params.vars
		83  		}
		84  		sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
		85  		return &sig
		86  	}
		87  
		88  	// In all other cases, the type of x.f is the type of x.
		89  	return s.obj.Type()
		90  }
		91  
		92  // Index describes the path from x to f in x.f.
		93  // The last index entry is the field or method index of the type declaring f;
		94  // either:
		95  //
		96  //	1) the list of declared methods of a named type; or
		97  //	2) the list of methods of an interface type; or
		98  //	3) the list of fields of a struct type.
		99  //
	 100  // The earlier index entries are the indices of the embedded fields implicitly
	 101  // traversed to get from (the type of) x to f, starting at embedding depth 0.
	 102  func (s *Selection) Index() []int { return s.index }
	 103  
	 104  // Indirect reports whether any pointer indirection was required to get from
	 105  // x to f in x.f.
	 106  func (s *Selection) Indirect() bool { return s.indirect }
	 107  
	 108  func (s *Selection) String() string { return SelectionString(s, nil) }
	 109  
	 110  // SelectionString returns the string form of s.
	 111  // The Qualifier controls the printing of
	 112  // package-level objects, and may be nil.
	 113  //
	 114  // Examples:
	 115  //	"field (T) f int"
	 116  //	"method (T) f(X) Y"
	 117  //	"method expr (T) f(X) Y"
	 118  //
	 119  func SelectionString(s *Selection, qf Qualifier) string {
	 120  	var k string
	 121  	switch s.kind {
	 122  	case FieldVal:
	 123  		k = "field "
	 124  	case MethodVal:
	 125  		k = "method "
	 126  	case MethodExpr:
	 127  		k = "method expr "
	 128  	default:
	 129  		unreachable()
	 130  	}
	 131  	var buf bytes.Buffer
	 132  	buf.WriteString(k)
	 133  	buf.WriteByte('(')
	 134  	WriteType(&buf, s.Recv(), qf)
	 135  	fmt.Fprintf(&buf, ") %s", s.obj.Name())
	 136  	if T := s.Type(); s.kind == FieldVal {
	 137  		buf.WriteByte(' ')
	 138  		WriteType(&buf, T, qf)
	 139  	} else {
	 140  		WriteSignature(&buf, T.(*Signature), qf)
	 141  	}
	 142  	return buf.String()
	 143  }
	 144  

View as plain text