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
26namespace android {
27
28CompositeDeclaration::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
39CompositeDeclaration::~CompositeDeclaration() {
40    if(mFieldDeclarations != NULL) {
41        for(auto* decl : *mFieldDeclarations) {
42            delete decl;
43        }
44    }
45    delete mFieldDeclarations;
46}
47
48void CompositeDeclaration::setName(const std::string &name) {
49    Declaration::setName(name);
50    forcePascalCase();
51}
52
53const Type::Qualifier::Qualification &CompositeDeclaration::getQualifier() const {
54    return mQualifier;
55}
56const std::vector<android::Declaration *>*
57    CompositeDeclaration::getFieldDeclarations() const {
58    return mFieldDeclarations;
59}
60
61void CompositeDeclaration::generateInterface(Formatter &out) const {
62    generateCommentText(out);
63    out << "interface " << getInterfaceName() << " {\n\n";
64
65    generateBody(out);
66
67    out << "};\n";
68}
69
70void 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
95void 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
107void 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
150std::string CompositeDeclaration::getInterfaceName() const {
151    return "I" + getName();
152}
153
154bool 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
167void CompositeDeclaration::setEnumTypeName(const std::string &name) {
168    CHECK(mQualifier == Type::Qualifier::ENUM);
169
170    mEnumTypeName = name;
171}
172
173} //namespace android
174