cuelang.org/go@v0.10.1/internal/astinternal/debugstr.go (about)

     1  // Copyright 2021 CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package astinternal
    16  
    17  import (
    18  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  
    22  	"cuelang.org/go/cue/ast"
    23  	"cuelang.org/go/cue/token"
    24  	"cuelang.org/go/internal"
    25  )
    26  
    27  func DebugStr(x interface{}) (out string) {
    28  	if n, ok := x.(ast.Node); ok {
    29  		comments := ""
    30  		for _, g := range ast.Comments(n) {
    31  			comments += DebugStr(g)
    32  		}
    33  		if comments != "" {
    34  			defer func() { out = "<" + comments + out + ">" }()
    35  		}
    36  	}
    37  	switch v := x.(type) {
    38  	case *ast.File:
    39  		out := ""
    40  		out += DebugStr(v.Decls)
    41  		return out
    42  
    43  	case *ast.Package:
    44  		out := "package "
    45  		out += DebugStr(v.Name)
    46  		return out
    47  
    48  	case *ast.LetClause:
    49  		out := "let "
    50  		out += DebugStr(v.Ident)
    51  		out += "="
    52  		out += DebugStr(v.Expr)
    53  		return out
    54  
    55  	case *ast.Alias:
    56  		out := DebugStr(v.Ident)
    57  		out += "="
    58  		out += DebugStr(v.Expr)
    59  		return out
    60  
    61  	case *ast.BottomLit:
    62  		return "_|_"
    63  
    64  	case *ast.BasicLit:
    65  		return v.Value
    66  
    67  	case *ast.Interpolation:
    68  		for _, e := range v.Elts {
    69  			out += DebugStr(e)
    70  		}
    71  		return out
    72  
    73  	case *ast.EmbedDecl:
    74  		out += DebugStr(v.Expr)
    75  		return out
    76  
    77  	case *ast.ImportDecl:
    78  		out := "import "
    79  		if v.Lparen != token.NoPos {
    80  			out += "( "
    81  			out += DebugStr(v.Specs)
    82  			out += " )"
    83  		} else {
    84  			out += DebugStr(v.Specs)
    85  		}
    86  		return out
    87  
    88  	case *ast.Comprehension:
    89  		out := DebugStr(v.Clauses)
    90  		out += DebugStr(v.Value)
    91  		return out
    92  
    93  	case *ast.StructLit:
    94  		out := "{"
    95  		out += DebugStr(v.Elts)
    96  		out += "}"
    97  		return out
    98  
    99  	case *ast.ListLit:
   100  		out := "["
   101  		out += DebugStr(v.Elts)
   102  		out += "]"
   103  		return out
   104  
   105  	case *ast.Ellipsis:
   106  		out := "..."
   107  		if v.Type != nil {
   108  			out += DebugStr(v.Type)
   109  		}
   110  		return out
   111  
   112  	case *ast.ForClause:
   113  		out := "for "
   114  		if v.Key != nil {
   115  			out += DebugStr(v.Key)
   116  			out += ": "
   117  		}
   118  		out += DebugStr(v.Value)
   119  		out += " in "
   120  		out += DebugStr(v.Source)
   121  		return out
   122  
   123  	case *ast.IfClause:
   124  		out := "if "
   125  		out += DebugStr(v.Condition)
   126  		return out
   127  
   128  	case *ast.Field:
   129  		out := DebugStr(v.Label)
   130  		if t, ok := internal.ConstraintToken(v); ok {
   131  			out += t.String()
   132  		}
   133  		if v.Value != nil {
   134  			switch v.Token {
   135  			case token.ILLEGAL, token.COLON:
   136  				out += ": "
   137  			default:
   138  				out += fmt.Sprintf(" %s ", v.Token)
   139  			}
   140  			out += DebugStr(v.Value)
   141  			for _, a := range v.Attrs {
   142  				out += " "
   143  				out += DebugStr(a)
   144  			}
   145  		}
   146  		return out
   147  
   148  	case *ast.Attribute:
   149  		return v.Text
   150  
   151  	case *ast.Ident:
   152  		return v.Name
   153  
   154  	case *ast.SelectorExpr:
   155  		return DebugStr(v.X) + "." + DebugStr(v.Sel)
   156  
   157  	case *ast.CallExpr:
   158  		out := DebugStr(v.Fun)
   159  		out += "("
   160  		out += DebugStr(v.Args)
   161  		out += ")"
   162  		return out
   163  
   164  	case *ast.ParenExpr:
   165  		out := "("
   166  		out += DebugStr(v.X)
   167  		out += ")"
   168  		return out
   169  
   170  	case *ast.UnaryExpr:
   171  		return v.Op.String() + DebugStr(v.X)
   172  
   173  	case *ast.BinaryExpr:
   174  		out := DebugStr(v.X)
   175  		op := v.Op.String()
   176  		if 'a' <= op[0] && op[0] <= 'z' {
   177  			op = fmt.Sprintf(" %s ", op)
   178  		}
   179  		out += op
   180  		out += DebugStr(v.Y)
   181  		return out
   182  
   183  	case []*ast.CommentGroup:
   184  		var a []string
   185  		for _, c := range v {
   186  			a = append(a, DebugStr(c))
   187  		}
   188  		return strings.Join(a, "\n")
   189  
   190  	case *ast.CommentGroup:
   191  		str := "["
   192  		if v.Doc {
   193  			str += "d"
   194  		}
   195  		if v.Line {
   196  			str += "l"
   197  		}
   198  		str += strconv.Itoa(int(v.Position))
   199  		var a = []string{}
   200  		for _, c := range v.List {
   201  			a = append(a, c.Text)
   202  		}
   203  		return str + strings.Join(a, " ") + "] "
   204  
   205  	case *ast.IndexExpr:
   206  		out := DebugStr(v.X)
   207  		out += "["
   208  		out += DebugStr(v.Index)
   209  		out += "]"
   210  		return out
   211  
   212  	case *ast.SliceExpr:
   213  		out := DebugStr(v.X)
   214  		out += "["
   215  		out += DebugStr(v.Low)
   216  		out += ":"
   217  		out += DebugStr(v.High)
   218  		out += "]"
   219  		return out
   220  
   221  	case *ast.ImportSpec:
   222  		out := ""
   223  		if v.Name != nil {
   224  			out += DebugStr(v.Name)
   225  			out += " "
   226  		}
   227  		out += DebugStr(v.Path)
   228  		return out
   229  
   230  	case *ast.Func:
   231  		return fmt.Sprintf("func(%v): %v", DebugStr(v.Args), DebugStr(v.Ret))
   232  
   233  	case []ast.Decl:
   234  		if len(v) == 0 {
   235  			return ""
   236  		}
   237  		out := ""
   238  		for _, d := range v {
   239  			out += DebugStr(d)
   240  			out += sep
   241  		}
   242  		return out[:len(out)-len(sep)]
   243  
   244  	case []ast.Clause:
   245  		if len(v) == 0 {
   246  			return ""
   247  		}
   248  		out := ""
   249  		for _, c := range v {
   250  			out += DebugStr(c)
   251  			out += " "
   252  		}
   253  		return out
   254  
   255  	case []ast.Expr:
   256  		if len(v) == 0 {
   257  			return ""
   258  		}
   259  		out := ""
   260  		for _, d := range v {
   261  			out += DebugStr(d)
   262  			out += sep
   263  		}
   264  		return out[:len(out)-len(sep)]
   265  
   266  	case []*ast.ImportSpec:
   267  		if len(v) == 0 {
   268  			return ""
   269  		}
   270  		out := ""
   271  		for _, d := range v {
   272  			out += DebugStr(d)
   273  			out += sep
   274  		}
   275  		return out[:len(out)-len(sep)]
   276  
   277  	default:
   278  		if v == nil {
   279  			return ""
   280  		}
   281  		return fmt.Sprintf("<%T>", x)
   282  	}
   283  }
   284  
   285  const sep = ", "