Skip to content

Commit 45fa39d

Browse files
committed
Merge branch 'develop' of https://github.com/EvilBeaver/OneScript into develop
2 parents 376a3f1 + ab6cb7f commit 45fa39d

File tree

4 files changed

+206
-26
lines changed

4 files changed

+206
-26
lines changed

src/VSCode.DebugAdapter/DebugeeProcess.cs

Lines changed: 97 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal abstract class DebugeeProcess
2626
private bool _stdoutEOF;
2727
private bool _stderrEOF;
2828
private bool _attachMode;
29-
29+
3030
private Encoding _dapEncoding;
3131

3232
private OneScriptDebuggerClient _debugger;
@@ -41,9 +41,22 @@ public DebugeeProcess(PathHandlingStrategy pathHandling)
4141
{
4242
_strategy = pathHandling;
4343
}
44-
45-
public bool HasExited => _process?.HasExited ?? true;
46-
public int ExitCode => _process.ExitCode;
44+
45+
public bool HasExited
46+
{
47+
get
48+
{
49+
if (_process != null)
50+
return _process.HasExited;
51+
52+
if (_attachMode && _debugger != null)
53+
return false;
54+
55+
return true;
56+
}
57+
}
58+
59+
public int ExitCode => _process?.ExitCode ?? 0;
4760

4861
public int DebugPort { get; set; }
4962

@@ -56,14 +69,16 @@ public int ProtocolVersion
5669
_activeProtocolVersion = value;
5770
}
5871
}
59-
72+
6073
public bool WaitOnStart { get; set; }
6174

75+
public WorkspaceMapper PathsMapper { get; set; }
76+
6277
public void Start()
6378
{
6479
_process = CreateProcess();
6580
var psi = _process.StartInfo;
66-
81+
6782
psi.RedirectStandardError = true;
6883
psi.RedirectStandardOutput = true;
6984

@@ -83,21 +98,57 @@ public void Start()
8398
_process.BeginOutputReadLine();
8499
_process.BeginErrorReadLine();
85100
}
86-
101+
87102
public void InitAttached()
88103
{
89104
var pid = _debugger.GetProcessId();
90-
_process = Process.GetProcessById(pid);
105+
106+
try
107+
{
108+
_process = Process.GetProcessById(pid);
109+
_process.EnableRaisingEvents = true;
110+
_process.Exited += Process_Exited;
111+
}
112+
catch
113+
{
114+
_process = null;
115+
}
116+
91117
_attachMode = true;
92-
_process.EnableRaisingEvents = true;
93-
_process.Exited += Process_Exited;
118+
94119
}
95-
120+
96121
public void Init(JObject args)
97122
{
98123
InitInternal(args);
99124
}
100-
125+
126+
public void InitPathsMapper(JObject args)
127+
{
128+
if (args == null)
129+
{
130+
PathsMapper = null;
131+
return;
132+
}
133+
134+
try
135+
{
136+
var mappingToken = args["pathsMapping"];
137+
if (mappingToken == null || mappingToken.Type == JTokenType.Null)
138+
{
139+
PathsMapper = null;
140+
return;
141+
}
142+
143+
PathsMapper = mappingToken.ToObject<WorkspaceMapper>();
144+
}
145+
catch (Exception ex)
146+
{
147+
Log.Warning(ex, "Failed to initialize paths mapper; path mapping will be disabled");
148+
PathsMapper = null;
149+
}
150+
}
151+
101152
protected abstract Process CreateProcess();
102153

