blob: 965db9ebc9c857c53e27cabad5413705eb351c6c [file] [log] [blame]
Adam Lesinski330edcd2015-05-04 17:40:56 -07001/*
2 * Copyright (C) 2015 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 "Debug.h"
18#include "ResourceTable.h"
19#include "ResourceValues.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "ValueVisitor.h"
Adam Lesinskicacb28f2016-10-19 12:18:14 -070021#include "util/Util.h"
Adam Lesinski330edcd2015-05-04 17:40:56 -070022
23#include <algorithm>
24#include <iostream>
25#include <map>
26#include <memory>
Adam Lesinskid13fb242015-05-12 20:40:48 -070027#include <queue>
Adam Lesinski330edcd2015-05-04 17:40:56 -070028#include <set>
29#include <vector>
30
31namespace aapt {
32
Adam Lesinski355f2852016-02-13 20:26:45 -080033class PrintVisitor : public ValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070034 public:
35 using ValueVisitor::visit;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070036
Adam Lesinskicacb28f2016-10-19 12:18:14 -070037 void visit(Attribute* attr) override {
38 std::cout << "(attr) type=";
39 attr->printMask(&std::cout);
40 static constexpr uint32_t kMask =
41 android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS;
42 if (attr->typeMask & kMask) {
43 for (const auto& symbol : attr->symbols) {
44 std::cout << "\n " << symbol.symbol.name.value().entry;
45 if (symbol.symbol.id) {
46 std::cout << " (" << symbol.symbol.id.value() << ")";
Adam Lesinski330edcd2015-05-04 17:40:56 -070047 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070048 std::cout << " = " << symbol.value;
49 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070050 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070051 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070052
Adam Lesinskicacb28f2016-10-19 12:18:14 -070053 void visit(Style* style) override {
54 std::cout << "(style)";
55 if (style->parent) {
56 const Reference& parentRef = style->parent.value();
57 std::cout << " parent=";
58 if (parentRef.name) {
59 if (parentRef.privateReference) {
60 std::cout << "*";
Adam Lesinski330edcd2015-05-04 17:40:56 -070061 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070062 std::cout << parentRef.name.value() << " ";
63 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070064
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 if (parentRef.id) {
66 std::cout << parentRef.id.value();
67 }
68 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070069
Adam Lesinskicacb28f2016-10-19 12:18:14 -070070 for (const auto& entry : style->entries) {
71 std::cout << "\n ";
72 if (entry.key.name) {
73 const ResourceName& name = entry.key.name.value();
74 if (!name.package.empty()) {
75 std::cout << name.package << ":";
Adam Lesinski330edcd2015-05-04 17:40:56 -070076 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 std::cout << name.entry;
78 }
79
80 if (entry.key.id) {
81 std::cout << "(" << entry.key.id.value() << ")";
82 }
83
84 std::cout << "=" << *entry.value;
Adam Lesinski330edcd2015-05-04 17:40:56 -070085 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070086 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070087
Adam Lesinskicacb28f2016-10-19 12:18:14 -070088 void visit(Array* array) override { array->print(&std::cout); }
Adam Lesinski330edcd2015-05-04 17:40:56 -070089
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 void visit(Plural* plural) override { plural->print(&std::cout); }
Adam Lesinski330edcd2015-05-04 17:40:56 -070091
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 void visit(Styleable* styleable) override {
93 std::cout << "(styleable)";
94 for (const auto& attr : styleable->entries) {
95 std::cout << "\n ";
96 if (attr.name) {
97 const ResourceName& name = attr.name.value();
98 if (!name.package.empty()) {
99 std::cout << name.package << ":";
Adam Lesinski355f2852016-02-13 20:26:45 -0800100 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 std::cout << name.entry;
102 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700103
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700104 if (attr.id) {
105 std::cout << "(" << attr.id.value() << ")";
106 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700107 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700108 }
109
110 void visitItem(Item* item) override { item->print(&std::cout); }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700111};
112
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113void Debug::printTable(ResourceTable* table,
114 const DebugPrintTableOptions& options) {
115 PrintVisitor visitor;
Adam Lesinski355f2852016-02-13 20:26:45 -0800116
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 for (auto& package : table->packages) {
118 std::cout << "Package name=" << package->name;
119 if (package->id) {
120 std::cout << " id=" << std::hex << (int)package->id.value() << std::dec;
121 }
122 std::cout << std::endl;
123
124 for (const auto& type : package->types) {
125 std::cout << "\n type " << type->type;
126 if (type->id) {
127 std::cout << " id=" << std::hex << (int)type->id.value() << std::dec;
128 }
129 std::cout << " entryCount=" << type->entries.size() << std::endl;
130
131 std::vector<const ResourceEntry*> sortedEntries;
132 for (const auto& entry : type->entries) {
133 auto iter = std::lower_bound(
134 sortedEntries.begin(), sortedEntries.end(), entry.get(),
135 [](const ResourceEntry* a, const ResourceEntry* b) -> bool {
136 if (a->id && b->id) {
137 return a->id.value() < b->id.value();
138 } else if (a->id) {
139 return true;
140 } else {
141 return false;
142 }
143 });
144 sortedEntries.insert(iter, entry.get());
145 }
146
147 for (const ResourceEntry* entry : sortedEntries) {
148 ResourceId id(package->id ? package->id.value() : uint8_t(0),
149 type->id ? type->id.value() : uint8_t(0),
150 entry->id ? entry->id.value() : uint16_t(0));
151 ResourceName name(package->name, type->type, entry->name);
152
153 std::cout << " spec resource " << id << " " << name;
154 switch (entry->symbolStatus.state) {
155 case SymbolState::kPublic:
156 std::cout << " PUBLIC";
157 break;
158 case SymbolState::kPrivate:
159 std::cout << " _PRIVATE_";
160 break;
161 default:
162 break;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700163 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700164
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700165 std::cout << std::endl;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700166
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 for (const auto& value : entry->values) {
168 std::cout << " (" << value->config << ") ";
169 value->value->accept(&visitor);
170 if (options.showSources && !value->value->getSource().path.empty()) {
171 std::cout << " src=" << value->value->getSource();
172 }
173 std::cout << std::endl;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700174 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700175 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700176 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700177 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700178}
179
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700180static size_t getNodeIndex(const std::vector<ResourceName>& names,
181 const ResourceName& name) {
182 auto iter = std::lower_bound(names.begin(), names.end(), name);
183 assert(iter != names.end() && *iter == name);
184 return std::distance(names.begin(), iter);
Adam Lesinski330edcd2015-05-04 17:40:56 -0700185}
186
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700187void Debug::printStyleGraph(ResourceTable* table,
188 const ResourceName& targetStyle) {
189 std::map<ResourceName, std::set<ResourceName>> graph;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700190
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700191 std::queue<ResourceName> stylesToVisit;
192 stylesToVisit.push(targetStyle);
193 for (; !stylesToVisit.empty(); stylesToVisit.pop()) {
194 const ResourceName& styleName = stylesToVisit.front();
195 std::set<ResourceName>& parents = graph[styleName];
196 if (!parents.empty()) {
197 // We've already visited this style.
198 continue;
199 }
200
201 Maybe<ResourceTable::SearchResult> result = table->findResource(styleName);
202 if (result) {
203 ResourceEntry* entry = result.value().entry;
204 for (const auto& value : entry->values) {
205 if (Style* style = valueCast<Style>(value->value.get())) {
206 if (style->parent && style->parent.value().name) {
207 parents.insert(style->parent.value().name.value());
208 stylesToVisit.push(style->parent.value().name.value());
209 }
Adam Lesinskid13fb242015-05-12 20:40:48 -0700210 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700211 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700212 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700213 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700214
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700215 std::vector<ResourceName> names;
216 for (const auto& entry : graph) {
217 names.push_back(entry.first);
218 }
219
220 std::cout << "digraph styles {\n";
221 for (const auto& name : names) {
222 std::cout << " node_" << getNodeIndex(names, name) << " [label=\"" << name
223 << "\"];\n";
224 }
225
226 for (const auto& entry : graph) {
227 const ResourceName& styleName = entry.first;
228 size_t styleNodeIndex = getNodeIndex(names, styleName);
229
230 for (const auto& parentName : entry.second) {
231 std::cout << " node_" << styleNodeIndex << " -> "
232 << "node_" << getNodeIndex(names, parentName) << ";\n";
Adam Lesinskid13fb242015-05-12 20:40:48 -0700233 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700234 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700235
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700236 std::cout << "}" << std::endl;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700237}
238
Adam Lesinski52364f72016-01-11 13:10:24 -0800239void Debug::dumpHex(const void* data, size_t len) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700240 const uint8_t* d = (const uint8_t*)data;
241 for (size_t i = 0; i < len; i++) {
242 std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i]
243 << " ";
244 if (i % 8 == 7) {
245 std::cerr << "\n";
Adam Lesinski52364f72016-01-11 13:10:24 -0800246 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700247 }
Adam Lesinski52364f72016-01-11 13:10:24 -0800248
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700249 if (len - 1 % 8 != 7) {
250 std::cerr << std::endl;
251 }
Adam Lesinski52364f72016-01-11 13:10:24 -0800252}
253
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700254namespace {
255
256class XmlPrinter : public xml::Visitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 public:
258 using xml::Visitor::visit;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700259
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700260 void visit(xml::Element* el) override {
261 std::cerr << mPrefix;
262 std::cerr << "E: ";
263 if (!el->namespaceUri.empty()) {
264 std::cerr << el->namespaceUri << ":";
265 }
266 std::cerr << el->name << " (line=" << el->lineNumber << ")\n";
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700267
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268 for (const xml::Attribute& attr : el->attributes) {
269 std::cerr << mPrefix << " A: ";
270 if (!attr.namespaceUri.empty()) {
271 std::cerr << attr.namespaceUri << ":";
272 }
273 std::cerr << attr.name << "=" << attr.value << "\n";
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700274 }
275
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700276 const size_t previousSize = mPrefix.size();
277 mPrefix += " ";
278 xml::Visitor::visit(el);
279 mPrefix.resize(previousSize);
280 }
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700281
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700282 void visit(xml::Namespace* ns) override {
283 std::cerr << mPrefix;
284 std::cerr << "N: " << ns->namespacePrefix << "=" << ns->namespaceUri
285 << " (line=" << ns->lineNumber << ")\n";
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700286
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700287 const size_t previousSize = mPrefix.size();
288 mPrefix += " ";
289 xml::Visitor::visit(ns);
290 mPrefix.resize(previousSize);
291 }
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700292
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700293 void visit(xml::Text* text) override {
294 std::cerr << mPrefix;
295 std::cerr << "T: '" << text->text << "'\n";
296 }
297
298 private:
299 std::string mPrefix;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700300};
301
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302} // namespace
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700303
304void Debug::dumpXml(xml::XmlResource* doc) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305 XmlPrinter printer;
306 doc->root->accept(&printer);
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700307}
Adam Lesinski52364f72016-01-11 13:10:24 -0800308
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700309} // namespace aapt