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/source_manager.h" 17 18#include "common/log_wrapper.h" 19#include "tooling/client/session/session.h" 20 21using PtJson = panda::ecmascript::tooling::PtJson; 22using Result = panda::ecmascript::tooling::Result; 23namespace OHOS::ArkCompiler::Toolchain { 24void SourceManager::SendRequeSource(int scriptId) 25{ 26 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 27 uint32_t id = session->GetMessageId(); 28 scriptIdMap_.emplace(std::make_pair(id, scriptId)); 29 30 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 31 request->Add("id", id); 32 request->Add("method", "Debugger.getScriptSource"); 33 34 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 35 params->Add("scriptId", std::to_string(scriptId).c_str()); 36 request->Add("params", params); 37 38 std::string message = request->Stringify(); 39 if (session->ClientSendReq(message)) { 40 session->GetDomainManager().SetDomainById(id, "Debugger"); 41 } 42 return; 43} 44 45void SourceManager::EnableReply(const std::unique_ptr<PtJson> json) 46{ 47 if (json == nullptr) { 48 LOGE("arkdb: json parse error"); 49 return; 50 } 51 52 if (!json->IsObject()) { 53 LOGE("arkdb: json parse format error"); 54 json->ReleaseRoot(); 55 return; 56 } 57 58 std::unique_ptr<PtJson> params; 59 Result ret = json->GetObject("params", ¶ms); 60 if (ret != Result::SUCCESS) { 61 LOGE("arkdb: find params error"); 62 return; 63 } 64 65 std::string scriptIdStr; 66 ret = params->GetString("scriptId", &scriptIdStr); 67 if (ret != Result::SUCCESS) { 68 LOGE("arkdb: find scriptId error"); 69 return; 70 } 71 72 std::string fileName; 73 ret = params->GetString("url", &fileName); 74 if (ret != Result::SUCCESS) { 75 LOGE("arkdb: find fileName error"); 76 return; 77 } 78 int scriptId = std::atoi(scriptIdStr.c_str()); 79 SetFileName(scriptId, fileName); 80 SendRequeSource(scriptId); 81 return; 82} 83 84void SourceManager::SetFileName(int scriptId, const std::string& fileName) 85{ 86 fileSource_.insert(std::make_pair(scriptId, std::make_pair(fileName, std::vector<std::string> {}))); 87 return; 88} 89 90void SourceManager::GetFileName() 91{ 92 for (auto it = fileSource_.begin(); it != fileSource_.end(); it++) { 93 std::cout << "scriptID : " << it->first; 94 std::cout << " fileName : " << it->second.first <<std::endl; 95 } 96 return; 97} 98 99void SourceManager::SetFileSource(int scriptIdIndex, const std::string& fileSource) 100{ 101 const int IGNOR_NEWLINE_FLAG = 2; 102 auto scriptIdIt = scriptIdMap_.find(scriptIdIndex); 103 if (scriptIdIt == scriptIdMap_.end()) { 104 return; 105 } 106 int scriptId = scriptIdIt->second; 107 108 auto it = fileSource_.find(scriptId); 109 if (it != fileSource_.end() && it->second.second.empty()) { 110 std::string::size_type startPos = 0; 111 std::string::size_type endPos = fileSource.find("\r\n"); 112 while (endPos != std::string::npos) { 113 std::string line = fileSource.substr(startPos, endPos - startPos); 114 it->second.second.push_back(line); 115 startPos = endPos + IGNOR_NEWLINE_FLAG; // ignore "\r\n" 116 endPos = fileSource.find("\r\n", startPos); 117 } 118 it->second.second.push_back(fileSource.substr(startPos)); 119 } 120 return; 121} 122 123std::vector<std::string> SourceManager::GetFileSource(int scriptId) 124{ 125 int linNum = 0; 126 auto it = fileSource_.find(scriptId); 127 if (it != fileSource_.end()) { 128 std::cout << "fileSource : " <<std::endl; 129 for (const std::string& value : it->second.second) { 130 std::cout << ++linNum << " " << value << std::endl; 131 } 132 return it->second.second; 133 } 134 return std::vector<std::string> {}; 135} 136 137void SourceManager::GetDebugSources(const std::unique_ptr<PtJson> json) 138{ 139 std::string funcName; 140 Result ret = json->GetString("functionName", &funcName); 141 if (ret != Result::SUCCESS) { 142 LOGE("arkdb: get functionName error"); 143 return; 144 } 145 146 std::unique_ptr<PtJson> location; 147 ret = json->GetObject("location", &location); 148 if (ret != Result::SUCCESS) { 149 LOGE("arkdb: get location error"); 150 return; 151 } 152 153 std::string scriptIdStr; 154 ret = location->GetString("scriptId", &scriptIdStr); 155 if (ret != Result::SUCCESS) { 156 LOGE("arkdb: get scriptId error"); 157 return; 158 } 159 scriptId_ = std::atoi(scriptIdStr.c_str()); 160 161 ret = location->GetInt("lineNumber", &debugLineNum_); 162 if (ret != Result::SUCCESS) { 163 LOGE("arkdb: get lineNumber error"); 164 return; 165 } 166 167 LOGE("arkdb: callFrames : funcName %{public}s, scriptid %{public}s, lineNum %{public}d", 168 funcName.c_str(), scriptIdStr.c_str(), debugLineNum_); 169 auto it = fileSource_.find(scriptId_); 170 if (it != fileSource_.end()) { 171 std::cout << (debugLineNum_ + 1) << " " << it->second.second[debugLineNum_] << std::endl; 172 std::cout << ">>> "; 173 fflush(stdout); 174 } 175 return; 176} 177 178void SourceManager::ListSourceCodeWithParameters(int startLine, int endLine) 179{ 180 const int BLANK_LINE = std::numeric_limits<int>::max(); 181 const int STATR_LINE_OFFSET = 6; 182 const int END_LINE_OFFSET = 4; 183 const int END_LINE = 10; 184 if (startLine != BLANK_LINE && endLine == BLANK_LINE) { 185 auto it = fileSource_.find(scriptId_); 186 if (it == fileSource_.end()) { 187 LOGE("arkdb: get file source error"); 188 return; 189 } 190 if (startLine >= static_cast<int>(it->second.second.size()) + STATR_LINE_OFFSET || 191 startLine < 0) { 192 std::cout << "Line number out of range, this file has " << 193 static_cast<int>(it->second.second.size()) << " lines" << std::endl; 194 return; 195 } 196 int showLine = startLine - STATR_LINE_OFFSET; 197 if (showLine < 0) { 198 showLine = 0; 199 endLine = END_LINE; 200 } else { 201 endLine = startLine + END_LINE_OFFSET; 202 } 203 if (endLine > static_cast<int>(it->second.second.size())) { 204 endLine = static_cast<int>(it->second.second.size()); 205 } 206 for (; showLine < endLine; showLine++) { 207 std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl; 208 } 209 } else if (startLine != BLANK_LINE && endLine != BLANK_LINE) { 210 auto it = fileSource_.find(scriptId_); 211 if (it == fileSource_.end()) { 212 LOGE("arkdb: get file source error"); 213 return; 214 } 215 if (startLine > static_cast<int>(it->second.second.size()) || 216 endLine > static_cast<int>(it->second.second.size()) || startLine < 1) { 217 std::cout << "Line number out of range, this file has " << 218 static_cast<int>(it->second.second.size()) << " lines" << std::endl; 219 return; 220 } 221 if (endLine > static_cast<int>(it->second.second.size())) { 222 endLine = static_cast<int>(it->second.second.size()); 223 } 224 for (int showLine = startLine - 1; showLine < endLine; showLine++) { 225 std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl; 226 } 227 } 228} 229 230void SourceManager::ListSource(int startLine, int endLine) 231{ 232 const int BLANK_LINE = std::numeric_limits<int>::max(); 233 const int STATR_LINE_OFFSET = 6; 234 const int END_LINE_OFFSET = 4; 235 const int END_LINE = 10; 236 if (startLine == BLANK_LINE && endLine == BLANK_LINE) { 237 auto it = fileSource_.find(scriptId_); 238 if (it == fileSource_.end()) { 239 LOGE("arkdb: get file source error"); 240 return; 241 } 242 int showLine = (debugLineNum_ + 1) - STATR_LINE_OFFSET; 243 if (showLine < 0) { 244 showLine = 0; 245 endLine = END_LINE; 246 } else { 247 endLine = debugLineNum_ + END_LINE_OFFSET; 248 } 249 if (endLine > static_cast<int>(it->second.second.size())) { 250 endLine = static_cast<int>(it->second.second.size()); 251 } 252 for (; showLine <= endLine; showLine++) { 253 std::cout << (showLine + 1) << " " << it->second.second[showLine] << std::endl; 254 } 255 } else { 256 ListSourceCodeWithParameters(startLine, endLine); 257 } 258} 259 260void SourceManager::GetListSource(std::string startLine, std::string endLine) 261{ 262 const int BLANK_LINE = std::numeric_limits<int>::max(); 263 int startline = startLine.empty() ? BLANK_LINE : std::stoi(startLine); 264 int endline = endLine.empty() ? BLANK_LINE : std::stoi(endLine); 265 ListSource(startline, endline); 266 return; 267} 268}