Source File
selection.go
Belonging Package
go/types
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file implements Selections.
package types
import (
)
// SelectionKind describes the kind of a selector expression x.f
// (excluding qualified identifiers).
type SelectionKind int
const (
FieldVal SelectionKind = iota // x.f is a struct field selector
MethodVal // x.f is a method selector
MethodExpr // x.f is a method expression
)
// A Selection describes a selector expression x.f.
// For the declarations:
//
// type T struct{ x int; E }
// type E struct{}
// func (e E) m() {}
// var p *T
//
// the following relations exist:
//
// Selector Kind Recv Obj Type Index Indirect
//
// p.x FieldVal T x int {0} true
// p.m MethodVal *T m func() {1, 0} true
// T.m MethodExpr T m func(T) {1, 0} false
//
type Selection struct {
kind SelectionKind
recv Type // type of x
obj Object // object denoted by x.f
index []int // path from x to x.f
indirect bool // set if there was any pointer indirection on the path
}
// Kind returns the selection kind.
func ( *Selection) () SelectionKind { return .kind }
// Recv returns the type of x in x.f.
func ( *Selection) () Type { return .recv }
// Obj returns the object denoted by x.f; a *Var for
// a field selection, and a *Func in all other cases.
func ( *Selection) () Object { return .obj }
// Type returns the type of x.f, which may be different from the type of f.
// See Selection for more information.
func ( *Selection) () Type {
switch .kind {
case MethodVal:
// The type of x.f is a method with its receiver type set
// to the type of x.
:= *.obj.(*Func).typ.(*Signature)
:= *.recv
.typ = .recv
.recv = &
return &
case MethodExpr:
// The type of x.f is a function (without receiver)
// and an additional first argument with the same type as x.
// TODO(gri) Similar code is already in call.go - factor!
// TODO(gri) Compute this eagerly to avoid allocations.
:= *.obj.(*Func).typ.(*Signature)
:= *.recv
.recv = nil
.typ = .recv
var []*Var
if .params != nil {
= .params.vars
}
.params = NewTuple(append([]*Var{&}, ...)...)
return &
}
// In all other cases, the type of x.f is the type of x.
return .obj.Type()
}
// Index describes the path from x to f in x.f.
// The last index entry is the field or method index of the type declaring f;
// either:
//
// 1) the list of declared methods of a named type; or
// 2) the list of methods of an interface type; or
// 3) the list of fields of a struct type.
//
// The earlier index entries are the indices of the embedded fields implicitly
// traversed to get from (the type of) x to f, starting at embedding depth 0.
func ( *Selection) () []int { return .index }
// Indirect reports whether any pointer indirection was required to get from
// x to f in x.f.
func ( *Selection) () bool { return .indirect }
func ( *Selection) () string { return SelectionString(, nil) }
// SelectionString returns the string form of s.
// The Qualifier controls the printing of
// package-level objects, and may be nil.
//
// Examples:
// "field (T) f int"
// "method (T) f(X) Y"
// "method expr (T) f(X) Y"
//
func ( *Selection, Qualifier) string {
var string
switch .kind {
case FieldVal:
= "field "
case MethodVal:
= "method "
case MethodExpr:
= "method expr "
default:
unreachable()
}
var bytes.Buffer
.WriteString()
.WriteByte('(')
WriteType(&, .Recv(), )
fmt.Fprintf(&, ") %s", .obj.Name())
if := .Type(); .kind == FieldVal {
.WriteByte(' ')
WriteType(&, , )
} else {
WriteSignature(&, .(*Signature), )
}
return .String()
}
The pages are generated with Golds v0.4.9. (GOOS=linux GOARCH=amd64)