blob: a7b9bbaa28f345457433ece47042c68cf00b329e [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"
20#include "Util.h"
21
22#include <algorithm>
23#include <iostream>
24#include <map>
25#include <memory>
26#include <set>
27#include <vector>
28
29namespace aapt {
30
31struct PrintVisitor : ConstValueVisitor {
32 void visit(const Attribute& attr, ValueVisitorArgs&) override {
33 std::cout << "(attr) type=";
34 attr.printMask(std::cout);
35 static constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM |
36 android::ResTable_map::TYPE_FLAGS;
37 if (attr.typeMask & kMask) {
38 for (const auto& symbol : attr.symbols) {
39 std::cout << "\n "
40 << symbol.symbol.name.entry << " (" << symbol.symbol.id << ") = "
41 << symbol.value;
42 }
43 }
44 }
45
46 void visit(const Style& style, ValueVisitorArgs&) override {
47 std::cout << "(style)";
48 if (style.parent.name.isValid() || style.parent.id.isValid()) {
49 std::cout << " parent=";
50 if (style.parent.name.isValid()) {
51 std::cout << style.parent.name << " ";
52 }
53
54 if (style.parent.id.isValid()) {
55 std::cout << style.parent.id;
56 }
57 }
58
59 for (const auto& entry : style.entries) {
60 std::cout << "\n ";
61 if (entry.key.name.isValid()) {
62 std::cout << entry.key.name.package << ":" << entry.key.name.entry;
63 }
64
65 if (entry.key.id.isValid()) {
66 std::cout << "(" << entry.key.id << ")";
67 }
68
69 std::cout << "=" << *entry.value;
70 }
71 }
72
73 void visit(const Array& array, ValueVisitorArgs&) override {
74 array.print(std::cout);
75 }
76
77 void visit(const Plural& plural, ValueVisitorArgs&) override {
78 plural.print(std::cout);
79 }
80
81 void visit(const Styleable& styleable, ValueVisitorArgs&) override {
82 styleable.print(std::cout);
83 }
84
85 void visitItem(const Item& item, ValueVisitorArgs& args) override {
86 item.print(std::cout);
87 }
88};
89
90void Debug::printTable(const std::shared_ptr<ResourceTable>& table) {
91 std::cout << "Package name=" << table->getPackage();
92 if (table->getPackageId() != ResourceTable::kUnsetPackageId) {
93 std::cout << " id=" << std::hex << table->getPackageId() << std::dec;
94 }
95 std::cout << std::endl;
96
97 for (const auto& type : *table) {
98 std::cout << " type " << type->type;
99 if (type->typeId != ResourceTableType::kUnsetTypeId) {
100 std::cout << " id=" << std::hex << type->typeId << std::dec;
101 }
102 std::cout << " entryCount=" << type->entries.size() << std::endl;
103
104 std::vector<const ResourceEntry*> sortedEntries;
105 for (const auto& entry : type->entries) {
106 auto iter = std::lower_bound(sortedEntries.begin(), sortedEntries.end(), entry.get(),
107 [](const ResourceEntry* a, const ResourceEntry* b) -> bool {
108 return a->entryId < b->entryId;
109 });
110 sortedEntries.insert(iter, entry.get());
111 }
112
113 for (const ResourceEntry* entry : sortedEntries) {
114 ResourceId id = { table->getPackageId(), type->typeId, entry->entryId };
115 ResourceName name = { table->getPackage(), type->type, entry->name };
116 std::cout << " spec resource " << id << " " << name;
117 if (entry->publicStatus.isPublic) {
118 std::cout << " PUBLIC";
119 }
120 std::cout << std::endl;
121
122 PrintVisitor visitor;
123 for (const auto& value : entry->values) {
124 std::cout << " (" << value.config << ") ";
125 value.value->accept(visitor, {});
126 std::cout << std::endl;
127 }
128 }
129 }
130}
131
132static size_t getNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) {
133 auto iter = std::lower_bound(names.begin(), names.end(), name);
134 assert(iter != names.end() && *iter == name);
135 return std::distance(names.begin(), iter);
136}
137
138void Debug::printStyleGraph(const std::shared_ptr<ResourceTable>& table) {
139 std::vector<ResourceName> names;
140 std::map<ResourceName, std::set<ResourceName>> graph;
141
142 for (const auto& type : *table) {
143 for (const auto& entry : type->entries) {
144 ResourceName name = { table->getPackage(), type->type, entry->name };
145 for (const auto& value : entry->values) {
146 visitFunc<Style>(*value.value, [&](const Style& style) {
147 if (style.parent.name.isValid()) {
148 names.push_back(style.parent.name);
149 names.push_back(name);
150 graph[style.parent.name].insert(name);
151 }
152 });
153 }
154 }
155 }
156
157 std::sort(names.begin(), names.end());
158 auto it1 = std::unique(names.begin(), names.end());
159 names.resize(std::distance(names.begin(), it1));
160
161 std::cout << "digraph styles {\n";
162
163 for (const auto& name : names) {
164 std::cout << " node_" << getNodeIndex(names, name)
165 << " [label=\"" << name.entry << "\"];\n";
166 }
167
168 for (const auto& entry : graph) {
169 const ResourceName& parent = entry.first;
170 size_t parentNodeIndex = getNodeIndex(names, parent);
171
172 for (const auto& childName : entry.second) {
173 std::cout << "node_" << getNodeIndex(names, childName) << " -> "
174 << "node_" << parentNodeIndex << ";\n";
175 }
176 }
177
178 std::cout << "}" << std::endl;
179}
180
181} // namespace aapt