Replace method_type with AidlMethod

As usual, we're leaving most of the same members in place and public. However,
we have removed the linked list pointer and switched to std::vector for lists
of methods.

Change-Id: Id0aa55340e2c56bfa1001c6c8a8343bb4815d38e
Test: unit tests
Bug: 24410295
Signed-off-by: Casey Dahlin <sadmac@google.com>
diff --git a/aidl.cpp b/aidl.cpp
index c88c9de..11a4fea 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -204,8 +204,8 @@
                 interface_type* c,
                 TypeNamespace* types) {
   int err = 0;
-  map<string,method_type*> method_names;
-  for (method_type* m = c->interface_items; m; m = m->next) {
+  set<string> method_names;
+  for (const auto& m : *c->methods) {
     if (!types->AddContainerType(m->type->type.data) ||
         !types->IsValidReturnType(*m->type, filename)) {
       err = 1;  // return type is invalid
@@ -221,7 +221,7 @@
 
     // prevent duplicate methods
     if (method_names.find(m->name.data) == method_names.end()) {
-      method_names[m->name.data] = m;
+      method_names.insert(m->name.data);
     } else {
       cerr << filename << ":" << m->name.lineno
            << " attempt to redefine method " << m->name.data << "," << endl
@@ -449,15 +449,14 @@
 }
 
 int check_and_assign_method_ids(const char * filename,
-                                method_type* first_item) {
+                                const std::vector<std::unique_ptr<AidlMethod>>& items) {
     // Check whether there are any methods with manually assigned id's and any that are not.
     // Either all method id's must be manually assigned or all of them must not.
     // Also, check for duplicates of user set id's and that the id's are within the proper bounds.
     set<int> usedIds;
-    method_type* item = first_item;
     bool hasUnassignedIds = false;
     bool hasAssignedIds = false;
-    while (item != NULL) {
+    for (const auto& item : items) {
         if (item->hasId) {
             hasAssignedIds = true;
             item->assigned_id = atoi(item->id.data);
@@ -490,16 +489,13 @@
                     filename);
             return 1;
         }
-        item = item->next;
     }
 
     // In the case that all methods have unassigned id's, set a unique id for them.
     if (hasUnassignedIds) {
         int newId = 0;
-        item = first_item;
-        while (item != NULL) {
+        for (const auto& item : items) {
             item->assigned_id = newId++;
-            item = item->next;
         }
     }
 
@@ -593,7 +589,7 @@
 
   // assign method ids and validate.
   err |= check_and_assign_method_ids(input_file_name.c_str(),
-                                     interface->interface_items);
+                                     *interface->methods);
 
   // after this, there shouldn't be any more errors because of the
   // input.
diff --git a/aidl_language.h b/aidl_language.h
index 9e7d25d..3de29ec 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -87,22 +87,24 @@
   DISALLOW_COPY_AND_ASSIGN(AidlArgument);
 };
 
-struct method_type {
-    struct method_type *next;
-    AidlType* type;
-    bool oneway;
-    buffer_type oneway_token;
-    buffer_type name;
-    buffer_type open_paren_token;
-    std::vector<std::unique_ptr<AidlArgument>>* args;
-    buffer_type close_paren_token;
-    bool hasId;
-    buffer_type equals_token;
-    buffer_type id;
-    // XXX missing comments/copy text here
-    buffer_type semicolon_token;
-    buffer_type* comments_token; // points into this structure, DO NOT DELETE
-    int assigned_id;
+class AidlMethod {
+ public:
+  AidlMethod() = default;
+  virtual ~AidlMethod() = default;
+
+  AidlType* type;
+  bool oneway;
+  buffer_type oneway_token;
+  buffer_type name;
+  std::vector<std::unique_ptr<AidlArgument>>* args;
+  bool hasId;
+  buffer_type id;
+  buffer_type semicolon_token;
+  buffer_type* comments_token; // points into this structure, DO NOT DELETE
+  int assigned_id;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AidlMethod);
 };
 
 enum {
@@ -133,7 +135,7 @@
     char* package;
     buffer_type name;
     buffer_type open_brace_token;
-    method_type* interface_items;
+    std::vector<std::unique_ptr<AidlMethod>>* methods;
     buffer_type close_brace_token;
     buffer_type* comments_token; // points into this structure, DO NOT DELETE
 };
diff --git a/aidl_language_l.l b/aidl_language_l.l
index a067bf7..d6508db 100644
--- a/aidl_language_l.l
+++ b/aidl_language_l.l
@@ -87,11 +87,12 @@
 ;               { SET_BUFFER(';'); return ';'; }
 \{              { SET_BUFFER('{'); return '{'; }
 \}              { SET_BUFFER('}'); return '}'; }
-\(              { SET_BUFFER('('); return '('; }
-\)              { SET_BUFFER(')'); return ')'; }
 ,               { SET_BUFFER(','); return ','; }
 =               { SET_BUFFER('='); return '='; }
 
+\(              { return '('; }
+\)              { return ')'; }
+
     /* keywords */
 parcelable      { SET_BUFFER(yy::parser::token::PARCELABLE); return yy::parser::token::PARCELABLE; }
 interface       { SET_BUFFER(yy::parser::token::INTERFACE); return yy::parser::token::INTERFACE; }
diff --git a/aidl_language_y.y b/aidl_language_y.y
index a6d4cbb..aee02db 100644
--- a/aidl_language_y.y
+++ b/aidl_language_y.y
@@ -28,19 +28,20 @@
     AidlArgument* arg;
     AidlArgument::Direction direction;
     std::vector<std::unique_ptr<AidlArgument>>* arg_list;
-    method_type* method;
+    AidlMethod* method;
+    std::vector<std::unique_ptr<AidlMethod>>* methods;
     interface_type* interface_obj;
     user_data_type* user_data;
     document_item_type* document_item;
 }
 
 %token<buffer> IMPORT PACKAGE IDENTIFIER IDVALUE GENERIC ARRAY PARCELABLE
-%token<buffer> ONEWAY INTERFACE ';' '{' '}' '(' ')' ',' '='
-%token IN OUT INOUT 
+%token<buffer> ONEWAY INTERFACE ';' '{' '}' ',' '='
+%token IN OUT INOUT '(' ')'
 
 %type<document_item> document_items declaration
 %type<user_data> parcelable_decl
-%type<method> interface_items
+%type<methods> methods
 %type<interface_obj> interface_decl interface_header
 %type<method> method_decl
 %type<type> type
@@ -151,17 +152,17 @@
     ;
 
 interface_decl:
-        interface_header IDENTIFIER '{' interface_items '}' { 
+        interface_header IDENTIFIER '{' methods '}' { 
                                                         interface_type* c = $1;
                                                         c->name = $2;
                                                         c->package =
                                                         cpp_strdup(ps->Package().c_str());
                                                         c->open_brace_token = $3;
-                                                        c->interface_items = $4;
+                                                        c->methods = $4;
                                                         c->close_brace_token = $5;
                                                         $$ = c;
                                                     }
-    |   INTERFACE error '{' interface_items '}'     {
+    |   INTERFACE error '{' methods '}'     {
                                                         fprintf(stderr, "%s:%d: syntax error in interface declaration.  Expected type name, saw \"%s\"\n",
                                                                     ps->FileName().c_str(), $2.lineno, $2.data);
                                                         $$ = NULL;
@@ -174,87 +175,66 @@
 
     ;
 
-interface_items:
-                                                    { $$ = NULL; }
-    |   interface_items method_decl                 {
-                                                        method_type* p=$1;
-                                                        while (p && p->next) {
-                                                            p=p->next;
-                                                        }
-                                                        if (p) {
-                                                            p->next = $2;
-                                                            $$ = $1;
-                                                        } else {
-                                                            $$ = $2;
-                                                        }
-                                                    }
-    |   interface_items error ';'                   {
-                                                        fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n",
-                                                                    ps->FileName().c_str(), $3.lineno);
-                                                        $$ = $1;
-                                                    }
-    ;
+methods
+ :
+  { $$ = new std::vector<std::unique_ptr<AidlMethod>>(); }
+ | methods method_decl
+  { $1->push_back(std::unique_ptr<AidlMethod>($2)); }
+ | methods error ';' {
+    fprintf(stderr, "%s:%d: syntax error before ';' "
+                    "(expected method declaration)\n",
+            ps->FileName().c_str(), $3.lineno);
+    $$ = $1;
+  };
 
 method_decl:
         type IDENTIFIER '(' arg_list ')' ';'  {
-                                                        method_type *method = new method_type();
+                                                        AidlMethod *method = new AidlMethod();
                                                         method->oneway = false;
                                                         method->type = $1;
                                                         memset(&method->oneway_token, 0, sizeof(buffer_type));
                                                         method->name = $2;
-                                                        method->open_paren_token = $3;
                                                         method->args = $4;
-                                                        method->close_paren_token = $5;
                                                         method->hasId = false;
-                                                        memset(&method->equals_token, 0, sizeof(buffer_type));
                                                         memset(&method->id, 0, sizeof(buffer_type));
                                                         method->semicolon_token = $6;
                                                         method->comments_token = &method->type->type;
                                                         $$ = method;
                                                     }
     |   ONEWAY type IDENTIFIER '(' arg_list ')' ';'  {
-                                                        method_type *method = new method_type();
+                                                        AidlMethod *method = new AidlMethod();
                                                         method->oneway = true;
                                                         method->oneway_token = $1;
                                                         method->type = $2;
                                                         method->name = $3;
-                                                        method->open_paren_token = $4;
                                                         method->args = $5;
-                                                        method->close_paren_token = $6;
                                                         method->hasId = false;
-                                                        memset(&method->equals_token, 0, sizeof(buffer_type));
                                                         memset(&method->id, 0, sizeof(buffer_type));
                                                         method->semicolon_token = $7;
                                                         method->comments_token = &method->oneway_token;
                                                         $$ = method;
                                                     }
     |    type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';'  {
-                                                        method_type *method = new method_type();
+                                                        AidlMethod *method = new AidlMethod();
                                                         method->oneway = false;
                                                         memset(&method->oneway_token, 0, sizeof(buffer_type));
                                                         method->type = $1;
                                                         method->name = $2;
-                                                        method->open_paren_token = $3;
                                                         method->args = $4;
-                                                        method->close_paren_token = $5;
                                                         method->hasId = true;
-                                                        method->equals_token = $6;
                                                         method->id = $7;
                                                         method->semicolon_token = $8;
                                                         method->comments_token = &method->type->type;
                                                         $$ = method;
                                                     }
     |   ONEWAY type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';'  {
-                                                        method_type *method = new method_type();
+                                                        AidlMethod *method = new AidlMethod();
                                                         method->oneway = true;
                                                         method->oneway_token = $1;
                                                         method->type = $2;
                                                         method->name = $3;
-                                                        method->open_paren_token = $4;
                                                         method->args = $5;
-                                                        method->close_paren_token = $6;
                                                         method->hasId = true;
-                                                        method->equals_token = $7;
                                                         method->id = $8;
                                                         method->semicolon_token = $9;
                                                         method->comments_token = &method->oneway_token;
@@ -262,7 +242,8 @@
                                                     }
     ;
 
-arg_list:
+arg_list
+ :
   { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); }
  | arg {
     $$ = new std::vector<std::unique_ptr<AidlArgument>>();
@@ -278,7 +259,8 @@
     $$ = new std::vector<std::unique_ptr<AidlArgument>>();
   };
 
-arg: direction type IDENTIFIER
+arg
+ : direction type IDENTIFIER
   { $$ = new AidlArgument($1, $2, $3); };
  | type IDENTIFIER
   { $$ = new AidlArgument($1, $2); };
@@ -301,7 +283,8 @@
                                 }
     ;
 
-direction: IN
+direction
+ : IN
   { $$ = AidlArgument::IN_DIR; }
  | OUT
   { $$ = AidlArgument::OUT_DIR; }
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 50dd392..5f14a61 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -65,17 +65,17 @@
                       type.Brackets().c_str());
 }
 
-unique_ptr<Declaration> BuildMethodDecl(const method_type* method,
+unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
                                         const TypeNamespace& types,
                                         bool for_interface) {
   vector<string> args;
-  for (const unique_ptr<AidlArgument>& arg : *method->args) {
+  for (const unique_ptr<AidlArgument>& arg : *method.args) {
     args.push_back(GetCPPVarDec(
           types, arg->GetType(), arg->GetName(),
           AidlArgument::OUT_DIR & arg->GetDirection()));
   }
 
-  string return_arg = GetCPPVarDec(types, *method->type, "_aidl_return", true);
+  string return_arg = GetCPPVarDec(types, *method.type, "_aidl_return", true);
   args.push_back(return_arg);
 
   uint32_t modifiers = 0;
@@ -88,7 +88,7 @@
 
   return unique_ptr<Declaration>{
       new MethodDecl{kAndroidStatusLiteral,
-                     method->name.Literal(),
+                     method.name.Literal(),
                      args,
                      modifiers}};
 }
@@ -171,10 +171,8 @@
   publics.push_back(std::move(constructor));
   publics.push_back(std::move(destructor));
 
-  for (method_type *item = parsed_doc.interface_items;
-       item;
-       item = item->next) {
-    publics.push_back(BuildMethodDecl(item, types, false));
+  for (const auto& item : *parsed_doc.methods) {
+    publics.push_back(BuildMethodDecl(*item, types, false));
   }
 
   unique_ptr<ClassDecl> bp_class{
@@ -234,10 +232,8 @@
           {ClassName(parsed_doc, ClassNames::BASE)}}});
 
   unique_ptr<Enum> call_enum{new Enum{"Call"}};
-  for (const method_type* method = parsed_doc.interface_items;
-       method;
-       method = method->next) {
-    if_class->AddPublic(BuildMethodDecl(method, types, true));
+  for (const auto& method : *parsed_doc.methods) {
+    if_class->AddPublic(BuildMethodDecl(*method, types, true));
     call_enum->AddValue(
         UpperCase(method->name.data),
         StringPrintf("android::IBinder::FIRST_CALL_TRANSACTION + %d",
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index 42b0a2e..b8fded0 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -263,18 +263,18 @@
 
 
 static void
-generate_method(const method_type* method, Class* interface,
+generate_method(const AidlMethod& method, Class* interface,
                 StubClass* stubClass, ProxyClass* proxyClass, int index,
                 JavaTypeNamespace* types)
 {
     int i;
     bool hasOutParams = false;
 
-    const bool oneway = proxyClass->mOneWay || method->oneway;
+    const bool oneway = proxyClass->mOneWay || method.oneway;
 
     // == the TRANSACT_ constant =============================================
     string transactCodeName = "TRANSACTION_";
-    transactCodeName += method->name.data;
+    transactCodeName += method.name.data;
 
     char transactCodeValue[60];
     sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
@@ -286,13 +286,13 @@
 
     // == the declaration in the interface ===================================
     Method* decl = new Method;
-        decl->comment = gather_comments(method->comments_token->extra);
+        decl->comment = gather_comments(method.comments_token->extra);
         decl->modifiers = PUBLIC;
-        decl->returnType = types->Find(method->type->type.data);
-        decl->returnTypeDimension = method->type->dimension;
-        decl->name = method->name.data;
+        decl->returnType = types->Find(method.type->type.data);
+        decl->returnTypeDimension = method.type->dimension;
+        decl->name = method.name.data;
 
-    for (const std::unique_ptr<AidlArgument>& arg : *method->args) {
+    for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
         decl->parameters.push_back(new Variable(
                             types->Find(arg->GetType().type.data), arg->GetName(),
                             arg->GetType().dimension));
@@ -306,7 +306,7 @@
 
     Case* c = new Case(transactCodeName);
 
-    MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data);
+    MethodCall* realCall = new MethodCall(THIS_VALUE, method.name.data);
 
     // interface token validation is the very first thing we do
     c->statements->Add(new MethodCall(stubClass->transact_data,
@@ -315,7 +315,7 @@
     // args
     Variable* cl = NULL;
     VariableFactory stubArgs("_arg");
-    for (const std::unique_ptr<AidlArgument>& arg : *method->args) {
+    for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
         const Type* t = types->Find(arg->GetType().type.data);
         Variable* v = stubArgs.Get(t);
         v->dimension = arg->GetType().dimension;
@@ -344,7 +344,7 @@
 
     // the real call
     Variable* _result = NULL;
-    if (0 == strcmp(method->type->type.data, "void")) {
+    if (0 == strcmp(method.type->type.data, "void")) {
         c->statements->Add(realCall);
 
         if (!oneway) {
@@ -373,7 +373,7 @@
 
     // out parameters
     i = 0;
-    for (const std::unique_ptr<AidlArgument>& arg : *method->args) {
+    for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
         const Type* t = types->Find(arg->GetType().type.data);
         Variable* v = stubArgs.Get(i++);
 
@@ -391,13 +391,13 @@
 
     // == the proxy method ===================================================
     Method* proxy = new Method;
-        proxy->comment = gather_comments(method->comments_token->extra);
+        proxy->comment = gather_comments(method.comments_token->extra);
         proxy->modifiers = PUBLIC | OVERRIDE;
-        proxy->returnType = types->Find(method->type->type.data);
-        proxy->returnTypeDimension = method->type->dimension;
-        proxy->name = method->name.data;
+        proxy->returnType = types->Find(method.type->type.data);
+        proxy->returnTypeDimension = method.type->dimension;
+        proxy->name = method.name.data;
         proxy->statements = new StatementBlock;
-        for (const std::unique_ptr<AidlArgument>& arg : *method->args) {
+        for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
             proxy->parameters.push_back(new Variable(
                             types->Find(arg->GetType().type.data), arg->GetName(),
                             arg->GetType().dimension));
@@ -420,9 +420,9 @@
 
     // the return value
     _result = NULL;
-    if (0 != strcmp(method->type->type.data, "void")) {
+    if (0 != strcmp(method.type->type.data, "void")) {
         _result = new Variable(proxy->returnType, "_result",
-                method->type->dimension);
+                method.type->dimension);
         proxy->statements->Add(new VariableDeclaration(_result));
     }
 
@@ -437,7 +437,7 @@
             1, new LiteralExpression("DESCRIPTOR")));
 
     // the parameters
-    for (const std::unique_ptr<AidlArgument>& arg : *method->args) {
+    for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
         const Type* t = types->Find(arg->GetType().type.data);
         Variable* v = new Variable(t, arg->GetName(), arg->GetType().dimension);
         AidlArgument::Direction dir = arg->GetDirection();
@@ -478,7 +478,7 @@
         }
 
         // the out/inout parameters
-        for (const std::unique_ptr<AidlArgument>& arg : *method->args) {
+        for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
             const Type* t = types->Find(arg->GetType().type.data);
             Variable* v = new Variable(t, arg->GetName(), arg->GetType().dimension);
             if (arg->GetDirection() & AidlArgument::OUT_DIR) {
@@ -552,11 +552,9 @@
 
     // all the declared methods of the interface
     int index = 0;
-    method_type* item = iface->interface_items;
-    while (item != NULL) {
-        generate_method(item, interface, stub, proxy,
+    for (const auto& item : *iface->methods) {
+        generate_method(*item, interface, stub, proxy,
                         item->assigned_id, types);
-        item = item->next;
         index++;
     }