github.com/wolfd/bazel-gazelle@v0.14.0/internal/language/proto/gen/gen_known_imports.go (about)

     1  /* Copyright 2018 The Bazel Authors. All rights reserved.
     2  
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7     http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  // gen_known_imports generates a .go file that with a map from either proto or
    17  // go import strings to Bazel label strings. The imports for all languages
    18  // are stored in a proto.csv file.
    19  
    20  package main
    21  
    22  import (
    23  	"bufio"
    24  	"bytes"
    25  	"encoding/csv"
    26  	"flag"
    27  	"fmt"
    28  	"io/ioutil"
    29  	"log"
    30  	"os"
    31  	"path/filepath"
    32  	"text/template"
    33  
    34  	"github.com/bazelbuild/bazel-gazelle/internal/label"
    35  )
    36  
    37  var progName = filepath.Base(os.Args[0])
    38  
    39  var knownImportsTpl = template.Must(template.New("known_imports.go").Parse(`
    40  // Generated by internal/language/proto/gen/gen_known_imports.go
    41  // From {{.ProtoCsv}}
    42  
    43  package {{.Package}}
    44  
    45  import "github.com/bazelbuild/bazel-gazelle/internal/label"
    46  
    47  var {{.Var}} = map[string]label.Label{
    48  {{range .Bindings}}
    49  	{{printf "%q: label.New(%q, %q, %q)" .Import .Label.Repo .Label.Pkg .Label.Name}},
    50  {{- end}}
    51  }
    52  `))
    53  
    54  type data struct {
    55  	ProtoCsv, Package, Var string
    56  	Bindings               []binding
    57  }
    58  
    59  type binding struct {
    60  	Import string
    61  	Label  label.Label
    62  }
    63  
    64  func main() {
    65  	log.SetPrefix(progName + ": ")
    66  	log.SetFlags(0)
    67  	if err := run(os.Args[1:]); err != nil {
    68  		log.Fatal(err)
    69  	}
    70  }
    71  
    72  func run(args []string) (err error) {
    73  	fs := flag.NewFlagSet(progName, flag.ExitOnError)
    74  	var protoCsvPath, knownImportsPath, package_, var_ string
    75  	var keyColumn, valueColumn int
    76  	fs.StringVar(&protoCsvPath, "proto_csv", "", "path to proto.csv input file")
    77  	fs.StringVar(&knownImportsPath, "known_imports", "", "path to known_imports.go output file")
    78  	fs.StringVar(&package_, "package", "", "package name in generated file")
    79  	fs.StringVar(&var_, "var", "", "var name in generated file")
    80  	fs.IntVar(&keyColumn, "key", 0, "key column number")
    81  	fs.IntVar(&valueColumn, "value", 1, "value column number")
    82  	fs.Parse(args)
    83  	if protoCsvPath == "" {
    84  		return fmt.Errorf("-proto_csv not set")
    85  	}
    86  	if knownImportsPath == "" {
    87  		return fmt.Errorf("-known_imports not set")
    88  	}
    89  	if package_ == "" {
    90  		return fmt.Errorf("-package not set")
    91  	}
    92  	if var_ == "" {
    93  		return fmt.Errorf("-var not set")
    94  	}
    95  
    96  	protoCsvFile, err := os.Open(protoCsvPath)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	r := csv.NewReader(bufio.NewReader(protoCsvFile))
   101  	r.Comment = '#'
   102  	r.FieldsPerRecord = 4
   103  	records, err := r.ReadAll()
   104  	protoCsvFile.Close()
   105  	if err != nil {
   106  		return err
   107  	}
   108  	data := data{
   109  		ProtoCsv: protoCsvPath,
   110  		Package:  package_,
   111  		Var:      var_,
   112  	}
   113  	seen := make(map[string]label.Label)
   114  	for _, rec := range records {
   115  		imp := rec[keyColumn]
   116  		lbl, err := label.Parse(rec[valueColumn])
   117  		if err != nil {
   118  			return err
   119  		}
   120  		if seenLabel, ok := seen[imp]; ok {
   121  			if !seenLabel.Equal(lbl) {
   122  				return fmt.Errorf("for key %s, multiple values (%s and %s)", imp, seenLabel, lbl)
   123  			}
   124  			continue
   125  		}
   126  		seen[imp] = lbl
   127  		data.Bindings = append(data.Bindings, binding{imp, lbl})
   128  	}
   129  
   130  	knownImportsBuf := &bytes.Buffer{}
   131  	if err := knownImportsTpl.Execute(knownImportsBuf, data); err != nil {
   132  		return err
   133  	}
   134  	return ioutil.WriteFile(knownImportsPath, knownImportsBuf.Bytes(), 0666)
   135  }