func (r *Relayer) IntrospectState(opts *IntrospectionOptions) RelayerRuntimeState {
	count := r.inbound.Count() + r.outbound.Count()
	return RelayerRuntimeState{
		Count:         count,
		InboundItems:  r.inbound.IntrospectState(opts, "inbound"),
		OutboundItems: r.outbound.IntrospectState(opts, "outbound"),
		MaxTimeout:    r.maxTimeout,
	}
}

func ( r * Relayer ) IntrospectState ( opts * IntrospectionOptions ) RelayerRuntimeState { count := r . inbound . Count ( ) + r . outbound . Count ( ) return RelayerRuntimeState { Count : count , InboundItems : r . inbound . IntrospectState ( opts , " " ) , OutboundItems : r . outbound . IntrospectState ( opts , " " ) , MaxTimeout : r . maxTimeout , } }

// IntrospectState returns the runtime state for this relayer.

IntrospectState returns the runtime state for this relayer .


func (ri *relayItems) IntrospectState(opts *IntrospectionOptions, name string) RelayItemSetState {
	ri.RLock()
	defer ri.RUnlock()

	setState := RelayItemSetState{
		Name:  name,
		Count: ri.Count(),
	}
	if opts.IncludeExchanges {
		setState.Items = make(map[string]RelayItemState, len(ri.items))
		for k, v := range ri.items {
			if !opts.IncludeTombstones && v.tomb {
				continue
			}
			state := RelayItemState{
				ID:                      k,
				RemapID:                 v.remapID,
				DestinationConnectionID: v.destination.conn.connID,
				Tomb:                    v.tomb,
			}
			setState.Items[strconv.Itoa(int(k))] = state
		}
	}

	return setState
}

func ( ri * relayItems ) IntrospectState ( opts * IntrospectionOptions , name string ) RelayItemSetState { ri . RLock ( ) defer ri . RUnlock ( ) setState := RelayItemSetState { Name : name , Count : ri . Count ( ) , } if opts . IncludeExchanges { setState . Items = make ( map [ string ] RelayItemState , len ( ri . items ) ) for k , v := range ri . items { if ! opts . IncludeTombstones && v . tomb { continue } state := RelayItemState { ID : k , RemapID : v . remapID , DestinationConnectionID : v . destination . conn . connID , Tomb : v . tomb , } setState . Items [ strconv . Itoa ( int ( k ) ) ] = state } } return setState }

// IntrospectState returns the runtime state for this relayItems.

IntrospectState returns the runtime state for this relayItems .


func (mexset *messageExchangeSet) IntrospectState(opts *IntrospectionOptions) ExchangeSetRuntimeState {
	mexset.RLock()
	setState := ExchangeSetRuntimeState{
		Name:  mexset.name,
		Count: len(mexset.exchanges),
	}

	if opts.IncludeExchanges {
		setState.Exchanges = make(map[string]ExchangeRuntimeState, len(mexset.exchanges))
		for k, v := range mexset.exchanges {
			state := ExchangeRuntimeState{
				ID:          k,
				MessageType: v.msgType,
			}
			setState.Exchanges[strconv.Itoa(int(k))] = state
		}
	}

	mexset.RUnlock()
	return setState
}

func ( mexset * messageExchangeSet ) IntrospectState ( opts * IntrospectionOptions ) ExchangeSetRuntimeState { mexset . RLock ( ) setState := ExchangeSetRuntimeState { Name : mexset . name , Count : len ( mexset . exchanges ) , } if opts . IncludeExchanges { setState . Exchanges = make ( map [ string ] ExchangeRuntimeState , len ( mexset . exchanges ) ) for k , v := range mexset . exchanges { state := ExchangeRuntimeState { ID : k , MessageType : v . msgType , } setState . Exchanges [ strconv . Itoa ( int ( k ) ) ] = state } } mexset . RUnlock ( ) return setState }

// IntrospectState returns the runtime state for this messsage exchange set.

IntrospectState returns the runtime state for this messsage exchange set .


func NewContext(timeout time.Duration) (Context, context.CancelFunc) {
	ctx, cancel := tchannel.NewContext(timeout)
	return tchannel.WrapWithHeaders(ctx, nil), cancel
}

func NewContext ( timeout time . Duration ) ( Context , context . CancelFunc ) { ctx , cancel := tchannel . NewContext ( timeout ) return tchannel . WrapWithHeaders ( ctx , nil ) , cancel }

// NewContext returns a Context that can be used to make JSON calls.

NewContext returns a Context that can be used to make JSON calls .


func WriteResponse(response *tchannel.InboundCallResponse, resp *Res) error {
	if resp.SystemErr != nil {
		return response.SendSystemError(resp.SystemErr)
	}
	if resp.IsErr {
		if err := response.SetApplicationError(); err != nil {
			return err
		}
	}
	if err := tchannel.NewArgWriter(response.Arg2Writer()).Write(resp.Arg2); err != nil {
		return err
	}
	return tchannel.NewArgWriter(response.Arg3Writer()).Write(resp.Arg3)
}

func WriteResponse ( response * tchannel . InboundCallResponse , resp * Res ) error { if resp . SystemErr != nil { return response . SendSystemError ( resp . SystemErr ) } if resp . IsErr { if err := response . SetApplicationError ( ) ; err != nil { return err } } if err := tchannel . NewArgWriter ( response . Arg2Writer ( ) ) . Write ( resp . Arg2 ) ; err != nil { return err } return tchannel . NewArgWriter ( response . Arg3Writer ( ) ) . Write ( resp . Arg3 ) }

// WriteResponse writes the given Res to the InboundCallResponse.

WriteResponse writes the given Res to the InboundCallResponse .


func Wrap(handler Handler) tchannel.Handler {
	return tchannel.HandlerFunc(func(ctx context.Context, call *tchannel.InboundCall) {
		args, err := ReadArgs(call)
		if err != nil {
			handler.OnError(ctx, err)
			return
		}

		resp, err := handler.Handle(ctx, args)
		response := call.Response()
		if err != nil {
			resp = &Res{
				SystemErr: err,
			}
		}
		if err := WriteResponse(response, resp); err != nil {
			handler.OnError(ctx, err)
		}
	})
}

func Wrap ( handler Handler ) tchannel . Handler { return tchannel . HandlerFunc ( func ( ctx context . Context , call * tchannel . InboundCall ) { args , err := ReadArgs ( call ) if err != nil { handler . OnError ( ctx , err ) return } resp , err := handler . Handle ( ctx , args ) response := call . Response ( ) if err != nil { resp = & Res { SystemErr : err , } } if err := WriteResponse ( response , resp ) ; err != nil { handler . OnError ( ctx , err ) } } ) }

// Wrap wraps a Handler as a tchannel.Handler that can be passed to tchannel.Register.

Wrap wraps a Handler as a tchannel . Handler that can be passed to tchannel . Register .


func (s *injectableSpan) initFromOpenTracing(span opentracing.Span) error {
	return span.Tracer().Inject(span.Context(), zipkinSpanFormat, s)
}

func ( s * injectableSpan ) initFromOpenTracing ( span opentracing . Span ) error { return span . Tracer ( ) . Inject ( span . Context ( ) , zipkinSpanFormat , s ) }

// initFromOpenTracing initializes injectableSpan fields from an OpenTracing Span,
// assuming the tracing implementation supports Zipkin-style span IDs.

initFromOpenTracing initializes injectableSpan fields from an OpenTracing Span assuming the tracing implementation supports Zipkin - style span IDs .


func (c *Connection) startOutboundSpan(ctx context.Context, serviceName, methodName string, call *OutboundCall, startTime time.Time) opentracing.Span {
	var parent opentracing.SpanContext // ok to be nil
	if s := opentracing.SpanFromContext(ctx); s != nil {
		parent = s.Context()
	}
	span := c.Tracer().StartSpan(
		methodName,
		opentracing.ChildOf(parent),
		opentracing.StartTime(startTime),
	)
	if isTracingDisabled(ctx) {
		ext.SamplingPriority.Set(span, 0)
	}
	ext.SpanKindRPCClient.Set(span)
	ext.PeerService.Set(span, serviceName)
	c.setPeerHostPort(span)
	span.SetTag("as", call.callReq.Headers[ArgScheme])
	var injectable injectableSpan
	if err := injectable.initFromOpenTracing(span); err == nil {
		call.callReq.Tracing = Span(injectable)
	} else {
		call.callReq.Tracing.initRandom()
	}
	return span
}

func
(
c
*
Connection
)
startOutboundSpan
(
ctx
context
.
Context
,
serviceName
,
methodName
string
,
call
*
OutboundCall
,
startTime
time
.
Time
)
opentracing
.
Span
{
var
parent
opentracing
.
SpanContext
// ok to be nil
if
s
:=
opentracing
.
SpanFromContext
(
ctx
)
;
s
!=
{
parent
=
s
.
Context
(
)
}
span
:=
c
.
Tracer
(
)
.
StartSpan
(
methodName
,
opentracing
.
ChildOf
(
parent
)
,
opentracing
.
StartTime
(
startTime
)
,
)
if
isTracingDisabled
(
ctx
)
{
ext
.
SamplingPriority
.
Set
(
span
,
0
)
}
ext
.
SpanKindRPCClient
.
Set
(
span
)
ext
.
PeerService
.
Set
(
span
,
serviceName
)
c
.
setPeerHostPort
(
span
)
span
.
SetTag
(
"
"
,
call
.
callReq
.
Headers
[
ArgScheme
]
)
var
injectable
injectableSpan
if
err
:=
injectable
.
initFromOpenTracing
(
span
)
;
err
==
{
call
.
callReq
.
Tracing
=
Span
(
injectable
)
}
else
{
call
.
callReq
.
Tracing
.
initRandom
(
)
}
return
span
}

// startOutboundSpan creates a new tracing span to represent the outbound RPC call.
// If the context already contains a span, it will be used as a parent, otherwise
// a new root span is created.
//
// If the tracer supports Zipkin-style trace IDs, then call.callReq.Tracing is
// initialized with those IDs. Otherwise it is assigned random values.

startOutboundSpan creates a new tracing span to represent the outbound RPC call . If the context already contains a span it will be used as a parent otherwise a new root span is created . If the tracer supports Zipkin - style trace IDs then call . callReq . Tracing is initialized with those IDs . Otherwise it is assigned random values .


func intToIP4(ip uint32) net.IP {
	return net.IP{
		byte(ip >> 24 & 0xff),
		byte(ip >> 16 & 0xff),
		byte(ip >> 8 & 0xff),
		byte(ip & 0xff),
	}
}

func intToIP4 ( ip uint32 ) net . IP { return net . IP { byte ( ip >> 24 & 0xff ) , byte ( ip >> 16 & 0xff ) , byte ( ip >> 8 & 0xff ) , byte ( ip & 0xff ) , } }

// intToIP4 converts an integer IP representation into a 4-byte net.IP struct

intToIP4 converts an integer IP representation into a 4 - byte net . IP struct


func servicePeerToHostPort(peer *hyperbahn.ServicePeer) string {
	host := intToIP4(uint32(*peer.IP.Ipv4)).String()
	port := strconv.Itoa(int(peer.Port))
	return net.JoinHostPort(host, port)
}

func servicePeerToHostPort ( peer * hyperbahn . ServicePeer ) string { host := intToIP4 ( uint32 ( * peer . IP . Ipv4 ) ) . String ( ) port := strconv . Itoa ( int ( peer . Port ) ) return net . JoinHostPort ( host , port ) }

// servicePeerToHostPort converts a Hyperbahn ServicePeer into a hostPort string.

servicePeerToHostPort converts a Hyperbahn ServicePeer into a hostPort string .


func NewStatsdReporter(addr, prefix string) (tchannel.StatsReporter, error) {
	client, err := statsd.NewBufferedClient(addr, prefix, time.Second, 0)
	if err != nil {
		return nil, err
	}

	return NewStatsdReporterClient(client), nil
}

func NewStatsdReporter ( addr , prefix string ) ( tchannel . StatsReporter , error ) { client , err := statsd . NewBufferedClient ( addr , prefix , time . Second , 0 ) if err != nil { return nil , err } return NewStatsdReporterClient ( client ) , nil }

// NewStatsdReporter returns a StatsReporter that reports to statsd on the given addr.

NewStatsdReporter returns a StatsReporter that reports to statsd on the given addr .


func (r *ToS) UnmarshalText(data []byte) error {
	if v, ok := _tosNameToValue[string(data)]; ok {
		*r = v
		return nil
	}

	return fmt.Errorf("invalid ToS %q", string(data))
}

func ( r * ToS ) UnmarshalText ( data [ ] byte ) error { if v , ok := _tosNameToValue [ string ( data ) ] ; ok { * r = v return nil } return fmt . Errorf ( " " , string ( data ) ) }

// UnmarshalText implements TextUnMarshaler from encoding


func (ph *peerHeap) Push(x interface{}) {
	n := len(ph.peerScores)
	item := x.(*peerScore)
	item.index = n
	ph.peerScores = append(ph.peerScores, item)
}

func ( ph * peerHeap ) Push ( x interface { } ) { n := len ( ph . peerScores ) item := x . ( * peerScore ) item . index = n ph . peerScores = append ( ph . peerScores , item ) }


func (ph *peerHeap) Pop() interface{} {
	old := *ph
	n := len(old.peerScores)
	item := old.peerScores[n-1]
	item.index = -1 // for safety
	ph.peerScores = old.peerScores[:n-1]
	return item
}

