Skip to content

Commit

Permalink
internal/core/export: support package and struct attributes
Browse files Browse the repository at this point in the history
Fixes #665

Change-Id: Id2ceec41ff3fcbedb22e74a488b1909da934287f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8342
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Jan 28, 2021
1 parent ba8eb37 commit 34587b9
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 4 deletions.
4 changes: 4 additions & 0 deletions cmd/cue/cmd/testdata/script/def_jsonschema.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ package schema
import "strings"

#Person: {
// Person
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
@jsonschema(id="https://example.com/person.schema.json")

// The person's first name.
firstName?: string

Expand Down
12 changes: 11 additions & 1 deletion internal/core/export/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct,
exporter: x,
values: &adt.Vertex{},
fields: map[adt.Feature]field{},
attrs: []*ast.Attribute{},
}

_, saved := e.pushFrame(orig)
Expand All @@ -101,6 +102,10 @@ func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct,

s := x.top().scope

for _, a := range e.attrs {
s.Elts = append(s.Elts, a)
}

// Unify values only for one level.
if len(e.values.Conjuncts) > 0 {
e.values.Finalize(e.ctx)
Expand Down Expand Up @@ -133,7 +138,7 @@ func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct,
switch len(e.exprs) {
case 0:
if len(e.structs) > 0 {
return ast.NewStruct()
return s
}
return ast.NewIdent("_")
case 1:
Expand Down Expand Up @@ -207,6 +212,7 @@ type conjuncts struct {
exprs []ast.Expr
structs []*adt.StructInfo
fields map[adt.Feature]field
attrs []*ast.Attribute
hasEllipsis bool
}

Expand Down Expand Up @@ -237,6 +243,10 @@ func (e *conjuncts) addExpr(env *adt.Environment, x adt.Expr) {
case *adt.StructLit:
e.top().upCount++

if e.cfg.ShowAttributes {
e.attrs = extractDeclAttrs(e.attrs, x.Src)
}

// Only add if it only has no bulk fields or elipsis.
if isComplexStruct(x) {
_, saved := e.pushFrame(nil)
Expand Down
29 changes: 29 additions & 0 deletions internal/core/export/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package export
import (
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/token"
"cuelang.org/go/internal"
"cuelang.org/go/internal/core/adt"
)

Expand Down Expand Up @@ -151,6 +152,34 @@ func ExtractFieldAttrs(a []adt.Conjunct) (attrs []*ast.Attribute) {
return attrs
}

func ExtractDeclAttrs(a []adt.Conjunct) (attrs []*ast.Attribute) {
for _, c := range a {
attrs = extractDeclAttrs(attrs, c.Expr().Source())
}
return attrs
}

func extractDeclAttrs(attrs []*ast.Attribute, n ast.Node) []*ast.Attribute {
switch x := n.(type) {
case nil:
case *ast.File:
info := internal.GetPackageInfo(x)
attrs = appendDeclAttrs(attrs, x.Decls[info.Index:])
case *ast.StructLit:
attrs = appendDeclAttrs(attrs, x.Elts)
}
return attrs
}

func appendDeclAttrs(a []*ast.Attribute, decls []ast.Decl) []*ast.Attribute {
for _, d := range decls {
if attr, ok := d.(*ast.Attribute); ok && !containsAttr(a, attr) {
a = append(a, attr)
}
}
return a
}

func containsAttr(a []*ast.Attribute, x *ast.Attribute) bool {
for _, e := range a {
if e.Text == x.Text {
Expand Down
3 changes: 3 additions & 0 deletions internal/core/export/testdata/adt.txtar
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
-- in.cue --
import mystrings "strings"

@foo(bar)

p1: [X=string]: name: X

d1: "foo\(bar)": int
Expand Down Expand Up @@ -254,6 +256,7 @@ _|_ // e3: index out of range [2] with length 2
_|_ // e3: index out of range [2] with length 2
== All
{
@foo(bar)
p1: {}
d1: {
foobar: int
Expand Down
84 changes: 84 additions & 0 deletions internal/core/export/testdata/attrs.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
-- a.cue --
@package("foo")

package bar

@file("foo")

a: {
@decl(1)
@decl(2)
} @field(2)

a: {
@decl(1)
@decl(3)

} @field(1) @field(4)

a: {} @field(1) @field(3)

-- b.cue --
@package("b")

package bar

@file("bar")

a: {
@decl(5)
} @field(5)


-- out/definition --
package bar

@file("foo")

@file("bar")
a: {
@decl(1)
@decl(2)
@decl(3)
@decl(5)
} @field(2) @field(1) @field(4) @field(3) @field(5)
-- out/doc --
[]
[a]
-- out/value --
== Simplified
{
a: {}
}
== Raw
{
a: {}
}
== Final
{
a: {}
}
== All
{
@file("foo")

@file("bar")
a: {
@decl(1)
@decl(2)
@decl(3)
@decl(5)
} @field(2) @field(1) @field(4) @field(3) @field(5)
}
== Eval
{
@file("foo")

@file("bar")
a: {
@decl(1)
@decl(2)
@decl(3)
@decl(5)
} @field(2) @field(1) @field(4) @field(3) @field(5)
}
6 changes: 6 additions & 0 deletions internal/core/export/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,12 @@ func (e *exporter) structComposite(v *adt.Vertex) ast.Expr {
e.addEmbed(e.value(x))
}

if e.cfg.ShowAttributes {
for _, a := range ExtractDeclAttrs(v.Conjuncts) {
s.Elts = append(s.Elts, a)
}
}

p := e.cfg
for _, label := range VertexFeatures(v) {
show := false
Expand Down
21 changes: 18 additions & 3 deletions internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,33 @@ func ListEllipsis(n *ast.ListLit) (elts []ast.Expr, e *ast.Ellipsis) {
return elts, e
}

func PackageInfo(f *ast.File) (p *ast.Package, name string, tok token.Pos) {
for _, d := range f.Decls {
type PkgInfo struct {
Package *ast.Package
Index int // position in File.Decls
Name string
}

func GetPackageInfo(f *ast.File) PkgInfo {
for i, d := range f.Decls {
switch x := d.(type) {
case *ast.CommentGroup:
case *ast.Attribute:
case *ast.Package:
if x.Name == nil {
break
}
return x, x.Name.Name, x.Name.Pos()
return PkgInfo{x, i, x.Name.Name}
}
}
return PkgInfo{}
}

// Deprecated: use GetPackageInfo
func PackageInfo(f *ast.File) (p *ast.Package, name string, tok token.Pos) {
x := GetPackageInfo(f)
if p := x.Package; p != nil {
return p, x.Name, p.Name.Pos()
}
return nil, "", f.Pos()
}

Expand Down

0 comments on commit 34587b9

Please sign in to comment.