`cue.Value.Attribute` only handles FieldAttr
A bit of an inconsistency with the cue.Value.Attribute(s) API
The singular and plural versions of the function seem to have an off by one in the tree height error.
Note, I expected the first Attributes call to return the attributes on the same value as the previous Attribute call. I'm not sure what the second Attributes call should return?
- should looking up
ashould return the inner value where we would only get teh@decl() - does
@field()apply to the a label, such that when we return at the LookupPath, it is lost? - intuitively it seems there should be exclusivity, or that only one of the two levels in calling
Attributeswould return an attribute of either type. Note sure whether Field or Decl Attributes should always return together when written as below, or if there are situations where they would be split between the two levels. - by "levels" I'm referring to the
avsAoutput and two calls ofAttributeson either side of theLookupPathcall
CUE v0.4.1
exec go run main.go
cmp stdout golden.stdout
-- main.go --
package main
import (
"fmt"
"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
)
var CTX cue.Context
// Our tasks specified as Cue
var input = `
a: {
@decl()
val: _
} @field()
`
func main() {
// create context
ctx := cuecontext.New()
// compile our input
val := ctx.CompileString(input, cue.Filename("input.cue"))
if val.Err() != nil {
fmt.Println("Error:", val.Err())
return
}
fmt.Printf("%# v\n", val)
d := val.Attribute("decl")
fmt.Printf("d: %#+v\n", d)
f := val.Attribute("field")
fmt.Printf("f: %#+v\n", f)
as := val.Attributes(cue.ValueAttr)
fmt.Println("len:", len(as))
for i, a := range as {
fmt.Printf("a[%d]: %#+v\n", i, a)
}
val = val.LookupPath(cue.ParsePath("a"))
as = val.Attributes(cue.ValueAttr)
fmt.Println("len:", len(as))
for i, a := range as {
fmt.Printf("A[%d]: %#+v\n", i, a)
}
}
-- golden.stdout --
a: {
val: _
}
d: @decl()
f: @field()
len: 2
a[0]: @field()
a[1]: @decl()
len: 2
A[0]: @field()
A[1]: @decl()
What actually printed
a: {
val: _
}
d: @decl()
f: @field()
len: 0
len: 2
A[0]: @field()
A[1]: @decl()
@verdverm - please can you provide an example of what you were trying to do here, but couldn't?
@myitcv I've updated the description with the reproducer I forgot to add
I think the issue title is clear, and it is true that Value.Attribute() only returns field attributes and not struct attributes.
But I don't understand the example/reproducer and the issue description, and the example doesn't call the Attribute method for a value with a struct attribute. In the example, the root value has no attributes. I guess the root can't really have field attributes. It can have struct attributes, but in the example it does not. So to me this explains why the first call to Attributes returns the empty list. I think some confusion may be because the Value.Attribute(key) method always returns an attribute and never an error even if there is no attribute for the key, so val.Attribute("whatever") will always succeed. So the calls to val.Attribute("field") val.Attribute("decl") in the example are for a value (root) that does not have any attributes "field" and "decl" (the method still returns non nil *Attribute, and these print as "@field()" and "@decl()"). The second level, the value under "a" has these attributes, so the second call to Attributes() returns these. The example never calls Attribute() on this value under "a".
Amending the example input to actually have some data in the attributes makes it a bit easier to see what's going on:
var input = `
a: {
@decl(foo)
val: _
} @field(bar)
`
Gives the output:
a: {
val: _
}
d: @decl()
f: @field()
len: 0
len: 2
A[0]: @field(bar)
A[1]: @decl(foo)
The first two attribute lookups are not on a. And top-level doesn't have attributes, so I don't see how this is wrong. Anyway, some upcoming attribute changes might help if you are nonetheless seeing issues.