github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/protoc/syntaxutil.go (about) 1 package protoc 2 3 import ( 4 "sort" 5 6 "github.com/bazelbuild/bazel-gazelle/rule" 7 "github.com/bazelbuild/buildtools/build" 8 ) 9 10 func MakeStringListDict(in map[string][]string) build.Expr { 11 items := make([]*build.KeyValueExpr, 0) 12 keys := make([]string, 0) 13 for k := range in { 14 keys = append(keys, k) 15 } 16 sort.Strings(keys) 17 for _, key := range keys { 18 values := in[key] 19 sort.Strings(values) 20 value := &build.ListExpr{List: make([]build.Expr, len(values))} 21 for i, val := range values { 22 value.List[i] = &build.StringExpr{Value: val} 23 } 24 items = append(items, &build.KeyValueExpr{ 25 Key: &build.StringExpr{Value: key}, 26 Value: value, 27 }) 28 } 29 return &build.DictExpr{List: items} 30 } 31 32 func MakeStringDict(in map[string]string) build.Expr { 33 dict := &build.DictExpr{} 34 keys := make([]string, 0) 35 for k := range in { 36 keys = append(keys, k) 37 } 38 sort.Strings(keys) 39 for _, key := range keys { 40 value := in[key] 41 dict.List = append(dict.List, &build.KeyValueExpr{ 42 Key: &build.StringExpr{Value: key}, 43 Value: &build.StringExpr{Value: value}, 44 }) 45 } 46 return dict 47 } 48 49 // GetKeptFileRuleAttrString returns the value of the rule attribute IFF the 50 // backing File rule attribute has a '# keep' comment on it. 51 func GetKeptFileRuleAttrString(file *rule.File, r *rule.Rule, name string) string { 52 if file == nil { 53 return "" 54 } 55 assign := getRuleAssignExpr(file.File, r.Kind(), r.Name(), name) 56 if assign == nil { 57 return "" 58 } 59 if !rule.ShouldKeep(assign) { 60 return "" 61 } 62 str, ok := assign.RHS.(*build.StringExpr) 63 if !ok { 64 return "" 65 } 66 return str.Value 67 } 68 69 // getRuleAssignExpr seeks through the file looking for call expressions having 70 // the given kind and rule name. If found, the assignment expression having the 71 // given name is returned. Otherwise, return nil. 72 func getRuleAssignExpr(file *build.File, kind string, name string, attrName string) *build.AssignExpr { 73 if file == nil { 74 return nil 75 } 76 for _, stmt := range file.Stmt { 77 call, ok := stmt.(*build.CallExpr) 78 if !ok { 79 continue 80 } 81 ident, ok := call.X.(*build.Ident) 82 if !ok { 83 continue 84 } 85 if ident.Name != kind { 86 continue 87 } 88 var ruleName string 89 var want *build.AssignExpr 90 for _, arg := range call.List { 91 attr, ok := arg.(*build.AssignExpr) 92 if !ok { 93 continue 94 } 95 key := attr.LHS.(*build.Ident) 96 switch key.Name { 97 case "name": 98 str, ok := attr.RHS.(*build.StringExpr) 99 if ok { 100 ruleName = str.Value 101 } 102 case attrName: 103 want = attr 104 } 105 } 106 if ruleName != name { 107 continue 108 } 109 return want 110 } 111 return nil 112 }