added api message options 12/31612/7
authorVladimir Lavor <vlavor@cisco.com>
Thu, 11 Mar 2021 09:13:17 +0000 (10:13 +0100)
committerVladimir Lavor <vlavor@cisco.com>
Thu, 22 Apr 2021 09:32:58 +0000 (11:32 +0200)
In case the API message contains option of type deprecated
or in-progress, the information is displayed in the generated
code in a form of additional comment:

// InProgress: <info>
// Deprecated: <info>

In case the <info> is not provided, a generic message is shown.
Possible future use to automatically search whether such
messages are in use.

Change-Id: Icf87cc9a2fe6bf31f7555320255c9f0736add6e1
Signed-off-by: Vladimir Lavor <vlavor@cisco.com>
binapigen/generate.go
binapigen/vppapi/api_schema.go
binapigen/vppapi/parse_json.go

index a2f941a..2ad3eb3 100644 (file)
@@ -41,6 +41,19 @@ const (
        fieldUnionData = "XXX_UnionData" // name for the union data field
 )
 
+// option keys
+const (
+       msgStatus     = "status"
+       msgDeprecated = "deprecated"
+       msgInProgress = "in_progress"
+)
+
+// generated option messages
+const (
+       deprecatedMsg = "the message will be removed in the future versions"
+       inProgressMsg = "the message form may change in the future versions"
+)
+
 func GenerateAPI(gen *Generator, file *File) *GenFile {
        logf("----------------------------")
        logf(" Generate API - %s", file.Desc.Name)
@@ -145,6 +158,23 @@ func genTypeComment(g *GenFile, goName string, vppName string, objKind string) {
        g.P("// ", goName, " defines ", objKind, " '", vppName, "'.")
 }
 
+func genTypeOptionComment(g *GenFile, options map[string]string) {
+       // all messages for API versions < 1.0.0 are in_progress by default
+       if msg, ok := options[msgInProgress]; ok || options[msgStatus] == msgInProgress ||
+               len(g.file.Version) > 1 && g.file.Version[0:2] == "0." {
+               if msg == "" {
+                       msg = inProgressMsg
+               }
+               g.P("// InProgress: ", msg)
+       }
+       if msg, ok := options[msgDeprecated]; ok || options[msgStatus] == msgDeprecated {
+               if msg == "" {
+                       msg = deprecatedMsg
+               }
+               g.P("// Deprecated: ", msg)
+       }
+}
+
 func genEnum(g *GenFile, enum *Enum) {
        logf("gen ENUM %s (%s) - %d entries", enum.GoName, enum.Name, len(enum.Entries))
 
@@ -453,6 +483,7 @@ func genMessage(g *GenFile, msg *Message) {
        logf("gen MESSAGE %s (%s) - %d fields", msg.GoName, msg.Name, len(msg.Fields))
 
        genTypeComment(g, msg.GoIdent.GoName, msg.Name, "message")
+       genTypeOptionComment(g, msg.Options)
 
        // generate message definition
        if len(msg.Fields) == 0 {
index e1c180e..4dd0ac9 100644 (file)
@@ -62,9 +62,10 @@ type (
        }
 
        Message struct {
-               Name   string
-               Fields []Field
-               CRC    string
+               Name    string
+               Fields  []Field
+               CRC     string
+               Options map[string]string
        }
 
        Field struct {
index a2ca257..ed7bcad 100644 (file)
@@ -46,10 +46,11 @@ const (
        fileServices   = "services"
        fileImports    = "imports"
        // type keys
-       messageCrc  = "crc"
-       enumType    = "enumtype"
-       aliasLength = "length"
-       aliasType   = "type"
+       messageCrc     = "crc"
+       messageOptions = "options"
+       enumType       = "enumtype"
+       aliasLength    = "length"
+       aliasType      = "type"
        // service
        serviceReply     = "reply"
        serviceStream    = "stream"
@@ -375,10 +376,30 @@ func parseMessage(msgNode *jsongo.Node) (*Message, error) {
        if !ok {
                return nil, fmt.Errorf("message crc invalid or missing")
        }
+       var msgOpts map[string]string
+       msgOptsNode := msgNode.At(msgNode.Len() - 1).Map(messageOptions)
+       if msgOptsNode.GetType() == jsongo.TypeMap {
+               msgOpts = make(map[string]string)
+               for _, opt := range msgOptsNode.GetKeys() {
+                       if _, ok := opt.(string); !ok {
+                               logf("invalid message option key, expected string")
+                               continue
+                       }
+                       msgOpts[opt.(string)] = ""
+                       if msgOptsNode.At(opt).Get() != nil {
+                               if optMsgStr, ok := msgOptsNode.At(opt).Get().(string); ok {
+                                       msgOpts[opt.(string)] = optMsgStr
+                               } else {
+                                       logf("invalid message option value, expected string")
+                               }
+                       }
+               }
+       }
 
        msg := Message{
-               Name: msgName,
-               CRC:  msgCRC,
+               Name:    msgName,
+               CRC:     msgCRC,
+               Options: msgOpts,
        }
 
        // loop through message fields, skip first (name) and last (crc)