github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/protoc/language_plugin_config.go (about) 1 package protoc 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "github.com/bazelbuild/bazel-gazelle/label" 8 ) 9 10 // LanguagePluginConfig associates metadata with a plugin implementation. 11 type LanguagePluginConfig struct { 12 // Name is the identifier for the configuration object 13 Name string 14 // Implementation is the identifier for the implementation 15 Implementation string 16 // Label is the bazel label of the PluginInfo provider 17 Label label.Label 18 // Options is a set of option strings. 19 Options map[string]bool 20 // Flags is a set of flag strings. 21 Flags map[string]bool 22 // Deps is a set of dep labels. For example, consider a plugin config for 23 // 'protoc-gen-go'. That plugin produces .go files. The 'Deps' field can 24 // be used by downstream Rule implementations to gather necessary 25 // dependencies for the .go files produced by that plugin. 26 Deps map[string]bool 27 // Enabled flag 28 Enabled bool 29 } 30 31 func newLanguagePluginConfig(name string) *LanguagePluginConfig { 32 return &LanguagePluginConfig{ 33 Name: name, 34 Options: make(map[string]bool), 35 Flags: make(map[string]bool), 36 Deps: make(map[string]bool), 37 Enabled: true, 38 } 39 } 40 41 // GetOptions returns the sorted list of options with positive intent. 42 func (c *LanguagePluginConfig) GetOptions() []string { 43 return ForIntent(c.Options, true) 44 } 45 46 // GetDeps returns the sorted list of deps with positive intent. 47 func (c *LanguagePluginConfig) GetDeps() []string { 48 return ForIntent(c.Deps, true) 49 } 50 51 // GetFlags returns the list of Flags configured for the plugin. 52 func (c *LanguagePluginConfig) GetFlags() []string { 53 return ForIntent(c.Flags, true) 54 } 55 56 func (c *LanguagePluginConfig) clone() *LanguagePluginConfig { 57 clone := newLanguagePluginConfig(c.Name) 58 clone.Label = c.Label 59 clone.Implementation = c.Implementation 60 clone.Enabled = c.Enabled 61 for k, v := range c.Options { 62 clone.Options[k] = v 63 } 64 for k, v := range c.Flags { 65 clone.Flags[k] = v 66 } 67 for k, v := range c.Deps { 68 clone.Deps[k] = v 69 } 70 return clone 71 } 72 73 // parseDirective parses the directive string or returns error. 74 func (c *LanguagePluginConfig) parseDirective(cfg *PackageConfig, d, param, value string) error { 75 intent := parseIntent(param) 76 switch intent.Value { 77 case "enabled", "enable": 78 enabled, err := strconv.ParseBool(value) 79 if err != nil { 80 return fmt.Errorf("enabled %s: %w", value, err) 81 } 82 c.Enabled = enabled 83 case "label": 84 l, err := label.Parse(value) 85 if err != nil { 86 return fmt.Errorf("label %q: %w", value, err) 87 } 88 c.Label = l 89 case "implementation": 90 c.Implementation = value 91 case "flag": 92 c.Flags[value] = intent.Want 93 case "option": 94 c.Options[value] = intent.Want 95 case "deps", "dep": 96 c.Deps[value] = intent.Want 97 default: 98 return fmt.Errorf("unknown parameter %q", intent.Value) 99 } 100 101 return nil 102 } 103 104 // fromYAML loads configuration from the yaml plugin confug. 105 func (c *LanguagePluginConfig) fromYAML(y *YPlugin) error { 106 if c.Name != y.Name { 107 return fmt.Errorf("yaml plugin mismatch: want %q got %q", c.Name, y.Name) 108 } 109 c.Implementation = y.Implementation 110 // only true intent is supported via yaml 111 for _, flag := range y.Flag { 112 c.Flags[flag] = true 113 } 114 for _, option := range y.Option { 115 c.Options[option] = true 116 } 117 for _, dep := range y.Dep { 118 c.Deps[dep] = true 119 } 120 if y.Label != "" { 121 l, err := label.Parse(y.Label) 122 if err != nil { 123 return fmt.Errorf("%s label parse error %w", y.Name, err) 124 } 125 c.Label = l 126 } 127 if y.Enabled != nil { 128 c.Enabled = *y.Enabled 129 } else { 130 c.Enabled = true 131 } 132 return nil 133 }