func
(
ph
*
peerHeap
)
Pop
(
)
interface
{
}
{
old
:=
*
ph
n
:=
len
(
old
.
peerScores
)
item
:=
old
.
peerScores
[
n
1
]
item
.
index
=
1
// for safety
ph
.
peerScores
=
old
.
peerScores
[
:
n
1
]
return
item
}


func (ph *peerHeap) updatePeer(peerScore *peerScore) {
	heap.Fix(ph, peerScore.index)
}

func ( ph * peerHeap ) updatePeer ( peerScore * peerScore ) { heap . Fix ( ph , peerScore . index ) }

// updatePeer updates the score for the given peer.

updatePeer updates the score for the given peer .


func (ph *peerHeap) removePeer(peerScore *peerScore) {
	heap.Remove(ph, peerScore.index)
}

func ( ph * peerHeap ) removePeer ( peerScore * peerScore ) { heap . Remove ( ph , peerScore . index ) }

// removePeer remove peer at specific index.

removePeer remove peer at specific index .


func (ph *peerHeap) pushPeer(peerScore *peerScore) {
	ph.order++
	newOrder := ph.order
	// randRange will affect the deviation of peer's chosenCount
	randRange := ph.Len()/2 + 1
	peerScore.order = newOrder + uint64(ph.rng.Intn(randRange))
	heap.Push(ph, peerScore)
}

// pushPeer pushes the new peer into the heap.

pushPeer pushes the new peer into the heap .


func (ph *peerHeap) addPeer(peerScore *peerScore) {
	ph.pushPeer(peerScore)

	// Pick a random element, and swap the order with that peerScore.
	r := ph.rng.Intn(ph.Len())
	ph.swapOrder(peerScore.index, r)
}

// AddPeer adds a peer to the peer heap.


func NewClient(ch *tchannel.Channel, serviceName string, opts *ClientOptions) TChanClient {
	client := &client{
		ch:          ch,
		sc:          ch.GetSubChannel(serviceName),
		serviceName: serviceName,
	}
	if opts != nil {
		client.opts = *opts
	}
	return client
}

func NewClient ( ch * tchannel . Channel , serviceName string , opts * ClientOptions ) TChanClient { client := & client { ch : ch , sc : ch . GetSubChannel ( serviceName ) , serviceName : serviceName , } if opts != nil { client . opts = * opts } return client }

// NewClient returns a Client that makes calls over the given tchannel to the given Hyperbahn service.

NewClient returns a Client that makes calls over the given tchannel to the given Hyperbahn service .


func (l *RootPeerList) Add(hostPort string) *Peer {
	l.RLock()

	if p, ok := l.peersByHostPort[hostPort]; ok {
		l.RUnlock()
		return p
	}

	l.RUnlock()
	l.Lock()
	defer l.Unlock()

	if p, ok := l.peersByHostPort[hostPort]; ok {
		return p
	}

	var p *Peer
	// To avoid duplicate connections, only the root list should create new
	// peers. All other lists should keep refs to the root list's peers.
	p = newPeer(l.channel, hostPort, l.onPeerStatusChanged, l.onClosedConnRemoved)
	l.peersByHostPort[hostPort] = p
	return p
}

// Add adds a peer to the root peer list if it does not exist, or return
// an existing peer if it exists.

Add adds a peer to the root peer list if it does not exist or return an existing peer if it exists .


func (l *RootPeerList) Get(hostPort string) (*Peer, bool) {
	l.RLock()
	p, ok := l.peersByHostPort[hostPort]
	l.RUnlock()
	return p, ok
}

func ( l * RootPeerList ) Get ( hostPort string ) ( * Peer , bool ) { l . RLock ( ) p , ok := l . peersByHostPort [ hostPort ] l . RUnlock ( ) return p , ok }

// Get returns a peer for the given hostPort if it exists.

Get returns a peer for the given hostPort if it exists .


func WithTimeout(timeout time.Duration) Option {
	return func(opts *options) {
		opts.timeout = timeout
	}
}

func WithTimeout ( timeout time . Duration ) Option { return func ( opts * options ) { opts . timeout = timeout } }

// WithTimeout sets the timeout to use for each call.

WithTimeout sets the timeout to use for each call .


func (s *Service) Methods() []*Method {
	if s.methods != nil {
		return s.methods
	}

	for _, m := range s.Service.Methods {
		s.methods = append(s.methods, &Method{m, s, s.state})
	}
	sort.Sort(byMethodName(s.methods))
	return s.methods
}

func ( s * Service ) Methods ( ) [ ] * Method { if s . methods != nil { return s . methods } for _ , m := range s . Service . Methods { s . methods = append ( s . methods , & Method { m , s , s . state } ) } sort . Sort ( byMethodName ( s . methods ) ) return s . methods }

// Methods returns the methods on this service, not including methods from inherited services.

Methods returns the methods on this service not including methods from inherited services .


func (s *Service) InheritedMethods() []string {
	if s.inheritedMethods != nil {
		return s.inheritedMethods
	}

	for svc := s.ExtendsService; svc != nil; svc = svc.ExtendsService {
		for m := range svc.Service.Methods {
			s.inheritedMethods = append(s.inheritedMethods, m)
		}
	}
	sort.Strings(s.inheritedMethods)

	return s.inheritedMethods
}

func ( s * Service ) InheritedMethods ( ) [ ] string { if s . inheritedMethods != nil { return s . inheritedMethods } for svc := s . ExtendsService ; svc != nil ; svc = svc . ExtendsService { for m := range svc . Service . Methods { s . inheritedMethods = append ( s . inheritedMethods , m ) } } sort . Strings ( s . inheritedMethods ) return s . inheritedMethods }

// InheritedMethods returns names for inherited methods on this service.

InheritedMethods returns names for inherited methods on this service .


func (m *Method) Arguments() []*Field {
	var args []*Field
	for _, f := range m.Method.Arguments {
		args = append(args, &Field{f, m.state})
	}
	return args
}

func ( m * Method ) Arguments ( ) [ ] * Field { var args [ ] * Field for _ , f := range m . Method . Arguments { args = append ( args , & Field { f , m . state } ) } return args }

// Arguments returns the argument declarations for this method.

Arguments returns the argument declarations for this method .


func (m *Method) ArgList() string {
	args := []string{"ctx " + contextType()}
	for _, arg := range m.Arguments() {
		args = append(args, arg.Declaration())
	}
	return strings.Join(args, ", ")
}

func ( m * Method ) ArgList ( ) string { args := [ ] string { " " + contextType ( ) } for _ , arg := range m . Arguments ( ) { args = append ( args , arg . Declaration ( ) ) } return strings . Join ( args , " " ) }

// ArgList returns the argument list for the function.

ArgList returns the argument list for the function .


func (m *Method) CallList(reqStruct string) string {
	args := []string{"ctx"}
	for _, arg := range m.Arguments() {
		args = append(args, reqStruct+"."+arg.ArgStructName())
	}
	return strings.Join(args, ", ")
}

func ( m * Method ) CallList ( reqStruct string ) string { args := [ ] string { " " } for _ , arg := range m . Arguments ( ) { args = append ( args , reqStruct + " " + arg . ArgStructName ( ) ) } return strings . Join ( args , " " ) }

// CallList creates the call to a function satisfying Interface from an Args struct.

CallList creates the call to a function satisfying Interface from an Args struct .


func (m *Method) RetType() string {
	if !m.HasReturn() {
		return "error"
	}
	return fmt.Sprintf("(%v, %v)", m.state.goType(m.Method.ReturnType), "error")
}

func ( m * Method ) RetType ( ) string { if ! m . HasReturn ( ) { return " " } return fmt . Sprintf ( " " , m . state . goType ( m . Method . ReturnType ) , " " ) }

// RetType returns the go return type of the method.

RetType returns the go return type of the method .


func (m *Method) WrapResult(respVar string) string {
	if !m.HasReturn() {
		panic("cannot wrap a return when there is no return mode")
	}

	if m.state.isResultPointer(m.ReturnType) {
		return respVar
	}
	return "&" + respVar
}

func ( m * Method ) WrapResult ( respVar string ) string { if ! m . HasReturn ( ) { panic ( " " ) } if m . state . isResultPointer ( m . ReturnType ) { return respVar } return " " + respVar }

// WrapResult wraps the result variable before being used in the result struct.

WrapResult wraps the result variable before being used in the result struct .


func (m *Method) ReturnWith(respName string, errName string) string {
	if !m.HasReturn() {
		return errName
	}
	return fmt.Sprintf("%v, %v", respName, errName)
}

func ( m * Method ) ReturnWith ( respName string , errName string ) string { if ! m . HasReturn ( ) { return errName } return fmt . Sprintf ( " " , respName , errName ) }

// ReturnWith takes the result name and the error name, and generates the return expression.

ReturnWith takes the result name and the error name and generates the return expression .


func (a *Field) Declaration() string {
	return fmt.Sprintf("%s %s", a.Name(), a.ArgType())
}

func ( a * Field ) Declaration ( ) string { return fmt . Sprintf ( " " , a . Name ( ) , a . ArgType ( ) ) }

// Declaration returns the declaration for this field.

Declaration returns the declaration for this field .


func startIdleSweep(ch *Channel, opts *ChannelOptions) *idleSweep {
	is := &idleSweep{
		ch:                ch,
		maxIdleTime:       opts.MaxIdleTime,
		idleCheckInterval: opts.IdleCheckInterval,
	}

	is.start()
	return is
}

func startIdleSweep ( ch * Channel , opts * ChannelOptions ) * idleSweep { is := & idleSweep { ch : ch , maxIdleTime : opts . MaxIdleTime , idleCheckInterval : opts . IdleCheckInterval , } is . start ( ) return is }

// startIdleSweep starts a poller that checks for idle connections at given
// intervals.

startIdleSweep starts a poller that checks for idle connections at given intervals .


func (is *idleSweep) start() {
	if is.started || is.idleCheckInterval <= 0 {
		return
	}

	is.ch.log.WithFields(
		LogField{"idleCheckInterval", is.idleCheckInterval},
		LogField{"maxIdleTime", is.maxIdleTime},
	).Info("Starting idle connections poller.")

	is.started = true
	is.stopCh = make(chan struct{})
	go is.pollerLoop()
}

func ( is * idleSweep ) start ( ) { if is . started || is . idleCheckInterval <= 0 { return } is . ch . log . WithFields ( LogField { " " , is . idleCheckInterval } , LogField { " " , is . maxIdleTime } , ) . Info ( " " ) is . started = true is . stopCh = make ( chan struct { } ) go is . pollerLoop ( ) }

// Start runs the goroutine responsible for checking idle connections.

Start runs the goroutine responsible for checking idle connections .


func (is *idleSweep) Stop() {
	if !is.started {
		return
	}

	is.started = false
	is.ch.log.Info("Stopping idle connections poller.")
	close(is.stopCh)
}

func ( is * idleSweep ) Stop ( ) { if ! is . started { return } is . started = false is . ch . log . Info ( " " ) close ( is . stopCh ) }

// Stop kills the poller checking for idle connections.

Stop kills the poller checking for idle connections .


func ResolveWithGoPath(filename string) (string, error) {
	for _, file := range goPathCandidates(filename) {
		if _, err := os.Stat(file); !os.IsNotExist(err) {
			return file, nil
		}
	}

	return "", fmt.Errorf("file not found on GOPATH: %q", filename)
}

func ResolveWithGoPath ( filename string ) ( string , error ) { for _ , file := range goPathCandidates ( filename ) { if _ , err := os . Stat ( file ) ; ! os . IsNotExist ( err ) { return file , nil } } return " " , fmt . Errorf ( " " , filename ) }

// ResolveWithGoPath will resolve the filename relative to GOPATH and returns
// the first file that exists, or an error otherwise.

ResolveWithGoPath will resolve the filename relative to GOPATH and returns the first file that exists or an error otherwise .


func setExtends(state map[string]parseState) error {
	for _, v := range state {
		for _, s := range v.services {
			if s.Extends == "" {
				continue
			}

			var searchServices []*Service
			var searchFor string
			parts := strings.SplitN(s.Extends, ".", 2)
			// If it's not imported, then look at the current file's services.
			if len(parts) < 2 {
				searchServices = v.services
				searchFor = s.Extends
			} else {
				include := v.global.includes[parts[0]]
				s.ExtendsPrefix = include.pkg + "."
				searchServices = state[include.file].services
				searchFor = parts[1]
			}

			foundService := sort.Search(len(searchServices), func(i int) bool {
				return searchServices[i].Name >= searchFor
			})
			if foundService == len(searchServices) {
				return fmt.Errorf("failed to find base service %q for %q", s.Extends, s.Name)
			}
			s.ExtendsService = searchServices[foundService]
		}
	}

	return nil
}

// setExtends will set the ExtendsService for all services.
// It is done after all files are parsed, as services may extend those
// found in an included file.

setExtends will set the ExtendsService for all services . It is done after all files are parsed as services may extend those found in an included file .


func (hmap *handlerMap) register(h Handler, method string) {
	hmap.Lock()
	defer hmap.Unlock()

	if hmap.handlers == nil {
		hmap.handlers = make(map[string]Handler)
	}

	hmap.handlers[method] = h
}

func ( hmap * handlerMap ) register ( h Handler , method string ) { hmap . Lock ( ) defer hmap . Unlock ( ) if hmap . handlers == nil { hmap . handlers = make ( map [ string ] Handler ) } hmap . handlers [ method ] = h }


