github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/plugin/bufbuild/es_plugin.go (about)

     1  package bufbuild
     2  
     3  import (
     4  	"flag"
     5  	"log"
     6  	"path"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/bazelbuild/bazel-gazelle/label"
    11  	"github.com/stackb/rules_proto/pkg/protoc"
    12  )
    13  
    14  func init() {
    15  	protoc.Plugins().MustRegisterPlugin(&EsProto{})
    16  }
    17  
    18  // EsProto implements Plugin for the bufbuild/protoc-gen-es plugin.
    19  type EsProto struct{}
    20  
    21  // Name implements part of the Plugin interface.
    22  func (p *EsProto) Name() string {
    23  	return "bufbuild:es"
    24  }
    25  
    26  // Configure implements part of the Plugin interface.
    27  func (p *EsProto) Configure(ctx *protoc.PluginContext) *protoc.PluginConfiguration {
    28  	flags := parseEsProtoOptions(p.Name(), ctx.PluginConfig.GetFlags())
    29  	imports := make(map[string]bool)
    30  	for _, file := range ctx.ProtoLibrary.Files() {
    31  		for _, imp := range file.Imports() {
    32  			imports[imp.Filename] = true
    33  		}
    34  	}
    35  	// TODO: get target option from directive
    36  	var options = []string{"keep_empty_files=true", "target=ts"}
    37  	tsFiles := make([]string, 0)
    38  	for _, file := range ctx.ProtoLibrary.Files() {
    39  		// TODO: outputs should be conditional on which target= value is used
    40  		tsFile := file.Name + "_pb.ts"
    41  		if flags.excludeOutput[filepath.Base(tsFile)] {
    42  			continue
    43  		}
    44  		if ctx.Rel != "" {
    45  			tsFile = path.Join(ctx.Rel, tsFile)
    46  		}
    47  		tsFiles = append(tsFiles, tsFile)
    48  	}
    49  
    50  	pc := &protoc.PluginConfiguration{
    51  		Label:   label.New("build_stack_rules_proto", "plugin/bufbuild", "es"),
    52  		Outputs: protoc.DeduplicateAndSort(tsFiles),
    53  		Options: protoc.DeduplicateAndSort(options),
    54  	}
    55  	if len(pc.Outputs) == 0 {
    56  		pc.Outputs = nil
    57  	}
    58  	return pc
    59  }
    60  
    61  // EsProtoOptions represents the parsed flag configuration for the
    62  // EsProto implementation.
    63  type EsProtoOptions struct {
    64  	excludeOutput map[string]bool
    65  }
    66  
    67  func parseEsProtoOptions(kindName string, args []string) *EsProtoOptions {
    68  	flags := flag.NewFlagSet(kindName, flag.ExitOnError)
    69  
    70  	var excludeOutput string
    71  	flags.StringVar(&excludeOutput, "exclude_output", "", "--exclude_output=foo.ts suppresses the file 'foo.ts' from the output list")
    72  
    73  	if err := flags.Parse(args); err != nil {
    74  		log.Fatalf("failed to parse flags for %q: %v", kindName, err)
    75  	}
    76  	config := &EsProtoOptions{
    77  		excludeOutput: make(map[string]bool),
    78  	}
    79  	for _, value := range strings.Split(excludeOutput, ",") {
    80  		config.excludeOutput[value] = true
    81  	}
    82  
    83  	return config
    84  }