Skip to content

Commit

Permalink
refined options
Browse files Browse the repository at this point in the history
  • Loading branch information
ArcturusZhang committed Apr 16, 2021
1 parent 93f6a3b commit 1d7aa97
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 52 deletions.
21 changes: 15 additions & 6 deletions tools/generator/autorest/autorest.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (
"fmt"
"io"
"os/exec"
"strings"

"github.com/Azure/azure-sdk-for-go/tools/generator/autorest/model"
)

// Generator collects all the related context of an autorest generation
type Generator struct {
arguments []string
arguments []model.Option
cmd *exec.Cmd
}

Expand All @@ -26,7 +27,7 @@ func NewGeneratorFromOptions(o model.Options) *Generator {

// WithOption appends an model.Option to the argument list of the autorest generation
func (g *Generator) WithOption(option model.Option) *Generator {
g.arguments = append(g.arguments, option.Format())
g.arguments = append(g.arguments, option)
return g
}

Expand Down Expand Up @@ -67,10 +68,14 @@ func (g *Generator) buildCommand() {
if g.cmd != nil {
return
}
g.cmd = exec.Command("autorest", g.arguments...)
arguments := make([]string, len(g.arguments))
for i, o := range g.arguments {
arguments[i] = o.Format()
}
g.cmd = exec.Command("autorest", arguments...)
}

func (g *Generator) Arguments() []string {
func (g *Generator) Arguments() []model.Option {
return g.arguments
}

Expand Down Expand Up @@ -124,11 +129,15 @@ func (g *Generator) StderrPipe() (io.ReadCloser, error) {

// GenerateError ...
type GenerateError struct {
Arguments []string
Arguments []model.Option
Message string
}

// Error ...
func (e *GenerateError) Error() string {
return fmt.Sprintf("autorest error with arguments '%s': \n%s", e.Arguments, e.Message)
arguments := make([]string, len(e.Arguments))
for i, o := range e.Arguments {
arguments[i] = o.Format()
}
return fmt.Sprintf("autorest error with arguments '%s': \n%s", strings.Join(arguments, ", "), e.Message)
}
33 changes: 33 additions & 0 deletions tools/generator/autorest/generationMetadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package autorest
import (
"encoding/json"
"fmt"
"github.com/Azure/azure-sdk-for-go/tools/generator/autorest/model"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -85,6 +86,38 @@ func GetGenerationMetadata(pkg track1.Package) (*GenerationMetadata, error) {
return &metadata, nil
}

// AdditionalOptions removes flags that may change over scenarios
func AdditionalOptions(arguments []model.Option) []model.Option {
var transformed []model.Option
for _, argument := range arguments {
switch o := argument.(type) {
case model.ArgumentOption: // omit the readme path argument
continue
case model.FlagOption:
if o.Flag() == "multiapi" { // omit the multiapi flag or use
continue
}
case model.KeyValueOption:
// omit go-sdk-folder, use, tag and metadata-output-folder
if o.Key() == "go-sdk-folder" || o.Key() == "use" || o.Key() == "tag" || o.Key() == "metadata-output-folder" {
continue
}
}
transformed = append(transformed, argument)
}
return transformed
}

// AdditionalOptionsToString removes flags that may change over scenarios and cast them to strings
func AdditionalOptionsToString(arguments []model.Option) []string {
transformed := AdditionalOptions(arguments)
result := make([]string, len(transformed))
for i, o := range transformed {
result[i] = o.Format()
}
return result
}

const (
// NormalizedSpecRoot this is the prefix for readme
NormalizedSpecRoot = "/_/azure-rest-api-specs/"
Expand Down
92 changes: 91 additions & 1 deletion tools/generator/autorest/model/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,132 @@

package model

import "fmt"
import (
"fmt"
"regexp"
"strings"
)

type OptionType string

const (
Argument OptionType = "Argument"
Flag OptionType = "Flag"
KeyValue OptionType = "KeyValue"
)

// Option describes an option of a autorest command line
type Option interface {
Type() OptionType
// Format returns the actual option in string
Format() string
}

type ArgumentOption interface {
Option
Argument() string
}

type FlagOption interface {
Option
Flag() string
}

type KeyValueOption interface {
Option
Key() string
Value() string
}

// NewOption returns an Option from a formatted string. We should hold this result using this function: input == result.Format()
func NewOption(input string) (Option, error) {
if strings.HasPrefix(input, "--") {
// this option is either a flag or a key value pair option
return parseFlagOrKeyValuePair(strings.TrimPrefix(input, "--"))
}
// this should be an argument
return argument{value: input}, nil
}

var flagRegex = regexp.MustCompile(`^[a-zA-Z]`)

func parseFlagOrKeyValuePair(input string) (Option, error) {
if !flagRegex.MatchString(input) {
return nil, fmt.Errorf("cannot parse flag '%s', a flag or option should only start with letters", input)
}
segments := strings.Split(input, "=")
if len(segments) <= 1 {
// this should be a flag
return flagOption{value: input}, nil
}
return keyValueOption{
key: segments[0],
value: strings.Join(segments[1:], "="),
}, nil
}

type argument struct {
value string
}

func (f argument) Type() OptionType {
return Argument
}

// Format ...
func (f argument) Format() string {
return f.value
}

func (f argument) Argument() string {
return f.value
}

var _ ArgumentOption = (*argument)(nil)

type flagOption struct {
value string
}

func (f flagOption) Type() OptionType {
return Flag
}

// Format ...
func (f flagOption) Format() string {
return fmt.Sprintf("--%s", f.value)
}

func (f flagOption) Flag() string {
return f.value
}

var _ FlagOption = (*flagOption)(nil)

type keyValueOption struct {
key string
value string
}

func (f keyValueOption) Type() OptionType {
return KeyValue
}

// Format ...
func (f keyValueOption) Format() string {
return fmt.Sprintf("--%s=%s", f.key, f.value)
}

func (f keyValueOption) Key() string {
return f.key
}

func (f keyValueOption) Value() string {
return f.value
}

var _ KeyValueOption = (*keyValueOption)(nil)

// NewArgument returns a new argument option (without "--")
func NewArgument(value string) Option {
return argument{
Expand Down
38 changes: 38 additions & 0 deletions tools/generator/autorest/model/option_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package model_test

import (
"reflect"
"testing"

"github.com/Azure/azure-sdk-for-go/tools/generator/autorest/model"
)

func TestNewOption(t *testing.T) {
testcase := []struct {
input string
expected model.Option
}{
{
input: "specification/compute/resource-manager/readme.md",
expected: model.NewArgument("specification/compute/resource-manager/readme.md"),
},
{
input: "--multiapi",
expected: model.NewFlagOption("multiapi"),
},
{
input: "--tag=package-2020-01-01",
expected: model.NewKeyValueOption("tag", "package-2020-01-01"),
},
}

for _, c := range testcase {
o, err := model.NewOption(c.input)
if err != nil {
t.Fatalf("unexpected error: %+v", err)
}
if !reflect.DeepEqual(o, c.expected) {
t.Fatalf("expecting %+v, but got %+v", c.expected, o)
}
}
}
46 changes: 33 additions & 13 deletions tools/generator/autorest/model/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,60 @@ import (
// Options ...
type Options interface {
// Arguments returns the argument defined in this options
Arguments() []string
Arguments() []Option
// CodeGeneratorVersion returns the code generator version defined in this options
CodeGeneratorVersion() string
}

type localOptions struct {
type generateOptions struct {
AutorestArguments []string `json:"autorestArguments"`
}

type localOptions struct {
arguments []Option
codeGenVersion string
}

// NewOptionsFrom returns a new instance of Options from the given io.Reader
func NewOptionsFrom(reader io.Reader) (Options, error) {
b, err := ioutil.ReadAll(reader)
if err != nil {
return nil, err
}
var result localOptions
if err := json.Unmarshal(b, &result); err != nil {
var raw generateOptions
if err := json.Unmarshal(b, &raw); err != nil {
return nil, err
}
return &result, nil
var options []Option
var codeGenVersion string
for _, r := range raw.AutorestArguments {
o, err := NewOption(r)
if err != nil {
return nil, err
}
options = append(options, o)
if v, ok := o.(KeyValueOption); ok && v.Key() == "use" {
codeGenVersion = v.Value()
}
}
return &localOptions{
arguments: options,
codeGenVersion: codeGenVersion,
}, nil
}

// Argument ...
func (o localOptions) Arguments() []string {
return o.AutorestArguments
// Arguments ...
func (o localOptions) Arguments() []Option {
return o.arguments
}

// CodeGeneratorVersion ...
func (o localOptions) CodeGeneratorVersion() string {
return o.codeGenVersion
}

// String ...
func (o localOptions) String() string {
b, _ := json.MarshalIndent(o, "", " ")
return string(b)
}

// CodeGeneratorVersion ...
func (o localOptions) CodeGeneratorVersion() string {
return ""
}
Loading

0 comments on commit 1d7aa97

Please sign in to comment.