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