...

Source file src/go/types/exprstring.go

     1	// Copyright 2013 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// This file implements printing of expressions.
     6	
     7	package types
     8	
     9	import (
    10		"bytes"
    11		"go/ast"
    12	)
    13	
    14	// ExprString returns the (possibly shortened) string representation for x.
    15	// Shortened representations are suitable for user interfaces but may not
    16	// necessarily follow Go syntax.
    17	func ExprString(x ast.Expr) string {
    18		var buf bytes.Buffer
    19		WriteExpr(&buf, x)
    20		return buf.String()
    21	}
    22	
    23	// WriteExpr writes the (possibly shortened) string representation for x to buf.
    24	// Shortened representations are suitable for user interfaces but may not
    25	// necessarily follow Go syntax.
    26	func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
    27		// The AST preserves source-level parentheses so there is
    28		// no need to introduce them here to correct for different
    29		// operator precedences. (This assumes that the AST was
    30		// generated by a Go parser.)
    31	
    32		switch x := x.(type) {
    33		default:
    34			buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr
    35	
    36		case *ast.Ident:
    37			buf.WriteString(x.Name)
    38	
    39		case *ast.Ellipsis:
    40			buf.WriteString("...")
    41			if x.Elt != nil {
    42				WriteExpr(buf, x.Elt)
    43			}
    44	
    45		case *ast.BasicLit:
    46			buf.WriteString(x.Value)
    47	
    48		case *ast.FuncLit:
    49			buf.WriteByte('(')
    50			WriteExpr(buf, x.Type)
    51			buf.WriteString(" literal)") // shortened
    52	
    53		case *ast.CompositeLit:
    54			buf.WriteByte('(')
    55			WriteExpr(buf, x.Type)
    56			buf.WriteString(" literal)") // shortened
    57	
    58		case *ast.ParenExpr:
    59			buf.WriteByte('(')
    60			WriteExpr(buf, x.X)
    61			buf.WriteByte(')')
    62	
    63		case *ast.SelectorExpr:
    64			WriteExpr(buf, x.X)
    65			buf.WriteByte('.')
    66			buf.WriteString(x.Sel.Name)
    67	
    68		case *ast.IndexExpr:
    69			WriteExpr(buf, x.X)
    70			buf.WriteByte('[')
    71			WriteExpr(buf, x.Index)
    72			buf.WriteByte(']')
    73	
    74		case *ast.SliceExpr:
    75			WriteExpr(buf, x.X)
    76			buf.WriteByte('[')
    77			if x.Low != nil {
    78				WriteExpr(buf, x.Low)
    79			}
    80			buf.WriteByte(':')
    81			if x.High != nil {
    82				WriteExpr(buf, x.High)
    83			}
    84			if x.Slice3 {
    85				buf.WriteByte(':')
    86				if x.Max != nil {
    87					WriteExpr(buf, x.Max)
    88				}
    89			}
    90			buf.WriteByte(']')
    91	
    92		case *ast.TypeAssertExpr:
    93			WriteExpr(buf, x.X)
    94			buf.WriteString(".(")
    95			WriteExpr(buf, x.Type)
    96			buf.WriteByte(')')
    97	
    98		case *ast.CallExpr:
    99			WriteExpr(buf, x.Fun)
   100			buf.WriteByte('(')
   101			for i, arg := range x.Args {
   102				if i > 0 {
   103					buf.WriteString(", ")
   104				}
   105				WriteExpr(buf, arg)
   106			}
   107			if x.Ellipsis.IsValid() {
   108				buf.WriteString("...")
   109			}
   110			buf.WriteByte(')')
   111	
   112		case *ast.StarExpr:
   113			buf.WriteByte('*')
   114			WriteExpr(buf, x.X)
   115	
   116		case *ast.UnaryExpr:
   117			buf.WriteString(x.Op.String())
   118			WriteExpr(buf, x.X)
   119	
   120		case *ast.BinaryExpr:
   121			WriteExpr(buf, x.X)
   122			buf.WriteByte(' ')
   123			buf.WriteString(x.Op.String())
   124			buf.WriteByte(' ')
   125			WriteExpr(buf, x.Y)
   126	
   127		case *ast.ArrayType:
   128			buf.WriteByte('[')
   129			if x.Len != nil {
   130				WriteExpr(buf, x.Len)
   131			}
   132			buf.WriteByte(']')
   133			WriteExpr(buf, x.Elt)
   134	
   135		case *ast.StructType:
   136			buf.WriteString("struct{")
   137			writeFieldList(buf, x.Fields, "; ", false)
   138			buf.WriteByte('}')
   139	
   140		case *ast.FuncType:
   141			buf.WriteString("func")
   142			writeSigExpr(buf, x)
   143	
   144		case *ast.InterfaceType:
   145			buf.WriteString("interface{")
   146			writeFieldList(buf, x.Methods, "; ", true)
   147			buf.WriteByte('}')
   148	
   149		case *ast.MapType:
   150			buf.WriteString("map[")
   151			WriteExpr(buf, x.Key)
   152			buf.WriteByte(']')
   153			WriteExpr(buf, x.Value)
   154	
   155		case *ast.ChanType:
   156			var s string
   157			switch x.Dir {
   158			case ast.SEND:
   159				s = "chan<- "
   160			case ast.RECV:
   161				s = "<-chan "
   162			default:
   163				s = "chan "
   164			}
   165			buf.WriteString(s)
   166			WriteExpr(buf, x.Value)
   167		}
   168	}
   169	
   170	func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) {
   171		buf.WriteByte('(')
   172		writeFieldList(buf, sig.Params, ", ", false)
   173		buf.WriteByte(')')
   174	
   175		res := sig.Results
   176		n := res.NumFields()
   177		if n == 0 {
   178			// no result
   179			return
   180		}
   181	
   182		buf.WriteByte(' ')
   183		if n == 1 && len(res.List[0].Names) == 0 {
   184			// single unnamed result
   185			WriteExpr(buf, res.List[0].Type)
   186			return
   187		}
   188	
   189		// multiple or named result(s)
   190		buf.WriteByte('(')
   191		writeFieldList(buf, res, ", ", false)
   192		buf.WriteByte(')')
   193	}
   194	
   195	func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) {
   196		for i, f := range fields.List {
   197			if i > 0 {
   198				buf.WriteString(sep)
   199			}
   200	
   201			// field list names
   202			for i, name := range f.Names {
   203				if i > 0 {
   204					buf.WriteString(", ")
   205				}
   206				buf.WriteString(name.Name)
   207			}
   208	
   209			// types of interface methods consist of signatures only
   210			if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface {
   211				writeSigExpr(buf, sig)
   212				continue
   213			}
   214	
   215			// named fields are separated with a blank from the field type
   216			if len(f.Names) > 0 {
   217				buf.WriteByte(' ')
   218			}
   219	
   220			WriteExpr(buf, f.Type)
   221	
   222			// ignore tag
   223		}
   224	}
   225	

View as plain text