-
Notifications
You must be signed in to change notification settings - Fork 38
/
annotation.go
104 lines (89 loc) · 2.25 KB
/
annotation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package core
import (
"encoding/json"
"fmt"
"regexp"
"sort"
"strings"
"github.com/klothoplatform/klotho/pkg/annotation"
"github.com/pelletier/go-toml/v2"
sitter "github.com/smacker/go-tree-sitter"
)
type (
Annotation struct {
Capability *annotation.Capability
// Node is the node that has been annotated; not the comment node representing the annotation itself.
Node *sitter.Node
}
AnnotationKey struct {
Capability string
ID string
}
AnnotationMap map[AnnotationKey]*Annotation
)
var (
lineIndentRE = regexp.MustCompile(`(?m)^`)
)
func (a *Annotation) MarshalJSON() ([]byte, error) {
m := map[string]interface{}{
"capability": a.Capability,
"node": map[string]interface{}{
"types": a.Node.String(),
},
}
return json.Marshal(m)
}
func (a Annotation) Format(s fmt.State, verb rune) {
fmt.Fprintf(s, "@klotho::%s", a.Capability.Name)
if len(a.Capability.Directives) > 0 {
if s.Flag('+') || s.Flag('#') {
fmt.Fprintf(s, " {")
dvals, _ := toml.Marshal(a.Capability.Directives)
directives := strings.TrimRight(string(dvals), "\n") // remove trailing newline so it doesn't get indented
directives = lineIndentRE.ReplaceAllString(directives, " ")
fmt.Fprintf(s, "\n%s\n}", directives)
} else {
fmt.Fprintf(s, " (%d directives)", len(a.Capability.Directives))
}
}
}
func (a Annotation) Key() AnnotationKey {
return AnnotationKey{Capability: a.Capability.Name, ID: a.Capability.ID}
}
func (m AnnotationMap) Update(other AnnotationMap) {
for k, v := range other {
if ex, ok := m[k]; ok {
// Update the contents not the pointer so existing annotation pointers are still valid
*ex = *v
} else {
m[k] = v
}
}
for k := range m {
if _, ok := other[k]; !ok {
delete(m, k)
}
}
}
func (m AnnotationMap) Add(a *Annotation) {
m[a.Key()] = a
}
// InSourceOrder returns a list of annotations in the order they are defined.
func (m AnnotationMap) InSourceOrder() []*Annotation {
var list []*Annotation
for _, v := range m {
list = append(list, v)
}
sort.Slice(list, func(i, j int) bool {
startI := 0
if list[i].Node != nil {
startI = int(list[i].Node.StartByte())
}
startJ := 0
if list[j].Node != nil {
startJ = int(list[j].Node.StartByte())
}
return startI < startJ
})
return list
}