Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Stedfast <jestedfa@microsoft.com>2019-05-14 19:27:45 +0300
committerJeffrey Stedfast <jestedfa@microsoft.com>2019-05-20 20:14:28 +0300
commit22e9afa19bbd85d24588876363b6f293760ee570 (patch)
tree914adc9f65d0e4a600c74d4e0e60b618cf5155ba /main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol
parent70ac70a3596b1fc5972510133fa700edecc49dd6 (diff)
[VSCodeDebugProtocol] Fix up the values used when creating ObjectValues to match Sdb/Cor backends
Diffstat (limited to 'main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol')
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs17
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs5
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs294
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeStackFrame.cs13
4 files changed, 296 insertions, 33 deletions
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs
index 4d92b280ba..be1189696e 100644
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs
@@ -109,10 +109,23 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
var source = new Source { Name = Path.GetFileName (fileName), Path = fileName };
var request = new GotoTargetsRequest (source, line) { Column = column };
var response = protocolClient.SendRequestSync (request);
- var target = response.Targets.FirstOrDefault (x => x.Line <= line && x.EndLine >= line && x.Column <= column && x.EndColumn >= column);
+ GotoTarget target = null;
+
+ foreach (var location in response.Targets) {
+ if (location.Line <= line && location.EndLine >= line && location.Column <= column && location.EndColumn >= column) {
+ // exact match for location
+ target = location;
+ break;
+ }
+
+ if (target == null) {
+ // closest match so far...
+ target = location;
+ }
+ }
if (target == null)
- throw new NotSupportedException ();
+ throw new NotImplementedException ();
protocolClient.SendRequestSync (new GotoRequest ((int) threadId, target.Id));
RaiseStopEvent ();
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs
index 28344c4949..9a7c611876 100644
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeBacktrace.cs
@@ -1,9 +1,12 @@
using System;
-using System.Collections.Generic;
using System.Linq;
+using System.Collections.Generic;
+
using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages;
+
using Mono.Debugging.Backend;
using Mono.Debugging.Client;
+
using VsFormat = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrameFormat;
namespace MonoDevelop.Debugger.VsCodeDebugProtocol
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs
index d98418ec98..19c8c4fa77 100644
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeObjectSource.cs
@@ -1,45 +1,280 @@
using System;
using System.Linq;
+using System.Text;
+using System.Globalization;
+
using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages;
+
using Mono.Debugging.Backend;
using Mono.Debugging.Client;
+using Mono.Debugging.Evaluation;
namespace MonoDevelop.Debugger.VsCodeDebugProtocol
{
class VSCodeObjectSource : IObjectValueSource
{
+ const VariablePresentationHint.AttributesValue ConstantReadOnlyStatic = VariablePresentationHint.AttributesValue.Constant | VariablePresentationHint.AttributesValue.ReadOnly | VariablePresentationHint.AttributesValue.Static;
+ static readonly char[] CommaDotOrSquareEndBracket = { ',', '.', ']' };
+ static readonly char[] CommaOrSquareEndBracket = { ',', ']' };
+ static readonly char[] LessThanOrSquareBracket = { '<', '[' };
- int parentVariablesReference;
- int variablesReference;
- int frameId;
- VSCodeDebuggerSession vsCodeDebuggerSession;
- ObjectValue [] objValChildren;
- readonly string name;
+ ObjectValue[] objValChildren;
+
+ readonly VSCodeDebuggerSession vsCodeDebuggerSession;
+ readonly int parentVariablesReference;
+ readonly ObjectValueFlags flags;
+ readonly int variablesReference;
+ readonly int frameId;
readonly string evalName;
+ readonly string display;
+ readonly string name;
readonly string type;
readonly string val;
+ static string GetActualTypeName (string type)
+ {
+ int startIndex;
+
+ if (type == null)
+ return string.Empty;
+
+ if ((startIndex = type.IndexOf (" {", StringComparison.Ordinal)) != -1) {
+ // The type is boxed. The string between the {}'s is the actual type name.
+ int endIndex = type.LastIndexOf ('}');
+
+ startIndex += 2;
+
+ if (endIndex > startIndex)
+ return type.Substring (startIndex, endIndex - startIndex);
+ }
+
+ return type;
+ }
+
+ static string GetFixedVariableName (string name)
+ {
+ // Check for a type attribute and strip it off.
+ var index = name.LastIndexOf (" [", StringComparison.Ordinal);
+
+ if (index != -1)
+ return name.Remove (index);
+
+ return name;
+ }
+
+ static bool IsMultiDimensionalArray (string type, out int arrayIndexer)
+ {
+ int index = type.IndexOfAny (LessThanOrSquareBracket);
+
+ arrayIndexer = -1;
+
+ if (index == -1)
+ return false;
+
+ if (type[index] == '<') {
+ int depth = 1;
+
+ index++;
+ while (index < type.Length && depth > 0) {
+ switch (type[index++]) {
+ case '<': depth++; break;
+ case '>': depth--; break;
+ }
+ }
+
+ if (index >= type.Length || type[index] != '[')
+ return false;
+ }
+
+ arrayIndexer = index++;
+
+ return index < type.Length && type[index] == ',';
+ }
+
+ // Note: displayType will often have spaces after commas
+ string GetFixedValue (string value, string canonType, string displayType)
+ {
+ int arrayIndex;
+
+ if (IsMultiDimensionalArray (displayType, out arrayIndex)) {
+ var arrayType = displayType.Substring (0, arrayIndex);
+ var prefix = $"{{{arrayType}[";
+
+ if (value.StartsWith (prefix, StringComparison.Ordinal)) {
+ var compacted = new StringBuilder (prefix.Replace (", ", ","));
+ int index = prefix.Length;
+
+ while (index < value.Length) {
+ int endIndex = value.IndexOfAny (CommaDotOrSquareEndBracket, index);
+ string number;
+
+ if (endIndex == -1)
+ return value;
+
+ if (endIndex + 1 < value.Length && value[endIndex] == '.' && value[endIndex + 1] == '.') {
+ int min, max;
+
+ number = value.Substring (index, endIndex - index);
+
+ if (!int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out min))
+ return value;
+
+ index = endIndex + 2;
+
+ if ((endIndex = value.IndexOfAny (CommaOrSquareEndBracket, index)) == -1)
+ return value;
+
+ number = value.Substring (index, endIndex - index);
+
+ if (!int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out max))
+ return value;
+
+ compacted.Append (((max - min) + 1).ToString (CultureInfo.InvariantCulture));
+ } else {
+ compacted.Append (value, index, endIndex - index);
+ }
+
+ compacted.Append (value[endIndex]);
+ index = endIndex + 1;
+
+ if (value[endIndex] == ']')
+ break;
+
+ if (index < value.Length && value[index] == ' ')
+ index++;
+ }
+
+ compacted.Append ('}');
+
+ return compacted.ToString ();
+ }
+ } else if (canonType == "char") {
+ int startIndex = value.IndexOf ('\'');
+
+ if (startIndex != -1)
+ return value.Substring (startIndex);
+ } else {
+ var request = new EvaluateRequest ($"typeof ({displayType}).IsEnum") { FrameId = frameId };
+ var result = vsCodeDebuggerSession.protocolClient.SendRequestSync (request);
+
+ if (result.Result.Equals ("true", StringComparison.OrdinalIgnoreCase)) {
+ int endIndex = value.IndexOf (" | ", StringComparison.Ordinal);
+
+ if (endIndex != -1) {
+ // The value a bitwise-or'd set of enum values
+ var expanded = new StringBuilder ();
+ int index = 0;
+
+ while (index < value.Length) {
+ endIndex = value.IndexOf (" | ", index, StringComparison.Ordinal);
+ string enumValue;
+
+ if (endIndex != -1)
+ enumValue = value.Substring (index, endIndex - index);
+ else if (index > 0)
+ enumValue = value.Substring (index);
+ else
+ enumValue = value;
+
+ expanded.Append (canonType).Append ('.').Append (enumValue);
+
+ if (endIndex == -1)
+ break;
+
+ expanded.Append (" | ");
+ index = endIndex + 3;
+ }
+
+ return expanded.ToString ();
+ }
+
+ return canonType + "." + value;
+ }
+ }
+
+ return value;
+ }
+
+ static bool IsCSError (int code, string message, string value, out string newValue)
+ {
+ var prefix = string.Format (CultureInfo.InvariantCulture, "error CS{0:D4}: '", code);
+
+ newValue = null;
+
+ if (value == null || !value.StartsWith (prefix, StringComparison.Ordinal))
+ return false;
+
+ int startIndex = prefix.Length;
+ int index = startIndex;
+
+ while (index < value.Length && value[index] != '\'')
+ index++;
+
+ newValue = value.Substring (startIndex, index - startIndex);
+ index++;
+
+ if (index >= value.Length || value[index] != ' ')
+ return false;
+
+ index++;
+
+ if (index + message.Length != value.Length)
+ return false;
+
+ return string.CompareOrdinal (value, index, message, 0, message.Length) == 0;
+ }
public VSCodeObjectSource (VSCodeDebuggerSession vsCodeDebuggerSession, int variablesReference, int parentVariablesReference, string name, string type, string evalName, int frameId, string val)
{
- this.type = type ?? string.Empty;
- this.frameId = frameId;
- this.evalName = evalName;
- var indexOfType = name.LastIndexOf (" [", StringComparison.Ordinal);
- if (indexOfType != -1)
- name = name.Remove (indexOfType);
- this.name = name;
this.vsCodeDebuggerSession = vsCodeDebuggerSession;
- this.variablesReference = variablesReference;
this.parentVariablesReference = parentVariablesReference;
- this.val = val;
+ this.variablesReference = variablesReference;
+ this.evalName = evalName;
+ this.frameId = frameId;
+
+ if (type == null) {
+ if (IsCSError (118, "is a namespace but is used like a variable", val, out string ns)) {
+ this.display = this.name = this.val = ns;
+ this.flags = ObjectValueFlags.Namespace;
+ this.type = "<namespace>";
+ return;
+ }
+
+ if (IsCSError (119, "is a type, which is not valid in the given context", val, out string vtype)) {
+ if (name.StartsWith ("global::", StringComparison.Ordinal))
+ vtype = name.Substring ("global::".Length);
+
+ this.display = this.name = this.val = ObjectValueAdaptor.GetCSharpTypeName (vtype);
+ this.flags = ObjectValueFlags.Type;
+ this.type = "<type>";
+ return;
+ }
+ }
+
+ var actualType = GetActualTypeName (type);
+
+ this.flags = parentVariablesReference > 0 ? ObjectValueFlags.None : ObjectValueFlags.ReadOnly;
+ this.type = actualType.Replace (", ", ",");
+ this.name = GetFixedVariableName (name);
+
+ if (actualType != "void")
+ this.val = GetFixedValue (val, this.type, actualType);
+ else
+ this.val = "No return value.";
+ this.display = val;
+
+ if (this.name[0] == '[')
+ flags |= ObjectValueFlags.ArrayElement;
+
+ if (type == null || val == $"'{this.name}' threw an exception of type '{this.type}'")
+ flags |= ObjectValueFlags.Error;
}
- public ObjectValue [] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+ public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
{
if (objValChildren == null) {
if (variablesReference <= 0) {
- objValChildren = new ObjectValue [0];
+ objValChildren = new ObjectValue[0];
} else {
using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) {
var children = vsCodeDebuggerSession.protocolClient.SendRequestSync (new VariablesRequest (
@@ -82,27 +317,30 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
public object GetRawValue (ObjectPath path, EvaluationOptions options)
{
- string val = null;
+ string rawValue = null;
+
using (var timer = vsCodeDebuggerSession.EvaluationStats.StartTimer ()) {
- val = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (evalName) { FrameId = frameId }).Result;
+ rawValue = vsCodeDebuggerSession.protocolClient.SendRequestSync (new EvaluateRequest (evalName) { FrameId = frameId }).Result;
timer.Success = true;
}
- if (val.StartsWith ("\"", StringComparison.Ordinal))
+
+ if (rawValue.StartsWith ("\"", StringComparison.Ordinal)) {
if (options.ChunkRawStrings)
- return new RawValueString (new RawString (val));
- else
- return val.Remove (val.Length - 1).Remove (0, 1);
- else
- throw new NotImplementedException ();
+ return new RawValueString (new RawString (rawValue));
+
+ return rawValue.Substring (1, rawValue.Length - 2);
+ }
+
+ throw new NotImplementedException ();
}
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
{
if (val == "null")
- return ObjectValue.CreateNullObject (this, name, type, parentVariablesReference > 0 ? ObjectValueFlags.None : ObjectValueFlags.ReadOnly);
+ return ObjectValue.CreateNullObject (this, name, type, flags);
if (variablesReference == 0)//This is some kind of primitive...
- return ObjectValue.CreatePrimitive (this, new ObjectPath (name), type, new EvaluationResult (val), parentVariablesReference > 0 ? ObjectValueFlags.None : ObjectValueFlags.ReadOnly);
- return ObjectValue.CreateObject (this, new ObjectPath (name), type, new EvaluationResult (val), parentVariablesReference > 0 ? ObjectValueFlags.None : ObjectValueFlags.ReadOnly, null);
+ return ObjectValue.CreatePrimitive (this, new ObjectPath (name), type, new EvaluationResult (val, display), flags);
+ return ObjectValue.CreateObject (this, new ObjectPath (name), type, new EvaluationResult (val, display), flags, null);
}
public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeStackFrame.cs b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeStackFrame.cs
index 833ab92c89..09930da9ee 100644
--- a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeStackFrame.cs
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VsCodeStackFrame.cs
@@ -1,7 +1,11 @@
using System;
using System.Linq;
+
using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages;
+
using Mono.Debugging.Client;
+
+using VsStackFrame = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrame;
using VsFormat = Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrameFormat;
namespace MonoDevelop.Debugger.VsCodeDebugProtocol
@@ -33,14 +37,19 @@ namespace MonoDevelop.Debugger.VsCodeDebugProtocol
return null;
}
+ static SourceLocation GetSourceLocation (VsStackFrame frame)
+ {
+ return new SourceLocation (frame.Name, frame.Source?.Path, frame.Line, frame.Column, frame.EndLine ?? -1, frame.EndColumn ?? -1, GetHashBytes (frame.Source));
+ }
+
VsFormat format;
readonly int threadId;
readonly int frameIndex;
internal readonly int frameId;
string fullStackframeText;
- public VsCodeStackFrame (VsFormat format, int threadId, int frameIndex, Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages.StackFrame frame)
- : base (0, new SourceLocation (frame.Name, frame.Source?.Path, frame.Line, frame.Column, frame.EndLine ?? -1, frame.EndColumn ?? -1, GetHashBytes (frame.Source)), GetLanguage (frame.Source?.Path))
+ public VsCodeStackFrame (VsFormat format, int threadId, int frameIndex, VsStackFrame frame)
+ : base (0, GetSourceLocation (frame), GetLanguage (frame.Source?.Path))
{
this.format = format;
this.threadId = threadId;