this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cmd/cue/cmd: add get to define CUE package from Go

Update #24

Change-Id: Ief47b7295249354d5eafbe0bcf33ea26dd6dfdc7
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/1723
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>

authored by

Marcel van Lohuizen and committed by
Marcel van Lohuizen
412e5ffd e9fd214d

+1608 -10
+1 -1
cmd/cue/cmd/common_test.go
··· 42 42 if err != nil { 43 43 log.Fatal(err) 44 44 } 45 - 46 45 const dir = "./testdata" 46 + 47 47 filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 48 48 t.Run(path, func(t *testing.T) { 49 49 if err != nil {
+45
cmd/cue/cmd/get.go
··· 1 + // Copyright 2018 The 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 cmd 16 + 17 + import ( 18 + "fmt" 19 + 20 + "github.com/spf13/cobra" 21 + ) 22 + 23 + // getCmd represents the extract command 24 + var getCmd = &cobra.Command{ 25 + Use: "get <language> [packages]", 26 + Short: "add dependencies to the current module", 27 + Long: `Get downloads packages or modules for CUE or another language 28 + to include them in the module's pkg directory. 29 + 30 + Get requires an additional language field to determine for which 31 + language definitions should be fetched. If get fetches definitions 32 + for a language other than CUE, the definitions are extracted from 33 + the source of the respective language and stored. 34 + The specifics on how dependencies are fechted and converted vary 35 + per language and are documented in the respective subcommands. 36 + `, 37 + RunE: func(cmd *cobra.Command, args []string) error { 38 + fmt.Println("get must be run as one of its subcommands") 39 + return nil 40 + }, 41 + } 42 + 43 + func init() { 44 + rootCmd.AddCommand(getCmd) 45 + }
+1073
cmd/cue/cmd/get_go.go
··· 1 + // Copyright 2018 The 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 cmd 16 + 17 + import ( 18 + "bytes" 19 + "fmt" 20 + "go/ast" 21 + "go/token" 22 + "go/types" 23 + "io" 24 + "io/ioutil" 25 + "os" 26 + "path" 27 + "path/filepath" 28 + "reflect" 29 + "regexp" 30 + "sort" 31 + "strconv" 32 + "strings" 33 + 34 + "cuelang.org/go/cue/format" 35 + "cuelang.org/go/cue/parser" 36 + cuetoken "cuelang.org/go/cue/token" 37 + "github.com/spf13/cobra" 38 + "golang.org/x/tools/go/packages" 39 + ) 40 + 41 + // TODO: 42 + // Document: 43 + // - how to deal with "oneOf" or sum types? 44 + // - generate cue files for cuego definitions? 45 + // - cue go get or cue get go 46 + // - include generation report in doc_gen.cue or report.txt. 47 + // Possible enums: 48 + // package foo 49 + // Type: enumType 50 + 51 + var getGoCmd = &cobra.Command{ 52 + Use: "go [packages]", 53 + Short: "add Go dependencies to the current module", 54 + Long: `go converts Go types into CUE definitions 55 + 56 + The command "cue get go" is like "go get", but converts the retrieved Go 57 + packages to CUE. The retrieved packages are put in the CUE module's pkg 58 + directory at the import path of the corresponding Go package. The converted 59 + definitions are available to any CUE file within the CUE module by using 60 + this import path. 61 + 62 + The Go type definitions are converted to CUE based on how they would be 63 + interpreted by Go's encoding/json package. Definitions for a Go file foo.go 64 + are written to a CUE file named foo_go_gen.cue. 65 + 66 + It is safe for users to add additional files to the generated directories, 67 + as long as their name does not end with _gen.*. 68 + 69 + 70 + Rules of Converting Go types to CUE 71 + 72 + Go structs are converted to cue structs adhering to the following conventions: 73 + 74 + - field names are translated based on the definition of a "json" or "yaml" 75 + tag, in that order. 76 + 77 + - embedded structs marked with a json inline tag unify with struct 78 + definition. For instance, the Go struct 79 + 80 + struct MyStruct { 81 + Common ` + "json:\",inline\"" + ` 82 + Field string 83 + } 84 + 85 + translates to the CUE struct 86 + 87 + MyStruct: Common & { 88 + Field: string 89 + } 90 + 91 + - a type that implements MarshalJSON, UnmarshalJSON, MarshalYAML, or 92 + UnmarshalYAML is translated to top (_) to indicate it may be any 93 + value. For some Go core types for which the implementation of these 94 + methods is known, like time.Time, the type may be more specific. 95 + 96 + - a type implementing MarshalText or UnmarshalText is represented as 97 + the CUE type string 98 + 99 + - slices and arrays convert to CUE lists, except when the element type is 100 + byte, in which case it translates to the CUE bytes type. 101 + In the case of arrays, the length of the CUE value is constrained 102 + accordingly, when possible. 103 + 104 + - Maps translate to a CUE struct, where all elements are constrained to 105 + be of Go map element type. Like for JSON, maps may only have string keys. 106 + 107 + - Pointers translate to a sum type with the default value of null and 108 + the Go type as an alternative value. 109 + 110 + - Field tags are translated to CUE's field attributes. In some cases, 111 + the contents are rewritten to reflect the corresponding types in CUE. 112 + The @go attribute is added if the field name or type definition differs 113 + between the generated CUE and the original Go. 114 + 115 + 116 + Native CUE Constraints 117 + 118 + Native CUE constraints may be defined in separate cue files alongside the 119 + generated files either in the original Go directory or in the generated 120 + directory. These files can impose additional constraints on types and values 121 + that are not otherwise expressible in Go. The package name for these CUE files 122 + must be the same as that of the Go package. 123 + 124 + For instance, for the type 125 + 126 + package foo 127 + 128 + type IP4String string 129 + 130 + defined in the Go package, one could add a cue file foo.cue with the following 131 + contents to allow IP4String to assume only valid IP4 addresses: 132 + 133 + package foo 134 + 135 + // IP4String defines a valid IP4 address. 136 + IP4String: =~#"^\#(byte)\.\#(byte)\.\#(byte)\.\#(byte)$"# 137 + 138 + // byte defines string allowing integer values of 0-255. 139 + byte = #"([01]?\d?\d|2[0-4]\d|25[0-5])"# 140 + 141 + 142 + The "cue get go" command copies any cue files in the original Go package 143 + directory that has a package clause with the same name as the Go package to the 144 + destination directory, replacing its .cue ending with _gen.cue. 145 + 146 + Alternatively, the additional native constraints can be added to the generated 147 + package, as long as the file name does not end with _gen.cue. 148 + Running cue get go again to regenerate the package will never overwrite any 149 + files not ending with _gen.*. 150 + 151 + 152 + Constants and Enums 153 + 154 + Go does not have an enum or sum type. Conventionally, a type that is supposed 155 + to be an enum is followed by a const block with the allowed values for that 156 + type. However, as that is only a guideline and not a hard rule, these cases 157 + cannot be translated to CUE disjunctions automatically. 158 + 159 + Constant values, however, are generated in a way that makes it easy to convert 160 + a type to a proper enum using native CUE constraints. For instance, the Go type 161 + 162 + package foo 163 + 164 + type Switch int 165 + 166 + const ( 167 + Off Switch = iota 168 + On 169 + ) 170 + 171 + translates into the following CUE definitions: 172 + 173 + package foo 174 + 175 + Switch: int // enumSwitch 176 + 177 + enumSwitch: Off | On 178 + 179 + Off: 0 180 + On: 1 181 + 182 + This definition allows any integer value for Switch, while the enumSwitch value 183 + defines all defined constants for Switch and thus all valid values if Switch 184 + were to be interpreted as an enum type. To turn Switch into an enum, 185 + include the following constraint in, say, enum.cue, in either the original 186 + source directory or the generated directory: 187 + 188 + package foo 189 + 190 + // limit the valid values for Switch to those existing as constants with 191 + // the same type. 192 + Switch: enumSwitch 193 + 194 + This tells CUE that only the values enumerated by enumSwitch are valid 195 + values for Switch. Note that there are now two definitions of Switch. 196 + CUE handles this in the usual way by unifying the two definitions, in which case 197 + the more restrictive enum interpretation of Switch remains. 198 + `, 199 + // - TODO: interpret cuego's struct tags and annotations. 200 + 201 + RunE: func(cmd *cobra.Command, args []string) error { 202 + return extract(cmd, args) 203 + }, 204 + } 205 + 206 + func init() { 207 + getCmd.AddCommand(getGoCmd) 208 + 209 + exclude = getGoCmd.Flags().StringP("exclude", "e", "", 210 + "comma-separated list of regexps of entries") 211 + } 212 + 213 + var ( 214 + cueTestRoot string // the CUE module root for test purposes. 215 + exclude *string 216 + 217 + exclusions []*regexp.Regexp 218 + ) 219 + 220 + type dstUsed struct { 221 + dst string 222 + used bool 223 + } 224 + 225 + func initExclusions() { 226 + for _, re := range strings.Split(*exclude, ",") { 227 + if re != "" { 228 + exclusions = append(exclusions, regexp.MustCompile(re)) 229 + } 230 + } 231 + } 232 + 233 + func filter(name string) bool { 234 + if !ast.IsExported(name) { 235 + return true 236 + } 237 + for _, ex := range exclusions { 238 + if ex.MatchString(name) { 239 + return true 240 + } 241 + } 242 + return false 243 + } 244 + 245 + type extractor struct { 246 + stderr io.Writer 247 + err error 248 + pkgs []*packages.Package 249 + done map[string]bool 250 + 251 + // per package 252 + orig map[types.Type]*ast.StructType 253 + usedPkgs map[string]bool 254 + 255 + // per file 256 + w *bytes.Buffer 257 + cmap ast.CommentMap 258 + pkg *packages.Package 259 + consts map[string][]string 260 + pkgNames map[string]string 261 + usedInFile map[string]bool 262 + indent int 263 + } 264 + 265 + func (e *extractor) logf(format string, args ...interface{}) { 266 + if *fVerbose { 267 + fmt.Fprintf(e.stderr, format+"\n", args...) 268 + } 269 + } 270 + 271 + func (e *extractor) usedPkg(pkg string) { 272 + e.usedPkgs[pkg] = true 273 + e.usedInFile[pkg] = true 274 + } 275 + 276 + func (e *extractor) errorf(format string, args ...interface{}) { 277 + err := fmt.Errorf(format, args...) 278 + fmt.Fprintln(e.stderr, err) 279 + if e.err == nil { 280 + e.err = err 281 + } 282 + } 283 + 284 + func initInterfaces() error { 285 + cfg := &packages.Config{ 286 + Mode: packages.LoadAllSyntax, 287 + } 288 + p, err := packages.Load(cfg, "cuelang.org/go/cmd/cue/cmd/interfaces") 289 + if err != nil { 290 + return err 291 + } 292 + 293 + for e, tt := range p[0].TypesInfo.Types { 294 + if n, ok := tt.Type.(*types.Named); ok && n.String() == "error" { 295 + continue 296 + } 297 + if tt.Type.Underlying().String() == "interface{}" { 298 + continue 299 + } 300 + 301 + switch tt.Type.Underlying().(type) { 302 + case *types.Interface: 303 + file := p[0].Fset.Position(e.Pos()).Filename 304 + switch filepath.Base(file) { 305 + case "top.go": 306 + toTop = append(toTop, tt.Type) 307 + case "text.go": 308 + toString = append(toString, tt.Type) 309 + } 310 + } 311 + } 312 + return nil 313 + } 314 + 315 + var ( 316 + toTop []types.Type 317 + toString []types.Type 318 + ) 319 + 320 + // TODO: 321 + // - consider not including types with any dropped fields. 322 + 323 + func extract(cmd *cobra.Command, args []string) error { 324 + // determine module root: 325 + binst := loadFromArgs(cmd, []string{"."})[0] 326 + 327 + if err := initInterfaces(); err != nil { 328 + return err 329 + } 330 + 331 + // TODO: require explicitly set root. 332 + root := binst.Root 333 + 334 + // Override root in testing mode. 335 + if cueTestRoot != "" { 336 + root = cueTestRoot 337 + } 338 + 339 + cfg := &packages.Config{ 340 + Mode: packages.LoadAllSyntax, 341 + } 342 + pkgs, err := packages.Load(cfg, args...) 343 + if err != nil { 344 + return err 345 + } 346 + 347 + e := extractor{ 348 + stderr: cmd.OutOrStderr(), 349 + pkgs: pkgs, 350 + orig: map[types.Type]*ast.StructType{}, 351 + } 352 + 353 + initExclusions() 354 + 355 + e.done = map[string]bool{} 356 + 357 + for _, p := range pkgs { 358 + e.done[p.PkgPath] = true 359 + } 360 + 361 + for _, p := range pkgs { 362 + if err := e.extractPkg(root, p); err != nil { 363 + return err 364 + } 365 + } 366 + return nil 367 + } 368 + 369 + func (e *extractor) recordTypeInfo(p *packages.Package) { 370 + for _, f := range p.Syntax { 371 + ast.Inspect(f, func(n ast.Node) bool { 372 + switch x := n.(type) { 373 + case *ast.StructType: 374 + e.orig[p.TypesInfo.TypeOf(x)] = x 375 + } 376 + return true 377 + }) 378 + } 379 + } 380 + 381 + func (e *extractor) extractPkg(root string, p *packages.Package) error { 382 + e.pkg = p 383 + e.logf("--- Package %s", p.PkgPath) 384 + 385 + e.recordTypeInfo(p) 386 + 387 + e.consts = map[string][]string{} 388 + 389 + for _, f := range p.Syntax { 390 + for _, d := range f.Decls { 391 + switch x := d.(type) { 392 + case *ast.GenDecl: 393 + e.recordConsts(x) 394 + } 395 + } 396 + } 397 + 398 + pkg := p.PkgPath 399 + dir := filepath.Join(root, "pkg", filepath.FromSlash(pkg)) 400 + if err := os.MkdirAll(dir, 0755); err != nil { 401 + return err 402 + } 403 + 404 + e.usedPkgs = map[string]bool{} 405 + 406 + args := pkg 407 + if *exclude != "" { 408 + args += " --exclude=" + *exclude 409 + } 410 + 411 + for i, f := range p.Syntax { 412 + e.w = &bytes.Buffer{} 413 + 414 + e.cmap = ast.NewCommentMap(p.Fset, f, f.Comments) 415 + 416 + e.pkgNames = map[string]string{} 417 + e.usedInFile = map[string]bool{} 418 + 419 + for _, spec := range f.Imports { 420 + key, _ := strconv.Unquote(spec.Path.Value) 421 + if spec.Name != nil { 422 + e.pkgNames[key] = spec.Name.Name 423 + } else { 424 + // TODO: incorrect, should be name of package clause 425 + e.pkgNames[key] = path.Base(key) 426 + } 427 + } 428 + 429 + hasEntries := false 430 + for _, d := range f.Decls { 431 + switch x := d.(type) { 432 + case *ast.GenDecl: 433 + if e.reportDecl(e.w, x) { 434 + hasEntries = true 435 + } 436 + } 437 + } 438 + 439 + if !hasEntries && f.Doc == nil { 440 + continue 441 + } 442 + 443 + pkgs := []string{} 444 + for k := range e.usedInFile { 445 + pkgs = append(pkgs, k) 446 + } 447 + sort.Strings(pkgs) 448 + 449 + w := &bytes.Buffer{} 450 + 451 + fmt.Fprintln(w, "// Code generated by cue get go. DO NOT EDIT.") 452 + fmt.Fprintln(w) 453 + fmt.Fprintln(w, "//cue:generate cue get go", args) 454 + fmt.Fprintln(w) 455 + if f.Doc != nil { 456 + for _, c := range f.Doc.List { 457 + fmt.Fprintln(w, c.Text) 458 + } 459 + } 460 + fmt.Fprintf(w, "package %s\n", p.Name) 461 + fmt.Fprintln(w) 462 + if len(pkgs) > 0 { 463 + fmt.Fprintln(w, "import (") 464 + for _, s := range pkgs { 465 + name := e.pkgNames[s] 466 + if p.Imports[s].Name == name { 467 + fmt.Fprintf(w, "%q\n", s) 468 + } else { 469 + fmt.Fprintf(w, "%v %q\n", name, s) 470 + } 471 + } 472 + fmt.Fprintln(w, ")") 473 + fmt.Fprintln(w) 474 + } 475 + fmt.Fprintln(w) 476 + io.Copy(w, e.w) 477 + 478 + file := filepath.Base(p.CompiledGoFiles[i]) 479 + 480 + file = strings.Replace(file, ".go", "_go", 1) 481 + file += "_gen.cue" 482 + b, err := format.Source(w.Bytes()) 483 + if err != nil { 484 + ioutil.WriteFile(filepath.Join(dir, file), w.Bytes(), 0644) 485 + fmt.Println(w.String()) 486 + fmt.Println(dir, file) 487 + return err 488 + } 489 + err = ioutil.WriteFile(filepath.Join(dir, file), b, 0644) 490 + if err != nil { 491 + return err 492 + } 493 + } 494 + 495 + for _, o := range p.CompiledGoFiles { 496 + root := filepath.Dir(o) 497 + err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { 498 + if fi.IsDir() && path != root { 499 + return filepath.SkipDir 500 + } 501 + if filepath.Ext(path) != ".cue" { 502 + return nil 503 + } 504 + f, err := parser.ParseFile(cuetoken.NewFileSet(), path, nil) 505 + if err != nil { 506 + return err 507 + } 508 + 509 + if f.Name != nil && f.Name.Name == p.Name { 510 + file := filepath.Base(path) 511 + file = file[:len(file)-len(".cue")] 512 + file += "_gen.cue" 513 + 514 + w := &bytes.Buffer{} 515 + fmt.Fprintln(w, "// Code generated by cue get go. DO NOT EDIT.") 516 + fmt.Fprintln(w) 517 + fmt.Fprintln(w, "//cue:generate cue get go", args) 518 + fmt.Fprintln(w) 519 + 520 + b, err := ioutil.ReadFile(path) 521 + if err != nil { 522 + return err 523 + } 524 + w.Write(b) 525 + 526 + dst := filepath.Join(dir, file) 527 + if err := ioutil.WriteFile(dst, w.Bytes(), 0644); err != nil { 528 + return err 529 + } 530 + } 531 + return nil 532 + }) 533 + if err != nil { 534 + return err 535 + } 536 + } 537 + 538 + for path := range e.usedPkgs { 539 + if !e.done[path] { 540 + e.done[path] = true 541 + p := p.Imports[path] 542 + if err := e.extractPkg(root, p); err != nil { 543 + return err 544 + } 545 + } 546 + } 547 + 548 + return nil 549 + } 550 + 551 + func (e *extractor) recordConsts(x *ast.GenDecl) { 552 + if x.Tok != token.CONST { 553 + return 554 + } 555 + for _, s := range x.Specs { 556 + v, ok := s.(*ast.ValueSpec) 557 + if !ok { 558 + continue 559 + } 560 + for _, n := range v.Names { 561 + typ := e.pkg.TypesInfo.TypeOf(n).String() 562 + e.consts[typ] = append(e.consts[typ], n.Name) 563 + } 564 + } 565 + } 566 + 567 + func (e *extractor) reportDecl(w io.Writer, x *ast.GenDecl) (added bool) { 568 + switch x.Tok { 569 + case token.TYPE: 570 + for _, s := range x.Specs { 571 + v, ok := s.(*ast.TypeSpec) 572 + if !ok || filter(v.Name.Name) { 573 + continue 574 + } 575 + 576 + typ := e.pkg.TypesInfo.TypeOf(v.Name) 577 + enums := e.consts[typ.String()] 578 + name := v.Name.Name 579 + switch tn, ok := e.pkg.TypesInfo.Defs[v.Name].(*types.TypeName); { 580 + case ok: 581 + if altType := e.altType(tn.Type()); altType != "" { 582 + // TODO: add the underlying tag as a Go tag once we have 583 + // proper string escaping for CUE. 584 + e.printDoc(x.Doc, true) 585 + fmt.Fprintf(e.w, "%s: %s", name, altType) 586 + added = true 587 + break 588 + } 589 + fallthrough 590 + 591 + default: 592 + if !supportedType(nil, typ) { 593 + e.logf(" Dropped declaration %v of unsupported type %v", name, typ) 594 + continue 595 + } 596 + added = true 597 + 598 + if s := e.altType(types.NewPointer(typ)); s != "" { 599 + e.printDoc(x.Doc, true) 600 + fmt.Fprint(e.w, name, ": ", s) 601 + break 602 + } 603 + // TODO: only print original type if value is not marked as enum. 604 + underlying := e.pkg.TypesInfo.TypeOf(v.Type) 605 + e.printField(name, false, underlying, x.Doc, true) 606 + } 607 + 608 + e.indent++ 609 + if len(enums) > 0 { 610 + fmt.Fprintf(e.w, " // enum%s", name) 611 + 612 + e.newLine() 613 + e.newLine() 614 + fmt.Fprintf(e.w, "enum%s:\n%v", name, enums[0]) 615 + for _, v := range enums[1:] { 616 + fmt.Fprint(e.w, " |") 617 + e.newLine() 618 + fmt.Fprint(e.w, v) 619 + } 620 + } 621 + e.indent-- 622 + e.newLine() 623 + e.newLine() 624 + } 625 + 626 + case token.CONST: 627 + // TODO: copy over comments for constant blocks. 628 + 629 + for _, s := range x.Specs { 630 + // TODO: determine type name and filter. 631 + v, ok := s.(*ast.ValueSpec) 632 + if !ok { 633 + continue 634 + } 635 + 636 + for i, name := range v.Names { 637 + if !ast.IsExported(name.Name) { 638 + continue 639 + } 640 + added = true 641 + 642 + e.printDoc(v.Doc, true) 643 + fmt.Fprint(e.w, name.Name, ": ") 644 + 645 + typ := e.pkg.TypesInfo.TypeOf(name) 646 + if s := typ.String(); !strings.Contains(s, "untyped") { 647 + switch s { 648 + case "byte", "string", "error": 649 + default: 650 + e.printType(typ) 651 + fmt.Fprint(e.w, " & ") 652 + } 653 + } 654 + 655 + val := "" 656 + comment := "" 657 + if i < len(v.Values) { 658 + if lit, ok := v.Values[i].(*ast.BasicLit); ok { 659 + val = lit.Value 660 + } 661 + } 662 + 663 + outer: 664 + switch { 665 + case len(val) <= 1: 666 + case val[0] == '\'': 667 + comment = " // " + val 668 + val = "" 669 + 670 + case strings.HasPrefix(val, "0"): 671 + for _, c := range val[1:] { 672 + if c < '0' || '9' < c { 673 + val = "" 674 + break outer 675 + } 676 + } 677 + val = "0o" + val[1:] 678 + } 679 + 680 + if val == "" { 681 + c := e.pkg.TypesInfo.Defs[v.Names[i]].(*types.Const) 682 + val = c.Val().String() 683 + } 684 + 685 + fmt.Fprint(e.w, val, comment) 686 + e.newLine() 687 + } 688 + } 689 + e.newLine() 690 + } 691 + return added 692 + } 693 + 694 + func shortTypeName(t types.Type) string { 695 + if n, ok := t.(*types.Named); ok { 696 + return n.Obj().Name() 697 + } 698 + return t.String() 699 + } 700 + 701 + func (e *extractor) altType(typ types.Type) string { 702 + ptr := types.NewPointer(typ) 703 + for _, x := range toTop { 704 + i := x.Underlying().(*types.Interface) 705 + if types.Implements(typ, i) || types.Implements(ptr, i) { 706 + t := shortTypeName(typ) 707 + e.logf(" %v implements %s; setting type to _", t, x) 708 + return "_" 709 + } 710 + } 711 + for _, x := range toString { 712 + i := x.Underlying().(*types.Interface) 713 + if types.Implements(typ, i) || types.Implements(ptr, i) { 714 + t := shortTypeName(typ) 715 + e.logf(" %v implements %s; setting type to string", t, x) 716 + return "string" 717 + } 718 + } 719 + return "" 720 + } 721 + 722 + func (e *extractor) printDoc(doc *ast.CommentGroup, newline bool) { 723 + if doc == nil { 724 + return 725 + } 726 + if newline { 727 + e.newLine() 728 + } 729 + for _, c := range doc.List { 730 + fmt.Fprint(e.w, c.Text) 731 + e.newLine() 732 + } 733 + } 734 + 735 + func (e *extractor) newLine() { 736 + fmt.Fprintln(e.w) 737 + fmt.Fprint(e.w, strings.Repeat(" ", e.indent)) 738 + } 739 + 740 + func supportedType(stack []types.Type, t types.Type) (ok bool) { 741 + // handle recursive types 742 + for _, t0 := range stack { 743 + if t0 == t { 744 + return true 745 + } 746 + } 747 + stack = append(stack, t) 748 + 749 + if named, ok := t.(*types.Named); ok { 750 + obj := named.Obj() 751 + 752 + // Redirect or drop Go standard library types. 753 + if obj.Pkg() == nil { 754 + // error interface 755 + return true 756 + } 757 + switch obj.Pkg().Path() { 758 + case "time": 759 + switch named.Obj().Name() { 760 + case "Time", "Duration", "Location", "Month", "Weekday": 761 + return true 762 + } 763 + return false 764 + case "math/big": 765 + switch named.Obj().Name() { 766 + case "Int", "Float": 767 + return true 768 + } 769 + // case "net": 770 + // // TODO: IP, Host, SRV, etc. 771 + // case "url": 772 + // // TODO: URL and Values 773 + } 774 + } 775 + 776 + t = t.Underlying() 777 + switch x := t.(type) { 778 + case *types.Basic: 779 + return x.String() != "invalid type" 780 + case *types.Named: 781 + return true 782 + case *types.Pointer: 783 + return supportedType(stack, x.Elem()) 784 + case *types.Slice: 785 + return supportedType(stack, x.Elem()) 786 + case *types.Array: 787 + return supportedType(stack, x.Elem()) 788 + case *types.Map: 789 + if b, ok := x.Key().Underlying().(*types.Basic); !ok || b.Kind() != types.String { 790 + return false 791 + } 792 + return supportedType(stack, x.Elem()) 793 + case *types.Struct: 794 + // Eliminate structs with fields for which all fields are filtered. 795 + if x.NumFields() == 0 { 796 + return true 797 + } 798 + for i := 0; i < x.NumFields(); i++ { 799 + f := x.Field(i) 800 + if f.Exported() && supportedType(stack, f.Type()) { 801 + return true 802 + } 803 + } 804 + case *types.Interface: 805 + return true 806 + } 807 + return false 808 + } 809 + 810 + func (e *extractor) printField(name string, opt bool, expr types.Type, doc *ast.CommentGroup, newline bool) (typename string) { 811 + e.printDoc(doc, newline) 812 + colon := ": " 813 + if opt { 814 + colon = "?: " 815 + } 816 + fmt.Fprint(e.w, name, colon) 817 + pos := e.w.Len() 818 + e.printType(expr) 819 + return e.w.String()[pos:] 820 + } 821 + 822 + func (e *extractor) printType(expr types.Type) { 823 + if x, ok := expr.(*types.Named); ok { 824 + obj := x.Obj() 825 + if obj.Pkg() == nil { 826 + fmt.Fprint(e.w, "_") 827 + return 828 + } 829 + // Check for builtin packages. 830 + // TODO: replace these literal types with a reference to the fixed 831 + // builtin type. 832 + switch obj.Type().String() { 833 + case "time.Time": 834 + e.usedInFile["time"] = true 835 + fmt.Fprint(e.w, e.pkgNames[obj.Pkg().Path()], ".", obj.Name()) 836 + return 837 + 838 + case "math/big.Int": 839 + fmt.Fprint(e.w, "int") 840 + return 841 + 842 + default: 843 + if !strings.ContainsAny(obj.Pkg().Path(), ".") { 844 + // Drop any standard library type if they haven't been handled 845 + // above. 846 + if s := e.altType(obj.Type()); s != "" { 847 + fmt.Fprint(e.w, s) 848 + return 849 + } 850 + } 851 + } 852 + if pkg := obj.Pkg(); pkg != nil { 853 + if name := e.pkgNames[pkg.Path()]; name != "" { 854 + fmt.Fprint(e.w, name, ".") 855 + e.usedPkg(pkg.Path()) 856 + } 857 + } 858 + fmt.Fprint(e.w, obj.Name()) 859 + return 860 + } 861 + 862 + switch x := expr.(type) { 863 + case *types.Pointer: 864 + fmt.Fprintf(e.w, "null | ") 865 + e.printType(x.Elem()) 866 + 867 + case *types.Struct: 868 + for i := 0; i < x.NumFields(); i++ { 869 + f := x.Field(i) 870 + if f.Anonymous() && e.isInline(x.Tag(i)) { 871 + typ := f.Type() 872 + if _, ok := typ.(*types.Named); ok { 873 + e.printType(typ) 874 + fmt.Fprintf(e.w, " & ") 875 + } 876 + } 877 + } 878 + fmt.Fprint(e.w, "{") 879 + e.indent++ 880 + e.printFields(x) 881 + e.indent-- 882 + e.newLine() 883 + fmt.Fprint(e.w, "}") 884 + 885 + case *types.Slice: 886 + // TODO: should this be x.Elem().Underlying().String()? One could 887 + // argue either way. 888 + if x.Elem().String() == "byte" { 889 + fmt.Fprint(e.w, "bytes") 890 + } else { 891 + fmt.Fprint(e.w, "[...") 892 + e.printType(x.Elem()) 893 + fmt.Fprint(e.w, "]") 894 + } 895 + 896 + case *types.Array: 897 + if x.Elem().String() == "byte" { 898 + // TODO: no way to constraint lengths of bytes for now, as regexps 899 + // operate on Unicode, not bytes. So we need 900 + // fmt.Fprint(e.w, fmt.Sprintf("=~ '^\C{%d}$'", x.Len())), 901 + // but regexp does not support that. 902 + // But translate to bytes, instead of [...byte] to be consistent. 903 + fmt.Fprint(e.w, "bytes") 904 + } else { 905 + fmt.Fprintf(e.w, "%d*[", x.Len()) 906 + e.printType(x.Elem()) 907 + fmt.Fprint(e.w, "]") 908 + } 909 + 910 + case *types.Map: 911 + if b, ok := x.Key().Underlying().(*types.Basic); !ok || b.Kind() != types.String { 912 + log.Panicf("unsupported map key type %T", x.Key()) 913 + } 914 + fmt.Fprintf(e.w, "{ <_>: ") 915 + e.printType(x.Elem()) 916 + fmt.Fprintf(e.w, " }") 917 + 918 + case *types.Basic: 919 + fmt.Fprint(e.w, x.String()) 920 + 921 + case *types.Interface: 922 + fmt.Fprintf(e.w, "_") 923 + 924 + default: 925 + // record error 926 + panic(fmt.Sprintf("unsupported type %T", x)) 927 + } 928 + } 929 + 930 + func (e *extractor) printFields(x *types.Struct) { 931 + s := e.orig[x] 932 + docs := []*ast.CommentGroup{} 933 + for _, f := range s.Fields.List { 934 + if len(f.Names) == 0 { 935 + docs = append(docs, f.Doc) 936 + } else { 937 + for range f.Names { 938 + docs = append(docs, f.Doc) 939 + } 940 + } 941 + } 942 + count := 0 943 + for i := 0; i < x.NumFields(); i++ { 944 + f := x.Field(i) 945 + if !ast.IsExported(f.Name()) { 946 + continue 947 + } 948 + if !supportedType(nil, f.Type()) { 949 + e.logf(" Dropped field %v for unsupported type %v", f.Name(), f.Type()) 950 + continue 951 + } 952 + if f.Anonymous() && e.isInline(x.Tag(i)) { 953 + typ := f.Type() 954 + if _, ok := typ.(*types.Named); !ok { 955 + switch x := typ.(type) { 956 + case *types.Struct: 957 + e.printFields(x) 958 + default: 959 + panic(fmt.Sprintf("unimplemented embedding for type %T", x)) 960 + } 961 + } 962 + continue 963 + } 964 + tag := x.Tag(i) 965 + name := getName(f.Name(), tag) 966 + if name == "-" { 967 + continue 968 + } 969 + e.newLine() 970 + cueType := e.printField(name, e.isOptional(tag), f.Type(), docs[i], count > 0) 971 + 972 + // Add field tag to convert back to Go. 973 + typeName := f.Type().String() 974 + // simplify type names: 975 + for path, name := range e.pkgNames { 976 + typeName = strings.Replace(typeName, path+".", name+".", -1) 977 + } 978 + typeName = strings.Replace(typeName, e.pkg.Types.Path()+".", "", -1) 979 + 980 + // TODO: remove fields in @go attr that are the same as printed? 981 + if name != f.Name() || typeName != cueType { 982 + fmt.Fprint(e.w, "@go(") 983 + if name != f.Name() { 984 + fmt.Fprint(e.w, f.Name()) 985 + } 986 + if typeName != cueType { 987 + if strings.ContainsAny(typeName, `#"',()=`) { 988 + typeName = strconv.Quote(typeName) 989 + } 990 + fmt.Fprint(e.w, ",", typeName) 991 + } 992 + fmt.Fprintf(e.w, ")") 993 + } 994 + 995 + // Carry over protobuf field tags with modifications. 996 + if t := reflect.StructTag(tag).Get("protobuf"); t != "" { 997 + split := strings.Split(t, ",") 998 + k := 0 999 + for _, s := range split { 1000 + if strings.HasPrefix(s, "name=") && s[len("name="):] == name { 1001 + continue 1002 + } 1003 + split[k] = s 1004 + k++ 1005 + } 1006 + split = split[:k] 1007 + 1008 + // Put tag first, as type could potentially be elided and is 1009 + // "more optional". 1010 + if len(split) >= 2 { 1011 + split[0], split[1] = split[1], split[0] 1012 + } 1013 + fmt.Fprintf(e.w, " @protobuf(%s)", strings.Join(split, ",")) 1014 + } 1015 + 1016 + // Carry over XML tags. 1017 + if t := reflect.StructTag(tag).Get("xml"); t != "" { 1018 + fmt.Fprintf(e.w, " @xml(%s)", t) 1019 + } 1020 + 1021 + // Carry over TOML tags. 1022 + if t := reflect.StructTag(tag).Get("toml"); t != "" { 1023 + fmt.Fprintf(e.w, " @toml(%s)", t) 1024 + } 1025 + 1026 + // TODO: should we in general carry over any unknown tag verbatim? 1027 + 1028 + count++ 1029 + } 1030 + } 1031 + 1032 + func (e *extractor) isInline(tag string) bool { 1033 + return hasFlag(tag, "json", "inline", 1) || 1034 + hasFlag(tag, "yaml", "inline", 1) 1035 + } 1036 + 1037 + func (e *extractor) isOptional(tag string) bool { 1038 + // TODO: also when the type is a list or other kind of pointer. 1039 + return hasFlag(tag, "json", "omitempty", 1) || 1040 + hasFlag(tag, "yaml", "omitempty", 1) 1041 + } 1042 + 1043 + func hasFlag(tag, key, flag string, offset int) bool { 1044 + if t := reflect.StructTag(tag).Get(key); t != "" { 1045 + split := strings.Split(t, ",") 1046 + if offset >= len(split) { 1047 + return false 1048 + } 1049 + for _, str := range split[offset:] { 1050 + if str == flag { 1051 + return true 1052 + } 1053 + } 1054 + } 1055 + return false 1056 + } 1057 + 1058 + func getName(name string, tag string) string { 1059 + tags := reflect.StructTag(tag) 1060 + for _, s := range []string{"json", "yaml"} { 1061 + if tag, ok := tags.Lookup(s); ok { 1062 + if p := strings.Index(tag, ","); p >= 0 { 1063 + tag = tag[:p] 1064 + } 1065 + if tag != "" { 1066 + return tag 1067 + } 1068 + } 1069 + } 1070 + // TODO: should we also consider to protobuf name? Probably not. 1071 + 1072 + return name 1073 + }
+102
cmd/cue/cmd/get_go_test.go
··· 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 cmd 16 + 17 + import ( 18 + "io/ioutil" 19 + "os" 20 + "path/filepath" 21 + "strings" 22 + "testing" 23 + 24 + "github.com/retr0h/go-gilt/copy" 25 + "github.com/spf13/cobra" 26 + ) 27 + 28 + func TestGetGo(t *testing.T) { 29 + // Leave the current working directory outside the testdata directory 30 + // so that Go loader finds the Go mod file and creates a proper path. 31 + // We need to trick the command to generate the data within the testdata 32 + // directory, though. 33 + tmp, err := ioutil.TempDir("", "cue_get_go") 34 + if err != nil { 35 + t.Fatal(err) 36 + } 37 + defer os.RemoveAll(tmp) 38 + 39 + cueTestRoot = tmp 40 + 41 + // We don't use runCommand here, as we are interested in generated packages. 42 + cmd := &cobra.Command{RunE: getGoCmd.RunE} 43 + cmd.SetArgs([]string{"./testdata/code/go/..."}) 44 + err = cmd.Execute() 45 + if err != nil { 46 + log.Fatal(err) 47 + } 48 + 49 + // Packages will generate differently in modules versus GOPATH. Search 50 + // for the common ground to not have breaking text if people run these 51 + // test in GOPATH mode. 52 + root := "" 53 + filepath.Walk(tmp, func(path string, info os.FileInfo, err error) error { 54 + if root != "" { 55 + return filepath.SkipDir 56 + } 57 + if filepath.Base(path) == "cuelang.org" { 58 + root = filepath.Dir(path) 59 + return filepath.SkipDir 60 + } 61 + return nil 62 + }) 63 + 64 + const dst = "testdata/pkg" 65 + 66 + if *update { 67 + os.RemoveAll(dst) 68 + err := copy.Dir(filepath.Join(root), dst) 69 + if err != nil { 70 + t.Fatal(err) 71 + } 72 + t.Skip("files updated") 73 + } 74 + 75 + prefix := "testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/" 76 + filepath.Walk(dst, func(path string, info os.FileInfo, err error) error { 77 + if info.IsDir() { 78 + return nil 79 + } 80 + t.Run(path, func(t *testing.T) { 81 + want := loadFile(t, path) 82 + got := loadFile(t, filepath.Join(root, path[len(dst):])) 83 + 84 + if want != got { 85 + t.Errorf("contexts for file %s differ", path[len(prefix):]) 86 + } 87 + }) 88 + return nil 89 + }) 90 + } 91 + 92 + func loadFile(t *testing.T, path string) string { 93 + t.Helper() 94 + b, err := ioutil.ReadFile(path) 95 + if err != nil { 96 + t.Fatalf("could not load file %s", path) 97 + } 98 + // Strip comments up till package clause. Local packages will generate 99 + // differently using GOPATH versuse modules. 100 + s := string(b) 101 + return s[strings.Index(s, "package"):] 102 + }
+22
cmd/cue/cmd/interfaces/text.go
··· 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 interfaces 16 + 17 + import "encoding" 18 + 19 + type ( 20 + textMarshaler = encoding.TextMarshaler 21 + textUnmarshaler = encoding.TextUnmarshaler 22 + )
+29
cmd/cue/cmd/interfaces/top.go
··· 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 interfaces 16 + 17 + import ( 18 + "encoding/json" 19 + ) 20 + 21 + type ( 22 + jsonMarshaler = json.Marshaler 23 + jsonUnmarshaler = json.Unmarshaler 24 + 25 + yamlMarshal interface{ MarshalYAML() (interface{}, error) } 26 + yamlUnmarshal interface { 27 + UnmarshalYAML(func(interface{}) error) error 28 + } 29 + )
+15 -8
cmd/cue/cmd/root.go
··· 28 28 // fix: rewrite/refactor configuration files 29 29 // -i interactive: open diff and ask to update 30 30 // serve: like cmd, but for servers 31 - // extract: extract cue from other languages, like proto and go. 31 + // get: convert cue from other languages, like proto and go. 32 32 // gen: generate files for other languages 33 33 // generate like go generate (also convert cue to go doc) 34 34 // test load and fully evaluate test files. ··· 151 151 } 152 152 153 153 var ( 154 - fDebug = rootCmd.PersistentFlags().Bool("debug", false, "give detailed error info") 155 - fTrace = rootCmd.PersistentFlags().Bool("trace", false, "trace computation") 156 - fDryrun = rootCmd.PersistentFlags().BoolP("dryrun", "n", false, "only run simulation") 157 - fPackage = rootCmd.PersistentFlags().StringP("package", "p", "", "CUE package to evaluate") 158 - fSimplify = rootCmd.PersistentFlags().BoolP("simplify", "s", false, "simplify output") 159 - fIgnore = rootCmd.PersistentFlags().BoolP("ignore", "i", false, "proceed in the presence of errors") 160 - fVerbose = rootCmd.PersistentFlags().BoolP("verbose", "v", false, "print information about progress") 154 + fDebug = rootCmd.PersistentFlags().Bool("debug", false, 155 + "give detailed error info") 156 + fTrace = rootCmd.PersistentFlags().Bool("trace", false, 157 + "trace computation") 158 + fDryrun = rootCmd.PersistentFlags().BoolP("dryrun", "n", false, 159 + "only run simulation") 160 + fPackage = rootCmd.PersistentFlags().StringP("package", "p", "", 161 + "CUE package to evaluate") 162 + fSimplify = rootCmd.PersistentFlags().BoolP("simplify", "s", false, 163 + "simplify output") 164 + fIgnore = rootCmd.PersistentFlags().BoolP("ignore", "i", false, 165 + "proceed in the presence of errors") 166 + fVerbose = rootCmd.PersistentFlags().BoolP("verbose", "v", false, 167 + "print information about progress") 161 168 ) 162 169 163 170 // initConfig reads in config file and ENV variables if set.
+104
cmd/cue/cmd/testdata/code/go/pkg1/file1.go
··· 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 pkg1 16 + 17 + import ( 18 + "encoding" 19 + "encoding/json" 20 + "time" 21 + 22 + p2 "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2" 23 + ) 24 + 25 + // Foozer foozes a jaman. 26 + type Foozer struct { 27 + Int int 28 + String string 29 + 30 + Inline `json:",inline"` 31 + NoInline 32 + 33 + CustomJSON CustomJSON 34 + CustomYAML *CustomYAML 35 + AnyJSON json.Marshaler 36 + AnyText encoding.TextMarshaler 37 + 38 + Bar int `json:"bar,omitempty"` 39 + 40 + exclude int 41 + 42 + // Time is mapped to CUE's internal type. 43 + Time time.Time 44 + 45 + Barzer p2.Barzer 46 + 47 + Map map[string]*CustomJSON 48 + Slice1 []int 49 + Slice2 []interface{} 50 + Slice3 *[]json.Unmarshaler 51 + Array1 [5]int 52 + Array2 [5]interface{} 53 + Array3 *[5]json.Marshaler 54 + 55 + Intf Interface `protobuf:"varint,2,name=intf"` 56 + Intf2 interface{} 57 + Intf3 struct{ Interface } 58 + Intf4 interface{ Foo() } 59 + 60 + // Even though this struct as a type implements MarshalJSON, it is known 61 + // that it is really only implemented by the embedded field. 62 + Embed struct{ CustomJSON } 63 + 64 + Unsupported map[int]string 65 + } 66 + 67 + // Level gives an indication of the extent of stuff. 68 + type Level int 69 + 70 + const ( 71 + Unknown Level = iota 72 + Low 73 + // Medium is neither High nor Low 74 + Medium 75 + High 76 + ) 77 + 78 + type CustomJSON struct { 79 + } 80 + 81 + func (c *CustomJSON) MarshalJSON() ([]byte, error) { 82 + return nil, nil 83 + } 84 + 85 + type CustomYAML struct { 86 + } 87 + 88 + func (c CustomYAML) MarshalYAML() ([]byte, error) { 89 + return nil, nil 90 + } 91 + 92 + type excludeType int 93 + 94 + type Inline struct { 95 + Kind string 96 + } 97 + 98 + type NoInline struct { 99 + Kind string 100 + } 101 + 102 + type Interface interface { 103 + Boomer() bool 104 + }
+19
cmd/cue/cmd/testdata/code/go/pkg2/add.cue
··· 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 pkg2 16 + 17 + Barzer: { 18 + S: =~"cat$" 19 + }
+42
cmd/cue/cmd/testdata/code/go/pkg2/pkg2.go
··· 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 pkg2 does other stuff. 16 + package pkg2 17 + 18 + import ( 19 + "math/big" 20 + t "time" 21 + ) 22 + 23 + // A Barzer barzes. 24 + type Barzer struct { 25 + A int `protobuf:"varint,2," json:"a"` 26 + 27 + T t.Time 28 + B *big.Int 29 + C big.Int 30 + F big.Float `xml:",attr"` 31 + G *big.Float 32 + H bool `json:"-"` 33 + S string 34 + 35 + Err error 36 + } 37 + 38 + const Perm = 0755 39 + 40 + const Few = 3 41 + 42 + const Couple int = 2
+14
cmd/cue/cmd/testdata/cue.mod
··· 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 +
+76
cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1/file1_go_gen.cue
··· 1 + // Code generated by cue get go. DO NOT EDIT. 2 + 3 + //cue:generate cue get go cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1 4 + 5 + package pkg1 6 + 7 + import ( 8 + p2 "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2" 9 + "time" 10 + ) 11 + 12 + // Foozer foozes a jaman. 13 + Foozer: Inline & { 14 + Int: int 15 + String: string 16 + NoInline: NoInline 17 + CustomJSON: CustomJSON 18 + CustomYAML: null | CustomYAML @go(,*CustomYAML) 19 + AnyJSON: _ @go(,json.Marshaler) 20 + AnyText: string @go(,encoding.TextMarshaler) 21 + bar?: int @go(Bar) 22 + 23 + // Time is mapped to CUE's internal type. 24 + Time: time.Time 25 + Barzer: p2.Barzer 26 + Map: {<_>: null | CustomJSON} @go(,map[string]*CustomJSON) 27 + Slice1: [...int] @go(,[]int) 28 + Slice2: [...] @go(,[]interface{}) 29 + Slice3: null | [...] @go(,*[]json.Unmarshaler) 30 + Array1: 5 * [int] @go(,[5]int) 31 + Array2: 5 * [_] @go(,[5]interface{}) 32 + Array3: null | 5*[_] @go(,*[5]json.Marshaler) 33 + Intf: Interface @protobuf(2,varint,name=intf) 34 + Intf2: _ @go(,interface{}) 35 + Intf3: { 36 + Interface: Interface 37 + } @go(,struct{Interface}) 38 + Intf4: _ @go(,"interface{Foo()}") 39 + 40 + // Even though this struct as a type implements MarshalJSON, it is known 41 + // that it is really only implemented by the embedded field. 42 + Embed: { 43 + CustomJSON: CustomJSON 44 + } @go(,struct{CustomJSON}) 45 + } 46 + 47 + // Level gives an indication of the extent of stuff. 48 + Level: int // enumLevel 49 + 50 + enumLevel: 51 + Unknown | 52 + Low | 53 + Medium | 54 + High 55 + 56 + Unknown: Level & 0 57 + Low: Level & 1 58 + 59 + // Medium is neither High nor Low 60 + Medium: Level & 2 61 + High: Level & 3 62 + 63 + CustomJSON: _ 64 + 65 + CustomYAML: { 66 + } 67 + 68 + Inline: { 69 + Kind: string 70 + } 71 + 72 + NoInline: { 73 + Kind: string 74 + } 75 + 76 + Interface: _
+23
cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/add_gen.cue
··· 1 + // Code generated by cue get go. DO NOT EDIT. 2 + 3 + //cue:generate cue get go cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2 4 + 5 + // Copyright 2019 CUE Authors 6 + // 7 + // Licensed under the Apache License, Version 2.0 (the "License"); 8 + // you may not use this file except in compliance with the License. 9 + // You may obtain a copy of the License at 10 + // 11 + // http://www.apache.org/licenses/LICENSE-2.0 12 + // 13 + // Unless required by applicable law or agreed to in writing, software 14 + // distributed under the License is distributed on an "AS IS" BASIS, 15 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 + // See the License for the specific language governing permissions and 17 + // limitations under the License. 18 + 19 + package pkg2 20 + 21 + Barzer: { 22 + S: =~"cat$" 23 + }
+28
cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/pkg2_go_gen.cue
··· 1 + // Code generated by cue get go. DO NOT EDIT. 2 + 3 + //cue:generate cue get go cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2 4 + 5 + // Package pkg2 does other stuff. 6 + package pkg2 7 + 8 + import ( 9 + t "time" 10 + ) 11 + 12 + // A Barzer barzes. 13 + Barzer: { 14 + a: int @go(A) @protobuf(2,varint,) 15 + T: t.Time 16 + B: null | int @go(,*big.Int) 17 + C: int @go(,big.Int) 18 + F: string @go(,big.Float) @xml(,attr) 19 + G: null | string @go(,*big.Float) 20 + S: string 21 + Err: _ @go(,error) 22 + } 23 + 24 + Perm: 0o755 25 + 26 + Few: 3 27 + 28 + Couple: int & 2
+1 -1
go.mod
··· 5 5 github.com/cockroachdb/apd v1.1.0 6 6 github.com/ghodss/yaml v1.0.0 7 7 github.com/google/go-cmp v0.2.0 8 - github.com/inconshreveable/mousetrap v1.0.0 // indirect 9 8 github.com/lib/pq v1.0.0 // indirect 10 9 github.com/mitchellh/go-homedir v1.0.0 11 10 github.com/pkg/errors v0.8.0 // indirect 11 + github.com/retr0h/go-gilt v0.0.0-20190206215556-f73826b37af2 12 12 github.com/spf13/cobra v0.0.3 13 13 github.com/spf13/viper v1.3.1 14 14 golang.org/x/exp/errors v0.0.0-20181221233300-b68661188fbf
+14
go.sum
··· 6 6 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 7 7 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 8 8 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 9 + github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 10 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 10 11 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 12 github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= ··· 18 19 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 19 20 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 20 21 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 22 + github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= 21 23 github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= 22 24 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 25 + github.com/logrusorgru/aurora v0.0.0-20180419164547-d694e6f975a9/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= 23 26 github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= 24 27 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 25 28 github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= ··· 32 35 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 33 36 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 34 37 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 38 + github.com/retr0h/go-gilt v0.0.0-20190206215556-f73826b37af2 h1:vZ42M1tDiMLtirFA1K5k2QVFhWRqR4BjdSw0IMclzH4= 39 + github.com/retr0h/go-gilt v0.0.0-20190206215556-f73826b37af2/go.mod h1:7PJr6TwZ6FwyTMn8zrm5QbMfH7yCiv56Wi9hRPhpWSM= 35 40 github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= 36 41 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 37 42 github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= 38 43 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 44 + github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 39 45 github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= 40 46 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 41 47 github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 42 48 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 49 + github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 43 50 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 44 51 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 45 52 github.com/spf13/viper v1.3.1 h1:5+8j8FTpnFV4nEImW/ofkzEt8VoOiLXxdYIDsB73T38= 46 53 github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 54 + github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 47 55 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 48 56 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 49 57 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 58 + github.com/xeipuuv/gojsonpointer v0.0.0-20170225233418-6fe8760cad35/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 59 + github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= 60 + github.com/xeipuuv/gojsonschema v0.0.0-20171230112544-511d08a359d1/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= 50 61 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 51 62 golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 52 63 golang.org/x/exp/errors v0.0.0-20181221233300-b68661188fbf h1:4SQtY0VxhI0RZe/PFmCCfHyaPVuC5DgyXEqehsAWjwc= 53 64 golang.org/x/exp/errors v0.0.0-20181221233300-b68661188fbf/go.mod h1:YgqsNsAu4fTvlab/7uiYK9LJrCIzKg/NiZUIH1/ayqo= 65 + golang.org/x/lint v0.0.0-20181011164241-5906bd5c48cd/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 54 66 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= 55 67 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 56 68 golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A= 57 69 golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 58 70 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 59 71 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 72 + golang.org/x/tools v0.0.0-20181018182439-def26773749b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 60 73 golang.org/x/tools v0.0.0-20181210225255-6a3e9aa2ab77 h1:s+6psEFi3o1QryeA/qyvUoVaHMCQkYVvZ0i2ZolwSJc= 61 74 golang.org/x/tools v0.0.0-20181210225255-6a3e9aa2ab77/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 62 75 golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373 h1:PPwnA7z1Pjf7XYaBP9GL1VAMZmcIWyFz7QCMSIIa3Bg= 63 76 golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 64 77 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 65 78 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 79 + gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 66 80 gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 67 81 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=