github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/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 "github.com/joomcode/cue/cue/ast" 23 "github.com/joomcode/cue/cue/token" 24 ) 25 26 func DebugStr(x interface{}) (out string) { 27 if n, ok := x.(ast.Node); ok { 28 comments := "" 29 for _, g := range n.Comments() { 30 comments += DebugStr(g) 31 } 32 if comments != "" { 33 defer func() { out = "<" + comments + out + ">" }() 34 } 35 } 36 switch v := x.(type) { 37 case *ast.File: 38 out := "" 39 out += DebugStr(v.Decls) 40 return out 41 42 case *ast.Package: 43 out := "package " 44 out += DebugStr(v.Name) 45 return out 46 47 case *ast.LetClause: 48 out := "let " 49 out += DebugStr(v.Ident) 50 out += "=" 51 out += DebugStr(v.Expr) 52 return out 53 54 case *ast.Alias: 55 out := DebugStr(v.Ident) 56 out += "=" 57 out += DebugStr(v.Expr) 58 return out 59 60 case *ast.BottomLit: 61 return "_|_" 62 63 case *ast.BasicLit: 64 return v.Value 65 66 case *ast.Interpolation: 67 for _, e := range v.Elts { 68 out += DebugStr(e) 69 } 70 return out 71 72 case *ast.EmbedDecl: 73 out += DebugStr(v.Expr) 74 return out 75 76 case *ast.ImportDecl: 77 out := "import " 78 if v.Lparen != token.NoPos { 79 out += "( " 80 out += DebugStr(v.Specs) 81 out += " )" 82 } else { 83 out += DebugStr(v.Specs) 84 } 85 return out 86 87 case *ast.Comprehension: 88 out := DebugStr(v.Clauses) 89 out += DebugStr(v.Value) 90 return out 91 92 case *ast.StructLit: 93 out := "{" 94 out += DebugStr(v.Elts) 95 out += "}" 96 return out 97 98 case *ast.ListLit: 99 out := "[" 100 out += DebugStr(v.Elts) 101 out += "]" 102 return out 103 104 case *ast.Ellipsis: 105 out := "..." 106 if v.Type != nil { 107 out += DebugStr(v.Type) 108 } 109 return out 110 111 case *ast.ForClause: 112 out := "for " 113 if v.Key != nil { 114 out += DebugStr(v.Key) 115 out += ": " 116 } 117 out += DebugStr(v.Value) 118 out += " in " 119 out += DebugStr(v.Source) 120 return out 121 122 case *ast.IfClause: 123 out := "if " 124 out += DebugStr(v.Condition) 125 return out 126 127 case *ast.Field: 128 out := DebugStr(v.Label) 129 if v.Optional != token.NoPos { 130 out += "?" 131 } 132 if v.Value != nil { 133 switch v.Token { 134 case token.ILLEGAL, token.COLON: 135 out += ": " 136 default: 137 out += fmt.Sprintf(" %s ", v.Token) 138 } 139 out += DebugStr(v.Value) 140 for _, a := range v.Attrs { 141 out += " " 142 out += DebugStr(a) 143 } 144 } 145 return out 146 147 case *ast.Attribute: 148 return v.Text 149 150 case *ast.Ident: 151 return v.Name 152 153 case *ast.SelectorExpr: 154 return DebugStr(v.X) + "." + DebugStr(v.Sel) 155 156 case *ast.CallExpr: 157 out := DebugStr(v.Fun) 158 out += "(" 159 out += DebugStr(v.Args) 160 out += ")" 161 return out 162 163 case *ast.ParenExpr: 164 out := "(" 165 out += DebugStr(v.X) 166 out += ")" 167 return out 168 169 case *ast.UnaryExpr: 170 return v.Op.String() + DebugStr(v.X) 171 172 case *ast.BinaryExpr: 173 out := DebugStr(v.X) 174 op := v.Op.String() 175 if 'a' <= op[0] && op[0] <= 'z' { 176 op = fmt.Sprintf(" %s ", op) 177 } 178 out += op 179 out += DebugStr(v.Y) 180 return out 181 182 case []*ast.CommentGroup: 183 var a []string 184 for _, c := range v { 185 a = append(a, DebugStr(c)) 186 } 187 return strings.Join(a, "\n") 188 189 case *ast.CommentGroup: 190 str := "[" 191 if v.Doc { 192 str += "d" 193 } 194 if v.Line { 195 str += "l" 196 } 197 str += strconv.Itoa(int(v.Position)) 198 var a = []string{} 199 for _, c := range v.List { 200 a = append(a, c.Text) 201 } 202 return str + strings.Join(a, " ") + "] " 203 204 case *ast.IndexExpr: 205 out := DebugStr(v.X) 206 out += "[" 207 out += DebugStr(v.Index) 208 out += "]" 209 return out 210 211 case *ast.SliceExpr: 212 out := DebugStr(v.X) 213 out += "[" 214 out += DebugStr(v.Low) 215 out += ":" 216 out += DebugStr(v.High) 217 out += "]" 218 return out 219 220 case *ast.ImportSpec: 221 out := "" 222 if v.Name != nil { 223 out += DebugStr(v.Name) 224 out += " " 225 } 226 out += DebugStr(v.Path) 227 return out 228 229 case []ast.Decl: 230 if len(v) == 0 { 231 return "" 232 } 233 out := "" 234 for _, d := range v { 235 out += DebugStr(d) 236 out += sep 237 } 238 return out[:len(out)-len(sep)] 239 240 case []ast.Clause: 241 if len(v) == 0 { 242 return "" 243 } 244 out := "" 245 for _, c := range v { 246 out += DebugStr(c) 247 out += " " 248 } 249 return out 250 251 case []ast.Expr: 252 if len(v) == 0 { 253 return "" 254 } 255 out := "" 256 for _, d := range v { 257 out += DebugStr(d) 258 out += sep 259 } 260 return out[:len(out)-len(sep)] 261 262 case []*ast.ImportSpec: 263 if len(v) == 0 { 264 return "" 265 } 266 out := "" 267 for _, d := range v { 268 out += DebugStr(d) 269 out += sep 270 } 271 return out[:len(out)-len(sep)] 272 273 default: 274 if v == nil { 275 return "" 276 } 277 return fmt.Sprintf("<%T>", x) 278 } 279 } 280 281 const sep = ", "