github.com/neugram/ng@v0.0.0-20180309130942-d472ff93d872/format/tipe.go (about)

     1  // Copyright 2017 The Neugram Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package format
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"sort"
    11  
    12  	"neugram.io/ng/syntax/tipe"
    13  )
    14  
    15  func (p *printer) tipe(t tipe.Type) {
    16  	if t == nil {
    17  		p.buf.WriteString("<nil>")
    18  		return
    19  	}
    20  	switch t := t.(type) {
    21  	case tipe.Basic:
    22  		p.buf.WriteString(string(t))
    23  	case *tipe.Struct:
    24  		if len(t.Fields) == 0 {
    25  			p.buf.WriteString("struct{}")
    26  			return
    27  		}
    28  		p.buf.WriteString("struct {")
    29  		p.indent++
    30  		maxlen := 0
    31  		for _, sf := range t.Fields {
    32  			if len(sf.Name) > maxlen {
    33  				maxlen = len(sf.Name)
    34  			}
    35  		}
    36  		for _, sf := range t.Fields {
    37  			p.newline()
    38  			name := sf.Name
    39  			if name == "" {
    40  				name = "*ERROR*No*Name*"
    41  			}
    42  			p.buf.WriteString(name)
    43  			for i := len(name); i <= maxlen; i++ {
    44  				p.buf.WriteByte(' ')
    45  			}
    46  			p.tipe(sf.Type)
    47  		}
    48  		p.indent--
    49  		p.newline()
    50  		p.buf.WriteByte('}')
    51  	case *tipe.Named:
    52  		p.buf.WriteString(t.Name)
    53  	case *tipe.Pointer:
    54  		p.buf.WriteByte('*')
    55  		p.tipe(t.Elem)
    56  	case *tipe.Unresolved:
    57  		if t.Package != "" {
    58  			p.buf.WriteString(t.Package)
    59  			p.buf.WriteByte('.')
    60  		}
    61  		p.buf.WriteString(t.Name)
    62  	case *tipe.Array:
    63  		if t.Ellipsis {
    64  			p.buf.WriteString("[...]")
    65  		} else {
    66  			fmt.Fprintf(p.buf, "[%d]", t.Len)
    67  		}
    68  		p.tipe(t.Elem)
    69  	case *tipe.Slice:
    70  		p.buf.WriteString("[]")
    71  		p.tipe(t.Elem)
    72  	case *tipe.Table:
    73  		p.buf.WriteString("[|]")
    74  		p.tipe(t.Type)
    75  	case *tipe.Interface:
    76  		if len(t.Methods) == 0 {
    77  			p.buf.WriteString("interface{}")
    78  			return
    79  		}
    80  		p.buf.WriteString("interface {")
    81  		p.indent++
    82  		names := make([]string, 0, len(t.Methods))
    83  		for name := range t.Methods {
    84  			names = append(names, name)
    85  		}
    86  		sort.Strings(names)
    87  		for _, name := range names {
    88  			p.newline()
    89  			p.buf.WriteString(name)
    90  			p.tipeFuncSig(t.Methods[name])
    91  		}
    92  		p.indent--
    93  		p.newline()
    94  		p.buf.WriteByte('}')
    95  	case *tipe.Map:
    96  		p.buf.WriteString("map[")
    97  		p.tipe(t.Key)
    98  		p.buf.WriteByte(']')
    99  		p.tipe(t.Value)
   100  	case *tipe.Chan:
   101  		if t.Direction == tipe.ChanRecv {
   102  			p.buf.WriteString("<-")
   103  		}
   104  		p.buf.WriteString("chan")
   105  		if t.Direction == tipe.ChanSend {
   106  			p.buf.WriteString("<-")
   107  		}
   108  		p.buf.WriteByte(' ')
   109  		p.tipe(t.Elem)
   110  	case *tipe.Func:
   111  		p.buf.WriteString("func")
   112  		p.tipeFuncSig(t)
   113  	case *tipe.Alias:
   114  		p.buf.WriteString(t.Name)
   115  	case *tipe.Tuple:
   116  		p.buf.WriteString("(")
   117  		for i, elt := range t.Elems {
   118  			if i > 0 {
   119  				p.buf.WriteString(", ")
   120  			}
   121  			p.tipe(elt)
   122  		}
   123  		p.buf.WriteString(")")
   124  	case *tipe.Ellipsis:
   125  		p.buf.WriteString("...")
   126  		p.tipe(t.Elem)
   127  	default:
   128  		p.buf.WriteString("format: unknown type: ")
   129  		WriteDebug(p.buf, t)
   130  	}
   131  }
   132  
   133  func (p *printer) tipeFuncSig(t *tipe.Func) {
   134  	p.buf.WriteByte('(')
   135  	if t.Params != nil {
   136  		for i, elem := range t.Params.Elems {
   137  			if i > 0 {
   138  				p.buf.WriteString(", ")
   139  			}
   140  			p.tipe(elem)
   141  		}
   142  	}
   143  	p.buf.WriteByte(')')
   144  	if t.Results != nil && len(t.Results.Elems) > 0 {
   145  		p.buf.WriteByte(' ')
   146  		if len(t.Results.Elems) > 1 {
   147  			p.buf.WriteByte('(')
   148  		}
   149  		for i, elem := range t.Results.Elems {
   150  			if i > 0 {
   151  				p.buf.WriteString(", ")
   152  			}
   153  			p.tipe(elem)
   154  		}
   155  		if len(t.Results.Elems) > 1 {
   156  			p.buf.WriteByte(')')
   157  		}
   158  	}
   159  }
   160  
   161  func WriteType(buf *bytes.Buffer, t tipe.Type) {
   162  	p := &printer{
   163  		buf: buf,
   164  	}
   165  	p.tipe(t)
   166  }
   167  
   168  func Type(t tipe.Type) string {
   169  	buf := new(bytes.Buffer)
   170  	WriteType(buf, t)
   171  	return buf.String()
   172  }