Clean up and simplify the main compiler code.
diff --git a/openapic/compiler.go b/openapic/compiler.go
index dc2df32..d85022e 100644
--- a/openapic/compiler.go
+++ b/openapic/compiler.go
@@ -36,6 +36,48 @@
Output string
}
+func (pluginCall *PluginCall) perform(document *openapi_v2.Document, sourceName string) {
+ if pluginCall.Name != "" {
+ request := &plugins.PluginRequest{}
+ request.Parameter = ""
+
+ version := &plugins.Version{}
+ version.Major = 0
+ version.Minor = 1
+ version.Patch = 0
+ request.CompilerVersion = version
+
+ wrapper := &plugins.Wrapper{}
+ wrapper.Name = sourceName
+ wrapper.Version = "v2"
+ protoBytes, _ := proto.Marshal(document)
+ wrapper.Value = protoBytes
+ request.Wrapper = []*plugins.Wrapper{wrapper}
+ requestBytes, _ := proto.Marshal(request)
+
+ cmd := exec.Command("openapi_" + pluginCall.Name)
+ cmd.Stdin = bytes.NewReader(requestBytes)
+ output, err := cmd.Output()
+ if err != nil {
+ fmt.Printf("Error: %+v\n", err)
+ }
+ response := &plugins.PluginResponse{}
+ err = proto.Unmarshal(output, response)
+
+ var writer io.Writer
+ if pluginCall.Output == "-" {
+ writer = os.Stdout
+ } else {
+ file, _ := os.Create(pluginCall.Output)
+ defer file.Close()
+ writer = file
+ }
+ for _, text := range response.Text {
+ writer.Write([]byte(text))
+ }
+ }
+}
+
func writeFile(name string, bytes []byte) {
var writer io.Writer
if name == "-" {
@@ -52,60 +94,63 @@
}
func main() {
- pb_regex, err := regexp.Compile("--pb_out=(.+)")
- json_regex, err := regexp.Compile("--json_out=(.+)")
- text_regex, err := regexp.Compile("--text_out=(.+)")
- errors_regex, err := regexp.Compile("--errors_out=(.+)")
- plugin_regex, err := regexp.Compile("--(.+)_out=(.+)")
-
+ usage := `
+Usage: openapic OPENAPI_SOURCE [OPTIONS]
+ OPENAPI_SOURCE is the filename or URL of an OpenAPI description to read.
+Options:
+ --pb_out=FILENAME Write a binary proto to a file with the specified name.
+ --json_out=FILENAME Write a json proto to a file with the specified name.
+ --text_out=FILENAME Write a text proto to a file with the specified name.
+ --errors_out=FILENAME Write compilation errors to a file with the specified name.
+ --PLUGIN_out=FILENAME Run the plugin named openapi_PLUGIN and write results to a file with the specified name.
+ --keep_refs Disable resolution of $ref references.
+`
+ // default values for all options
sourceName := ""
binaryProtoFileName := ""
jsonProtoFileName := ""
textProtoFileName := ""
errorFileName := ""
+ pluginCalls := make([]*PluginCall, 0)
keepReferences := false
- var pluginCalls []*PluginCall
+ // arg processing matches patterns of the form "--PLUGIN_out=PATH"
+ plugin_regex, err := regexp.Compile("--(.+)_out=(.+)")
for i, arg := range os.Args {
if i == 0 {
- continue
+ continue // skip the tool name
}
- argbytes := []byte(arg)
var m [][]byte
- if m = pb_regex.FindSubmatch(argbytes); m != nil {
- binaryProtoFileName = string(m[1])
- } else if m = json_regex.FindSubmatch(argbytes); m != nil {
- jsonProtoFileName = string(m[1])
- } else if m = text_regex.FindSubmatch(argbytes); m != nil {
- textProtoFileName = string(m[1])
- } else if m = errors_regex.FindSubmatch(argbytes); m != nil {
- errorFileName = string(m[1])
- } else if m = plugin_regex.FindSubmatch(argbytes); m != nil {
- pluginCall := &PluginCall{Name: string(m[1]), Output: string(m[2])}
- pluginCalls = append(pluginCalls, pluginCall)
+ if m = plugin_regex.FindSubmatch([]byte(arg)); m != nil {
+ pluginName := string(m[1])
+ outputName := string(m[2])
+ switch pluginName {
+ case "pb":
+ binaryProtoFileName = outputName
+ case "json":
+ jsonProtoFileName = outputName
+ case "text":
+ textProtoFileName = outputName
+ case "errors":
+ errorFileName = outputName
+ default:
+ pluginCall := &PluginCall{Name: pluginName, Output: outputName}
+ pluginCalls = append(pluginCalls, pluginCall)
+ }
} else if arg == "--keep_refs" {
keepReferences = true
+ } else if arg[0] == '-' {
+ fmt.Printf("Unknown option: %s.\n%s\n", arg, usage)
+ os.Exit(-1)
} else {
sourceName = arg
}
}
- usage := `
-Usage: openapic OPENAPI_SOURCE [OPTIONS]
- OPENAPI_SOURCE is the filename or URL of the OpenAPI description to read.
-Options:
- --pb_out=FILENAME Write a binary proto to a file with the specified name.
- --text_out=FILENAME Write a text proto to a file with the specified name.
- --json_out=FILENAME Write a json proto to a file with the specified name.
- --errors_out=FILENAME Write compilation errors to a file with the specified name.
- --PLUGIN_out=FILENAME Run the plugin named openapi_PLUGIN and write results to a file with the specified name.
- --keep_refs Disable resolution of $ref references.
-`
-
- if textProtoFileName == "" &&
+ if binaryProtoFileName == "" &&
jsonProtoFileName == "" &&
- binaryProtoFileName == "" &&
+ textProtoFileName == "" &&
errorFileName == "" &&
len(pluginCalls) == 0 {
fmt.Printf("Missing output directives.\n%s\n", usage)
@@ -117,22 +162,24 @@
os.Exit(-1)
}
+ // If we get here and the error output is unspecified, write errors to stdout.
if errorFileName == "" {
errorFileName = "-"
}
+ // read and compile the OpenAPI source
raw, err := compiler.ReadFile(sourceName)
if err != nil {
fmt.Printf("Error: %+v\n", err)
os.Exit(-1)
}
-
document, err := openapi_v2.NewDocument(raw, compiler.NewContext("$root", nil))
if err != nil {
writeFile(errorFileName, []byte(err.Error()))
os.Exit(-1)
}
+ // optionally resolve internal references
if !keepReferences {
_, err = document.ResolveReferences(sourceName)
if err != nil {
@@ -141,60 +188,23 @@
}
}
- if textProtoFileName != "" {
- bytes := []byte(proto.MarshalTextString(document))
- writeFile(textProtoFileName, bytes)
- }
-
- if jsonProtoFileName != "" {
- jsonBytes, _ := json.Marshal(document)
- writeFile(jsonProtoFileName, jsonBytes)
- }
-
+ // perform all specified actions
if binaryProtoFileName != "" {
+ // write proto in binary format
protoBytes, _ := proto.Marshal(document)
writeFile(binaryProtoFileName, protoBytes)
}
-
+ if jsonProtoFileName != "" {
+ // write proto in json format
+ jsonBytes, _ := json.Marshal(document)
+ writeFile(jsonProtoFileName, jsonBytes)
+ }
+ if textProtoFileName != "" {
+ // write proto in text format
+ bytes := []byte(proto.MarshalTextString(document))
+ writeFile(textProtoFileName, bytes)
+ }
for _, pluginCall := range pluginCalls {
- if pluginCall.Name != "" {
- request := &plugins.PluginRequest{}
- request.Parameter = ""
-
- version := &plugins.Version{}
- version.Major = 0
- version.Minor = 1
- version.Patch = 0
- request.CompilerVersion = version
-
- wrapper := &plugins.Wrapper{}
- wrapper.Name = sourceName
- wrapper.Version = "v2"
- protoBytes, _ := proto.Marshal(document)
- wrapper.Value = protoBytes
- request.Wrapper = []*plugins.Wrapper{wrapper}
- requestBytes, _ := proto.Marshal(request)
-
- cmd := exec.Command("openapi_" + pluginCall.Name)
- cmd.Stdin = bytes.NewReader(requestBytes)
- output, err := cmd.Output()
- if err != nil {
- fmt.Printf("Error: %+v\n", err)
- }
- response := &plugins.PluginResponse{}
- err = proto.Unmarshal(output, response)
-
- var writer io.Writer
- if pluginCall.Output == "-" {
- writer = os.Stdout
- } else {
- file, _ := os.Create(pluginCall.Output)
- defer file.Close()
- writer = file
- }
- for _, text := range response.Text {
- writer.Write([]byte(text))
- }
- }
+ pluginCall.perform(document, sourceName)
}
}