// Copyright 2017 Google LLC. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "strings" "github.com/googleapis/gnostic/printer" ) // ProtoOption represents an option to be added to generated .proto files. type ProtoOption struct { Name string Value string Comment string } // generateProto produces the contents of a .proto file corresponding to the domain. func (domain *Domain) generateProto(packageName string, license string, options []ProtoOption, imports []string) string { code := &printer.Code{} code.Print(license) code.Print("// THIS FILE IS AUTOMATICALLY GENERATED.") code.Print() code.Print("syntax = \"proto3\";") code.Print() code.Print("package " + packageName + ";") for _, importString := range imports { code.Print() code.Print("import \"" + importString + "\";") } code.Print() // generate option declarations for _, option := range options { domain.generateOptionDeclaration(code, option) } // generate message definitions typeNames := domain.sortedTypeNames() for _, typeName := range typeNames { domain.generateProtoMessage(code, typeName) } return code.String() } func (domain *Domain) generateOptionDeclaration(code *printer.Code, option ProtoOption) { commentLines := strings.Split(option.Comment, "\n") for _, commentLine := range commentLines { code.Print(commentLine) } line := "option " + option.Name + " = " if option.Value == "true" || option.Value == "false" { line += option.Value } else { line += "\"" + option.Value + "\"" } line += ";\n" code.Print(line) } func (domain *Domain) generateProtoMessage(code *printer.Code, typeName string) { typeModel := domain.TypeModels[typeName] if typeModel.Description != "" { code.Print("// %s", typeModel.Description) } code.Print("message %s {", typeName) code.Indent() if typeModel.OneOfWrapper { code.Print("oneof oneof {") code.Indent() } var fieldNumber = 0 for _, propertyModel := range typeModel.Properties { // print a leading comment if available if propertyModel.Description != "" { code.Print("// %s", propertyModel.Description) } // adjust the property type to a valid type name propertyType := propertyModel.Type if propertyType == "int" { propertyType = "int64" } if propertyType == "float" { propertyType = "double" } if propertyType == "blob" { propertyType = "string" } // adjust the display name to a valid identifier propertyName := propertyModel.Name var displayName = propertyName if displayName == "$ref" { displayName = "_ref" } if displayName == "$schema" { displayName = "_schema" } displayName = camelCaseToSnakeCase(displayName) // assign a field number to the property fieldNumber++ // print the field declaration var line = fmt.Sprintf("%s %s = %d;", propertyType, displayName, fieldNumber) if propertyModel.Repeated { line = "repeated " + line } code.Print(line) } if typeModel.OneOfWrapper { code.Outdent() code.Print("}") } code.Outdent() code.Print("}") code.Print() }