1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "tooling/client/manager/variable_manager.h" 17 18#include <iomanip> 19 20#include "common/log_wrapper.h" 21 22using PtJson = panda::ecmascript::tooling::PtJson; 23namespace OHOS::ArkCompiler::Toolchain { 24void TreeNode::AddChild(std::unique_ptr<PropertyDescriptor> descriptor) 25{ 26 children.push_back(std::make_unique<TreeNode>(std::move(descriptor))); 27} 28 29void TreeNode::AddChild(DescriptorMap descriptorMap) 30{ 31 children.push_back(std::make_unique<TreeNode>(std::move(descriptorMap))); 32} 33 34void TreeNode::AddChild(std::unique_ptr<TreeNode> child) 35{ 36 children.push_back(std::move(child)); 37} 38 39void TreeNode::Print(int depth) const 40{ 41 int actualIndent = 0; 42 if (depth > 1) { 43 actualIndent = (depth - 1) * 4; // 4: four spaces 44 } 45 std::string indent(actualIndent, ' '); 46 47 if (std::holds_alternative<int32_t>(data)) { 48 std::cout << indent << "CallFrameId: " << std::get<int32_t>(data) << std::endl; 49 } else if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(data)) { 50 const auto& outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(data); 51 for (const auto& [key, innerMap] : outerMap) { 52 for (const auto& [innerKey, value] : innerMap) { 53 std::cout << key << ". " << value << std::endl; 54 } 55 } 56 } else if (std::holds_alternative<std::unique_ptr<PropertyDescriptor>>(data)) { 57 const auto &descriptor = std::get<std::unique_ptr<PropertyDescriptor>>(data); 58 if (descriptor && descriptor->GetValue()) { 59 if (descriptor->GetValue()->HasDescription()) { 60 std::cout << indent << " " << descriptor->GetName() << " = " 61 << descriptor->GetValue()->GetDescription() << std::endl; 62 } else { 63 std::cout << indent << " " << descriptor->GetName() << " = " 64 << descriptor->GetValue()->GetType() << std::endl; 65 } 66 } 67 } else if (std::holds_alternative<DescriptorMap>(data)) { 68 const auto &descriptorMap = std::get<DescriptorMap>(data); 69 for (const auto& [key, descriptor] : descriptorMap) { 70 std::cout << indent << key << ". "; 71 if (descriptor && descriptor->GetValue()) { 72 std::cout << descriptor->GetName() << " = " << descriptor->GetValue()->GetDescription() << std::endl; 73 } 74 } 75 } 76 77 for (const auto &child : children) { 78 child->Print(depth + 1); 79 } 80} 81 82Tree::Tree(const std::map<int32_t, std::map<int32_t, std::string>>& dataMap, int32_t index) 83{ 84 root_ = std::make_unique<TreeNode>(index); 85 86 auto it = dataMap.find(index); 87 if (it != dataMap.end()) { 88 for (const auto& [key, value] : it->second) { 89 std::map<int32_t, std::map<int32_t, std::string>> childData; 90 childData[index_] = {{key, value}}; 91 root_->children.push_back(std::make_unique<TreeNode>(childData)); 92 index_++; 93 } 94 } 95} 96 97void Tree::PrintRootAndImmediateChildren() const 98{ 99 if (std::holds_alternative<int32_t>(root_->data)) { 100 std::cout << "CallFrame ID: " << std::get<int32_t>(root_->data) << std::endl; 101 } 102 103 for (const auto& child : root_->children) { 104 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(child->data)) { 105 const auto& outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(child->data); 106 for (const auto& [index, innerMap] : outerMap) { 107 std::cout << " Index: " << index << std::endl; 108 for (const auto& [objectId, type] : innerMap) { 109 std::cout << " Object ID: " << objectId << ", Type: " << type << std::endl; 110 } 111 } 112 } 113 } 114} 115 116void Tree::Clear() 117{ 118 if (root_ != nullptr) { 119 root_.reset(); 120 } 121} 122 123void Tree::Print() const 124{ 125 if (root_) { 126 root_->Print(); 127 } 128} 129 130TreeNode* Tree::FindNodeWithObjectId(int32_t objectId) const 131{ 132 return FindNodeWithObjectIdRecursive(root_.get(), objectId); 133} 134 135void Tree::AddVariableNode(TreeNode* parentNode, std::unique_ptr<PropertyDescriptor> descriptor) 136{ 137 if (!parentNode) { 138 return; 139 } 140 parentNode->AddChild(std::move(descriptor)); 141} 142 143void Tree::AddObjectNode(TreeNode* parentNode, std::unique_ptr<PropertyDescriptor> descriptor) 144{ 145 if (!parentNode) { 146 return; 147 } 148 DescriptorMap descriptorMap; 149 descriptorMap[index_] = std::move(descriptor); 150 parentNode->AddChild(std::move(descriptorMap)); 151 index_++; 152} 153 154TreeNode* Tree::GetRoot() const 155{ 156 return root_.get(); 157} 158 159TreeNode* Tree::FindNodeWithObjectIdRecursive(TreeNode* node, int32_t objectId) const 160{ 161 if (!node) { 162 return nullptr; 163 } 164 165 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(node->data)) { 166 const auto& outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(node->data); 167 for (const auto& [key, innerMap] : outerMap) { 168 if (innerMap.find(objectId) != innerMap.end()) { 169 return node; 170 } 171 } 172 } else if (std::holds_alternative<DescriptorMap>(node->data)) { 173 const auto& descriptorMap = std::get<DescriptorMap>(node->data); 174 for (const auto& [key, descriptor] : descriptorMap) { 175 if (descriptor && descriptor->GetValue() && descriptor->GetValue()->GetObjectId() == objectId) { 176 return node; 177 } 178 } 179 } 180 181 for (const auto& child : node->children) { 182 TreeNode* foundNode = FindNodeWithObjectIdRecursive(child.get(), objectId); 183 if (foundNode) { 184 return foundNode; 185 } 186 } 187 188 return nullptr; 189} 190 191TreeNode* Tree::FindNodeWithInnerKeyZero(TreeNode* node) const 192{ 193 if (!node) { 194 return nullptr; 195 } 196 197 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(node->data)) { 198 const auto &outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(node->data); 199 for (const auto &innerMapPair : outerMap) { 200 if (innerMapPair.second.find(0) != innerMapPair.second.end()) { 201 return node; 202 } 203 } 204 } 205 206 for (const auto &child : node->children) { 207 TreeNode* foundNode = FindNodeWithInnerKeyZero(child.get()); 208 if (foundNode) { 209 return foundNode; 210 } 211 } 212 213 return nullptr; 214} 215TreeNode* Tree::FindNodeWithCondition() const 216{ 217 return FindNodeWithInnerKeyZero(root_.get()); 218} 219 220int32_t Tree::FindObjectByIndex(int32_t index) const 221{ 222 return FindObjectByIndexRecursive(root_.get(), index); 223} 224 225int32_t Tree::FindObjectByIndexRecursive(const TreeNode* node, int32_t index) const 226{ 227 if (!node) { 228 return 0; 229 } 230 231 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(node->data)) { 232 const auto &outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(node->data); 233 auto it = outerMap.find(index); 234 if (it != outerMap.end() && !it->second.empty()) { 235 return it->second.begin()->first; 236 } 237 } else if (std::holds_alternative<DescriptorMap>(node->data)) { 238 const auto &descriptorMap = std::get<DescriptorMap>(node->data); 239 auto it = descriptorMap.find(index); 240 if (it != descriptorMap.end() && it->second && it->second->GetValue()) { 241 return it->second->GetValue()->GetObjectId(); 242 } 243 } 244 245 for (const auto& child : node->children) { 246 int32_t result = FindObjectByIndexRecursive(child.get(), index); 247 if (result != 0) { 248 return result; 249 } 250 } 251 252 return 0; 253} 254 255void VariableManager::SetHeapUsageInfo(std::unique_ptr<GetHeapUsageReturns> heapUsageReturns) 256{ 257 heapUsageInfo_.SetUsedSize(heapUsageReturns->GetUsedSize()); 258 heapUsageInfo_.SetTotalSize(heapUsageReturns->GetTotalSize()); 259} 260 261void VariableManager::ShowHeapUsageInfo() const 262{ 263 std::cout << std::endl; 264 std::cout << "UsedSize is: " << heapUsageInfo_.GetUsedSize() << std::endl; 265 std::cout << "TotalSize is: " << std::fixed << std::setprecision(0) << heapUsageInfo_.GetTotalSize() << std::endl; 266} 267 268void VariableManager::ShowVariableInfos() const 269{ 270 variableInfo_.Print(); 271} 272 273void VariableManager::ClearVariableInfo() 274{ 275 variableInfo_.Clear(); 276} 277void VariableManager::InitializeTree(std::map<int32_t, std::map<int32_t, std::string>> dataMap, int index) 278{ 279 variableInfo_ = Tree(dataMap, index); 280} 281 282void VariableManager::PrintVariableInfo() 283{ 284 variableInfo_.Print(); 285} 286 287TreeNode* VariableManager::FindNodeWithObjectId(int32_t objectId) 288{ 289 return variableInfo_.FindNodeWithObjectId(objectId); 290} 291 292void VariableManager::AddVariableInfo(TreeNode *parentNode, std::unique_ptr<PropertyDescriptor> variableInfo) 293{ 294 if (variableInfo && variableInfo->GetValue() && variableInfo->GetValue()->HasObjectId()) { 295 variableInfo_.AddObjectNode(parentNode, std::move(variableInfo)); 296 } else { 297 variableInfo_.AddVariableNode(parentNode, std::move(variableInfo)); 298 } 299} 300 301TreeNode* VariableManager::FindNodeObjectZero() 302{ 303 return variableInfo_.FindNodeWithCondition(); 304} 305 306int32_t VariableManager::FindObjectIdWithIndex(int index) 307{ 308 return variableInfo_.FindObjectByIndex(index); 309} 310 311void VariableManager::Printinfo() const 312{ 313 variableInfo_.PrintRootAndImmediateChildren(); 314} 315}