func NewClient(hosts []string, optFns ...Option) Client {
	opts := getOptions(optFns)
	if opts.external {
		return newExternalClient(hosts, opts)
	}
	if opts.numClients > 1 {
		return newInternalMultiClient(hosts, opts)
	}
	return newClient(hosts, opts)
}

func NewClient ( hosts [ ] string , optFns ... Option ) Client { opts := getOptions ( optFns ) if opts . external { return newExternalClient ( hosts , opts ) } if opts . numClients > 1 { return newInternalMultiClient ( hosts , opts ) } return newClient ( hosts , opts ) }

// NewClient returns a new Client that can make calls to a benchmark server.

NewClient returns a new Client that can make calls to a benchmark server .


func ListenIP() (net.IP, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	return listenIP(interfaces)
}

func ListenIP ( ) ( net . IP , error ) { interfaces , err := net . Interfaces ( ) if err != nil { return nil , err } return listenIP ( interfaces ) }

// ListenIP returns the IP to bind to in Listen. It tries to find an IP that can be used
// by other machines to reach this machine.

ListenIP returns the IP to bind to in Listen . It tries to find an IP that can be used by other machines to reach this machine .


func (s *listener) Close() error {
	if err := s.Listener.Close(); err != nil {
		return err
	}

	s.cond.L.Lock()
	for s.refs > 0 {
		s.cond.Wait()
	}
	s.cond.L.Unlock()
	return nil
}

func ( s * listener ) Close ( ) error { if err := s . Listener . Close ( ) ; err != nil { return err } s . cond . L . Lock ( ) for s . refs > 0 { s . cond . Wait ( ) } s . cond . L . Unlock ( ) return nil }

// Close closes the listener.
// Any blocked Accept operations will be unblocked and return errors.

Close closes the listener . Any blocked Accept operations will be unblocked and return errors .


func ReadArgsV2(r tchannel.ArgReadable) ([]byte, []byte, error) {
	var arg2, arg3 []byte

	if err := tchannel.NewArgReader(r.Arg2Reader()).Read(&arg2); err != nil {
		return nil, nil, err
	}

	if err := tchannel.NewArgReader(r.Arg3Reader()).Read(&arg3); err != nil {
		return nil, nil, err
	}

	return arg2, arg3, nil
}

func ReadArgsV2 ( r tchannel . ArgReadable ) ( [ ] byte , [ ] byte , error ) { var arg2 , arg3 [ ] byte if err := tchannel . NewArgReader ( r . Arg2Reader ( ) ) . Read ( & arg2 ) ; err != nil { return nil , nil , err } if err := tchannel . NewArgReader ( r . Arg3Reader ( ) ) . Read ( & arg3 ) ; err != nil { return nil , nil , err } return arg2 , arg3 , nil }

// ReadArgsV2 reads arg2 and arg3 from a reader.

ReadArgsV2 reads arg2 and arg3 from a reader .


func WriteArgs(call *tchannel.OutboundCall, arg2, arg3 []byte) ([]byte, []byte, *tchannel.OutboundCallResponse, error) {
	if err := tchannel.NewArgWriter(call.Arg2Writer()).Write(arg2); err != nil {
		return nil, nil, nil, err
	}

	if err := tchannel.NewArgWriter(call.Arg3Writer()).Write(arg3); err != nil {
		return nil, nil, nil, err
	}

	resp := call.Response()
	var respArg2 []byte
	if err := tchannel.NewArgReader(resp.Arg2Reader()).Read(&respArg2); err != nil {
		return nil, nil, nil, err
	}

	var respArg3 []byte
	if err := tchannel.NewArgReader(resp.Arg3Reader()).Read(&respArg3); err != nil {
		return nil, nil, nil, err
	}

	return respArg2, respArg3, resp, nil
}

func WriteArgs ( call * tchannel . OutboundCall , arg2 , arg3 [ ] byte ) ( [ ] byte , [ ] byte , * tchannel . OutboundCallResponse , error ) { if err := tchannel . NewArgWriter ( call . Arg2Writer ( ) ) . Write ( arg2 ) ; err != nil { return nil , nil , nil , err } if err := tchannel . NewArgWriter ( call . Arg3Writer ( ) ) . Write ( arg3 ) ; err != nil { return nil , nil , nil , err } resp := call . Response ( ) var respArg2 [ ] byte if err := tchannel . NewArgReader ( resp . Arg2Reader ( ) ) . Read ( & respArg2 ) ; err != nil { return nil , nil , nil , err } var respArg3 [ ] byte if err := tchannel . NewArgReader ( resp . Arg3Reader ( ) ) . Read ( & respArg3 ) ; err != nil { return nil , nil , nil , err } return respArg2 , respArg3 , resp , nil }

// WriteArgs writes the given arguments to the call, and returns the response args.

WriteArgs writes the given arguments to the call and returns the response args .


func Call(ctx context.Context, ch *tchannel.Channel, hostPort string, serviceName, method string,
	arg2, arg3 []byte) ([]byte, []byte, *tchannel.OutboundCallResponse, error) {

	call, err := ch.BeginCall(ctx, hostPort, serviceName, method, nil)
	if err != nil {
		return nil, nil, nil, err
	}

	return WriteArgs(call, arg2, arg3)
}

func Call ( ctx context . Context , ch * tchannel . Channel , hostPort string , serviceName , method string , arg2 , arg3 [ ] byte ) ( [ ] byte , [ ] byte , * tchannel . OutboundCallResponse , error ) { call , err := ch . BeginCall ( ctx , hostPort , serviceName , method , nil ) if err != nil { return nil , nil , nil , err } return WriteArgs ( call , arg2 , arg3 ) }

// Call makes a call to the given hostPort with the given arguments and returns the response args.

Call makes a call to the given hostPort with the given arguments and returns the response args .


func CallSC(ctx context.Context, sc *tchannel.SubChannel, method string, arg2, arg3 []byte) (
	[]byte, []byte, *tchannel.OutboundCallResponse, error) {

	call, err := sc.BeginCall(ctx, method, nil)
	if err != nil {
		return nil, nil, nil, err
	}

	return WriteArgs(call, arg2, arg3)
}

func CallSC ( ctx context . Context , sc * tchannel . SubChannel , method string , arg2 , arg3 [ ] byte ) ( [ ] byte , [ ] byte , * tchannel . OutboundCallResponse , error ) { call , err := sc . BeginCall ( ctx , method , nil ) if err != nil { return nil , nil , nil , err } return WriteArgs ( call , arg2 , arg3 ) }

// CallSC makes a call using the given subcahnnel


func CallV2(ctx context.Context, sc *tchannel.SubChannel, cArgs CArgs) (*CRes, error) {
	call, err := sc.BeginCall(ctx, cArgs.Method, cArgs.CallOptions)
	if err != nil {
		return nil, err
	}

	arg2, arg3, res, err := WriteArgs(call, cArgs.Arg2, cArgs.Arg3)
	if err != nil {
		return nil, err
	}

	return &CRes{
		Arg2:     arg2,
		Arg3:     arg3,
		AppError: res.ApplicationError(),
	}, nil
}

func CallV2 ( ctx context . Context , sc * tchannel . SubChannel , cArgs CArgs ) ( * CRes , error ) { call , err := sc . BeginCall ( ctx , cArgs . Method , cArgs . CallOptions ) if err != nil { return nil , err } arg2 , arg3 , res , err := WriteArgs ( call , cArgs . Arg2 , cArgs . Arg3 ) if err != nil { return nil , err } return & CRes { Arg2 : arg2 , Arg3 : arg3 , AppError : res . ApplicationError ( ) , } , nil }

// CallV2 makes a call and does not attempt any retries.

CallV2 makes a call and does not attempt any retries .


func NewRealRelay(services map[string][]string) (Relay, error) {
	hosts := &fixedHosts{hosts: services}
	ch, err := tchannel.NewChannel("relay", &tchannel.ChannelOptions{
		RelayHost: relaytest.HostFunc(hosts.Get),
		Logger:    tchannel.NewLevelLogger(tchannel.NewLogger(os.Stderr), tchannel.LogLevelWarn),
	})
	if err != nil {
		return nil, err
	}

	if err := ch.ListenAndServe("127.0.0.1:0"); err != nil {
		return nil, err
	}

	return &realRelay{
		ch:    ch,
		hosts: hosts,
	}, nil
}

func NewRealRelay ( services map [ string ] [ ] string ) ( Relay , error ) { hosts := & fixedHosts { hosts : services } ch , err := tchannel . NewChannel ( " " , & tchannel . ChannelOptions { RelayHost : relaytest . HostFunc ( hosts . Get ) , Logger : tchannel . NewLevelLogger ( tchannel . NewLogger ( os . Stderr ) , tchannel . LogLevelWarn ) , } ) if err != nil { return nil , err } if err := ch . ListenAndServe ( " " ) ; err != nil { return nil , err } return & realRelay { ch : ch , hosts : hosts , } , nil }

// NewRealRelay creates a TChannel relay.


func NewServer(registrar tchannel.Registrar) *Server {
	metaHandler := newMetaHandler()
	server := &Server{
		ch:          registrar,
		log:         registrar.Logger(),
		handlers:    make(map[string]handler),
		metaHandler: metaHandler,
		ctxFn:       defaultContextFn,
	}
	server.Register(newTChanMetaServer(metaHandler))
	if ch, ok := registrar.(*tchannel.Channel); ok {
		// Register the meta endpoints on the "tchannel" service name.
		NewServer(ch.GetSubChannel("tchannel"))
	}
	return server
}

// NewServer returns a server that can serve thrift services over TChannel.

NewServer returns a server that can serve thrift services over TChannel .


func (s *Server) RegisterHealthHandler(f HealthFunc) {
	wrapped := func(ctx Context, r HealthRequest) (bool, string) {
		return f(ctx)
	}
	s.metaHandler.setHandler(wrapped)
}

func ( s * Server ) RegisterHealthHandler ( f HealthFunc ) { wrapped := func ( ctx Context , r HealthRequest ) ( bool , string ) { return f ( ctx ) } s . metaHandler . setHandler ( wrapped ) }

// RegisterHealthHandler uses the user-specified function f for the Health endpoint.

RegisterHealthHandler uses the user - specified function f for the Health endpoint .


func (s *Server) Handle(ctx context.Context, call *tchannel.InboundCall) {
	op := call.MethodString()
	service, method, ok := getServiceMethod(op)
	if !ok {
		log.Fatalf("Handle got call for %s which does not match the expected call format", op)
	}

	s.RLock()
	handler, ok := s.handlers[service]
	s.RUnlock()
	if !ok {
		log.Fatalf("Handle got call for service %v which is not registered", service)
	}

	if err := s.handle(ctx, handler, method, call); err != nil {
		s.onError(call, err)
	}
}

func ( s * Server ) Handle ( ctx context . Context , call * tchannel . InboundCall ) { op := call . MethodString ( ) service , method , ok := getServiceMethod ( op ) if ! ok { log . Fatalf ( " " , op ) } s . RLock ( ) handler , ok := s . handlers [ service ] s . RUnlock ( ) if ! ok { log . Fatalf ( " " , service ) } if err := s . handle ( ctx , handler , method , call ) ; err != nil { s . onError ( call , err ) } }

// Handle handles an incoming TChannel call and forwards it to the correct handler.

Handle handles an incoming TChannel call and forwards it to the correct handler .


func (c SystemErrCode) MetricsKey() string {
	switch c {
	case ErrCodeInvalid:
		// Shouldn't ever need this.
		return "invalid"
	case ErrCodeTimeout:
		return "timeout"
	case ErrCodeCancelled:
		return "cancelled"
	case ErrCodeBusy:
		return "busy"
	case ErrCodeDeclined:
		return "declined"
	case ErrCodeUnexpected:
		return "unexpected-error"
	case ErrCodeBadRequest:
		return "bad-request"
	case ErrCodeNetwork:
		return "network-error"
	case ErrCodeProtocol:
		return "protocol-error"
	default:
		return c.String()
	}
}

func
(
c
SystemErrCode
)
MetricsKey
(
)
string
{
switch
c
{
case
ErrCodeInvalid
:
// Shouldn't ever need this.
return
"
"
case
ErrCodeTimeout
:
return
"
"
case
ErrCodeCancelled
:
return
"
"
case
ErrCodeBusy
:
return
"
"
case
ErrCodeDeclined
:
return
"
"
case
ErrCodeUnexpected
:
return
"
"
case
ErrCodeBadRequest
:
return
"
"
case
ErrCodeNetwork
:
return
"
"
case
ErrCodeProtocol
:
return
"
"
default
:
return
c
.
String
(
)
}
}

// MetricsKey is a string representation of the error code that's suitable for
// inclusion in metrics tags.

MetricsKey is a string representation of the error code that s suitable for inclusion in metrics tags .


func NewSystemError(code SystemErrCode, msg string, args ...interface{}) error {
	return SystemError{code: code, msg: fmt.Sprintf(msg, args...)}
}

func NewSystemError ( code SystemErrCode , msg string , args ... interface { } ) error { return SystemError { code : code , msg : fmt . Sprintf ( msg , args ... ) } }

// NewSystemError defines a new SystemError with a code and message


func NewWrappedSystemError(code SystemErrCode, wrapped error) error {
	if se, ok := wrapped.(SystemError); ok {
		return se
	}

	return SystemError{code: code, msg: fmt.Sprint(wrapped), wrapped: wrapped}
}

