1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <map> 6 7 #include "fidl/raw_ast.h" 8 #include "fidl/tree_visitor.h" 9 10 namespace fidl { 11 namespace raw { 12 OnFile(std::unique_ptr<File> const & element)13void DeclarationOrderTreeVisitor::OnFile(std::unique_ptr<File> const& element) { 14 OnSourceElementStart(*element); 15 16 OnCompoundIdentifier(element->library_name); 17 for (auto i = element->using_list.begin(); 18 i != element->using_list.end(); 19 ++i) { 20 OnUsing(*i); 21 } 22 23 auto const_decls_it = element->const_declaration_list.begin(); 24 auto enum_decls_it = element->enum_declaration_list.begin(); 25 auto interface_decls_it = element->interface_declaration_list.begin(); 26 auto struct_decls_it = element->struct_declaration_list.begin(); 27 auto table_decls_it = element->table_declaration_list.begin(); 28 auto union_decls_it = element->union_declaration_list.begin(); 29 30 enum Next { 31 const_t, 32 enum_t, 33 interface_t, 34 struct_t, 35 table_t, 36 union_t 37 }; 38 39 std::map<const char*, Next> m; 40 do { 41 // We want to visit these in declaration order, rather than grouped 42 // by type of declaration. std::map is sorted by key. For each of 43 // these lists of declarations, we make a map where the key is "the 44 // next start location of the earliest element in the list" to a 45 // variable representing the type. We then identify which type was 46 // put earliest in the map. That will be the earliest declaration 47 // in the file. We then visit the declaration accordingly. 48 m.clear(); 49 if (const_decls_it != element->const_declaration_list.end()) { 50 m[(*const_decls_it)->start_.previous_end().data().data()] = const_t; 51 } 52 if (enum_decls_it != element->enum_declaration_list.end()) { 53 m[(*enum_decls_it)->start_.previous_end().data().data()] = enum_t; 54 } 55 if (interface_decls_it != element->interface_declaration_list.end()) { 56 if (*interface_decls_it == nullptr) { 57 // Used to indicate empty, so let's wind it forward. 58 interface_decls_it = element->interface_declaration_list.end(); 59 } else { 60 m[(*interface_decls_it)->start_.previous_end().data().data()] = interface_t; 61 } 62 } 63 if (struct_decls_it != element->struct_declaration_list.end()) { 64 m[(*struct_decls_it)->start_.previous_end().data().data()] = struct_t; 65 } 66 if (table_decls_it != element->table_declaration_list.end()) { 67 m[(*table_decls_it)->start_.previous_end().data().data()] = table_t; 68 } 69 if (union_decls_it != element->union_declaration_list.end()) { 70 m[(*union_decls_it)->start_.previous_end().data().data()] = union_t; 71 } 72 if (m.size() == 0) 73 break; 74 75 // And the earliest top level declaration is... 76 switch (m.begin()->second) { 77 case const_t: 78 OnConstDeclaration(*const_decls_it); 79 ++const_decls_it; 80 break; 81 case enum_t: 82 OnEnumDeclaration(*enum_decls_it); 83 ++enum_decls_it; 84 break; 85 case interface_t: 86 OnInterfaceDeclaration(*interface_decls_it); 87 ++interface_decls_it; 88 break; 89 case struct_t: 90 OnStructDeclaration(*struct_decls_it); 91 ++struct_decls_it; 92 break; 93 case table_t: 94 OnTableDeclaration(*table_decls_it); 95 ++table_decls_it; 96 break; 97 case union_t: 98 OnUnionDeclaration(*union_decls_it); 99 ++union_decls_it; 100 break; 101 } 102 } while (1); 103 OnSourceElementEnd(*element); 104 } 105 106 } // namespace raw 107 } // namespace fidl 108