103154
protected abstract void InitInternal(JObject args);
@@ -106,12 +157,12 @@ protected string ConvertClientPathToDebugger(string clientPath)
106157
{
107158
return _strategy.ConvertClientPathToDebugger(clientPath);
108159
}
109-
160+
110161
protected void LoadEnvironment(ProcessStartInfo psi, IDictionary<string, string> variables)
111162
{
112163
if (variables == null || variables.Count <= 0)
113164
return;
114-
165+
115166
foreach (var pair in variables)
116167
{
117168
psi.EnvironmentVariables[pair.Key] = pair.Value;
@@ -128,7 +179,7 @@ protected void SetEncoding(string encodingFromOptions)
128179
{
129180
_dapEncoding = Utilities.GetEncodingFromOptions(encodingFromOptions);
130181
}
131-
182+
132183
Log.Information("Encoding for debuggee output is {Encoding}", _dapEncoding);
133184
}
134185

@@ -142,10 +193,10 @@ public void SetClient(OneScriptDebuggerClient service)
142193
_debugger = service;
143194
ProtocolVersion = service.ProtocolVersion;
144195
}
145-
196+
146197
public event EventHandler<DebugeeOutputEventArgs> OutputReceived;
147198
public event EventHandler ProcessExited;
148-
199+
149200
private void Process_Exited(object sender, EventArgs e)
150201
{
151202
_debugger?.Stop();
@@ -194,7 +245,7 @@ private void Terminate()
194245
{
195246
System.Threading.Thread.Sleep(100);
196247
}
197-
248+
198249
_terminated = true;
199250
_process = null;
200251
_debugger = null;
@@ -211,7 +262,7 @@ public void HandleDisconnect(bool terminate)
211262
_debugger.Disconnect(terminate);
212263

213264
var mustKill = terminate && !_attachMode;
214-
265+
215266
if (mustKill && _process != null && !_process.HasExited)
216267
{
217268
Log.Debug("Stopping child process...");
@@ -225,12 +276,15 @@ public void HandleDisconnect(bool terminate)
225276
Log.Debug("Process killed");
226277
}
227278
}
228-
279+
229280
Log.Debug("Debuggee disconnected");
230281
}
231282

232283
public void Kill()
233284
{
285+
if (_process == null)
286+
return;
287+
234288
_process.Kill();
235289
_process.WaitForExit(1500);
236290
}
@@ -259,30 +313,48 @@ public void SetExceptionsBreakpoints((string Id, string Condition)[] filters)
259313

260314
public Breakpoint[] SetBreakpoints(IEnumerable<Breakpoint> breakpoints)
261315
{
262-
var confirmedBreaks = _debugger.SetMachineBreakpoints(breakpoints.ToArray());
263-
316+
var breakpointsArray = breakpoints.ToArray();
317+
318+
if (PathsMapper != null)
319+
{
320+
for (int i = 0; i < breakpointsArray.Length; i++)
321+
{
322+
breakpointsArray[i].Source = PathsMapper.LocalToRemote(breakpointsArray[i].Source);
323+
}
324+
}
325+
326+
var confirmedBreaks = _debugger.SetMachineBreakpoints(breakpointsArray);
327+
264328
return confirmedBreaks;
265329
}
266330