func NewWrappedSystemError ( code SystemErrCode , wrapped error ) error { if se , ok := wrapped . ( SystemError ) ; ok { return se } return SystemError { code : code , msg : fmt . Sprint ( wrapped ) , wrapped : wrapped } }

// NewWrappedSystemError defines a new SystemError wrapping an existing error


func (se SystemError) Error() string {
	return fmt.Sprintf("tchannel error %v: %s", se.Code(), se.msg)
}

func ( se SystemError ) Error ( ) string { return fmt . Sprintf ( " " , se . Code ( ) , se . msg ) }

// Error returns the code and message, conforming to the error interface

Error returns the code and message conforming to the error interface


func GetContextError(err error) error {
	if err == context.DeadlineExceeded {
		return ErrTimeout
	}
	if err == context.Canceled {
		return ErrRequestCancelled
	}
	return err
}

func GetContextError ( err error ) error { if err == context . DeadlineExceeded { return ErrTimeout } if err == context . Canceled { return ErrRequestCancelled } return err }

// GetContextError converts the context error to a tchannel error.

GetContextError converts the context error to a tchannel error .


func GetSystemErrorCode(err error) SystemErrCode {
	if err == nil {
		return ErrCodeInvalid
	}

	if se, ok := err.(SystemError); ok {
		return se.Code()
	}

	return ErrCodeUnexpected
}

func GetSystemErrorCode ( err error ) SystemErrCode { if err == nil { return ErrCodeInvalid } if se , ok := err . ( SystemError ) ; ok { return se . Code ( ) } return ErrCodeUnexpected }

// GetSystemErrorCode returns the code to report for the given error.  If the error is a
// SystemError, we can get the code directly.  Otherwise treat it as an unexpected error

GetSystemErrorCode returns the code to report for the given error . If the error is a SystemError we can get the code directly . Otherwise treat it as an unexpected error


func (c *Connection) ping(ctx context.Context) error {
	req := &pingReq{id: c.NextMessageID()}
	mex, err := c.outbound.newExchange(ctx, c.opts.FramePool, req.messageType(), req.ID(), 1)
	if err != nil {
		return c.connectionError("create ping exchange", err)
	}
	defer c.outbound.removeExchange(req.ID())

	if err := c.sendMessage(req); err != nil {
		return c.connectionError("send ping", err)
	}

	return c.recvMessage(ctx, &pingRes{}, mex)
}

func ( c * Connection ) ping ( ctx context . Context ) error { req := & pingReq { id : c . NextMessageID ( ) } mex , err := c . outbound . newExchange ( ctx , c . opts . FramePool , req . messageType ( ) , req . ID ( ) , 1 ) if err != nil { return c . connectionError ( " " , err ) } defer c . outbound . removeExchange ( req . ID ( ) ) if err := c . sendMessage ( req ) ; err != nil { return c . connectionError ( " " , err ) } return c . recvMessage ( ctx , & pingRes { } , mex ) }

// ping sends a ping message and waits for a ping response.

ping sends a ping message and waits for a ping response .


func (c *Connection) handlePingRes(frame *Frame) bool {
	if err := c.outbound.forwardPeerFrame(frame); err != nil {
		c.log.WithFields(LogField{"response", frame.Header}).Warn("Unexpected ping response.")
		return true
	}
	// ping req is waiting for this frame, and will release it.
	return false
}

// handlePingRes calls registered ping handlers.

handlePingRes calls registered ping handlers .


func (c *Connection) handlePingReq(frame *Frame) {
	if state := c.readState(); state != connectionActive {
		c.protocolError(frame.Header.ID, errConnNotActive{"ping on incoming", state})
		return
	}

	pingRes := &pingRes{id: frame.Header.ID}
	if err := c.sendMessage(pingRes); err != nil {
		c.connectionError("send pong", err)
	}
}

func ( c * Connection ) handlePingReq ( frame * Frame ) { if state := c . readState ( ) ; state != connectionActive { c . protocolError ( frame . Header . ID , errConnNotActive { " " , state } ) return } pingRes := & pingRes { id : frame . Header . ID } if err := c . sendMessage ( pingRes ) ; err != nil { c . connectionError ( " " , err ) } }

// handlePingReq responds to the pingReq message with a pingRes.

handlePingReq responds to the pingReq message with a pingRes .


func (c *Connection) SendSystemError(id uint32, span Span, err error) error {
	frame := c.opts.FramePool.Get()

	if err := frame.write(&errorMessage{
		id:      id,
		errCode: GetSystemErrorCode(err),
		tracing: span,
		message: GetSystemErrorMessage(err),
	}); err != nil {

		// This shouldn't happen - it means writing the errorMessage is broken.
		c.log.WithFields(
			LogField{"remotePeer", c.remotePeerInfo},
			LogField{"id", id},
			ErrField(err),
		).Warn("Couldn't create outbound frame.")
		return fmt.Errorf("failed to create outbound error frame: %v", err)
	}

	// When sending errors, we hold the state rlock to ensure that sendCh is not closed
	// as we are sending the frame.
	return c.withStateRLock(func() error {
		// Errors cannot be sent if the connection has been closed.
		if c.state == connectionClosed {
			c.log.WithFields(
				LogField{"remotePeer", c.remotePeerInfo},
				LogField{"id", id},
			).Info("Could not send error frame on closed connection.")
			return fmt.Errorf("failed to send error frame, connection state %v", c.state)
		}

		select {
		case c.sendCh <- frame: // Good to go
			return nil
		default: // If the send buffer is full, log and return an error.
		}
		c.log.WithFields(
			LogField{"remotePeer", c.remotePeerInfo},
			LogField{"id", id},
			ErrField(err),
		).Warn("Couldn't send outbound frame.")
		return fmt.Errorf("failed to send error frame, buffer full")
	})
}

// SendSystemError sends an error frame for the given system error.

SendSystemError sends an error frame for the given system error .


func (c *Connection) connectionError(site string, err error) error {
	var closeLogFields LogFields
	if err == io.EOF {
		closeLogFields = LogFields{{"reason", "network connection EOF"}}
	} else {
		closeLogFields = LogFields{
			{"reason", "connection error"},
			ErrField(err),
		}
	}

	c.stopHealthCheck()
	err = c.logConnectionError(site, err)
	c.close(closeLogFields...)

	// On any connection error, notify the exchanges of this error.
	if c.stoppedExchanges.CAS(false, true) {
		c.outbound.stopExchanges(err)
		c.inbound.stopExchanges(err)
	}

	// checkExchanges will close the connection due to stoppedExchanges.
	c.checkExchanges()
	return err
}

// connectionError handles a connection level error


func (c *Connection) withStateLock(f func() error) error {
	c.stateMut.Lock()
	err := f()
	c.stateMut.Unlock()

	return err
}

func ( c * Connection ) withStateLock ( f func ( ) error ) error { c . stateMut . Lock ( ) err := f ( ) c . stateMut . Unlock ( ) return err }

// withStateLock performs an action with the connection state mutex locked


func (c *Connection) withStateRLock(f func() error) error {
	c.stateMut.RLock()
	err := f()
	c.stateMut.RUnlock()

	return err
}

func ( c * Connection ) withStateRLock ( f func ( ) error ) error { c . stateMut . RLock ( ) err := f ( ) c . stateMut . RUnlock ( ) return err }

// withStateRLock performs an action with the connection state mutex rlocked.

withStateRLock performs an action with the connection state mutex rlocked .


func (c *Connection) readFrames(_ uint32) {
	headerBuf := make([]byte, FrameHeaderSize)

	handleErr := func(err error) {
		if !c.closeNetworkCalled.Load() {
			c.connectionError("read frames", err)
		} else {
			c.log.Debugf("Ignoring error after connection was closed: %v", err)
		}
	}

	for {
		// Read the header, avoid allocating the frame till we know the size
		// we need to allocate.
		if _, err := io.ReadFull(c.conn, headerBuf); err != nil {
			handleErr(err)
			return
		}

		frame := c.opts.FramePool.Get()
		if err := frame.ReadBody(headerBuf, c.conn); err != nil {
			handleErr(err)
			c.opts.FramePool.Release(frame)
			return
		}

		c.updateLastActivity(frame)

		var releaseFrame bool
		if c.relay == nil {
			releaseFrame = c.handleFrameNoRelay(frame)
		} else {
			releaseFrame = c.handleFrameRelay(frame)
		}
		if releaseFrame {
			c.opts.FramePool.Release(frame)
		}
	}
}

// readFrames is the loop that reads frames from the network connection and
// dispatches to the appropriate handler. Run within its own goroutine to
// prevent overlapping reads on the socket.  Most handlers simply send the
// incoming frame to a channel; the init handlers are a notable exception,
// since we cannot process new frames until the initialization is complete.

readFrames is the loop that reads frames from the network connection and dispatches to the appropriate handler . Run within its own goroutine to prevent overlapping reads on the socket . Most handlers simply send the incoming frame to a channel ; the init handlers are a notable exception since we cannot process new frames until the initialization is complete .


func (c *Connection) writeFrames(_ uint32) {
	for {
		select {
		case f := <-c.sendCh:
			if c.log.Enabled(LogLevelDebug) {
				c.log.Debugf("Writing frame %s", f.Header)
			}

			c.updateLastActivity(f)
			err := f.WriteOut(c.conn)
			c.opts.FramePool.Release(f)
			if err != nil {
				c.connectionError("write frames", err)
				return
			}
		case <-c.stopCh:
			// If there are frames in sendCh, we want to drain them.
			if len(c.sendCh) > 0 {
				continue
			}
			// Close the network once we're no longer writing frames.
			c.closeNetwork()
			return
		}
	}
}

// writeFrames is the main loop that pulls frames from the send channel and
// writes them to the connection.

writeFrames is the main loop that pulls frames from the send channel and writes them to the connection .


func (c *Connection) hasPendingCalls() bool {
	if c.inbound.count() > 0 || c.outbound.count() > 0 {
		return true
	}
	if !c.relay.canClose() {
		return true
	}

	return false
}

func ( c * Connection ) hasPendingCalls ( ) bool { if c . inbound . count ( ) > 0 || c . outbound . count ( ) > 0 { return true } if ! c . relay . canClose ( ) { return true } return false }

// hasPendingCalls returns whether there's any pending inbound or outbound calls on this connection.

hasPendingCalls returns whether there s any pending inbound or outbound calls on this connection .


func (c *Connection) checkExchanges() {
	c.callOnExchangeChange()

	moveState := func(fromState, toState connectionState) bool {
		err := c.withStateLock(func() error {
			if c.state != fromState {
				return errors.New("")
			}
			c.state = toState
			return nil
		})
		return err == nil
	}

	curState := c.readState()
	origState := curState

	if curState != connectionClosed && c.stoppedExchanges.Load() {
		if moveState(curState, connectionClosed) {
			curState = connectionClosed
		}
	}

	if curState == connectionStartClose {
		if !c.relay.canClose() {
			return
		}
		if c.inbound.count() == 0 && moveState(connectionStartClose, connectionInboundClosed) {
			curState = connectionInboundClosed
		}
	}

	if curState == connectionInboundClosed {
		// Safety check -- this should never happen since we already did the check
		// when transitioning to connectionInboundClosed.
		if !c.relay.canClose() {
			c.relay.logger.Error("Relay can't close even though state is InboundClosed.")
			return
		}

		if c.outbound.count() == 0 && moveState(connectionInboundClosed, connectionClosed) {
			curState = connectionClosed
		}
	}

	if curState != origState {
		// If the connection is closed, we can notify writeFrames to stop which
		// closes the underlying network connection. We never close sendCh to avoid
		// races causing panics, see 93ef5c112c8b321367ae52d2bd79396e2e874f31
		if curState == connectionClosed {
			close(c.stopCh)
		}

		c.log.WithFields(
			LogField{"newState", curState},
		).Debug("Connection state updated during shutdown.")
		c.callOnCloseStateChange()
	}
}

// checkExchanges is called whenever an exchange is removed, and when Close is called.

checkExchanges is called whenever an exchange is removed and when Close is called .


func (c *Connection) closeNetwork() {
	// NB(mmihic): The sender goroutine will exit once the connection is
	// closed; no need to close the send channel (and closing the send
	// channel would be dangerous since other goroutine might be sending)
	c.log.Debugf("Closing underlying network connection")
	c.stopHealthCheck()
	c.closeNetworkCalled.Store(true)
	if err := c.conn.Close(); err != nil {
		c.log.WithFields(
			LogField{"remotePeer", c.remotePeerInfo},
			ErrField(err),
		).Warn("Couldn't close connection to peer.")
	}
}

// closeNetwork closes the network connection and all network-related channels.
// This should only be done in response to a fatal connection or protocol
// error, or after all pending frames have been sent.

closeNetwork closes the network connection and all network - related channels . This should only be done in response to a fatal connection or protocol error or after all pending frames have been sent .


func (c *Connection) getLastActivityTime() time.Time {
	return time.Unix(0, c.lastActivity.Load())
}

func ( c * Connection ) getLastActivityTime ( ) time . Time { return time . Unix ( 0 , c . lastActivity . Load ( ) ) }

// getLastActivityTime returns the timestamp of the last frame read or written,
// excluding pings. If no frames were transmitted yet, it will return the time
// this connection was created.

getLastActivityTime returns the timestamp of the last frame read or written excluding pings . If no frames were transmitted yet it will return the time this connection was created .


