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  }