Skip to content

Commit

Permalink
Merge branch 'master' into release/v2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Harry committed Jul 21, 2021
2 parents 3f03913 + 396364e commit 7d56b25
Show file tree
Hide file tree
Showing 19 changed files with 168 additions and 95 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning">
<Version>3.4.205</Version>
<Version>3.4.220</Version>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
Expand Down
56 changes: 29 additions & 27 deletions src/adapter3/DebugAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,16 @@ private class DebugViewArguments : DebugRequestArguments
public string DebugView { get; set; } = string.Empty;
}

private readonly DebugSessionFactory sessionFactory;
private readonly Action<LogCategory, string> logger;
private readonly bool trace;
private readonly DebugView defaultDebugView;
private IDebugSession? session;

public DebugAdapter(DebugSessionFactory sessionFactory,
System.IO.Stream @in,
public DebugAdapter(System.IO.Stream @in,
System.IO.Stream @out,
Action<LogCategory, string>? logger,
bool trace,
DebugView defaultDebugView)
{
this.sessionFactory = sessionFactory;
this.logger = logger ?? ((_, __) => { });
this.trace = trace;
this.defaultDebugView = defaultDebugView;

InitializeProtocolClient(@in, @out);
Expand All @@ -62,13 +56,10 @@ private void Log(string message, LogCategory category = LogCategory.DebugAdapter

protected override InitializeResponse HandleInitializeRequest(InitializeArguments arguments)
{
Protocol.SendEvent(new InitializedEvent());

return new InitializeResponse()
{
SupportsEvaluateForHovers = true,
SupportsExceptionInfoRequest = true,
SupportsStepBack = trace,
ExceptionBreakpointFilters = new List<ExceptionBreakpointsFilter>
{
new ExceptionBreakpointsFilter(
Expand All @@ -87,27 +78,38 @@ protected override InitializeResponse HandleInitializeRequest(InitializeArgument
};
}

protected override LaunchResponse HandleLaunchRequest(LaunchArguments arguments)
protected override void HandleLaunchRequestAsync(IRequestResponder<LaunchArguments> responder)
{
// since CreateDebugSession is an async method, we should be using HandleLaunchRequestAsync.
// However, using HandleLaunchRequestAsync causes VSCode to send setBreakpoints and
// threads request before receiving the launch response.

try
{
if (session != null) throw new InvalidOperationException();

session = sessionFactory(arguments, Protocol.SendEvent, defaultDebugView)
.GetAwaiter().GetResult();
session.Start();

return new LaunchResponse();
}
catch (Exception ex)
if (session != null)
{
var ex = new InvalidOperationException();
Log(ex.Message, LogCategory.DebugAdapterOutput);
throw new ProtocolException(ex.Message, ex);
responder.SetError(new ProtocolException(ex.Message, ex));
return;
}

LaunchConfigParser.CreateDebugSessionAsync(responder.Arguments, Protocol.SendEvent, defaultDebugView)
.ContinueWith(t =>
{
if (t.IsCompletedSuccessfully)
{
session = t.Result;
session.Start();
Protocol.SendEvent(new InitializedEvent());
responder.SetResponse(new LaunchResponse());
}
else
{
if (t.Exception != null)
{
responder.SetError(new ProtocolException(t.Exception.Message, t.Exception));
}
else
{
responder.SetError(new ProtocolException($"Unknown error in {nameof(LaunchConfigParser.CreateDebugSessionAsync)}"));
}
}
});
}

private void HandleDebugViewRequest(DebugViewArguments arguments)
Expand Down
12 changes: 6 additions & 6 deletions src/adapter3/DebugApplicationEngine.ExecutionContextAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ private class ExecutionContextAdapter : IExecutionContext
public ExecutionContextAdapter(ExecutionContext context, IDictionary<UInt160, UInt160> scriptIdMap)
{
this.context = context;
this.ScriptIdentifier = context.GetScriptHash();
this.ScriptHash = context.GetScriptHash();

if (scriptIdMap.TryGetValue(this.ScriptIdentifier, out var scriptHash))
if (scriptIdMap.TryGetValue(this.ScriptHash, out var scriptHash))
{
this.ScriptHash = scriptHash;
this.ScriptIdentifier = scriptHash;
}
else
{
this.ScriptHash = Neo.SmartContract.Helper.ToScriptHash(context.Script);
scriptIdMap[this.ScriptIdentifier] = this.ScriptHash;
this.ScriptIdentifier = Neo.SmartContract.Helper.ToScriptHash(context.Script);
scriptIdMap[this.ScriptHash] = this.ScriptIdentifier;
}
}

Expand All @@ -43,8 +43,8 @@ public ExecutionContextAdapter(ExecutionContext context, IDictionary<UInt160, UI

public Script Script => context.Script;

public UInt160 ScriptIdentifier { get; }
public UInt160 ScriptHash { get; }
public UInt160 ScriptIdentifier { get; }

static IReadOnlyList<StackItem> Coalese(Neo.VM.Slot? slot) => (slot == null) ? Array.Empty<StackItem>() : slot;
}
Expand Down
3 changes: 3 additions & 0 deletions src/adapter3/DebugApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using Neo;
using Neo.BlockchainToolkit.Persistence;
using Neo.BlockchainToolkit.SmartContract;
Expand Down Expand Up @@ -42,6 +43,8 @@ public override void Dispose()
base.Dispose();
}

bool IApplicationEngine.SupportsStepBack => false;

private void OnNotify(object? sender, NotifyEventArgs args)
{
var name = GetContractName(args.ScriptHash);
Expand Down
30 changes: 20 additions & 10 deletions src/adapter3/DebugSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ public DebugSession(IApplicationEngine engine, IReadOnlyList<DebugInfo> debugInf

this.engine.DebugNotify += OnNotify;
this.engine.DebugLog += OnLog;

if (engine.SupportsStepBack)
{
sendEvent(new CapabilitiesEvent
{
Capabilities = new Capabilities { SupportsStepBack = true }
});
}
}

private void OnNotify(object? sender, (UInt160 scriptHash, string scriptName, string eventName, NeoArray state) args)
Expand Down Expand Up @@ -78,7 +86,7 @@ private bool TryGetScript(UInt160 scriptHash, [MaybeNullWhen(false)] out Neo.VM.

foreach (var context in engine.InvocationStack)
{
if (scriptHash == context.ScriptHash)
if (scriptHash == context.ScriptIdentifier)
{
script = context.Script;
return true;
Expand Down Expand Up @@ -114,9 +122,9 @@ public IEnumerable<StackFrame> GetStackFrames(StackTraceArguments args)

foreach (var (context, index) in engine.InvocationStack.Select((c, i) => (c, i)))
{
var scriptId = context.ScriptIdentifier;
var scriptId = context.ScriptHash;
DebugInfo.Method? method = null;
if (debugInfoMap.TryGetValue(context.ScriptHash, out var debugInfo))
if (debugInfoMap.TryGetValue(context.ScriptIdentifier, out var debugInfo))
{
method = debugInfo.GetMethod(context.InstructionPointer);
}
Expand Down Expand Up @@ -179,7 +187,7 @@ public IEnumerable<StackFrame> GetStackFrames(StackTraceArguments args)
public IEnumerable<Scope> GetScopes(ScopesArguments args)
{
var context = engine.InvocationStack.ElementAt(args.FrameId);
var scriptId = context.ScriptIdentifier;
var scriptId = context.ScriptHash;

if (disassemblyView)
{
Expand All @@ -191,12 +199,13 @@ public IEnumerable<Scope> GetScopes(ScopesArguments args)
}
else
{
var debugInfo = debugInfoMap.TryGetValue(context.ScriptHash, out var _debugInfo) ? _debugInfo : null;
var debugInfo = debugInfoMap.TryGetValue(context.ScriptIdentifier, out var _debugInfo) ? _debugInfo : null;
var container = new ExecutionContextContainer(context, debugInfo);
yield return AddScope("Variables", container);
}

yield return AddScope("Storage", engine.GetStorageContainer(scriptId));
yield return AddScope("Engine", new EngineContainer(engine));

Scope AddScope(string name, IVariableContainer container)
{
Expand Down Expand Up @@ -232,7 +241,7 @@ public SourceResponse GetSource(SourceArguments arguments)
{
if (text.StartsWith(STORAGE_PREFIX))
{
var container = engine.GetStorageContainer(context.ScriptIdentifier);
var container = engine.GetStorageContainer(context.ScriptHash);
var storage = container.Evaluate(text);
return (storage.item, ContractParameterType.Any, storage.remaining);
}
Expand All @@ -249,7 +258,7 @@ public SourceResponse GetSource(SourceArguments arguments)
if (TryEvaluateIndexedSlot(name, STATIC_SLOTS_PREFIX, context.StaticFields, out item)) return (item, ContractParameterType.Any, remaining);
}

if (debugInfoMap.TryGetValue(context.ScriptHash, out var debugInfo))
if (debugInfoMap.TryGetValue(context.ScriptIdentifier, out var debugInfo))
{
if (TryEvaluateNamedSlot(context.StaticFields, debugInfo.StaticVariables, name, out var result))
{
Expand Down Expand Up @@ -547,6 +556,7 @@ private void Step(Func<int, bool> compareStepDepth, bool stepBack = false)
output += $" Contract Exception: {engine.FaultException.InnerException.Message} [{engine.FaultException.InnerException.GetType().Name}]\n";
}
}
output += $"Gas Consumed: {engine.GasConsumedAsBigDecimal}\n";

sendEvent(new OutputEvent()
{
Expand All @@ -565,7 +575,7 @@ private void Step(Func<int, bool> compareStepDepth, bool stepBack = false)
sendEvent(new OutputEvent()
{
Category = OutputEvent.CategoryValue.Stdout,
Output = $"Return: {result}\n",
Output = $"Gas Consumed: {engine.GasConsumedAsBigDecimal}\nReturn: {result}\n",
});
}
sendEvent(new ExitedEvent());
Expand Down Expand Up @@ -608,7 +618,7 @@ private void Step(Func<int, bool> compareStepDepth, bool stepBack = false)
}
}

if (breakpointManager.CheckBreakpoint(engine.CurrentContext?.ScriptIdentifier ?? UInt160.Zero, engine.CurrentContext?.InstructionPointer))
if (breakpointManager.CheckBreakpoint(engine.CurrentContext?.ScriptHash ?? UInt160.Zero, engine.CurrentContext?.InstructionPointer))
{
FireStoppedEvent(StoppedEvent.ReasonValue.Breakpoint);
break;
Expand All @@ -627,7 +637,7 @@ bool CheckSequencePoint()
if (engine.CurrentContext != null)
{
var ip = engine.CurrentContext.InstructionPointer;
if (debugInfoMap.TryGetValue(engine.CurrentContext.ScriptHash, out var info))
if (debugInfoMap.TryGetValue(engine.CurrentContext.ScriptIdentifier, out var info))
{
var methods = info.Methods;
for (int i = 0; i < methods.Count; i++)
Expand Down
22 changes: 14 additions & 8 deletions src/adapter3/DisassemblyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
Expand Down Expand Up @@ -57,7 +58,7 @@ public DisassemblyManager(TryGetScript tryGetScript, TryGetDebugInfo tryGetDebug
}

public Disassembly GetDisassembly(IExecutionContext context, DebugInfo? debugInfo)
=> GetDisassembly(context.ScriptHash, context.Script, debugInfo);
=> GetDisassembly(context.ScriptIdentifier, context.Script, debugInfo);

public Disassembly GetDisassembly(UInt160 scriptHash, Script script, DebugInfo? debugInfo)
=> disassemblies.GetOrAdd(scriptHash.GetHashCode(), sourceRef => ToDisassembly(sourceRef, scriptHash, script, debugInfo));
Expand Down Expand Up @@ -86,7 +87,7 @@ static Disassembly ToDisassembly(int sourceRef, UInt160 scriptHash, Script scrip
var lineMapBuilder = ImmutableDictionary.CreateBuilder<int, int>();

var documents = debugInfo?.Documents
.Select(path => (fileName: System.IO.Path.GetFileName(path), lines: System.IO.File.ReadAllLines(path)))
.Select(path => (fileName: Path.GetFileName(path), lines: File.Exists(path) ? File.ReadAllLines(path) : Array.Empty<string>()))
.ToImmutableList() ?? ImmutableList<(string, string[])>.Empty;
var methodStarts = debugInfo?.Methods.ToImmutableDictionary(m => m.Range.Start)
?? ImmutableDictionary<int, DebugInfo.Method>.Empty;
Expand All @@ -112,14 +113,19 @@ static Disassembly ToDisassembly(int sourceRef, UInt160 scriptHash, Script scrip
&& sp.Document < documents.Count)
{
var doc = documents[sp.Document];
var srcLine = doc.lines[sp.Start.line - 1].Substring(sp.Start.column - 1);
if (sp.Start.line == sp.End.line)
if (doc.lines.Length > sp.Start.line - 1)
{
srcLine = srcLine.Substring(0, sp.End.column - sp.Start.column);
}
var srcLine = doc.lines[sp.Start.line - 1];

sourceBuilder.AppendLine($"# Code {doc.fileName} line {sp.Start.line}: \"{srcLine}\"");
line++;
if (sp.Start.column > 1) srcLine = srcLine.Substring(sp.Start.column - 1);
if (sp.Start.line == sp.End.line && sp.End.column > sp.Start.column)
{
srcLine = srcLine.Substring(0, sp.End.column - sp.Start.column);
}

sourceBuilder.AppendLine($"# Code {doc.fileName} line {sp.Start.line}: \"{srcLine.Trim()}\"");
line++;
}
}

AddSource(sourceBuilder, instructions[i].address, instructions[i].instruction, padString);
Expand Down
14 changes: 13 additions & 1 deletion src/adapter3/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,22 @@ static JObject MapToJson(Neo.VM.Types.Map map)
var json = new JObject();
foreach (var (key, value) in map)
{
json.Add(key.GetString() ?? throw new Exception(), value.ToJson());
json.Add(PrimitiveTypeToString(key), value.ToJson());
}
return json;
}

static string PrimitiveTypeToString(Neo.VM.Types.PrimitiveType item)
{
try
{
return item.GetString() ?? throw new Exception();
}
catch
{
return Convert.ToHexString(item.GetSpan());
}
}
}

// public static string? TryConvert(this StackItem item, CastOperation typeHint = CastOperation.None)
Expand Down
3 changes: 3 additions & 0 deletions src/adapter3/IApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ internal interface IApplicationEngine : IDisposable
bool TryGetContract(UInt160 scriptHash, [MaybeNullWhen(false)] out Script script);
StorageContainerBase GetStorageContainer(UInt160 scriptHash);

bool SupportsStepBack { get; }
byte AddressVersion { get; }
IReadOnlyCollection<IExecutionContext> InvocationStack { get; }
IExecutionContext? CurrentContext { get; }
IReadOnlyList<StackItem> ResultStack { get; }
long GasConsumed { get; }
BigDecimal GasConsumedAsBigDecimal => new BigDecimal((System.Numerics.BigInteger)GasConsumed, Neo.SmartContract.Native.NativeContract.GAS.Decimals);
Exception? FaultException { get; }
VMState State { get; }
bool AtStart { get; }
Expand Down
2 changes: 1 addition & 1 deletion src/adapter3/IExecutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ internal interface IExecutionContext
{
Instruction CurrentInstruction { get; }
int InstructionPointer { get; }
UInt160 ScriptIdentifier { get; }
UInt160 ScriptHash { get; }
UInt160 ScriptIdentifier { get; }
Script Script { get; }
IReadOnlyList<StackItem> EvaluationStack { get; }
IReadOnlyList<StackItem> LocalVariables { get; }
Expand Down
Loading

0 comments on commit 7d56b25

Please sign in to comment.