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
21 using PtJson = panda::ecmascript::tooling::PtJson;
22 using Result = panda::ecmascript::tooling::Result;
23 namespace OHOS::ArkCompiler::Toolchain {
SendRequeSource(int scriptId)24 void 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
EnableReply(const std::unique_ptr<PtJson> json)45 void 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
SetFileName(int scriptId,const std::string & fileName)84 void 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
GetFileName()90 void 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
SetFileSource(int scriptIdIndex,const std::string & fileSource)99 void 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
GetFileSource(int scriptId)123 std::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
GetDebugSources(const std::unique_ptr<PtJson> json)137 void 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
ListSourceCodeWithParameters(int startLine,int endLine)178 void 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
ListSource(int startLine,int endLine)230 void 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
GetListSource(std::string startLine,std::string endLine)260 void 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 }