func Validate(svc *parser.Service) error {
	for _, m := range svc.Methods {
		if err := validateMethod(svc, m); err != nil {
			return err
		}
	}
	return nil
}

func Validate ( svc * parser . Service ) error { for _ , m := range svc . Methods { if err := validateMethod ( svc , m ) ; err != nil { return err } } return nil }

// Validate validates that the given spec is supported by thrift-gen.

Validate validates that the given spec is supported by thrift - gen .


func (c *Client) logFailedRegistrationRetry(errLogger tchannel.Logger, consecutiveFailures uint) {
	logFn := errLogger.Info
	if consecutiveFailures > maxAdvertiseFailures {
		logFn = errLogger.Warn
	}

	logFn("Hyperbahn client registration failed, will retry.")
}

func ( c * Client ) logFailedRegistrationRetry ( errLogger tchannel . Logger , consecutiveFailures uint ) { logFn := errLogger . Info if consecutiveFailures > maxAdvertiseFailures { logFn = errLogger . Warn } logFn ( " " ) }

// logFailedRegistrationRetry logs either a warning or info depending on the number of
// consecutiveFailures. If consecutiveFailures > maxAdvertiseFailures, then we log a warning.

logFailedRegistrationRetry logs either a warning or info depending on the number of consecutiveFailures . If consecutiveFailures > maxAdvertiseFailures then we log a warning .


func (c *Client) initialAdvertise() error {
	var err error
	for attempt := uint(0); attempt < maxAdvertiseFailures; attempt++ {
		err = c.sendAdvertise()
		if err == nil || err == errEphemeralPeer {
			break
		}

		c.tchan.Logger().WithFields(tchannel.ErrField(err)).Info(
			"Hyperbahn client initial registration failure, will retry")

		// Back off for a while.
		sleepFor := fuzzInterval(advertiseRetryInterval * time.Duration(1<<attempt))
		c.sleep(sleepFor)
	}
	return err
}

func
(
c
*
Client
)
initialAdvertise
(
)
error
{
var
err
error
for
attempt
:=
uint
(
0
)
;
attempt
<
maxAdvertiseFailures
;
attempt
++
{
err
=
c
.
sendAdvertise
(
)
if
err
==
||
err
==
errEphemeralPeer
{
break
}
c
.
tchan
.
Logger
(
)
.
WithFields
(
tchannel
.
ErrField
(
err
)
)
.
Info
(
"
"
)
// Back off for a while.
sleepFor
:=
fuzzInterval
(
advertiseRetryInterval
*
time
.
Duration
(
1
<<
attempt
)
)
c
.
sleep
(
sleepFor
)
}
return
err
}

// initialAdvertise will do the initial Advertise call to Hyperbahn with additional
// retries on top of the built-in TChannel retries. It will use exponential backoff
// between each of the call attempts.

initialAdvertise will do the initial Advertise call to Hyperbahn with additional retries on top of the built - in TChannel retries . It will use exponential backoff between each of the call attempts .


func (f lazyCallReq) Service() []byte {
	l := f.Payload[_serviceLenIndex]
	return f.Payload[_serviceNameIndex : _serviceNameIndex+l]
}

func ( f lazyCallReq ) Service ( ) [ ] byte { l := f . Payload [ _serviceLenIndex ] return f . Payload [ _serviceNameIndex : _serviceNameIndex + l ] }

// Service returns the name of the destination service for this callReq.

Service returns the name of the destination service for this callReq .


func (f lazyCallReq) TTL() time.Duration {
	ttl := binary.BigEndian.Uint32(f.Payload[_ttlIndex : _ttlIndex+_ttlLen])
	return time.Duration(ttl) * time.Millisecond
}

func ( f lazyCallReq ) TTL ( ) time . Duration { ttl := binary . BigEndian . Uint32 ( f . Payload [ _ttlIndex : _ttlIndex + _ttlLen ] ) return time . Duration ( ttl ) * time . Millisecond }

// TTL returns the time to live for this callReq.

TTL returns the time to live for this callReq .


func (f lazyCallReq) SetTTL(d time.Duration) {
	ttl := uint32(d / time.Millisecond)
	binary.BigEndian.PutUint32(f.Payload[_ttlIndex:_ttlIndex+_ttlLen], ttl)
}

func ( f lazyCallReq ) SetTTL ( d time . Duration ) { ttl := uint32 ( d / time . Millisecond ) binary . BigEndian . PutUint32 ( f . Payload [ _ttlIndex : _ttlIndex + _ttlLen ] , ttl ) }


func finishesCall(f *Frame) bool {
	switch f.messageType() {
	case messageTypeError:
		return true
	case messageTypeCallRes, messageTypeCallResContinue:
		flags := f.Payload[_flagsIndex]
		return flags&hasMoreFragmentsFlag == 0
	default:
		return false
	}
}

func finishesCall ( f * Frame ) bool { switch f . messageType ( ) { case messageTypeError : return true case messageTypeCallRes , messageTypeCallResContinue : flags := f . Payload [ _flagsIndex ] return flags & hasMoreFragmentsFlag == 0 default : return false } }

// finishesCall checks whether this frame is the last one we should expect for
// this RPC req-res.

finishesCall checks whether this frame is the last one we should expect for this RPC req - res .


func (ps *PlatformStrings) Flat() []string {
	unique := make(map[string]struct{})
	for _, s := range ps.Generic {
		unique[s] = struct{}{}
	}
	for _, ss := range ps.OS {
		for _, s := range ss {
			unique[s] = struct{}{}
		}
	}
	for _, ss := range ps.Arch {
		for _, s := range ss {
			unique[s] = struct{}{}
		}
	}
	for _, ss := range ps.Platform {
		for _, s := range ss {
			unique[s] = struct{}{}
		}
	}
	flat := make([]string, 0, len(unique))
	for s := range unique {
		flat = append(flat, s)
	}
	sort.Strings(flat)
	return flat
}

func ( ps * PlatformStrings ) Flat ( ) [ ] string { unique := make ( map [ string ] struct { } ) for _ , s := range ps . Generic { unique [ s ] = struct { } { } } for _ , ss := range ps . OS { for _ , s := range ss { unique [ s ] = struct { } { } } } for _ , ss := range ps . Arch { for _ , s := range ss { unique [ s ] = struct { } { } } } for _ , ss := range ps . Platform { for _ , s := range ss { unique [ s ] = struct { } { } } } flat := make ( [ ] string , 0 , len ( unique ) ) for s := range unique { flat = append ( flat , s ) } sort . Strings ( flat ) return flat }

// Flat returns all the strings in the set, sorted and de-duplicated.

Flat returns all the strings in the set sorted and de - duplicated .


func (ps *PlatformStrings) Map(f func(s string) (string, error)) (PlatformStrings, []error) {
	var errors []error
	mapSlice := func(ss []string) ([]string, error) {
		rs := make([]string, 0, len(ss))
		for _, s := range ss {
			if r, err := f(s); err != nil {
				errors = append(errors, err)
			} else if r != "" {
				rs = append(rs, r)
			}
		}
		return rs, nil
	}
	result, _ := ps.MapSlice(mapSlice)
	return result, errors
}

func ( ps * PlatformStrings ) Map ( f func ( s string ) ( string , error ) ) ( PlatformStrings , [ ] error ) { var errors [ ] error mapSlice := func ( ss [ ] string ) ( [ ] string , error ) { rs := make ( [ ] string , 0 , len ( ss ) ) for _ , s := range ss { if r , err := f ( s ) ; err != nil { errors = append ( errors , err ) } else if r != " " { rs = append ( rs , r ) } } return rs , nil } result , _ := ps . MapSlice ( mapSlice ) return result , errors }

// Map applies a function that processes individual strings to the strings
// in "ps" and returns a new PlatformStrings with the result. Empty strings
// returned by the function are dropped.

Map applies a function that processes individual strings to the strings in ps and returns a new PlatformStrings with the result . Empty strings returned by the function are dropped .


func (ps *PlatformStrings) MapSlice(f func([]string) ([]string, error)) (PlatformStrings, []error) {
	var errors []error

	mapSlice := func(ss []string) []string {
		rs, err := f(ss)
		if err != nil {
			errors = append(errors, err)
			return nil
		}
		return rs
	}

	mapStringMap := func(m map[string][]string) map[string][]string {
		if m == nil {
			return nil
		}
		rm := make(map[string][]string)
		for k, ss := range m {
			ss = mapSlice(ss)
			if len(ss) > 0 {
				rm[k] = ss
			}
		}
		if len(rm) == 0 {
			return nil
		}
		return rm
	}

	mapPlatformMap := func(m map[Platform][]string) map[Platform][]string {
		if m == nil {
			return nil
		}
		rm := make(map[Platform][]string)
		for k, ss := range m {
			ss = mapSlice(ss)
			if len(ss) > 0 {
				rm[k] = ss
			}
		}
		if len(rm) == 0 {
			return nil
		}
		return rm
	}

	result := PlatformStrings{
		Generic:  mapSlice(ps.Generic),
		OS:       mapStringMap(ps.OS),
		Arch:     mapStringMap(ps.Arch),
		Platform: mapPlatformMap(ps.Platform),
	}
	return result, errors
}

func ( ps * PlatformStrings ) MapSlice ( f func ( [ ] string ) ( [ ] string , error ) ) ( PlatformStrings , [ ] error ) { var errors [ ] error mapSlice := func ( ss [ ] string ) [ ] string { rs , err := f ( ss ) if err != nil { errors = append ( errors , err ) return nil } return rs } mapStringMap := func ( m map [ string ] [ ] string ) map [ string ] [ ] string { if m == nil { return nil } rm := make ( map [ string ] [ ] string ) for k , ss := range m { ss = mapSlice ( ss ) if len ( ss ) > 0 { rm [ k ] = ss } } if len ( rm ) == 0 { return nil } return rm } mapPlatformMap := func ( m map [ Platform ] [ ] string ) map [ Platform ] [ ] string { if m == nil { return nil } rm := make ( map [ Platform ] [ ] string ) for k , ss := range m { ss = mapSlice ( ss ) if len ( ss ) > 0 { rm [ k ] = ss } } if len ( rm ) == 0 { return nil } return rm } result := PlatformStrings { Generic : mapSlice ( ps . Generic ) , OS : mapStringMap ( ps . OS ) , Arch : mapStringMap ( ps . Arch ) , Platform : mapPlatformMap ( ps . Platform ) , } return result , errors }

// MapSlice applies a function that processes slices of strings to the strings
// in "ps" and returns a new PlatformStrings with the results.

MapSlice applies a function that processes slices of strings to the strings in ps and returns a new PlatformStrings with the results .


func GetProtoConfig(c *config.Config) *ProtoConfig {
	pc := c.Exts[protoName]
	if pc == nil {
		return nil
	}
	return pc.(*ProtoConfig)
}

func GetProtoConfig ( c * config . Config ) * ProtoConfig { pc := c . Exts [ protoName ] if pc == nil { return nil } return pc . ( * ProtoConfig ) }

// GetProtoConfig returns the proto language configuration. If the proto
// extension was not run, it will return nil.

GetProtoConfig returns the proto language configuration . If the proto extension was not run it will return nil .


func MapExprStrings(e bzl.Expr, f func(string) string) bzl.Expr {
	if e == nil {
		return nil
	}
	switch expr := e.(type) {
	case *bzl.StringExpr:
		s := f(expr.Value)
		if s == "" {
			return nil
		}
		ret := *expr
		ret.Value = s
		return &ret

	case *bzl.ListExpr:
		var list []bzl.Expr
		for _, elem := range expr.List {
			elem = MapExprStrings(elem, f)
			if elem != nil {
				list = append(list, elem)
			}
		}
		if len(list) == 0 && len(expr.List) > 0 {
			return nil
		}
		ret := *expr
		ret.List = list
		return &ret

	case *bzl.DictExpr:
		var cases []bzl.Expr
		isEmpty := true
		for _, kv := range expr.List {
			keyval, ok := kv.(*bzl.KeyValueExpr)
			if !ok {
				log.Panicf("unexpected expression in generated imports dict: %#v", kv)
			}
			value := MapExprStrings(keyval.Value, f)
			if value != nil {
				cases = append(cases, &bzl.KeyValueExpr{Key: keyval.Key, Value: value})
				if key, ok := keyval.Key.(*bzl.StringExpr); !ok || key.Value != "//conditions:default" {
					isEmpty = false
				}
			}
		}
		if isEmpty {
			return nil
		}
		ret := *expr
		ret.List = cases
		return &ret

	case *bzl.CallExpr:
		if x, ok := expr.X.(*bzl.Ident); !ok || x.Name != "select" || len(expr.List) != 1 {
			log.Panicf("unexpected call expression in generated imports: %#v", e)
		}
		arg := MapExprStrings(expr.List[0], f)
		if arg == nil {
			return nil
		}
		call := *expr
		call.List[0] = arg
		return &call

	case *bzl.BinaryExpr:
		x := MapExprStrings(expr.X, f)
		y := MapExprStrings(expr.Y, f)
		if x == nil {
			return y
		}
		if y == nil {
			return x
		}
		binop := *expr
		binop.X = x
		binop.Y = y
		return &binop

	default:
		return nil
	}
}

