github.com/jmigpin/editor@v1.6.0/core/godebug/stringifyitem.go (about)

     1  package godebug
     2  
     3  import (
     4  	"fmt"
     5  	"go/token"
     6  	"strings"
     7  
     8  	"github.com/jmigpin/editor/core/godebug/debug"
     9  )
    10  
    11  func StringifyItem(item debug.Item) string {
    12  	is := NewItemStringifier()
    13  	is.stringify(item)
    14  	return is.b.String()
    15  }
    16  func StringifyItemFull(item debug.Item) string {
    17  	is := NewItemStringifier()
    18  	is.fullStr = true
    19  	is.stringify(item)
    20  	return is.b.String()
    21  }
    22  
    23  //----------
    24  
    25  type ItemStringifier struct {
    26  	b       *strings.Builder
    27  	fullStr bool
    28  }
    29  
    30  func NewItemStringifier() *ItemStringifier {
    31  	is := &ItemStringifier{}
    32  	is.b = &strings.Builder{}
    33  	return is
    34  }
    35  
    36  func (is *ItemStringifier) p(s string) {
    37  	is.b.WriteString(s)
    38  }
    39  
    40  //----------
    41  
    42  //func (is *ItemStringifier) captureStringify(item debug.Item) (start, end int, s string) {
    43  //	start = len(is.Str)
    44  //	is.stringify(item)
    45  //	end = len(is.Str)
    46  //	return start, end, is.Str[start:end]
    47  //}
    48  
    49  //func (is *ItemStringifier) stringify(item debug.Item) {
    50  //// capture value
    51  //start := len(is.Str)
    52  //defer func() {
    53  //	end := len(is.Str)
    54  //	if is.Offset >= start && is.Offset < end {
    55  //		s := is.Str[start:end]
    56  //		if is.OffsetValueString == "" || len(s) < len(is.OffsetValueString) {
    57  //			is.OffsetValueString = s
    58  //		}
    59  //	}
    60  //}()
    61  
    62  //is.stringify2(item)
    63  //}
    64  
    65  //----------
    66  
    67  func (is *ItemStringifier) stringify(item debug.Item) {
    68  	is.stringify2(item)
    69  }
    70  
    71  func (is *ItemStringifier) stringify2(item debug.Item) {
    72  	// NOTE: the string append is done sequentially to allow to detect where the strings are positioned (if later supported)
    73  
    74  	//log.Printf("stringifyitem: %T", item)
    75  
    76  	switch t := item.(type) {
    77  	case *debug.ItemValue:
    78  		if is.fullStr {
    79  			is.p(t.Str)
    80  		} else {
    81  			is.p(debug.SprintCutCheckQuote(20, t.Str))
    82  		}
    83  
    84  	case *debug.ItemList: // ex: func args list
    85  		if t == nil {
    86  			break
    87  		}
    88  		for i, e := range t.List {
    89  			if i > 0 {
    90  				is.p(", ")
    91  			}
    92  			is.stringify(e)
    93  		}
    94  
    95  	case *debug.ItemList2:
    96  		if t == nil {
    97  			break
    98  		}
    99  		for i, e := range t.List {
   100  			if i > 0 {
   101  				is.p("; ")
   102  			}
   103  			is.stringify(e)
   104  		}
   105  
   106  	case *debug.ItemAssign:
   107  		is.stringify(t.Lhs)
   108  
   109  		// it's misleading to get a "2 += 1", better to just show "2 = 1"
   110  		//is.p(" " + token.Token(t.Op).String() + " ")
   111  		is.p(" ")
   112  		switch t2 := token.Token(t.Op); t2 {
   113  		case token.ADD_ASSIGN, token.SUB_ASSIGN,
   114  			token.MUL_ASSIGN, token.QUO_ASSIGN,
   115  			token.REM_ASSIGN,
   116  			token.INC, token.DEC:
   117  			is.p("=")
   118  		default:
   119  			is.p(t2.String())
   120  		}
   121  		is.p(" ")
   122  
   123  		is.stringify(t.Rhs)
   124  
   125  	case *debug.ItemSend:
   126  		is.stringify(t.Chan)
   127  		is.p(" <- ")
   128  		is.stringify(t.Value)
   129  
   130  	case *debug.ItemCallEnter:
   131  		is.p("=> ")
   132  		is.stringify(t.Fun)
   133  		is.p("(")
   134  		is.stringify(t.Args)
   135  		is.p(")")
   136  	case *debug.ItemCall:
   137  		_ = is.result(t.Result)
   138  		is.stringify(t.Enter.Fun)
   139  		is.p("(")
   140  		is.stringify(t.Enter.Args)
   141  		is.p(")")
   142  
   143  	case *debug.ItemIndex:
   144  		_ = is.result(t.Result)
   145  		if t.Expr != nil {
   146  			//switch t2 := t.Expr.(type) {
   147  			//case string:
   148  			//	is.p( t2
   149  			//default:
   150  			//	is.p( "("
   151  			//	is.stringify(t.Expr)
   152  			//	is.p( ")"
   153  			//}
   154  			is.stringify(t.Expr)
   155  		}
   156  		is.p("[")
   157  		if t.Index != nil {
   158  			is.stringify(t.Index)
   159  		}
   160  		is.p("]")
   161  
   162  	case *debug.ItemIndex2:
   163  		_ = is.result(t.Result)
   164  		if t.Expr != nil {
   165  			//switch t2 := t.Expr.(type) {
   166  			//case string:
   167  			//	is.p( t2
   168  			//default:
   169  			//	is.p( "("
   170  			//	is.stringify(t.Expr)
   171  			//	is.p( ")"
   172  			//}
   173  			is.stringify(t.Expr)
   174  		}
   175  		is.p("[")
   176  		if t.Low != nil {
   177  			is.stringify(t.Low)
   178  		}
   179  		is.p(":")
   180  		if t.High != nil {
   181  			is.stringify(t.High)
   182  		}
   183  		if t.Slice3 {
   184  			is.p(":")
   185  		}
   186  		if t.Max != nil {
   187  			is.stringify(t.Max)
   188  		}
   189  		is.p("]")
   190  
   191  	case *debug.ItemKeyValue:
   192  		is.stringify(t.Key)
   193  		is.p(":")
   194  		is.stringify(t.Value)
   195  
   196  	case *debug.ItemSelector:
   197  		is.p("(")
   198  		is.stringify(t.X)
   199  		is.p(").")
   200  		is.stringify(t.Sel)
   201  
   202  	case *debug.ItemTypeAssert:
   203  		is.stringify(t.Type)
   204  		is.p("=type(")
   205  		is.stringify(t.X)
   206  		is.p(")")
   207  
   208  	case *debug.ItemBinary:
   209  		showRes := is.result(t.Result)
   210  		if showRes {
   211  			is.p("(")
   212  		}
   213  		is.stringify(t.X)
   214  		is.p(" " + token.Token(t.Op).String() + " ")
   215  		is.stringify(t.Y)
   216  		if showRes {
   217  			is.p(")")
   218  		}
   219  
   220  	case *debug.ItemUnaryEnter:
   221  		is.p("=> ")
   222  		is.p(token.Token(t.Op).String())
   223  		is.stringify(t.X)
   224  	case *debug.ItemUnary:
   225  		_ = is.result(t.Result)
   226  		is.p(token.Token(t.Enter.Op).String())
   227  		is.stringify(t.Enter.X)
   228  
   229  	case *debug.ItemParen:
   230  		is.p("(")
   231  		is.stringify(t.X)
   232  		is.p(")")
   233  
   234  	case *debug.ItemLiteral:
   235  		is.p("{") // other runes: τ, s // ex: A{a:1}, []byte{1,2}
   236  		if t != nil {
   237  			is.stringify(t.Fields)
   238  		}
   239  		is.p("}")
   240  
   241  	case *debug.ItemAnon:
   242  		is.p("_")
   243  
   244  	case *debug.ItemBranch:
   245  		is.p("#")
   246  	case *debug.ItemStep:
   247  		is.p("#")
   248  	case *debug.ItemLabel:
   249  		is.p("#")
   250  		if t.Reason != "" {
   251  			is.p(" label: " + t.Reason)
   252  		}
   253  	case *debug.ItemNotAnn:
   254  		is.p(fmt.Sprintf("# not annotated: %v", t.Reason))
   255  
   256  	default:
   257  		is.p(fmt.Sprintf("[TODO:(%T)%v]", item, item))
   258  	}
   259  }
   260  
   261  //----------
   262  
   263  func (is *ItemStringifier) result(result debug.Item) bool {
   264  	if result == nil {
   265  		return false
   266  	}
   267  
   268  	isList := false
   269  	if _, ok := result.(*debug.ItemList); ok {
   270  		isList = true
   271  	}
   272  	if isList {
   273  		is.p("(")
   274  	}
   275  
   276  	is.stringify(result)
   277  
   278  	if isList {
   279  		is.p(")")
   280  	}
   281  
   282  	is.p("=") // other runes: ≡ // nice, but not all fonts have it defined
   283  
   284  	return true
   285  }