...

Source file src/github.com/vektah/gqlparser/ast/dumper.go

Documentation: github.com/vektah/gqlparser/ast

     1  package ast
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // Dump turns ast into a stable string format for assertions in tests
    12  func Dump(i interface{}) string {
    13  	v := reflect.ValueOf(i)
    14  
    15  	d := dumper{Buffer: &bytes.Buffer{}}
    16  	d.dump(v)
    17  
    18  	return d.String()
    19  }
    20  
    21  type dumper struct {
    22  	*bytes.Buffer
    23  	indent int
    24  }
    25  
    26  type Dumpable interface {
    27  	Dump() string
    28  }
    29  
    30  func (d *dumper) dump(v reflect.Value) {
    31  	if dumpable, isDumpable := v.Interface().(Dumpable); isDumpable {
    32  		d.WriteString(dumpable.Dump())
    33  		return
    34  	}
    35  	switch v.Kind() {
    36  	case reflect.Bool:
    37  		if v.Bool() {
    38  			d.WriteString("true")
    39  		} else {
    40  			d.WriteString("false")
    41  		}
    42  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    43  		d.WriteString(fmt.Sprintf("%d", v.Int()))
    44  
    45  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
    46  		d.WriteString(fmt.Sprintf("%d", v.Uint()))
    47  
    48  	case reflect.Float32, reflect.Float64:
    49  		d.WriteString(fmt.Sprintf("%.2f", v.Float()))
    50  
    51  	case reflect.String:
    52  		if v.Type().Name() != "string" {
    53  			d.WriteString(v.Type().Name() + "(" + strconv.Quote(v.String()) + ")")
    54  		} else {
    55  			d.WriteString(strconv.Quote(v.String()))
    56  		}
    57  
    58  	case reflect.Array, reflect.Slice:
    59  		d.dumpArray(v)
    60  
    61  	case reflect.Interface, reflect.Ptr:
    62  		d.dumpPtr(v)
    63  
    64  	case reflect.Struct:
    65  		d.dumpStruct(v)
    66  
    67  	default:
    68  		panic(fmt.Errorf("unsupported kind: %s\n buf: %s", v.Kind().String(), d.String()))
    69  	}
    70  }
    71  
    72  func (d *dumper) writeIndent() {
    73  	d.Buffer.WriteString(strings.Repeat("  ", d.indent))
    74  }
    75  
    76  func (d *dumper) nl() {
    77  	d.Buffer.WriteByte('\n')
    78  	d.writeIndent()
    79  }
    80  
    81  func typeName(t reflect.Type) string {
    82  	if t.Kind() == reflect.Ptr {
    83  		return typeName(t.Elem())
    84  	}
    85  	return t.Name()
    86  }
    87  
    88  func (d *dumper) dumpArray(v reflect.Value) {
    89  	d.WriteString("[" + typeName(v.Type().Elem()) + "]")
    90  
    91  	for i := 0; i < v.Len(); i++ {
    92  		d.nl()
    93  		d.WriteString("- ")
    94  		d.indent++
    95  		d.dump(v.Index(i))
    96  		d.indent--
    97  	}
    98  }
    99  
   100  func (d *dumper) dumpStruct(v reflect.Value) {
   101  	d.WriteString("<" + v.Type().Name() + ">")
   102  	d.indent++
   103  
   104  	typ := v.Type()
   105  	for i := 0; i < v.NumField(); i++ {
   106  		f := v.Field(i)
   107  		if typ.Field(i).Tag.Get("dump") == "-" {
   108  			continue
   109  		}
   110  
   111  		if isZero(f) {
   112  			continue
   113  		}
   114  		d.nl()
   115  		d.WriteString(typ.Field(i).Name)
   116  		d.WriteString(": ")
   117  		d.dump(v.Field(i))
   118  	}
   119  
   120  	d.indent--
   121  }
   122  
   123  func isZero(v reflect.Value) bool {
   124  	switch v.Kind() {
   125  	case reflect.Ptr, reflect.Interface:
   126  		return v.IsNil()
   127  	case reflect.Func, reflect.Map:
   128  		return v.IsNil()
   129  
   130  	case reflect.Array, reflect.Slice:
   131  		if v.IsNil() {
   132  			return true
   133  		}
   134  		z := true
   135  		for i := 0; i < v.Len(); i++ {
   136  			z = z && isZero(v.Index(i))
   137  		}
   138  		return z
   139  	case reflect.Struct:
   140  		z := true
   141  		for i := 0; i < v.NumField(); i++ {
   142  			z = z && isZero(v.Field(i))
   143  		}
   144  		return z
   145  	case reflect.String:
   146  		return v.String() == ""
   147  	}
   148  
   149  	// Compare other types directly:
   150  	return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()))
   151  }
   152  
   153  func (d *dumper) dumpPtr(v reflect.Value) {
   154  	if v.IsNil() {
   155  		d.WriteString("nil")
   156  		return
   157  	}
   158  	d.dump(v.Elem())
   159  }
   160  

View as plain text