func MapExprStrings ( e bzl . Expr , f func ( string ) string ) bzl . Expr { if e == nil { return nil } switch expr := e . ( type ) { case * bzl . StringExpr : s := f ( expr . Value ) if s == " " { return nil } ret := * expr ret . Value = s return & ret case * bzl . ListExpr : var list [ ] bzl . Expr for _ , elem := range expr . List { elem = MapExprStrings ( elem , f ) if elem != nil { list = append ( list , elem ) } } if len ( list ) == 0 && len ( expr . List ) > 0 { return nil } ret := * expr ret . List = list return & ret case * bzl . DictExpr : var cases [ ] bzl . Expr isEmpty := true for _ , kv := range expr . List { keyval , ok := kv . ( * bzl . KeyValueExpr ) if ! ok { log . Panicf ( " " , kv ) } value := MapExprStrings ( keyval . Value , f ) if value != nil { cases = append ( cases , & bzl . KeyValueExpr { Key : keyval . Key , Value : value } ) if key , ok := keyval . Key . ( * bzl . StringExpr ) ; ! ok || key . Value != " " { isEmpty = false } } } if isEmpty { return nil } ret := * expr ret . List = cases return & ret case * bzl . CallExpr : if x , ok := expr . X . ( * bzl . Ident ) ; ! ok || x . Name != " " || len ( expr . List ) != 1 { log . Panicf ( " " , e ) } arg := MapExprStrings ( expr . List [ 0 ] , f ) if arg == nil { return nil } call := * expr call . List [ 0 ] = arg return & call case * bzl . BinaryExpr : x := MapExprStrings ( expr . X , f ) y := MapExprStrings ( expr . Y , f ) if x == nil { return y } if y == nil { return x } binop := * expr binop . X = x binop . Y = y return & binop default : return nil } }

// MapExprStrings applies a function to string sub-expressions within e.
// An expression containing the results with the same structure as e is
// returned.

MapExprStrings applies a function to string sub - expressions within e . An expression containing the results with the same structure as e is returned .


func FlattenExpr(e bzl.Expr) bzl.Expr {
	ps, err := extractPlatformStringsExprs(e)
	if err != nil {
		return e
	}

	ls := makeListSquasher()
	addElem := func(e bzl.Expr) bool {
		s, ok := e.(*bzl.StringExpr)
		if !ok {
			return false
		}
		ls.add(s)
		return true
	}
	addList := func(e bzl.Expr) bool {
		l, ok := e.(*bzl.ListExpr)
		if !ok {
			return false
		}
		for _, elem := range l.List {
			if !addElem(elem) {
				return false
			}
		}
		return true
	}
	addDict := func(d *bzl.DictExpr) bool {
		for _, kv := range d.List {
			if !addList(kv.(*bzl.KeyValueExpr).Value) {
				return false
			}
		}
		return true
	}

	if ps.generic != nil {
		if !addList(ps.generic) {
			return e
		}
	}
	for _, d := range []*bzl.DictExpr{ps.os, ps.arch, ps.platform} {
		if d == nil {
			continue
		}
		if !addDict(d) {
			return e
		}
	}

	return ls.list()
}

func FlattenExpr ( e bzl . Expr ) bzl . Expr { ps , err := extractPlatformStringsExprs ( e ) if err != nil { return e } ls := makeListSquasher ( ) addElem := func ( e bzl . Expr ) bool { s , ok := e . ( * bzl . StringExpr ) if ! ok { return false } ls . add ( s ) return true } addList := func ( e bzl . Expr ) bool { l , ok := e . ( * bzl . ListExpr ) if ! ok { return false } for _ , elem := range l . List { if ! addElem ( elem ) { return false } } return true } addDict := func ( d * bzl . DictExpr ) bool { for _ , kv := range d . List { if ! addList ( kv . ( * bzl . KeyValueExpr ) . Value ) { return false } } return true } if ps . generic != nil { if ! addList ( ps . generic ) { return e } } for _ , d := range [ ] * bzl . DictExpr { ps . os , ps . arch , ps . platform } { if d == nil { continue } if ! addDict ( d ) { return e } } return ls . list ( ) }

// FlattenExpr takes an expression that may have been generated from
// PlatformStrings and returns its values in a flat, sorted, de-duplicated
// list. Comments are accumulated and de-duplicated across duplicate
// expressions. If the expression could not have been generted by
// PlatformStrings, the expression will be returned unmodified.

FlattenExpr takes an expression that may have been generated from PlatformStrings and returns its values in a flat sorted de - duplicated list . Comments are accumulated and de - duplicated across duplicate expressions . If the expression could not have been generted by PlatformStrings the expression will be returned unmodified .


func makePlatformStringsExpr(ps platformStringsExprs) bzl.Expr {
	makeSelect := func(dict *bzl.DictExpr) bzl.Expr {
		return &bzl.CallExpr{
			X:    &bzl.Ident{Name: "select"},
			List: []bzl.Expr{dict},
		}
	}
	forceMultiline := func(e bzl.Expr) {
		switch e := e.(type) {
		case *bzl.ListExpr:
			e.ForceMultiLine = true
		case *bzl.CallExpr:
			e.List[0].(*bzl.DictExpr).ForceMultiLine = true
		}
	}

	var parts []bzl.Expr
	if ps.generic != nil {
		parts = append(parts, ps.generic)
	}
	if ps.os != nil {
		parts = append(parts, makeSelect(ps.os))
	}
	if ps.arch != nil {
		parts = append(parts, makeSelect(ps.arch))
	}
	if ps.platform != nil {
		parts = append(parts, makeSelect(ps.platform))
	}

	if len(parts) == 0 {
		return nil
	}
	if len(parts) == 1 {
		return parts[0]
	}
	expr := parts[0]
	forceMultiline(expr)
	for _, part := range parts[1:] {
		forceMultiline(part)
		expr = &bzl.BinaryExpr{
			Op: "+",
			X:  expr,
			Y:  part,
		}
	}
	return expr
}

func makePlatformStringsExpr ( ps platformStringsExprs ) bzl . Expr { makeSelect := func ( dict * bzl . DictExpr ) bzl . Expr { return & bzl . CallExpr { X : & bzl . Ident { Name : " " } , List : [ ] bzl . Expr { dict } , } } forceMultiline := func ( e bzl . Expr ) { switch e := e . ( type ) { case * bzl . ListExpr : e . ForceMultiLine = true case * bzl . CallExpr : e . List [ 0 ] . ( * bzl . DictExpr ) . ForceMultiLine = true } } var parts [ ] bzl . Expr if ps . generic != nil { parts = append ( parts , ps . generic ) } if ps . os != nil { parts = append ( parts , makeSelect ( ps . os ) ) } if ps . arch != nil { parts = append ( parts , makeSelect ( ps . arch ) ) } if ps . platform != nil { parts = append ( parts , makeSelect ( ps . platform ) ) } if len ( parts ) == 0 { return nil } if len ( parts ) == 1 { return parts [ 0 ] } expr := parts [ 0 ] forceMultiline ( expr ) for _ , part := range parts [ 1 : ] { forceMultiline ( part ) expr = & bzl . BinaryExpr { Op : " " , X : expr , Y : part , } } return expr }

// makePlatformStringsExpr constructs a single expression from the
// sub-expressions in ps.

makePlatformStringsExpr constructs a single expression from the sub - expressions in ps .


func (p Platform) String() string {
	switch {
	case p.OS != "" && p.Arch != "":
		return p.OS + "_" + p.Arch
	case p.OS != "":
		return p.OS
	case p.Arch != "":
		return p.Arch
	default:
		return ""
	}
}

func ( p Platform ) String ( ) string { switch { case p . OS != " " && p . Arch != " " : return p . OS + " " + p . Arch case p . OS != " " : return p . OS case p . Arch != " " : return p . Arch default : return " " } }

// String returns OS, Arch, or "OS_Arch" if both are set. This must match
// the names of config_setting rules in @io_bazel_rules_go//go/platform.

String returns OS Arch or OS_Arch if both are set . This must match the names of config_setting rules in


func Find(dir string) (string, error) {
	dir, err := filepath.Abs(dir)
	if err != nil {
		return "", err
	}

	for {
		_, err = os.Stat(filepath.Join(dir, workspaceFile))
		if err == nil {
			return dir, nil
		}
		if !os.IsNotExist(err) {
			return "", err
		}
		if strings.HasSuffix(dir, string(os.PathSeparator)) { // stop at root dir
			return "", os.ErrNotExist
		}
		dir = filepath.Dir(dir)
	}
}

func
Find
(
dir
string
)
(
string
,
error
)
{
dir
,
err
:=
filepath
.
Abs
(
dir
)
if
err
!=
{
return
"
"
,
err
}
for
{
_
,
err
=
os
.
Stat
(
filepath
.
Join
(
dir
,
workspaceFile
)
)
if
err
==
{
return
dir
,
}
if
!
os
.
IsNotExist
(
err
)
{
return
"
"
,
err
}
if
strings
.
HasSuffix
(
dir
,
string
(
os
.
PathSeparator
)
)
{
// stop at root dir
return
"
"
,
os
.
ErrNotExist
}
dir
=
filepath
.
Dir
(
dir
)
}
}

// Find searches from the given dir and up for the WORKSPACE file
// returning the directory containing it, or an error if none found in the tree.

Find searches from the given dir and up for the WORKSPACE file returning the directory containing it or an error if none found in the tree .


func runGazelle(mode mode, dirs []string) error {
	if mode == fastMode && len(dirs) == 0 {
		return nil
	}

	args := []string{os.Getenv("BAZEL_REAL"), "run", *gazelleLabel, "--", "-args"}
	args = append(args, "-index=false")
	if mode == fastMode {
		args = append(args, "-r=false")
		args = append(args, dirs...)
	}

	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	log.Printf("running gazelle: %s\n", strings.Join(cmd.Args, " "))
	return cmd.Run()
}

func runGazelle ( mode mode , dirs [ ] string ) error { if mode == fastMode && len ( dirs ) == 0 { return nil } args := [ ] string { os . Getenv ( " " ) , " " , * gazelleLabel , " " , " " } args = append ( args , " " ) if mode == fastMode { args = append ( args , " " ) args = append ( args , dirs ... ) } cmd := exec . Command ( args [ 0 ] , args [ 1 : ] ... ) cmd . Stdout = os . Stdout cmd . Stderr = os . Stderr log . Printf ( " \n " , strings . Join ( cmd . Args , " " ) ) return cmd . Run ( ) }

// runGazelle invokes gazelle with "bazel run". In fullMode, gazelle will
// run in the entire repository. In fastMode, gazelle will only run
// in the given directories.

runGazelle invokes gazelle with bazel run . In fullMode gazelle will run in the entire repository . In fastMode gazelle will only run in the given directories .


func restoreBuildFilesInRepo() {
	err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			log.Print(err)
			return nil
		}
		restoreBuildFilesInDir(path)
		return nil
	})
	if err != nil {
		log.Print(err)
	}
}

func restoreBuildFilesInRepo ( ) { err := filepath . Walk ( " " , func ( path string , info os . FileInfo , err error ) error { if err != nil { log . Print ( err ) return nil } restoreBuildFilesInDir ( path ) return nil } ) if err != nil { log . Print ( err ) } }

// restoreBuildFilesInRepo copies BUILD.in and BUILD.bazel.in files and
// copies them to BUILD and BUILD.bazel.

restoreBuildFilesInRepo copies BUILD . in and BUILD . bazel . in files and copies them to BUILD and BUILD . bazel .


func FixLoads(f *rule.File, knownLoads []rule.LoadInfo) {
	knownFiles := make(map[string]bool)
	knownKinds := make(map[string]string)
	for _, l := range knownLoads {
		knownFiles[l.Name] = true
		for _, k := range l.Symbols {
			knownKinds[k] = l.Name
		}
	}

	// Sync the file. We need File.Loads and File.Rules to contain inserted
	// statements and not deleted statements.
	f.Sync()

	// Scan load statements in the file. Keep track of loads of known files,
	// since these may be changed. Keep track of symbols loaded from unknown
	// files; we will not add loads for these.
	var loads []*rule.Load
	otherLoadedKinds := make(map[string]bool)
	for _, l := range f.Loads {
		if knownFiles[l.Name()] {
			loads = append(loads, l)
			continue
		}
		for _, sym := range l.Symbols() {
			otherLoadedKinds[sym] = true
		}
	}

	// Make a map of all the symbols from known files used in this file.
	usedKinds := make(map[string]map[string]bool)
	for _, r := range f.Rules {
		kind := r.Kind()
		if file, ok := knownKinds[kind]; ok && !otherLoadedKinds[kind] {
			if usedKinds[file] == nil {
				usedKinds[file] = make(map[string]bool)
			}
			usedKinds[file][kind] = true
		}
	}

	// Fix the load statements. The order is important, so we iterate over
	// knownLoads instead of knownFiles.
	for _, known := range knownLoads {
		file := known.Name
		first := true
		for _, l := range loads {
			if l.Name() != file {
				continue
			}
			if first {
				fixLoad(l, file, usedKinds[file], knownKinds)
				first = false
			} else {
				fixLoad(l, file, nil, knownKinds)
			}
			if l.IsEmpty() {
				l.Delete()
			}
		}
		if first {
			load := fixLoad(nil, file, usedKinds[file], knownKinds)
			if load != nil {
				index := newLoadIndex(f, known.After)
				load.Insert(f, index)
			}
		}
	}
}

// FixLoads removes loads of unused go rules and adds loads of newly used rules.
// This should be called after FixFile and MergeFile, since symbols
// may be introduced that aren't loaded.
//
// This function calls File.Sync before processing loads.