267331
public void BeginExecution(int threadId)
268332
{
269333
_debugger.Execute(threadId);
270334
}
271-
335+
272336
public StackFrame[] GetStackTrace(int threadId, int firstFrameIdx, int limit)
273337
{
274338
var allFrames = _debugger.GetStackFrames(threadId);
275-
339+
var pathsMapperInit = PathsMapper != null;
340+
276341
if (limit == 0)
277342
limit = allFrames.Length;
278343

279-
if(allFrames.Length < firstFrameIdx)
344+
if (allFrames.Length < firstFrameIdx)
280345
return new StackFrame[0];
281346

282347
var result = new List<StackFrame>();
283348
for (int i = firstFrameIdx; i < limit && i < allFrames.Length; i++)
284349
{
350+
285351
allFrames[i].ThreadId = threadId;
352+
353+
if (pathsMapperInit)
354+
{
355+
allFrames[i].Source = PathsMapper.RemoteToLocal(allFrames[i].Source);
356+
}
357+
286358
result.Add(allFrames[i]);
287359
}
288360

src/VSCode.DebugAdapter/OscriptDebugSession.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public override void Initialize(Response response, dynamic args)
3535
LogCommandReceived();
3636
AdapterID = (string) args.adapterID;
3737

38-
_debuggee = DebugeeFactory.CreateProcess(AdapterID, PathStrategy);
38+
_debuggee = DebugeeFactory.CreateProcess(AdapterID, PathStrategy);
3939

4040
SendResponse(response, new Capabilities
4141
{
@@ -137,7 +137,9 @@ public override void Attach(Response response, dynamic arguments)
137137
{
138138
LogCommandReceived();
139139
SubscribeForDebuggeeProcessEvents();
140+
140141
_debuggee.DebugPort = GetFromContainer(arguments, "debugPort", 2801);
142+
_debuggee.InitPathsMapper(arguments);
141143

142144
DebugClientFactory debugClientFactory;
143145
try
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
using System;
8+
using System.Runtime.InteropServices;
9+
using Newtonsoft.Json;
10+
11+
namespace VSCode.DebugAdapter
12+
{
13+
public class WorkspaceMapper
14+
{
15+
16+
private Workspace _localWorkspace;
17+
private Workspace _remoteWorkspace;
18+
19+
[JsonProperty("localPath")]
20+
private string LocalPathForDeserialization
21+
{
22+
set { _localWorkspace = new Workspace(value ?? ""); }
23+
}
24+
25+
[JsonProperty("remotePath")]
26+
private string RemotePathForDeserialization
27+
{
28+
set { _remoteWorkspace = new Workspace(value ?? ""); }
29+
}
30+
31+
public WorkspaceMapper(){}
32+
33+
public WorkspaceMapper(string localPath, string remotePath) {
34+
35+
this._localWorkspace = new Workspace(localPath);
36+
this._remoteWorkspace = new Workspace(remotePath);
37+
}
38+
39+
public string LocalToRemote(string path)
40+
{
41+
return ConvertPath(path, _localWorkspace, _remoteWorkspace);
42+
}
43+
44+
public string RemoteToLocal(string path)
45+
{
46+
return ConvertPath(path, _remoteWorkspace, _localWorkspace);
47+
}
48+
49+
private string ConvertPath(string path, Workspace fromPrefix, Workspace toPrefix)
50+
{
51+
if (string.IsNullOrWhiteSpace(path) ||
52+
string.IsNullOrWhiteSpace(fromPrefix.Original) ||
53+
string.IsNullOrWhiteSpace(toPrefix.Original))
54+
return path;
55+
56+
var normalizedPath = path.Replace('\\', '/');
57+
var normalizedFrom = fromPrefix.Normalized;
58+
59+
var comparison = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
60+
? StringComparison.OrdinalIgnoreCase
61+
: StringComparison.Ordinal;
62+
63+
if (normalizedPath.StartsWith(toPrefix.Normalized, comparison) ||
64+
!normalizedPath.StartsWith(normalizedFrom, comparison))
65+
return path;
66+
67+
var relativePath = normalizedPath.Substring(normalizedFrom.Length).TrimStart('/');
68+
var result = toPrefix.Normalized + "/" + relativePath;
69+
70+
return result;
71+
}
72+
73+
}
74+
75+
internal class Workspace
76+
{
77+
public string Original;
78+
public string Normalized;
79+
80+
internal Workspace(string path)
81+
{
82+
this.Original = path;
83+
this.Normalized = path.Replace('\\', '/').TrimEnd('/');
84+
}
85+
86+
}
87+
88+
}

src/VSCode.DebugAdapter/package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,25 @@
132132
"type": "string",
133133
"description": "Кодировка вывода отлаживаемого приложения. Отладчик будет интерпретировать вывод приложения в указанной кодировке",
134134
"default": ""
135+
},
136+
"pathsMapping": {
137+
"type": "object",
138+
"description": "Сопоставление путей между локальной и удаленной машиной (для удаленной отладки)",
139+
"properties": {
140+
"localPath": {
141+
"type": "string",
142+
"description": "Путь к каталогу проекта на локальной машине.",
143+
"default": ""
144+
},
145+
"remotePath": {
146+
"type": "string",
147+
"description": "Путь к каталогу проекта на удаленной машине.",
148+
"default": ""
149+
}
150+
},
151+
"required": ["localPath", "remotePath"]
135152
}
153+
136154
}
137155
}
138156
}

0 commit comments

Comments
 (0)