Binapi generator: improved file input 16/28516/4
authorVladimir Lavor <vlavor@cisco.com>
Wed, 19 Aug 2020 14:08:39 +0000 (16:08 +0200)
committerOndrej Fabry <ofabry@cisco.com>
Tue, 25 Aug 2020 10:01:49 +0000 (10:01 +0000)
In addition to the standard file name input (for example "vpe"),
binary API generator now again accepts full file path like
"/usr/share/vpp/api/core/vpe.api.json" as an input direcotry or
argument.

Change-Id: I591b5d26e7f101cdcc4af64d3bdabaab48b5b2ef
Signed-off-by: Vladimir Lavor <vlavor@cisco.com>
binapigen/binapigen_test.go
binapigen/generator.go
binapigen/run.go
binapigen/vppapi/vppapi.go
cmd/binapi-generator/main.go

index 9a25420..0352635 100644 (file)
@@ -40,11 +40,11 @@ func TestGenerator(t *testing.T) {
                t.Run(test.name, func(t *testing.T) {
                        RegisterTestingT(t)
 
-                       apifiles := []*vppapi.File{test.file}
+                       apiFiles := []*vppapi.File{test.file}
 
                        gen, err := New(Options{
                                ImportPrefix: "test",
-                       }, apifiles, nil)
+                       }, apiFiles, nil)
                        Expect(err).ToNot(HaveOccurred(), "unexpected generator error: %v", err)
 
                        Expect(gen.Files).To(HaveLen(1))
index ce0954a..a6f1615 100644 (file)
@@ -38,6 +38,7 @@ import (
 type Generator struct {
        Files       []*File
        FilesByName map[string]*File
+       FilesByPath map[string]*File
 
        opts       Options
        apifiles   []*vppapi.File
@@ -53,11 +54,12 @@ type Generator struct {
        messagesByName map[string]*Message
 }
 
-func New(opts Options, apifiles []*vppapi.File, filesToGen []string) (*Generator, error) {
+func New(opts Options, apiFiles []*vppapi.File, filesToGen []string) (*Generator, error) {
        gen := &Generator{
                FilesByName:    make(map[string]*File),
+               FilesByPath:    make(map[string]*File),
                opts:           opts,
-               apifiles:       apifiles,
+               apifiles:       apiFiles,
                filesToGen:     filesToGen,
                enumsByName:    map[string]*Enum{},
                aliasesByName:  map[string]*Alias{},
@@ -68,9 +70,9 @@ func New(opts Options, apifiles []*vppapi.File, filesToGen []string) (*Generator
 
        // Normalize API files
        SortFilesByImports(gen.apifiles)
-       for _, apifile := range apifiles {
-               RemoveImportedTypes(gen.apifiles, apifile)
-               SortFileObjectsByName(apifile)
+       for _, apiFile := range apiFiles {
+               RemoveImportedTypes(gen.apifiles, apiFile)
+               SortFileObjectsByName(apiFile)
        }
 
        // prepare package names and import paths
@@ -96,6 +98,7 @@ func New(opts Options, apifiles []*vppapi.File, filesToGen []string) (*Generator
                }
                gen.Files = append(gen.Files, file)
                gen.FilesByName[apifile.Name] = file
+               gen.FilesByPath[apifile.Path] = file
 
                logrus.Debugf("added file %q (path: %v)", apifile.Name, apifile.Path)
        }
@@ -103,16 +106,24 @@ func New(opts Options, apifiles []*vppapi.File, filesToGen []string) (*Generator
        // mark files for generation
        if len(gen.filesToGen) > 0 {
                logrus.Debugf("Checking %d files to generate: %v", len(gen.filesToGen), gen.filesToGen)
-               for _, genfile := range gen.filesToGen {
-                       file, ok := gen.FilesByName[genfile]
-                       if !ok {
-                               return nil, fmt.Errorf("nol API file found for: %v", genfile)
+               for _, genFile := range gen.filesToGen {
+                       markGen := func(file *File) {
+                               file.Generate = true
+                               // generate all imported files
+                               for _, impFile := range file.importedFiles(gen) {
+                                       impFile.Generate = true
+                               }
                        }
-                       file.Generate = true
-                       // generate all imported files
-                       for _, impFile := range file.importedFiles(gen) {
-                               impFile.Generate = true
+                       if file, ok := gen.FilesByName[genFile]; ok {
+                               markGen(file)
+                               continue
+                       }
+                       logrus.Debugf("File %s was not found by name", genFile)
+                       if file, ok := gen.FilesByPath[genFile]; ok {
+                               markGen(file)
+                               continue
                        }
+                       return nil, fmt.Errorf("no API file found for: %v", genFile)
                }
        } else {
                logrus.Debugf("Files to generate not specified, marking all %d files for generate", len(gen.Files))
@@ -233,7 +244,7 @@ func (g *GenFile) injectImports(original []byte) ([]byte, error) {
        var importPaths []Import
        for importPath := range g.packageNames {
                importPaths = append(importPaths, Import{
-                       Name: string(g.packageNames[GoImportPath(importPath)]),
+                       Name: string(g.packageNames[importPath]),
                        Path: string(importPath),
                })
        }
index f7776c9..8bb88fb 100644 (file)
@@ -43,7 +43,7 @@ func Run(apiDir string, filesToGenerate []string, opts Options, f func(*Generato
 }
 
 func run(apiDir string, filesToGenerate []string, opts Options, fn func(*Generator) error) error {
-       apifiles, err := vppapi.ParseDir(apiDir)
+       apiFiles, err := vppapi.ParseDir(apiDir)
        if err != nil {
                return err
        }
@@ -56,7 +56,7 @@ func run(apiDir string, filesToGenerate []string, opts Options, fn func(*Generat
                logrus.Infof("resolved import path prefix: %s", opts.ImportPrefix)
        }
 
-       gen, err := New(opts, apifiles, filesToGenerate)
+       gen, err := New(opts, apiFiles, filesToGenerate)
        if err != nil {
                return err
        }
index 665fa81..b54d287 100644 (file)
@@ -24,6 +24,9 @@ import (
 const (
        // DefaultDir is default location of API files.
        DefaultDir = "/usr/share/vpp/api"
+
+       // APIFileExtension is a VPP API file extension suffix
+       APIFileExtension = ".api.json"
 )
 
 // FindFiles finds API files located in dir or in a nested directory that is not nested deeper than deep.
@@ -40,7 +43,7 @@ func FindFiles(dir string, deep int) (files []string, err error) {
                        } else {
                                files = append(files, nested...)
                        }
-               } else if !e.IsDir() && strings.HasSuffix(e.Name(), ".api.json") {
+               } else if !e.IsDir() && strings.HasSuffix(e.Name(), APIFileExtension) {
                        files = append(files, filepath.Join(dir, e.Name()))
                }
        }
@@ -54,13 +57,13 @@ func Parse() ([]*File, error) {
 
 // ParseDir finds and parses API files in given directory and returns parsed files.
 // Supports API files in JSON format (.api.json) only.
-func ParseDir(apidir string) ([]*File, error) {
-       list, err := FindFiles(apidir, 1)
+func ParseDir(apiDir string) ([]*File, error) {
+       list, err := FindFiles(apiDir, 1)
        if err != nil {
                return nil, err
        }
 
-       logf("found %d files in API dir %q", len(list), apidir)
+       logf("found %d files in API dir %q", len(list), apiDir)
 
        var files []*File
        for _, file := range list {
@@ -74,17 +77,17 @@ func ParseDir(apidir string) ([]*File, error) {
 }
 
 // ParseFile parses API file and returns File.
-func ParseFile(apifile string) (*File, error) {
-       if !strings.HasSuffix(apifile, ".api.json") {
-               return nil, fmt.Errorf("unsupported file format: %q", apifile)
+func ParseFile(apiFile string) (*File, error) {
+       if !strings.HasSuffix(apiFile, APIFileExtension) {
+               return nil, fmt.Errorf("unsupported file format: %q", apiFile)
        }
 
-       data, err := ioutil.ReadFile(apifile)
+       data, err := ioutil.ReadFile(apiFile)
        if err != nil {
-               return nil, fmt.Errorf("reading file %s failed: %v", apifile, err)
+               return nil, fmt.Errorf("reading file %s failed: %v", apiFile, err)
        }
 
-       base := filepath.Base(apifile)
+       base := filepath.Base(apiFile)
        name := base[:strings.Index(base, ".")]
 
        logf("parsing file %q", base)
@@ -94,7 +97,7 @@ func ParseFile(apifile string) (*File, error) {
                return nil, fmt.Errorf("parsing file %s failed: %v", base, err)
        }
        module.Name = name
-       module.Path = apifile
+       module.Path = apiFile
 
        return module, nil
 }
index 3dc2c08..af60628 100644 (file)
@@ -32,6 +32,7 @@ import (
 func init() {
        flag.Usage = func() {
                fmt.Fprintf(os.Stderr, "Usage: %s [OPTION] API_FILES\n", os.Args[0])
+               fmt.Fprintln(os.Stderr, "Provide API_FILES by file name, or with full path including extension.")
                fmt.Fprintln(os.Stderr, "Parse API_FILES and generate Go bindings based on the options given:")
                flag.PrintDefaults()
        }