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 = ", "