1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "CompositeDeclaration.h"
18 #include "FunctionDeclaration.h"
19 #include "VarDeclaration.h"
20 #include "Declaration.h"
21 
22 #include <algorithm>
23 #include <iostream>
24 #include <string>
25 
26 namespace android {
27 
CompositeDeclaration(const Type::Qualifier::Qualification qualifier,const std::string & name,std::vector<android::Declaration * > * fieldDeclarations)28 CompositeDeclaration::CompositeDeclaration(
29         const Type::Qualifier::Qualification qualifier,
30         const std::string &name,
31         std::vector<android::Declaration *> *fieldDeclarations)
32     : Declaration(""),
33       mQualifier(qualifier),
34       mFieldDeclarations(fieldDeclarations)
35     {
36         setName(name);
37     }
38 
~CompositeDeclaration()39 CompositeDeclaration::~CompositeDeclaration() {
40     if(mFieldDeclarations != NULL) {
41         for(auto* decl : *mFieldDeclarations) {
42             delete decl;
43         }
44     }
45     delete mFieldDeclarations;
46 }
47 
setName(const std::string & name)48 void CompositeDeclaration::setName(const std::string &name) {
49     Declaration::setName(name);
50     forcePascalCase();
51 }
52 
getQualifier() const53 const Type::Qualifier::Qualification &CompositeDeclaration::getQualifier() const {
54     return mQualifier;
55 }
56 const std::vector<android::Declaration *>*
getFieldDeclarations() const57     CompositeDeclaration::getFieldDeclarations() const {
58     return mFieldDeclarations;
59 }
60 
generateInterface(Formatter & out) const61 void CompositeDeclaration::generateInterface(Formatter &out) const {
62     generateCommentText(out);
63     out << "interface " << getInterfaceName() << " {\n\n";
64 
65     generateBody(out);
66 
67     out << "};\n";
68 }
69 
generateSource(Formatter & out) const70 void CompositeDeclaration::generateSource(Formatter &out) const {
71     CHECK(mQualifier == Type::Qualifier::STRUCT ||
72           mQualifier == Type::Qualifier::UNION ||
73           mQualifier == Type::Qualifier::ENUM);
74 
75     out << Type::qualifierText(mQualifier) << " " << getName();
76 
77     if (mQualifier == Type::Qualifier::ENUM) {
78         out << " : ";
79 
80         if (mEnumTypeName.empty()) {
81             out << "int32_t /* NOTE: type is guessed */";
82         } else {
83             out << mEnumTypeName;
84         }
85 
86     }
87 
88     out << " {\n";
89 
90     generateBody(out);
91 
92     out << "};\n";
93 }
94 
generateBody(Formatter & out) const95 void CompositeDeclaration::generateBody(Formatter &out) const {
96     out.indent();
97 
98     for (auto *declaration : *mFieldDeclarations) {
99         declaration->generateCommentText(out);
100         declaration->generateSource(out);
101         out << "\n";
102     }
103 
104     out.unindent();
105 }
106 
processContents(AST & ast)107 void CompositeDeclaration::processContents(AST &ast) {
108     for (auto &declaration : *mFieldDeclarations) {
109         declaration->processContents(ast);
110     }
111 
112     if (isInterface()) {
113         // move non function fields into a containing struct
114 
115         auto nonFpDecs = new std::vector<Declaration*>;
116 
117         auto it = mFieldDeclarations->begin();
118         while (it != mFieldDeclarations->end()) {
119             if((*it)->decType() != FunctionDeclaration::type()) {
120                 bool keep = true;
121                 if((*it)->decType() == VarDeclaration::type()) {
122                   VarDeclaration* var = (VarDeclaration *)(*it);
123                   // Conventional HALs were all required to have
124                   // a member of this type.
125                   // This member is no longer needed for HIDL
126                   if(var->getType()->isHwDevice()) {
127                     keep = false;
128                   }
129                 }
130 
131                 if (keep) {
132                   nonFpDecs->push_back(*it);
133                 }
134                 it = mFieldDeclarations->erase(it);
135             } else {
136                 it++;
137             }
138         }
139 
140         if (!nonFpDecs->empty()) {
141             auto subStruct = new CompositeDeclaration(Type::Qualifier::STRUCT,
142                                                       getName(),
143                                                       nonFpDecs);
144 
145             mFieldDeclarations->insert(mFieldDeclarations->begin(), subStruct);
146         }
147     }
148 }
149 
getInterfaceName() const150 std::string CompositeDeclaration::getInterfaceName() const {
151     return "I" + getName();
152 }
153 
isInterface() const154 bool CompositeDeclaration::isInterface() const {
155     if (mQualifier != Type::Qualifier::STRUCT) {
156         return false;
157     }
158 
159     for (auto &declaration : *mFieldDeclarations) {
160         if (declaration->decType() == FunctionDeclaration::type()) {
161             return true;
162         }
163     }
164     return false;
165 }
166 
setEnumTypeName(const std::string & name)167 void CompositeDeclaration::setEnumTypeName(const std::string &name) {
168     CHECK(mQualifier == Type::Qualifier::ENUM);
169 
170     mEnumTypeName = name;
171 }
172 
173 } //namespace android
174