Skip to content

Commit fbfa705

Browse files
author
Charlie Egan
authored
[ast/opa parse] Support marshalling of all ast location data (#5576)
Signed-off-by: Charlie Egan <[email protected]>
1 parent 9e97f98 commit fbfa705

File tree

11 files changed

+1574
-60
lines changed

11 files changed

+1574
-60
lines changed

ast/annotations.go

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ const (
2626
type (
2727
// Annotations represents metadata attached to other AST nodes such as rules.
2828
Annotations struct {
29-
Location *Location `json:"-"`
3029
Scope string `json:"scope"`
3130
Title string `json:"title,omitempty"`
3231
Entrypoint bool `json:"entrypoint,omitempty"`
@@ -36,8 +35,11 @@ type (
3635
Authors []*AuthorAnnotation `json:"authors,omitempty"`
3736
Schemas []*SchemaAnnotation `json:"schemas,omitempty"`
3837
Custom map[string]interface{} `json:"custom,omitempty"`
39-
node Node
40-
comments []*Comment
38+
Location *Location `json:"location,omitempty"`
39+
40+
comments []*Comment
41+
node Node
42+
jsonOptions JSONOptions
4143
}
4244

4345
// SchemaAnnotation contains a schema declaration for the document identified by the path.
@@ -70,10 +72,13 @@ type (
7072
}
7173

7274
AnnotationsRef struct {
73-
Location *Location `json:"location"` // The location of the node the annotations are applied to
74-
Path Ref `json:"path"` // The path of the node the annotations are applied to
75+
Path Ref `json:"path"` // The path of the node the annotations are applied to
7576
Annotations *Annotations `json:"annotations,omitempty"`
76-
node Node // The node the annotations are applied to
77+
Location *Location `json:"location,omitempty"` // The location of the node the annotations are applied to
78+
79+
jsonOptions JSONOptions
80+
81+
node Node // The node the annotations are applied to
7782
}
7883

7984
AnnotationsRefSet []*AnnotationsRef
@@ -82,7 +87,7 @@ type (
8287
)
8388

8489
func (a *Annotations) String() string {
85-
bs, _ := json.Marshal(a)
90+
bs, _ := a.MarshalJSON()
8691
return string(bs)
8792
}
8893

@@ -175,6 +180,60 @@ func (a *Annotations) GetTargetPath() Ref {
175180
}
176181
}
177182

183+
func (a *Annotations) setJSONOptions(opts JSONOptions) {
184+
a.jsonOptions = opts
185+
}
186+
187+
func (a *Annotations) MarshalJSON() ([]byte, error) {
188+
if a == nil {
189+
return []byte(`{"scope":""}`), nil
190+
}
191+
192+
data := map[string]interface{}{
193+
"scope": a.Scope,
194+
}
195+
196+
if a.Title != "" {
197+
data["title"] = a.Title
198+
}
199+
200+
if a.Description != "" {
201+
data["description"] = a.Description
202+
}
203+
204+
if a.Entrypoint {
205+
data["entrypoint"] = a.Entrypoint
206+
}
207+
208+
if len(a.Organizations) > 0 {
209+
data["organizations"] = a.Organizations
210+
}
211+
212+
if len(a.RelatedResources) > 0 {
213+
data["related_resources"] = a.RelatedResources
214+
}
215+
216+
if len(a.Authors) > 0 {
217+
data["authors"] = a.Authors
218+
}
219+
220+
if len(a.Schemas) > 0 {
221+
data["schemas"] = a.Schemas
222+
}
223+
224+
if len(a.Custom) > 0 {
225+
data["custom"] = a.Custom
226+
}
227+
228+
if a.jsonOptions.MarshalOptions.IncludeLocation.Annotations {
229+
if a.Location != nil {
230+
data["location"] = a.Location
231+
}
232+
}
233+
234+
return json.Marshal(data)
235+
}
236+
178237
func NewAnnotationsRef(a *Annotations) *AnnotationsRef {
179238
var loc *Location
180239
if a.node != nil {
@@ -209,6 +268,24 @@ func (ar *AnnotationsRef) GetRule() *Rule {
209268
}
210269
}
211270

271+
func (ar *AnnotationsRef) MarshalJSON() ([]byte, error) {
272+
data := map[string]interface{}{
273+
"path": ar.Path,
274+
}
275+
276+
if ar.Annotations != nil {
277+
data["annotations"] = ar.Annotations
278+
}
279+
280+
if ar.jsonOptions.MarshalOptions.IncludeLocation.AnnotationsRef {
281+
if ar.Location != nil {
282+
data["location"] = ar.Location
283+
}
284+
}
285+
286+
return json.Marshal(data)
287+
}
288+
212289
func scopeCompare(s1, s2 string) int {
213290

214291
o1 := scopeOrder(s1)

ast/annotations_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ p := 7`},
5252
}
5353

5454
// Output:
55-
// data.foo at foo.rego:5 has annotations {"scope":"subpackages","organizations":["Acme Corp."]}
56-
// data.foo.bar at mod:3 has annotations {"scope":"package","description":"A couple of useful rules"}
55+
// data.foo at foo.rego:5 has annotations {"organizations":["Acme Corp."],"scope":"subpackages"}
56+
// data.foo.bar at mod:3 has annotations {"description":"A couple of useful rules","scope":"package"}
5757
// data.foo.bar.p at mod:7 has annotations {"scope":"rule","title":"My Rule P"}
5858
}
5959

@@ -102,8 +102,8 @@ p := 7`},
102102

103103
// Output:
104104
// data.foo.bar.p at mod:7 has annotations {"scope":"rule","title":"My Rule P"}
105-
// data.foo.bar at mod:3 has annotations {"scope":"package","description":"A couple of useful rules"}
106-
// data.foo at foo.rego:5 has annotations {"scope":"subpackages","organizations":["Acme Corp."]}
105+
// data.foo.bar at mod:3 has annotations {"description":"A couple of useful rules","scope":"package"}
106+
// data.foo at foo.rego:5 has annotations {"organizations":["Acme Corp."],"scope":"subpackages"}
107107
}
108108

109109
func TestAnnotationSet_Flatten(t *testing.T) {

ast/marshal.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package ast
2+
3+
// customJSON is an interface that can be implemented by AST nodes that
4+
// allows the parser to set options for JSON operations on that node.
5+
type customJSON interface {
6+
setJSONOptions(JSONOptions)
7+
}

0 commit comments

Comments
 (0)