cuelang.org/go@v0.10.1/cue/ast/astutil/apply_test.go (about) 1 // Copyright 2019 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 astutil_test 16 17 import ( 18 "strings" 19 "testing" 20 21 "github.com/go-quicktest/qt" 22 23 "cuelang.org/go/cue/ast" 24 "cuelang.org/go/cue/ast/astutil" 25 "cuelang.org/go/cue/format" 26 "cuelang.org/go/cue/parser" 27 "cuelang.org/go/cue/token" 28 ) 29 30 func TestApply(t *testing.T) { 31 testCases := []struct { 32 name string 33 in string 34 out string 35 before func(astutil.Cursor) bool 36 after func(astutil.Cursor) bool 37 }{{ 38 // This should pass 39 }, { 40 name: "insert before", 41 in: ` 42 // foo is a 43 foo: { 44 a: 3 45 } 46 `, 47 out: ` 48 iam: new 49 50 // foo is a 51 foo: { 52 iam: new 53 a: 3 54 } 55 `, 56 before: func(c astutil.Cursor) bool { 57 switch c.Node().(type) { 58 case *ast.Field: 59 c.InsertBefore(&ast.Field{ 60 Label: ast.NewIdent("iam"), 61 Value: ast.NewIdent("new"), 62 }) 63 } 64 return true 65 }, 66 }, { 67 name: "insert after", 68 in: ` 69 foo: { 70 a: 3 @test() 71 } 72 `, 73 out: ` 74 foo: { 75 a: 3 @test() 76 iam: new 77 } 78 iam: new 79 `, 80 before: func(c astutil.Cursor) bool { 81 switch c.Node().(type) { 82 case *ast.Field: 83 c.InsertAfter(&ast.Field{ 84 Label: ast.NewIdent("iam"), 85 Value: ast.NewIdent("new"), 86 }) 87 } 88 return true 89 }, 90 }, { 91 name: "insert after recursive", 92 in: ` 93 foo: { 94 a: 3 @test() 95 } 96 `, 97 out: ` 98 foo: { 99 a: 3 @test() 100 iam: { 101 here: new 102 there: new 103 } 104 everywhere: new 105 } 106 iam: { 107 here: new 108 there: new 109 } 110 everywhere: new 111 `, 112 before: func(c astutil.Cursor) bool { 113 switch x := c.Node().(type) { 114 case *ast.Field: 115 switch x.Label.(*ast.Ident).Name { 116 default: 117 c.InsertAfter(astutil.ApplyRecursively(&ast.Field{ 118 Label: ast.NewIdent("iam"), 119 Value: ast.NewStruct(ast.NewIdent("here"), ast.NewIdent("new")), 120 })) 121 case "iam": 122 c.InsertAfter(&ast.Field{ 123 Label: ast.NewIdent("everywhere"), 124 Value: ast.NewIdent("new"), 125 }) 126 case "here": 127 c.InsertAfter(&ast.Field{ 128 Label: ast.NewIdent("there"), 129 Value: ast.NewIdent("new"), 130 }) 131 case "everywhere": 132 } 133 } 134 return true 135 }}, { 136 name: "templates", 137 in: ` 138 foo: { 139 a: [string]: c: 3 140 } 141 `, 142 out: ` 143 foo: { 144 a: [string]: { 145 c: 3 146 iam: new 147 } 148 } 149 `, 150 before: func(c astutil.Cursor) bool { 151 switch x := c.Node().(type) { 152 case *ast.Field: 153 if _, ok := x.Value.(*ast.StructLit); !ok { 154 c.InsertAfter(&ast.Field{ 155 Label: ast.NewIdent("iam"), 156 Value: ast.NewIdent("new"), 157 }) 158 } 159 } 160 return true 161 }, 162 }, { 163 name: "replace", 164 in: ` 165 // keep comment 166 a: "string" // and this one 167 b: 3 168 c: [ 1, 2, 8, 4 ] 169 d: "\(foo) is \(0)" 170 `, 171 out: ` 172 // keep comment 173 a: s // and this one 174 b: 4 175 c: [4, 4, 4, 4] 176 d: "\(foo) is \(4)" 177 `, 178 before: func(c astutil.Cursor) bool { 179 switch x := c.Node().(type) { 180 case *ast.BasicLit: 181 switch x.Kind { 182 case token.STRING: 183 if c.Index() < 0 { 184 c.Replace(ast.NewIdent("s")) 185 } 186 case token.INT: 187 c.Replace(ast.NewLit(token.INT, "4")) 188 } 189 } 190 return true 191 }, 192 }, { 193 name: "delete", 194 in: ` 195 z: 0 196 a: "foo" 197 b: 3 198 b: "bar" 199 c: 2 200 `, 201 out: ` 202 a: "foo" 203 b: "bar" 204 `, 205 before: func(c astutil.Cursor) bool { 206 f, ok := c.Node().(*ast.Field) 207 if !ok { 208 return true 209 } 210 switch x := f.Value.(type) { 211 case *ast.BasicLit: 212 switch x.Kind { 213 case token.INT: 214 c.Delete() 215 } 216 } 217 return true 218 }, 219 }, { 220 name: "comments", 221 in: ` 222 // test 223 a: "string" 224 `, 225 out: ` 226 // 1, 2, 3 227 a: "string" 228 `, 229 before: func(c astutil.Cursor) bool { 230 switch c.Node().(type) { 231 case *ast.Comment: 232 c.Replace(&ast.Comment{Text: "// 1, 2, 3"}) 233 } 234 return true 235 }, 236 }, { 237 name: "comments after", 238 in: ` 239 // test 240 a: "string" 241 `, 242 out: ` 243 // 1, 2, 3 244 a: "string" 245 `, 246 after: func(c astutil.Cursor) bool { 247 switch c.Node().(type) { 248 case *ast.Comment: 249 c.Replace(&ast.Comment{Text: "// 1, 2, 3"}) 250 } 251 return true 252 }, 253 }, { 254 name: "imports add", 255 in: ` 256 a: "string" 257 `, 258 out: ` 259 import list6c6973 "list" 260 261 a: list6c6973 262 `, 263 after: func(c astutil.Cursor) bool { 264 switch c.Node().(type) { 265 case *ast.BasicLit: 266 c.Replace(c.Import("list")) 267 } 268 return true 269 }, 270 }, { 271 name: "imports add to", 272 in: `package foo 273 274 import "math" 275 276 a: 3 277 `, 278 out: `package foo 279 280 import ( 281 "math" 282 list6c6973 "list" 283 ) 284 285 a: list6c6973 286 `, 287 after: func(c astutil.Cursor) bool { 288 switch x := c.Node().(type) { 289 case *ast.BasicLit: 290 if x.Kind == token.INT { 291 c.Replace(c.Import("list")) 292 } 293 } 294 return true 295 }, 296 }, { 297 name: "imports duplicate", 298 in: `package foo 299 300 import "list" 301 302 a: 3 303 `, 304 out: `package foo 305 306 import ( 307 "list" 308 list6c6973 "list" 309 ) 310 311 a: list6c6973 312 `, 313 after: func(c astutil.Cursor) bool { 314 switch x := c.Node().(type) { 315 case *ast.BasicLit: 316 if x.Kind == token.INT { 317 c.Replace(c.Import("list")) 318 } 319 } 320 return true 321 }, 322 }} 323 for _, tc := range testCases { 324 t.Run(tc.name, func(t *testing.T) { 325 f, err := parser.ParseFile(tc.name, tc.in, parser.ParseComments) 326 if err != nil { 327 t.Fatal(err) 328 } 329 330 n := astutil.Apply(f, tc.before, tc.after) 331 332 b, err := format.Node(n) 333 qt.Assert(t, qt.IsNil(err)) 334 got := strings.TrimSpace(string(b)) 335 want := strings.TrimSpace(tc.out) 336 qt.Assert(t, qt.Equals(got, want)) 337 }) 338 } 339 }