FixLoads removes loads of unused go rules and adds loads of newly used rules . This should be called after FixFile and MergeFile since symbols may be introduced that aren t loaded . This function calls File . Sync before processing loads .


func fixLoad(load *rule.Load, file string, kinds map[string]bool, knownKinds map[string]string) *rule.Load {
	if load == nil {
		if len(kinds) == 0 {
			return nil
		}
		load = rule.NewLoad(file)
	}

	for k := range kinds {
		load.Add(k)
	}
	for _, k := range load.Symbols() {
		if knownKinds[k] != "" && !kinds[k] {
			load.Remove(k)
		}
	}
	return load
}

func fixLoad ( load * rule . Load , file string , kinds map [ string ] bool , knownKinds map [ string ] string ) * rule . Load { if load == nil { if len ( kinds ) == 0 { return nil } load = rule . NewLoad ( file ) } for k := range kinds { load . Add ( k ) } for _ , k := range load . Symbols ( ) { if knownKinds [ k ] != " " && ! kinds [ k ] { load . Remove ( k ) } } return load }

// fixLoad updates a load statement with the given symbols. If load is nil,
// a new load may be created and returned. Symbols in kinds will be added
// to the load if they're not already present. Known symbols not in kinds
// will be removed if present. Other symbols will be preserved. If load is
// empty, nil is returned.

fixLoad updates a load statement with the given symbols . If load is nil a new load may be created and returned . Symbols in kinds will be added to the load if they re not already present . Known symbols not in kinds will be removed if present . Other symbols will be preserved . If load is empty nil is returned .


func newLoadIndex(f *rule.File, after []string) int {
	if len(after) == 0 {
		return 0
	}
	index := 0
	for _, r := range f.Rules {
		for _, a := range after {
			if r.Kind() == a && r.Index() >= index {
				index = r.Index() + 1
			}
		}
	}
	return index
}

func newLoadIndex ( f * rule . File , after [ ] string ) int { if len ( after ) == 0 { return 0 } index := 0 for _ , r := range f . Rules { for _ , a := range after { if r . Kind ( ) == a && r . Index ( ) >= index { index = r . Index ( ) + 1 } } } return index }

// newLoadIndex returns the index in stmts where a new load statement should
// be inserted. after is a list of function names that the load should not
// be inserted before.

newLoadIndex returns the index in stmts where a new load statement should be inserted . after is a list of function names that the load should not be inserted before .


func removeLegacyGoRepository(f *rule.File) {
	for _, l := range f.Loads {
		if l.Name() == "@io_bazel_rules_go//go:def.bzl" {
			l.Remove("go_repository")
			if l.IsEmpty() {
				l.Delete()
			}
		}
	}
}

func removeLegacyGoRepository ( f * rule . File ) { for _ , l := range f . Loads { if l . Name ( ) == " " { l . Remove ( " " ) if l . IsEmpty ( ) { l . Delete ( ) } } } }

// removeLegacyGoRepository removes loads of go_repository from
// @io_bazel_rules_go. FixLoads should be called after this; it will load from
// @bazel_gazelle.


func (x Version) Compare(y Version) int {
	n := len(x)
	if len(y) < n {
		n = len(y)
	}
	for i := 0; i < n; i++ {
		cmp := x[i] - y[i]
		if cmp != 0 {
			return cmp
		}
	}
	return len(x) - len(y)
}

func ( x Version ) Compare ( y Version ) int { n := len ( x ) if len ( y ) < n { n = len ( y ) } for i := 0 ; i < n ; i ++ { cmp := x [ i ] - y [ i ] if cmp != 0 { return cmp } } return len ( x ) - len ( y ) }

// Compare returns an integer comparing two versions lexicographically.

Compare returns an integer comparing two versions lexicographically .


func ParseVersion(vs string) (Version, error) {
	i := strings.IndexByte(vs, '-')
	if i >= 0 {
		vs = vs[:i]
	}
	cstrs := strings.Split(vs, ".")
	v := make(Version, len(cstrs))
	for i, cstr := range cstrs {
		cn, err := strconv.Atoi(cstr)
		if err != nil {
			return nil, fmt.Errorf("could not parse version string: %q is not an integer", cstr)
		}
		if cn < 0 {
			return nil, fmt.Errorf("could not parse version string: %q is negative", cstr)
		}
		v[i] = cn
	}
	return v, nil
}

func ParseVersion ( vs string ) ( Version , error ) { i := strings . IndexByte ( vs , '-' ) if i >= 0 { vs = vs [ : i ] } cstrs := strings . Split ( vs , " " ) v := make ( Version , len ( cstrs ) ) for i , cstr := range cstrs { cn , err := strconv . Atoi ( cstr ) if err != nil { return nil , fmt . Errorf ( " " , cstr ) } if cn < 0 { return nil , fmt . Errorf ( " " , cstr ) } v [ i ] = cn } return v , nil }

// ParseVersion parses a version of the form "12.34.56-abcd". Non-negative
// integer components are separated by dots. An arbitrary suffix may appear
// after '-', which is ignored.

ParseVersion parses a version of the form 12 . 34 . 56 - abcd . Non - negative integer components are separated by dots . An arbitrary suffix may appear after - which is ignored .


func EmptyFile(path, pkg string) *File {
	return &File{
		File: &bzl.File{Path: path, Type: bzl.TypeBuild},
		Path: path,
		Pkg:  pkg,
	}
}

func EmptyFile ( path , pkg string ) * File { return & File { File : & bzl . File { Path : path , Type : bzl . TypeBuild } , Path : path , Pkg : pkg , } }

// EmptyFile creates a File wrapped around an empty syntax tree.

EmptyFile creates a File wrapped around an empty syntax tree .


func LoadWorkspaceFile(path, pkg string) (*File, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return LoadWorkspaceData(path, pkg, data)
}

func LoadWorkspaceFile ( path , pkg string ) ( * File , error ) { data , err := ioutil . ReadFile ( path ) if err != nil { return nil , err } return LoadWorkspaceData ( path , pkg , data ) }

// LoadWorkspaceFile is similar to LoadFile but parses the file as a WORKSPACE
// file.

LoadWorkspaceFile is similar to LoadFile but parses the file as a WORKSPACE file .


func LoadMacroFile(path, pkg, defName string) (*File, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return LoadMacroData(path, pkg, defName, data)
}

func LoadMacroFile ( path , pkg , defName string ) ( * File , error ) { data , err := ioutil . ReadFile ( path ) if err != nil { return nil , err } return LoadMacroData ( path , pkg , defName , data ) }

// LoadMacroFile loads a bzl file from disk, parses it, then scans for the load
// statements and the rules called from the given Starlark function. If there is
// no matching function name, then a new function with that name will be created.
// The function's syntax tree will be returned within File and can be modified by
// Sync and Save calls.

LoadMacroFile loads a bzl file from disk parses it then scans for the load statements and the rules called from the given Starlark function . If there is no matching function name then a new function with that name will be created . The function s syntax tree will be returned within File and can be modified by Sync and Save calls .


func EmptyMacroFile(path, pkg, defName string) (*File, error) {
	_, err := os.Create(path)
	if err != nil {
		return nil, err
	}
	return LoadMacroData(path, pkg, defName, nil)
}

func EmptyMacroFile ( path , pkg , defName string ) ( * File , error ) { _ , err := os . Create ( path ) if err != nil { return nil , err } return LoadMacroData ( path , pkg , defName , nil ) }

// EmptyMacroFile creates a bzl file at the given path and within the file creates
// a Starlark function with the provided name. The function can then be modified
// by Sync and Save calls.

EmptyMacroFile creates a bzl file at the given path and within the file creates a Starlark function with the provided name . The function can then be modified by Sync and Save calls .


func LoadData(path, pkg string, data []byte) (*File, error) {
	ast, err := bzl.ParseBuild(path, data)
	if err != nil {
		return nil, err
	}
	return ScanAST(pkg, ast), nil
}

func LoadData ( path , pkg string , data [ ] byte ) ( * File , error ) { ast , err := bzl . ParseBuild ( path , data ) if err != nil { return nil , err } return ScanAST ( pkg , ast ) , nil }

// LoadData parses a build file from a byte slice and scans it for rules and
// load statements. The syntax tree within the returned File will be modified
// by editing methods.

LoadData parses a build file from a byte slice and scans it for rules and load statements . The syntax tree within the returned File will be modified by editing methods .


func LoadWorkspaceData(path, pkg string, data []byte) (*File, error) {
	ast, err := bzl.ParseWorkspace(path, data)
	if err != nil {
		return nil, err
	}
	return ScanAST(pkg, ast), nil
}

func LoadWorkspaceData ( path , pkg string , data [ ] byte ) ( * File , error ) { ast , err := bzl . ParseWorkspace ( path , data ) if err != nil { return nil , err } return ScanAST ( pkg , ast ) , nil }

// LoadWorkspaceData is similar to LoadData but parses the data as a
// WORKSPACE file.

LoadWorkspaceData is similar to LoadData but parses the data as a WORKSPACE file .


func LoadMacroData(path, pkg, defName string, data []byte) (*File, error) {
	ast, err := bzl.ParseBzl(path, data)
	if err != nil {
		return nil, err
	}
	return ScanASTBody(pkg, defName, ast), nil
}

func LoadMacroData ( path , pkg , defName string , data [ ] byte ) ( * File , error ) { ast , err := bzl . ParseBzl ( path , data ) if err != nil { return nil , err } return ScanASTBody ( pkg , defName , ast ) , nil }

// LoadMacroData parses a bzl file from a byte slice and scans for the load
// statements and the rules called from the given Starlark function. If there is
// no matching function name, then a new function will be created, and added to the
// File the next time Sync is called. The function's syntax tree will be returned
// within File and can be modified by Sync and Save calls.

LoadMacroData parses a bzl file from a byte slice and scans for the load statements and the rules called from the given Starlark function . If there is no matching function name then a new function will be created and added to the File the next time Sync is called . The function s syntax tree will be returned within File and can be modified by Sync and Save calls .


func ScanAST(pkg string, bzlFile *bzl.File) *File {
	return ScanASTBody(pkg, "", bzlFile)
}

func ScanAST ( pkg string , bzlFile * bzl . File ) * File { return ScanASTBody ( pkg , " " , bzlFile ) }

// ScanAST creates a File wrapped around the given syntax tree. This tree
// will be modified by editing methods.

ScanAST creates a File wrapped around the given syntax tree . This tree will be modified by editing methods .


func ScanASTBody(pkg, defName string, bzlFile *bzl.File) *File {
	f := &File{
		File: bzlFile,
		Pkg:  pkg,
		Path: bzlFile.Path,
	}
	var defStmt *bzl.DefStmt
	f.Rules, f.Loads, defStmt = scanExprs(defName, bzlFile.Stmt)
	if defStmt != nil {
		f.Rules, _, _ = scanExprs("", defStmt.Body)
		f.function = &function{
			stmt:     defStmt,
			inserted: true,
		}
		if len(defStmt.Body) == 1 {
			if v, ok := defStmt.Body[0].(*bzl.BranchStmt); ok && v.Token == "pass" {
				f.function.hasPass = true
			}
		}
	} else if defName != "" {
		f.function = &function{
			stmt:     &bzl.DefStmt{Name: defName},
			inserted: false,
		}
	}
	f.Directives = ParseDirectives(bzlFile)
	return f
}

func ScanASTBody ( pkg , defName string , bzlFile * bzl . File ) * File { f := & File { File : bzlFile , Pkg : pkg , Path : bzlFile . Path , } var defStmt * bzl . DefStmt f . Rules , f . Loads , defStmt = scanExprs ( defName , bzlFile . Stmt ) if defStmt != nil { f . Rules , _ , _ = scanExprs ( " " , defStmt . Body ) f . function = & function { stmt : defStmt , inserted : true , } if len ( defStmt . Body ) == 1 { if v , ok := defStmt . Body [ 0 ] . ( * bzl . BranchStmt ) ; ok && v . Token == " " { f . function . hasPass = true } } } else if defName != " " { f . function = & function { stmt : & bzl . DefStmt { Name : defName } , inserted : false , } } f . Directives = ParseDirectives ( bzlFile ) return f }

// ScanASTBody creates a File wrapped around the given syntax tree. It will also
// scan the AST for a function matching the given defName, and if the function
// does not exist it will create a new one and mark it to be added to the File
// the next time Sync is called.

ScanASTBody creates a File wrapped around the given syntax tree . It will also scan the AST for a function matching the given defName and if the function does not exist it will create a new one and mark it to be added to the File the next time Sync is called .


func MatchBuildFileName(dir string, names []string, files []os.FileInfo) string {
	for _, name := range names {
		for _, fi := range files {
			if fi.Name() == name && !fi.IsDir() {
				return filepath.Join(dir, name)
			}
		}
	}
	return ""
}

func MatchBuildFileName ( dir string , names [ ] string , files [ ] os . FileInfo ) string { for _ , name := range names { for _ , fi := range files { if fi . Name ( ) == name && ! fi . IsDir ( ) { return filepath . Join ( dir , name ) } } } return " " }

// MatchBuildFileName looks for a file in files that has a name from names.
// If there is at least one matching file, a path will be returned by joining
// dir and the first matching name. If there are no matching files, the
// empty string is returned.

MatchBuildFileName looks for a file in files that has a name from names . If there is at least one matching file a path will be returned by joining dir and the first matching name . If there are no matching files the empty string is returned .


