github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/protoc/protoc_configuration.go (about)

     1  package protoc
     2  
     3  import (
     4  	"path"
     5  	"strings"
     6  )
     7  
     8  // ProtocConfiguration represents the complete configuration and source
     9  // mappings.
    10  type ProtocConfiguration struct {
    11  	// PackageConfig parent
    12  	PackageConfig *PackageConfig
    13  	// The config for the p
    14  	LanguageConfig *LanguageConfig
    15  	// the workspace relative path of the BUILD file where this rule is being
    16  	// generated.
    17  	Rel string
    18  	// the prefix for the rule (e.g. 'java')
    19  	Prefix string
    20  	// the library thar holds the proto files
    21  	Library ProtoLibrary
    22  	// the configuration for the plugins
    23  	Plugins []*PluginConfiguration
    24  	// The merged set of Source files for the compilations
    25  	Outputs []string
    26  	// The merged set of imports for the compilations
    27  	Imports []string
    28  	// The generated source mappings
    29  	Mappings map[string]string
    30  }
    31  
    32  func newProtocConfiguration(pc *PackageConfig, lc *LanguageConfig, workDir, rel, prefix string, lib ProtoLibrary, plugins []*PluginConfiguration) *ProtocConfiguration {
    33  	srcs, mappings := mergeSources(workDir, rel, plugins, lib.StripImportPrefix())
    34  
    35  	return &ProtocConfiguration{
    36  		PackageConfig:  pc,
    37  		LanguageConfig: lc,
    38  		Rel:            rel,
    39  		Prefix:         prefix,
    40  		Library:        lib,
    41  		Plugins:        plugins,
    42  		Outputs:        srcs,
    43  		Mappings:       mappings,
    44  	}
    45  }
    46  
    47  func (c *ProtocConfiguration) GetPluginConfiguration(implementationName string) *PluginConfiguration {
    48  	for _, plugin := range c.Plugins {
    49  		if plugin.Config.Implementation == implementationName {
    50  			return plugin
    51  		}
    52  	}
    53  	return nil
    54  }
    55  
    56  func (c *ProtocConfiguration) GetPluginOutputs(implementationName string) []string {
    57  	plugin := c.GetPluginConfiguration(implementationName)
    58  	if plugin == nil {
    59  		return nil
    60  	}
    61  	return plugin.Outputs
    62  }
    63  
    64  // mergeSources computes the source files that are generated by the rule and any
    65  // necessary mappings.
    66  func mergeSources(workDir, rel string, plugins []*PluginConfiguration, stripImportPrefix string) ([]string, map[string]string) {
    67  	srcs := make([]string, 0)
    68  	mappings := make(map[string]string)
    69  
    70  	// if the stripImportPrefix is defined and "absolute" (starting with a
    71  	// slash), this means it is relative to the repository root.
    72  	// https://github.com/bazelbuild/bazel/issues/3867#issuecomment-441971525
    73  	prefix := strings.TrimPrefix(stripImportPrefix, "/")
    74  
    75  	for _, plugin := range plugins {
    76  
    77  		// if plugin provided mappings for us, use those preferentially
    78  		if len(plugin.Mappings) > 0 {
    79  			srcs = append(srcs, plugin.Outputs...)
    80  
    81  			for k, v := range plugin.Mappings {
    82  				mappings[k] = v
    83  			}
    84  			continue
    85  		}
    86  
    87  		// otherwise, fallback to baseline method
    88  		for _, filename := range plugin.Outputs {
    89  			if prefix != "" {
    90  				filename = strings.TrimPrefix(filename, prefix)
    91  			}
    92  			dir := path.Dir(filename)
    93  			if dir == "." && rel == "" {
    94  				dir = rel
    95  			}
    96  			if dir == rel {
    97  				// no mapping required, just add to the srcs list
    98  				srcs = append(srcs, strings.TrimPrefix(filename, rel+"/"))
    99  			} else {
   100  				// add the basename only to the srcs list and add a mapping.
   101  				base := path.Base(filename)
   102  				mappings[base] = filename
   103  				srcs = append(srcs, base)
   104  			}
   105  		}
   106  	}
   107  
   108  	return srcs, mappings
   109  }