blob: 5c90529e9b7674684c13cb4a4ca76cab91c3c8a7 [file] [log] [blame]
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001#include "AST.h"
2
3#include "Annotation.h"
4#include "Coordinator.h"
5#include "Formatter.h"
6#include "Interface.h"
7#include "Method.h"
8#include "Scope.h"
9
10#include <android-base/logging.h>
11#include <string>
12#include <vector>
13
14namespace android {
15
16// Remove the double quotas in a string.
17static std::string removeQuotes(const std::string in) {
18 std::string out{in};
19 return out.substr(1, out.size() - 2);
20}
21
22status_t AST::emitVtsTypeDeclarations(
23 Formatter &out,
24 Vector<Type*> types) const {
25 for (const auto& type : types) {
26 out << "attribute: {\n";
27 out.indent();
28 status_t status = type->emitVtsTypeDeclarations(out);
29 if (status != OK) {
30 return status;
31 }
32 out.unindent();
33 out << "}\n\n";
34 }
35 return OK;
36}
37
38status_t AST::generateVts(const std::string &outputPath) const {
39 std::string path = outputPath;
40 path.append(mCoordinator->convertPackageRootToPath(mPackage));
41 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
42
43 std::string ifaceName;
44 std::string baseName;
45
46 bool isInterface = true;
47 if (!AST::isInterface(&ifaceName)) {
48 baseName = "types";
49 isInterface = false;
50 } else {
51 baseName = ifaceName.substr(1); // cut off the leading 'I'.
52 }
53
54 path.append(baseName);
55 path.append(".vts");
56
57 CHECK(Coordinator::MakeParentHierarchy(path));
58 FILE *file = fopen(path.c_str(), "w");
59
60 if (file == NULL) {
61 return -errno;
62 }
63
64 Formatter out(file);
65
66 out << "component_class: HAL_HIDL\n";
67
68 // Get the component_type for interface from annotation.
69 if (isInterface) {
70 const Interface *iface = mRootScope->getInterface();
71 Annotation *annotation = iface->annotations().valueFor("hal_type");
72 if (annotation != NULL) {
73 std::vector<std::string> * values = annotation->params().valueFor(
74 "type");
75 if (values != NULL) {
76 out << "component_type: "
77 << removeQuotes(values->at(0))
78 << "\n";
79 }
80 }
81 }
82
83 out << "component_type_version: " << mPackage.version().substr(1) << "\n";
84 out << "component_name: \""
85 << (isInterface ? ifaceName : "types")
86 << "\"\n\n";
87
88 out << "package: \"" << mPackage.package() << "\"\n\n";
89
90 for (const auto &item : mImportedNames) {
91 out << "import: \"" << item.string() << "\"\n";
92 }
93
94 out << "\n";
95
96 if (isInterface) {
97 const Interface *iface = mRootScope->getInterface();
98 out << "interface: {\n";
99 out.indent();
100
101 status_t status = emitVtsTypeDeclarations(out, iface->getSubTypes());
102 if (status != OK) {
103 return status;
104 }
105
106 for (const auto &method : iface->methods()) {
107 out << "api: {\n";
108 out.indent();
109 out << "name: \"" << method->name() << "\"\n";
110 for (const auto &result : method->results()) {
111 out << "return_type_hidl: {\n";
112 out.indent();
113 status_t status = result->type().emitVtsArgumentType(out);
114 if (status != OK) {
115 return status;
116 }
117 out.unindent();
118 out << "}\n";
119 }
120 for (const auto &arg : method->args()) {
121 out << "arg: {\n";
122 out.indent();
123 status_t status = arg->type().emitVtsArgumentType(out);
124 if (status != OK) {
125 return status;
126 }
127 out.unindent();
128 out << "}\n";
129 }
130 out.unindent();
131 out << "}\n\n";
132 }
133
134 out.unindent();
135 out << "}\n";
136 } else {
137 status_t status = emitVtsTypeDeclarations(out,
138 mRootScope->getSubTypes());
139 if (status != OK) {
140 return status;
141 }
142 }
143 return OK;
144}
145
146} // namespace android
147
148
149
150