func (f *File) SyncMacroFile(from *File) {
	fromFunc := *from.function.stmt
	_, _, toFunc := scanExprs(from.function.stmt.Name, f.File.Stmt)
	if toFunc != nil {
		*toFunc = fromFunc
	} else {
		f.File.Stmt = append(f.File.Stmt, &fromFunc)
	}
}

func ( f * File ) SyncMacroFile ( from * File ) { fromFunc := * from . function . stmt _ , _ , toFunc := scanExprs ( from . function . stmt . Name , f . File . Stmt ) if toFunc != nil { * toFunc = fromFunc } else { f . File . Stmt = append ( f . File . Stmt , & fromFunc ) } }

// SyncMacroFile syncs the file's syntax tree with another file's. This is
// useful for keeping multiple macro definitions from the same .bzl file in sync.

SyncMacroFile syncs the file s syntax tree with another file s . This is useful for keeping multiple macro definitions from the same . bzl file in sync .


func (f *File) MacroName() string {
	if f.function != nil && f.function.stmt != nil {
		return f.function.stmt.Name
	}
	return ""
}

func ( f * File ) MacroName ( ) string { if f . function != nil && f . function . stmt != nil { return f . function . stmt . Name } return " " }

// MacroName returns the name of the macro function that this file is editing,
// or an empty string if a macro function is not being edited.

MacroName returns the name of the macro function that this file is editing or an empty string if a macro function is not being edited .


func (f *File) Sync() {
	var loadInserts, loadDeletes, loadStmts []*stmt
	var r, w int
	for r, w = 0, 0; r < len(f.Loads); r++ {
		s := f.Loads[r]
		s.sync()
		if s.deleted {
			loadDeletes = append(loadDeletes, &s.stmt)
			continue
		}
		if s.inserted {
			loadInserts = append(loadInserts, &s.stmt)
			s.inserted = false
		} else {
			loadStmts = append(loadStmts, &s.stmt)
		}
		f.Loads[w] = s
		w++
	}
	f.Loads = f.Loads[:w]
	var ruleInserts, ruleDeletes, ruleStmts []*stmt
	for r, w = 0, 0; r < len(f.Rules); r++ {
		s := f.Rules[r]
		s.sync()
		if s.deleted {
			ruleDeletes = append(ruleDeletes, &s.stmt)
			continue
		}
		if s.inserted {
			ruleInserts = append(ruleInserts, &s.stmt)
			s.inserted = false
		} else {
			ruleStmts = append(ruleStmts, &s.stmt)
		}
		f.Rules[w] = s
		w++
	}
	f.Rules = f.Rules[:w]

	if f.function == nil {
		deletes := append(ruleDeletes, loadDeletes...)
		inserts := append(ruleInserts, loadInserts...)
		stmts := append(ruleStmts, loadStmts...)
		updateStmt(&f.File.Stmt, inserts, deletes, stmts)
	} else {
		updateStmt(&f.File.Stmt, loadInserts, loadDeletes, loadStmts)
		if f.function.hasPass && len(ruleInserts) > 0 {
			f.function.stmt.Body = []bzl.Expr{}
			f.function.hasPass = false
		}
		updateStmt(&f.function.stmt.Body, ruleInserts, ruleDeletes, ruleStmts)
		if len(f.function.stmt.Body) == 0 {
			f.function.stmt.Body = append(f.function.stmt.Body, &bzl.BranchStmt{Token: "pass"})
			f.function.hasPass = true
		}
		if !f.function.inserted {
			f.File.Stmt = append(f.File.Stmt, f.function.stmt)
			f.function.inserted = true
		}
	}
}

func ( f * File ) Sync ( ) { var loadInserts , loadDeletes , loadStmts [ ] * stmt var r , w int for r , w = 0 , 0 ; r < len ( f . Loads ) ; r ++ { s := f . Loads [ r ] s . sync ( ) if s . deleted { loadDeletes = append ( loadDeletes , & s . stmt ) continue } if s . inserted { loadInserts = append ( loadInserts , & s . stmt ) s . inserted = false } else { loadStmts = append ( loadStmts , & s . stmt ) } f . Loads [ w ] = s w ++ } f . Loads = f . Loads [ : w ] var ruleInserts , ruleDeletes , ruleStmts [ ] * stmt for r , w = 0 , 0 ; r < len ( f . Rules ) ; r ++ { s := f . Rules [ r ] s . sync ( ) if s . deleted { ruleDeletes = append ( ruleDeletes , & s . stmt ) continue } if s . inserted { ruleInserts = append ( ruleInserts , & s . stmt ) s . inserted = false } else { ruleStmts = append ( ruleStmts , & s . stmt ) } f . Rules [ w ] = s w ++ } f . Rules = f . Rules [ : w ] if f . function == nil { deletes := append ( ruleDeletes , loadDeletes ... ) inserts := append ( ruleInserts , loadInserts ... ) stmts := append ( ruleStmts , loadStmts ... ) updateStmt ( & f . File . Stmt , inserts , deletes , stmts ) } else { updateStmt ( & f . File . Stmt , loadInserts , loadDeletes , loadStmts ) if f . function . hasPass && len ( ruleInserts ) > 0 { f . function . stmt . Body = [ ] bzl . Expr { } f . function . hasPass = false } updateStmt ( & f . function . stmt . Body , ruleInserts , ruleDeletes , ruleStmts ) if len ( f . function . stmt . Body ) == 0 { f . function . stmt . Body = append ( f . function . stmt . Body , & bzl . BranchStmt { Token : " " } ) f . function . hasPass = true } if ! f . function . inserted { f . File . Stmt = append ( f . File . Stmt , f . function . stmt ) f . function . inserted = true } } }

// Sync writes all changes back to the wrapped syntax tree. This should be
// called after editing operations, before reading the syntax tree again.

Sync writes all changes back to the wrapped syntax tree . This should be called after editing operations before reading the syntax tree again .


func (f *File) Format() []byte {
	f.Sync()
	return bzl.Format(f.File)
}

func ( f * File ) Format ( ) [ ] byte { f . Sync ( ) return bzl . Format ( f . File ) }

// Format formats the build file in a form that can be written to disk.
// This method calls Sync internally.

Format formats the build file in a form that can be written to disk . This method calls Sync internally .


func (f *File) Save(path string) error {
	f.Sync()
	data := bzl.Format(f.File)
	return ioutil.WriteFile(path, data, 0666)
}

func ( f * File ) Save ( path string ) error { f . Sync ( ) data := bzl . Format ( f . File ) return ioutil . WriteFile ( path , data , 0666 ) }

// Save writes the build file to disk. This method calls Sync internally.

Save writes the build file to disk . This method calls Sync internally .


func (f *File) HasDefaultVisibility() bool {
	for _, r := range f.Rules {
		if r.Kind() == "package" && r.Attr("default_visibility") != nil {
			return true
		}
	}
	return false
}

func ( f * File ) HasDefaultVisibility ( ) bool { for _ , r := range f . Rules { if r . Kind ( ) == " " && r . Attr ( " " ) != nil { return true } } return false }

// HasDefaultVisibility returns whether the File contains a "package" rule with
// a "default_visibility" attribute. Rules generated by Gazelle should not
// have their own visibility attributes if this is the case.

HasDefaultVisibility returns whether the File contains a package rule with a default_visibility attribute . Rules generated by Gazelle should not have their own visibility attributes if this is the case .


func NewLoad(name string) *Load {
	return &Load{
		stmt: stmt{
			expr: &bzl.LoadStmt{
				Module:       &bzl.StringExpr{Value: name},
				ForceCompact: true,
			},
		},
		name:    name,
		symbols: make(map[string]identPair),
	}
}

func NewLoad ( name string ) * Load { return & Load { stmt : stmt { expr : & bzl . LoadStmt { Module : & bzl . StringExpr { Value : name } , ForceCompact : true , } , } , name : name , symbols : make ( map [ string ] identPair ) , } }

// NewLoad creates a new, empty load statement for the given file name.

NewLoad creates a new empty load statement for the given file name .


func (l *Load) Symbols() []string {
	syms := make([]string, 0, len(l.symbols))
	for sym := range l.symbols {
		syms = append(syms, sym)
	}
	sort.Strings(syms)
	return syms
}

func ( l * Load ) Symbols ( ) [ ] string { syms := make ( [ ] string , 0 , len ( l . symbols ) ) for sym := range l . symbols { syms = append ( syms , sym ) } sort . Strings ( syms ) return syms }

// Symbols returns a list of symbols this statement loads.

Symbols returns a list of symbols this statement loads .


func (l *Load) Has(sym string) bool {
	_, ok := l.symbols[sym]
	return ok
}

func ( l * Load ) Has ( sym string ) bool { _ , ok := l . symbols [ sym ] return ok }

// Has returns true if sym is loaded by this statement.

Has returns true if sym is loaded by this statement .


func (l *Load) Add(sym string) {
	if _, ok := l.symbols[sym]; !ok {
		i := &bzl.Ident{Name: sym}
		l.symbols[sym] = identPair{to: i, from: i}
		l.updated = true
	}
}

func ( l * Load ) Add ( sym string ) { if _ , ok := l . symbols [ sym ] ; ! ok { i := & bzl . Ident { Name : sym } l . symbols [ sym ] = identPair { to : i , from : i } l . updated = true } }

// Add inserts a new symbol into the load statement. This has no effect if
// the symbol is already loaded. Symbols will be sorted, so the order
// doesn't matter.

Add inserts a new symbol into the load statement . This has no effect if the symbol is already loaded . Symbols will be sorted so the order doesn t matter .


func (l *Load) Remove(sym string) {
	if _, ok := l.symbols[sym]; ok {
		delete(l.symbols, sym)
		l.updated = true
	}
}

func ( l * Load ) Remove ( sym string ) { if _ , ok := l . symbols [ sym ] ; ok { delete ( l . symbols , sym ) l . updated = true } }

// Remove deletes a symbol from the load statement. This has no effect if
// the symbol is not loaded.

Remove deletes a symbol from the load statement . This has no effect if the symbol is not loaded .


func (l *Load) Insert(f *File, index int) {
	l.index = index
	l.inserted = true
	f.Loads = append(f.Loads, l)
}

func ( l * Load ) Insert ( f * File , index int ) { l . index = index l . inserted = true f . Loads = append ( f . Loads , l ) }

// Insert marks this statement for insertion at the given index. If multiple
// statements are inserted at the same index, they will be inserted in the
// order Insert is called.

Insert marks this statement for insertion at the given index . If multiple statements are inserted at the same index they will be inserted in the order Insert is called .


func NewRule(kind, name string) *Rule {
	nameAttr := &bzl.AssignExpr{
		LHS: &bzl.Ident{Name: "name"},
		RHS: &bzl.StringExpr{Value: name},
		Op:  "=",
	}
	r := &Rule{
		stmt: stmt{
			expr: &bzl.CallExpr{
				X:    &bzl.Ident{Name: kind},
				List: []bzl.Expr{nameAttr},
			},
		},
		kind:    kind,
		attrs:   map[string]*bzl.AssignExpr{"name": nameAttr},
		private: map[string]interface{}{},
	}
	return r
}

func NewRule ( kind , name string ) * Rule { nameAttr := & bzl . AssignExpr { LHS : & bzl . Ident { Name : " " } , RHS : & bzl . StringExpr { Value : name } , Op : " " , } r := & Rule { stmt : stmt { expr : & bzl . CallExpr { X : & bzl . Ident { Name : kind } , List : [ ] bzl . Expr { nameAttr } , } , } , kind : kind , attrs : map [ string ] * bzl . AssignExpr { " " : nameAttr } , private : map [ string ] interface { } { } , } return r }

// NewRule creates a new, empty rule with the given kind and name.

NewRule creates a new empty rule with the given kind and name .


func (r *Rule) SetKind(kind string) {
	r.kind = kind
	r.updated = true
}

func ( r * Rule ) SetKind ( kind string ) { r . kind = kind r . updated = true }

// SetKind changes the kind of rule this is.

SetKind changes the kind of rule this is .


func (r *Rule) AttrKeys() []string {
	keys := make([]string, 0, len(r.attrs))
	for k := range r.attrs {
		keys = append(keys, k)
	}
	sort.SliceStable(keys, func(i, j int) bool {
		if cmp := bt.NamePriority[keys[i]] - bt.NamePriority[keys[j]]; cmp != 0 {
			return cmp < 0
		}
		return keys[i] < keys[j]
	})
	return keys
}

func ( r * Rule ) AttrKeys ( ) [ ] string { keys := make ( [ ] string , 0 , len ( r . attrs ) ) for k := range r . attrs { keys = append ( keys , k ) } sort . SliceStable ( keys , func ( i , j int ) bool { if cmp := bt . NamePriority [ keys [ i ] ] - bt . NamePriority [ keys [ j ] ] ; cmp != 0 { return cmp < 0 } return keys [ i ] < keys [ j ] } ) return keys }

// AttrKeys returns a sorted list of attribute keys used in this rule.

AttrKeys returns a sorted list of attribute keys used in this rule .


func (r *Rule) Attr(key string) bzl.Expr {
	attr, ok := r.attrs[key]
	if !ok {
		return nil
	}
	return attr.RHS
}

func ( r * Rule ) Attr ( key string ) bzl . Expr { attr , ok := r . attrs [ key ] if ! ok { return nil } return attr . RHS }

// Attr returns the value of the named attribute. nil is returned when the
// attribute is not set.

Attr returns the value of the named attribute . nil is returned when the attribute is not set .