1
15
16 package rule
17
18 import (
19 "fmt"
20 "log"
21 "reflect"
22 "sort"
23
24 bzl "github.com/bazelbuild/buildtools/build"
25 )
26
27
28
29 type KeyValue struct {
30 Key string
31 Value interface{}
32 }
33
34
35 type GlobValue struct {
36 Patterns []string
37 Excludes []string
38 }
39
40 func (g GlobValue) BzlExpr() bzl.Expr {
41 patternsValue := ExprFromValue(g.Patterns)
42 globArgs := []bzl.Expr{patternsValue}
43 if len(g.Excludes) > 0 {
44 excludesValue := ExprFromValue(g.Excludes)
45 globArgs = append(globArgs, &bzl.AssignExpr{
46 LHS: &bzl.LiteralExpr{Token: "exclude"},
47 Op: "=",
48 RHS: excludesValue,
49 })
50 }
51 return &bzl.CallExpr{
52 X: &bzl.LiteralExpr{Token: "glob"},
53 List: globArgs,
54 }
55 }
56
57
58
59 type BzlExprValue interface {
60 BzlExpr() bzl.Expr
61 }
62
63
64
65
66
67
68
69 type Merger interface {
70 Merge(other bzl.Expr) bzl.Expr
71 }
72
73 type SortedStrings []string
74
75 func (s SortedStrings) BzlExpr() bzl.Expr {
76 list := make([]bzl.Expr, len(s))
77 for i, v := range s {
78 list[i] = &bzl.StringExpr{Value: v}
79 }
80 listExpr := &bzl.ListExpr{List: list}
81 sortExprLabels(listExpr, []bzl.Expr{})
82 return listExpr
83 }
84
85 func (s SortedStrings) Merge(other bzl.Expr) bzl.Expr {
86 if other == nil {
87 return s.BzlExpr()
88 }
89 merged := MergeList(s.BzlExpr(), other)
90 sortExprLabels(merged, []bzl.Expr{})
91 return merged
92 }
93
94 type UnsortedStrings []string
95
96 func (s UnsortedStrings) Merge(other bzl.Expr) bzl.Expr {
97 if other == nil {
98 return ExprFromValue(s)
99 }
100 return MergeList(ExprFromValue(s), other)
101 }
102
103
104
105 type SelectStringListValue map[string][]string
106
107 func (s SelectStringListValue) BzlExpr() bzl.Expr {
108 defaultKey := "//conditions:default"
109 keys := make([]string, 0, len(s))
110 haveDefaultKey := false
111 for key := range s {
112 if key == defaultKey {
113 haveDefaultKey = true
114 } else {
115 keys = append(keys, key)
116 }
117 }
118 sort.Strings(keys)
119 if haveDefaultKey {
120 keys = append(keys, defaultKey)
121 }
122
123 args := make([]*bzl.KeyValueExpr, 0, len(s))
124 for _, key := range keys {
125 value := ExprFromValue(s[key])
126 if key != defaultKey {
127 value.(*bzl.ListExpr).ForceMultiLine = true
128 }
129 args = append(args, &bzl.KeyValueExpr{
130 Key: &bzl.StringExpr{Value: key},
131 Value: value,
132 })
133 }
134 sel := &bzl.CallExpr{
135 X: &bzl.Ident{Name: "select"},
136 List: []bzl.Expr{&bzl.DictExpr{List: args, ForceMultiLine: true}},
137 }
138 return sel
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152
153 func ExprFromValue(val interface{}) bzl.Expr {
154 if e, ok := val.(bzl.Expr); ok {
155 return e
156 }
157 if be, ok := val.(BzlExprValue); ok {
158 return be.BzlExpr()
159 }
160
161 rv := reflect.ValueOf(val)
162 switch rv.Kind() {
163 case reflect.Bool:
164 tok := "False"
165 if rv.Bool() {
166 tok = "True"
167 }
168 return &bzl.LiteralExpr{Token: tok}
169
170 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
171 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
172 return &bzl.LiteralExpr{Token: fmt.Sprintf("%d", val)}
173
174 case reflect.Float32, reflect.Float64:
175 return &bzl.LiteralExpr{Token: fmt.Sprintf("%f", val)}
176
177 case reflect.String:
178 return &bzl.StringExpr{Value: val.(string)}
179
180 case reflect.Slice, reflect.Array:
181 var list []bzl.Expr
182 for i := 0; i < rv.Len(); i++ {
183 elem := ExprFromValue(rv.Index(i).Interface())
184 list = append(list, elem)
185 }
186 return &bzl.ListExpr{List: list}
187
188 case reflect.Map:
189 rkeys := rv.MapKeys()
190 sort.Sort(byString(rkeys))
191 args := make([]*bzl.KeyValueExpr, len(rkeys))
192 for i, rk := range rkeys {
193 k := &bzl.StringExpr{Value: mapKeyString(rk)}
194 v := ExprFromValue(rv.MapIndex(rk).Interface())
195 if l, ok := v.(*bzl.ListExpr); ok {
196 l.ForceMultiLine = true
197 }
198 args[i] = &bzl.KeyValueExpr{Key: k, Value: v}
199 }
200 return &bzl.DictExpr{List: args, ForceMultiLine: true}
201 }
202
203 log.Panicf("type not supported: %T", val)
204 return nil
205 }
206
207 func mapKeyString(k reflect.Value) string {
208 switch s := k.Interface().(type) {
209 case string:
210 return s
211 default:
212 log.Panicf("unexpected map key: %v", k)
213 return ""
214 }
215 }
216
217 type byString []reflect.Value
218
219 var _ sort.Interface = byString{}
220
221 func (s byString) Len() int {
222 return len(s)
223 }
224
225 func (s byString) Less(i, j int) bool {
226 return mapKeyString(s[i]) < mapKeyString(s[j])
227 }
228
229 func (s byString) Swap(i, j int) {
230 s[i], s[j] = s[j], s[i]
231 }
232
View as plain text