Mono.Debugging
This commit is contained in:
parent
592ef8f783
commit
f2faa957b7
|
|
@ -0,0 +1,154 @@
|
|||
// DissassemblyBuffer.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public abstract class DissassemblyBuffer
|
||||
{
|
||||
List<AssemblyLine> lines = new List<AssemblyLine> ();
|
||||
int baseIndex = 0;
|
||||
long baseAddress;
|
||||
|
||||
const int AddrPerLine = 4;
|
||||
const int ExtraDownLines = 5;
|
||||
const int ExtraUpLines = 20;
|
||||
|
||||
public DissassemblyBuffer (long baseAddress)
|
||||
{
|
||||
this.baseAddress = baseAddress;
|
||||
}
|
||||
|
||||
public AssemblyLine[] GetLines (int firstIndex, int lastIndex)
|
||||
{
|
||||
//Console.WriteLine ("pp GET LINES: " + firstIndex + " " + lastIndex + " " + baseIndex);
|
||||
|
||||
if (lastIndex >= 0)
|
||||
FillDown (lastIndex);
|
||||
if (firstIndex < 0)
|
||||
FillUp (firstIndex);
|
||||
|
||||
AssemblyLine[] array = new AssemblyLine [lastIndex - firstIndex + 1];
|
||||
lines.CopyTo (baseIndex + firstIndex, array, 0, lastIndex - firstIndex + 1);
|
||||
return array;
|
||||
}
|
||||
|
||||
public void FillUp (int targetLine)
|
||||
{
|
||||
if (baseIndex + targetLine >= 0)
|
||||
return;
|
||||
|
||||
// Lines we are missing
|
||||
int linesReq = -(baseIndex + targetLine);
|
||||
|
||||
//Console.WriteLine ("pp FILLUP: " + linesReq);
|
||||
|
||||
// Last known valid address
|
||||
long lastAddr = lines.Count > 0 ? lines [0].Address : baseAddress;
|
||||
|
||||
// Addresses we are going to query to get the required lines
|
||||
long addr = lastAddr - (linesReq + ExtraUpLines) * AddrPerLine; // 4 is just a guess
|
||||
|
||||
int lastCount = 0;
|
||||
bool limitFound = false;
|
||||
AssemblyLine[] alines;
|
||||
do {
|
||||
alines = GetLines (addr, lastAddr);
|
||||
if (alines.Length <= lastCount) {
|
||||
limitFound = true;
|
||||
break;
|
||||
}
|
||||
addr -= (linesReq + ExtraUpLines - alines.Length) * AddrPerLine;
|
||||
lastCount = alines.Length;
|
||||
}
|
||||
while (alines.Length < linesReq + ExtraUpLines);
|
||||
|
||||
int max = limitFound ? alines.Length : alines.Length - ExtraUpLines;
|
||||
if (max < 0) max = 0;
|
||||
|
||||
// Fill the lines
|
||||
for (int n=0; n < max; n++)
|
||||
lines.Insert (n, alines [n + (alines.Length - max)]);
|
||||
|
||||
long firstAddr = lines [0].Address;
|
||||
for (int n=0; n < (linesReq - max); n++) {
|
||||
AssemblyLine line = new AssemblyLine (--firstAddr, "");
|
||||
lines.Insert (0, line);
|
||||
max++;
|
||||
}
|
||||
baseIndex += max;
|
||||
}
|
||||
|
||||
public void FillDown (int targetLine)
|
||||
{
|
||||
if (baseIndex + targetLine < lines.Count)
|
||||
return;
|
||||
|
||||
// Lines we are missing
|
||||
int linesReq = (baseIndex + targetLine) - lines.Count + 1;
|
||||
|
||||
//Console.WriteLine ("pp FILLDOWN: " + linesReq);
|
||||
|
||||
// Last known valid address
|
||||
long lastAddr = lines.Count > 0 ? lines [lines.Count - 1].Address : baseAddress;
|
||||
|
||||
// Addresses we are going to query to get the required lines
|
||||
long addr = lastAddr + (linesReq + ExtraDownLines) * AddrPerLine; // 4 is just a guess
|
||||
|
||||
int lastCount = 0;
|
||||
bool limitFound = false;
|
||||
AssemblyLine[] alines;
|
||||
do {
|
||||
alines = GetLines (lastAddr, addr);
|
||||
if (alines.Length <= lastCount) {
|
||||
limitFound = true;
|
||||
break;
|
||||
}
|
||||
addr += (linesReq + ExtraDownLines - alines.Length) * AddrPerLine;
|
||||
lastCount = alines.Length;
|
||||
}
|
||||
while (alines.Length < linesReq + ExtraDownLines);
|
||||
|
||||
int max = limitFound ? alines.Length : alines.Length - ExtraDownLines;
|
||||
|
||||
// Fill the lines
|
||||
for (int n=0; n < max; n++)
|
||||
lines.Add (alines [n]);
|
||||
|
||||
lastAddr = lines [lines.Count - 1].Address;
|
||||
for (int n=0; n < (linesReq - max); n++) {
|
||||
AssemblyLine line = new AssemblyLine (++lastAddr, "");
|
||||
lines.Add (line);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract AssemblyLine[] GetLines (long startAddr, long endAddr);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// EvaluationResult.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez <lluis@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
|
||||
[Serializable]
|
||||
public class EvaluationResult
|
||||
{
|
||||
public EvaluationResult (string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public EvaluationResult (string value, string displayValue)
|
||||
{
|
||||
Value = value;
|
||||
DisplayValue = displayValue;
|
||||
}
|
||||
|
||||
public string Value { get; private set; }
|
||||
public string DisplayValue { get; private set; }
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
VisualPascalABCNETLinux/MonoDebugging/Backend/IBacktrace.cs
Normal file
20
VisualPascalABCNETLinux/MonoDebugging/Backend/IBacktrace.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IBacktrace: IDebuggerBackendObject
|
||||
{
|
||||
int FrameCount { get; }
|
||||
StackFrame[] GetStackFrames (int firstIndex, int lastIndex);
|
||||
ObjectValue[] GetLocalVariables (int frameIndex, EvaluationOptions options);
|
||||
ObjectValue[] GetParameters (int frameIndex, EvaluationOptions options);
|
||||
ObjectValue GetThisReference (int frameIndex, EvaluationOptions options);
|
||||
ExceptionInfo GetException (int frameIndex, EvaluationOptions options);
|
||||
ObjectValue[] GetAllLocals (int frameIndex, EvaluationOptions options);
|
||||
ObjectValue[] GetExpressionValues (int frameIndex, string[] expressions, EvaluationOptions options);
|
||||
CompletionData GetExpressionCompletionData (int frameIndex, string exp);
|
||||
AssemblyLine[] Disassemble (int frameIndex, int firstLine, int count);
|
||||
ValidationResult ValidateExpression (int frameIndex, string expression, EvaluationOptions options);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// IDebuggerBackendObject.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez <lluis@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IDebuggerBackendObject
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// IDebuggerSession.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IDebuggerSessionFrontend
|
||||
{
|
||||
void NotifyTargetEvent (TargetEventArgs args);
|
||||
void NotifyTargetOutput (bool isStderr, string line);
|
||||
void NotifyDebuggerOutput (bool isStderr, string line);
|
||||
void BindSourceFileBreakpoints (string fullFilePath);
|
||||
void UnbindSourceFileBreakpoints (string fullFilePath);
|
||||
|
||||
// To be called when the process is ready to run.
|
||||
void NotifyStarted ();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// IObjectValueSource.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IObjectValueSource: IDebuggerBackendObject
|
||||
{
|
||||
ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options);
|
||||
EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options);
|
||||
ObjectValue GetValue (ObjectPath path, EvaluationOptions options);
|
||||
|
||||
object GetRawValue (ObjectPath path, EvaluationOptions options);
|
||||
void SetRawValue (ObjectPath path, object value, EvaluationOptions options);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// IObjectValueUpdateCallback.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
internal interface IObjectValueUpdateCallback
|
||||
{
|
||||
void UpdateValue (ObjectValue newValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// IObjectValueUpdater.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IObjectValueUpdater: IDebuggerBackendObject
|
||||
{
|
||||
void RegisterUpdateCallbacks (UpdateCallback[] callbacks);
|
||||
}
|
||||
}
|
||||
39
VisualPascalABCNETLinux/MonoDebugging/Backend/IRawValue.cs
Normal file
39
VisualPascalABCNETLinux/MonoDebugging/Backend/IRawValue.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// IRawValue.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez <lluis@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IRawValue: IDebuggerBackendObject
|
||||
{
|
||||
object CallMethod (string name, object[] parameters, EvaluationOptions options);
|
||||
object CallMethod (string name, object[] parameters, out object[] outArgs, EvaluationOptions options);
|
||||
object GetMemberValue (string name, EvaluationOptions options);
|
||||
void SetMemberValue (string name, object value, EvaluationOptions options);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// IRawValueArray.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez <lluis@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IRawValueArray: IDebuggerBackendObject
|
||||
{
|
||||
object GetValue (int[] index);
|
||||
Array GetValues (int[] index, int count);
|
||||
void SetValue (int[] index, object value);
|
||||
int[] Dimensions { get; }
|
||||
Array ToArray ();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// IRawValueString.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez <lluis@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
public interface IRawValueString: IDebuggerBackendObject
|
||||
{
|
||||
string Substring (int index, int length);
|
||||
string Value { get; }
|
||||
int Length { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// UpdateCallback.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Backend
|
||||
{
|
||||
[Serializable]
|
||||
public class UpdateCallback
|
||||
{
|
||||
ObjectPath path;
|
||||
IObjectValueUpdateCallback callback;
|
||||
|
||||
internal UpdateCallback ()
|
||||
{
|
||||
}
|
||||
|
||||
internal UpdateCallback (IObjectValueUpdateCallback callback, ObjectPath path)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public ObjectPath Path {
|
||||
get { return path; }
|
||||
}
|
||||
|
||||
internal IObjectValueUpdateCallback Callback {
|
||||
get {
|
||||
return callback;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateValue (ObjectValue newValue)
|
||||
{
|
||||
try {
|
||||
callback.UpdateValue (newValue);
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
133
VisualPascalABCNETLinux/MonoDebugging/Client/Assembly.cs
Normal file
133
VisualPascalABCNETLinux/MonoDebugging/Client/Assembly.cs
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
//
|
||||
// Assembly.cs
|
||||
//
|
||||
// Author:
|
||||
// Jonathan Chang <t-jochang@microsoft.com>
|
||||
//
|
||||
// Copyright (c) 2022
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the assembly loaded during the debugging session.
|
||||
/// </summary>
|
||||
public class Assembly
|
||||
{
|
||||
public Assembly (string name, string path, bool optimized, bool userCode, string symbolStatus, string symbolFile, int? order, string version, string timestamp, string address, string process, string appdomain, long? processId, bool hasSymbol = false, bool isDynamic = false)
|
||||
{
|
||||
Name = name;
|
||||
Path = path;
|
||||
Optimized = optimized;
|
||||
SymbolStatus = symbolStatus;
|
||||
SymbolFile = symbolFile;
|
||||
Order = order.GetValueOrDefault (-1);
|
||||
TimeStamp = timestamp;
|
||||
Address = address;
|
||||
Process = process;
|
||||
AppDomain = appdomain;
|
||||
Version = version;
|
||||
UserCode = userCode;
|
||||
ProcessId = processId;
|
||||
IsDynamic = isDynamic;
|
||||
HasSymbols = hasSymbol;
|
||||
}
|
||||
|
||||
public Assembly (string path)
|
||||
{
|
||||
Path = path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the name of the assembly.
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the local path of the assembly is loaded from.
|
||||
/// </summary>
|
||||
public string Path { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows if the assembly has been optimized, true if the assembly is optimized.
|
||||
/// </summary>
|
||||
public bool Optimized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows if the assembly is considered 'user code' by a debugger that supports 'Just My Code'.True if it's considered.
|
||||
/// </summary>
|
||||
public bool UserCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the Description on if symbols were found for the assembly (ex: 'Symbols Loaded', 'Symbols not found', etc.
|
||||
/// </summary>
|
||||
public string SymbolStatus { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the Logical full path to the symbol file. The exact definition is implementation defined.
|
||||
/// </summary>
|
||||
public string SymbolFile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the order in which the assembly was loaded.
|
||||
/// </summary>
|
||||
public int Order { get; private set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the version of assembly.
|
||||
/// </summary>
|
||||
public string Version { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the time when the assembly was built in the units of UNIX timestamp formatted as a 64-bit unsigned decimal number in a string.
|
||||
/// </summary>
|
||||
public string TimeStamp { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the Address where the assembly was loaded as a 64-bit unsigned decimal number.
|
||||
/// </summary>
|
||||
public string Address { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represent the process name and process ID the assembly is loaded.
|
||||
/// </summary>
|
||||
public string Process { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represent the name of the AppDomain where the assembly is loaded.
|
||||
/// </summary>
|
||||
public string AppDomain { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represent the process ID the assembly is loaded.
|
||||
/// </summary>
|
||||
public long? ProcessId { get; private set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the assembly has symbol file. Mainly use for mono project.
|
||||
/// </summary>
|
||||
public bool HasSymbols { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the assembly is a dynamic. Mainly use for mono project.
|
||||
/// </summary>
|
||||
public bool IsDynamic { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// AssemblyEventArg.cs
|
||||
//
|
||||
// Author:
|
||||
// Matt Ward <matt.ward@microsoft.com>
|
||||
//
|
||||
// Copyright (c) 2018 Microsoft
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class AssemblyEventArgs : EventArgs
|
||||
{
|
||||
public AssemblyEventArgs (Assembly assembly)
|
||||
{
|
||||
Location = assembly.Path;
|
||||
Assembly = assembly;
|
||||
}
|
||||
|
||||
public AssemblyEventArgs (string location)
|
||||
{
|
||||
Location = location;
|
||||
Assembly = new Assembly (location);
|
||||
}
|
||||
|
||||
public string Location {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public Assembly Assembly {
|
||||
get; private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
VisualPascalABCNETLinux/MonoDebugging/Client/AssemblyLine.cs
Normal file
90
VisualPascalABCNETLinux/MonoDebugging/Client/AssemblyLine.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// AssemblyLine.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class AssemblyLine
|
||||
{
|
||||
long address;
|
||||
string code;
|
||||
int sourceLine;
|
||||
string addressSpace;
|
||||
|
||||
public string Code {
|
||||
get {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
public long Address {
|
||||
get {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
public string AddressSpace {
|
||||
get {
|
||||
return addressSpace;
|
||||
}
|
||||
}
|
||||
|
||||
public int SourceLine {
|
||||
get {
|
||||
return sourceLine;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOutOfRange {
|
||||
get { return address == -1 && code == null; }
|
||||
}
|
||||
|
||||
public static readonly AssemblyLine OutOfRange = new AssemblyLine (-1, null, null);
|
||||
|
||||
public AssemblyLine (long address, string code): this (address, "", code, -1)
|
||||
{
|
||||
}
|
||||
|
||||
public AssemblyLine (long address, string code, int sourceLine): this (address, "", code, sourceLine)
|
||||
{
|
||||
}
|
||||
|
||||
public AssemblyLine (long address, string addressSpace, string code): this (address, addressSpace, code, -1)
|
||||
{
|
||||
}
|
||||
|
||||
public AssemblyLine (long address, string addressSpace, string code, int sourceLine)
|
||||
{
|
||||
this.address = address;
|
||||
this.code = code;
|
||||
this.sourceLine = sourceLine;
|
||||
this.addressSpace = addressSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
VisualPascalABCNETLinux/MonoDebugging/Client/Backtrace.cs
Normal file
76
VisualPascalABCNETLinux/MonoDebugging/Client/Backtrace.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class Backtrace
|
||||
{
|
||||
IBacktrace serverBacktrace;
|
||||
int count;
|
||||
|
||||
[NonSerialized]
|
||||
DebuggerSession session;
|
||||
|
||||
List<StackFrame> frames;
|
||||
|
||||
public Backtrace (IBacktrace serverBacktrace)
|
||||
{
|
||||
this.serverBacktrace = serverBacktrace;
|
||||
|
||||
count = serverBacktrace.FrameCount;
|
||||
|
||||
// Get first frame, which is most used(for thread location)
|
||||
if (count > 0)
|
||||
GetFrame (0, 1);
|
||||
}
|
||||
|
||||
internal void Attach (DebuggerSession debuggerSession)
|
||||
{
|
||||
session = debuggerSession;
|
||||
serverBacktrace = session.WrapDebuggerObject (serverBacktrace);
|
||||
|
||||
if (frames != null) {
|
||||
foreach (var frame in frames) {
|
||||
frame.Attach (debuggerSession);
|
||||
frame.SourceBacktrace = serverBacktrace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DebuggerSession DebuggerSession {
|
||||
get { return session; }
|
||||
}
|
||||
|
||||
public int FrameCount {
|
||||
get { return count; }
|
||||
}
|
||||
|
||||
public StackFrame GetFrame (int n)
|
||||
{
|
||||
return GetFrame (n, 20);
|
||||
}
|
||||
|
||||
StackFrame GetFrame (int index, int fetchMultipleCount)
|
||||
{
|
||||
if (frames == null)
|
||||
frames = new List<StackFrame>();
|
||||
|
||||
if (index >= frames.Count) {
|
||||
var stackFrames = serverBacktrace.GetStackFrames (frames.Count, index + fetchMultipleCount);
|
||||
foreach (var frame in stackFrames) {
|
||||
frame.SourceBacktrace = serverBacktrace;
|
||||
frame.Index = frames.Count;
|
||||
frames.Add (frame);
|
||||
frame.Attach (session);
|
||||
}
|
||||
}
|
||||
|
||||
if (frames.Count > 0)
|
||||
return frames[Math.Min (Math.Max (0, index), frames.Count - 1)];
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
398
VisualPascalABCNETLinux/MonoDebugging/Client/BreakEvent.cs
Normal file
398
VisualPascalABCNETLinux/MonoDebugging/Client/BreakEvent.cs
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
// BreakEvent.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class BreakEvent
|
||||
{
|
||||
bool breakIfConditionChanges;
|
||||
string conditionExpression;
|
||||
string lastConditionValue;
|
||||
|
||||
[NonSerialized] BreakpointStore store;
|
||||
[NonSerialized] bool enabled = true;
|
||||
|
||||
HitAction hitAction = HitAction.Break;
|
||||
string customActionId;
|
||||
string traceExpression;
|
||||
int hitCount;
|
||||
string lastTraceValue;
|
||||
|
||||
public BreakEvent ()
|
||||
{
|
||||
}
|
||||
|
||||
internal BreakEvent (XmlElement elem, string baseDir)
|
||||
{
|
||||
string s = elem.GetAttribute ("enabled");
|
||||
if (s.Length > 0)
|
||||
bool.TryParse (s, out enabled);
|
||||
s = elem.GetAttribute ("hitAction");
|
||||
if (s.Length > 0)
|
||||
Enum.TryParse<HitAction> (s, out hitAction);
|
||||
s = elem.GetAttribute ("customActionId");
|
||||
if (s.Length > 0)
|
||||
customActionId = s;
|
||||
s = elem.GetAttribute ("traceExpression");
|
||||
if (s.Length > 0)
|
||||
traceExpression = s;
|
||||
s = elem.GetAttribute ("hitCountMode");
|
||||
HitCountMode mode;
|
||||
if (s.Length > 0 && Enum.TryParse<HitCountMode> (s, out mode))
|
||||
HitCountMode = mode;
|
||||
s = elem.GetAttribute ("hitCount");
|
||||
if (s.Length > 0)
|
||||
int.TryParse (s, out hitCount);
|
||||
|
||||
// this is to facilitate backward compatibility
|
||||
if (hitCount > 0 && HitCountMode == HitCountMode.None)
|
||||
HitCountMode = HitCountMode.GreaterThan;
|
||||
|
||||
s = elem.GetAttribute ("conditionExpression");
|
||||
if (!string.IsNullOrEmpty (s))
|
||||
conditionExpression = s;
|
||||
|
||||
s = elem.GetAttribute ("breakIfConditionChanges");
|
||||
if (!string.IsNullOrEmpty (s) && !bool.TryParse (s, out breakIfConditionChanges))
|
||||
breakIfConditionChanges = false;
|
||||
}
|
||||
|
||||
internal virtual XmlElement ToXml (XmlDocument doc, string baseDir)
|
||||
{
|
||||
XmlElement elem = doc.CreateElement (GetType().Name);
|
||||
if (!enabled)
|
||||
elem.SetAttribute ("enabled", "false");
|
||||
if ((hitAction & HitAction.Break) == HitAction.None)
|
||||
elem.SetAttribute ("hitAction", hitAction.ToString ());
|
||||
if (!string.IsNullOrEmpty (customActionId))
|
||||
elem.SetAttribute ("customActionId", customActionId);
|
||||
if (!string.IsNullOrEmpty (traceExpression))
|
||||
elem.SetAttribute ("traceExpression", traceExpression);
|
||||
if (HitCountMode != HitCountMode.None)
|
||||
elem.SetAttribute ("hitCountMode", HitCountMode.ToString ());
|
||||
if (hitCount > 0)
|
||||
elem.SetAttribute ("hitCount", hitCount.ToString ());
|
||||
if (!string.IsNullOrEmpty (conditionExpression)) {
|
||||
elem.SetAttribute ("conditionExpression", conditionExpression);
|
||||
if (breakIfConditionChanges)
|
||||
elem.SetAttribute ("breakIfConditionChanges", "True");
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
internal static BreakEvent FromXml (XmlElement elem, string baseDir)
|
||||
{
|
||||
if (elem.Name == "FunctionBreakpoint")
|
||||
return new FunctionBreakpoint (elem, baseDir);
|
||||
if (elem.Name == "Breakpoint")
|
||||
return new Breakpoint (elem, baseDir);
|
||||
if (elem.Name == "Catchpoint")
|
||||
return new Catchpoint (elem, baseDir);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="Mono.Debugging.Client.BreakEvent"/> is enabled.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// Changes in this property are automatically applied. There is no need to call CommitChanges().
|
||||
/// </remarks>
|
||||
public bool Enabled {
|
||||
get {
|
||||
return enabled;
|
||||
}
|
||||
set {
|
||||
if (store != null && store.IsReadOnly)
|
||||
return;
|
||||
bool previous = enabled;
|
||||
enabled = value;
|
||||
if (store != null)
|
||||
store.EnableBreakEvent (this, previous, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status of the break event
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The status of the break event for the given debug session
|
||||
/// </returns>
|
||||
/// <param name='session'>
|
||||
/// Session for which to get the status of the break event
|
||||
/// </param>
|
||||
public BreakEventStatus GetStatus (DebuggerSession session)
|
||||
{
|
||||
if (store == null || session == null)
|
||||
return BreakEventStatus.Disconnected;
|
||||
return session.GetBreakEventStatus (this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a message describing the status of the break event
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The status message of the break event for the given debug session
|
||||
/// </returns>
|
||||
/// <param name='session'>
|
||||
/// Session for which to get the status message of the break event
|
||||
/// </param>
|
||||
public string GetStatusMessage (DebuggerSession session)
|
||||
{
|
||||
if (store == null || session == null)
|
||||
return string.Empty;
|
||||
return session.GetBreakEventStatusMessage (this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the expression to be traced when the breakpoint is hit
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this break event is hit and the HitAction is TraceExpression, the debugger
|
||||
/// will evaluate and print the value of this property.
|
||||
/// The CommitChanges() method has to be called for changes in this
|
||||
/// property to take effect.
|
||||
/// </remarks>
|
||||
public string TraceExpression {
|
||||
get {
|
||||
return traceExpression;
|
||||
}
|
||||
set {
|
||||
traceExpression = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last value traced.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property returns the last evaluation of TraceExpression.
|
||||
/// </remarks>
|
||||
public string LastTraceValue {
|
||||
get {
|
||||
return lastTraceValue;
|
||||
}
|
||||
internal set {
|
||||
lastTraceValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the action to be performed when the breakpoint is hit
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the value is Break, the debugger will pause the execution.
|
||||
/// If the value is PrintExpression, the debugger will evaluate and
|
||||
/// print the value of the TraceExpression property.
|
||||
/// If the value is CustomAction, the debugger will execute the
|
||||
/// CustomBreakEventHitHandler callback specified in DebuggerSession,
|
||||
/// and will provide the value of CustomActionId as argument.
|
||||
/// The CommitChanges() method has to be called for changes in this
|
||||
/// property to take effect.
|
||||
/// </remarks>
|
||||
public HitAction HitAction {
|
||||
get {
|
||||
return hitAction;
|
||||
}
|
||||
set {
|
||||
hitAction = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the hit count mode.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the break event is hit, the HitCountMode is used to compare the CurrentHitCount
|
||||
/// with the TargetHitCount to determine if the break event should trigger.
|
||||
/// </remarks>
|
||||
public HitCountMode HitCountMode {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target hit count.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the break event is hit, if the value of HitCountMode is not None, then
|
||||
/// the value of CurrentHitCount will be incremented. Execution will immediately
|
||||
/// resume if it is determined that the CurrentHitCount vs TargetHitCount
|
||||
/// comparison does not meet the requirements of HitCountMode.
|
||||
///
|
||||
/// The CommitChanges() method has to be called for changes in this property
|
||||
/// to take effect.
|
||||
/// </remarks>
|
||||
///
|
||||
/// FIXME: rename this to TargetHitCount
|
||||
public int HitCount {
|
||||
get {
|
||||
return hitCount;
|
||||
}
|
||||
set {
|
||||
hitCount = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current hit count.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the break event is hit, the HitCountMode is used to compare the CurrentHitCount
|
||||
/// with the TargetHitCount to determine if the break event should trigger.
|
||||
/// </remarks>
|
||||
public int CurrentHitCount {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the custom action identifier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this break event is hit and the value of HitAction is CustomAction,
|
||||
/// the debugger will execute the CustomBreakEventHitHandler callback
|
||||
/// specified in DebuggerSession, and will provide the value of this property
|
||||
/// as argument.
|
||||
/// The CommitChanges() method has to be called for changes in this
|
||||
/// property to take effect.
|
||||
/// </remarks>
|
||||
public string CustomActionId {
|
||||
get {
|
||||
return customActionId;
|
||||
}
|
||||
set {
|
||||
customActionId = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal BreakpointStore Store {
|
||||
get {
|
||||
return store;
|
||||
}
|
||||
set {
|
||||
store = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ConditionExpression {
|
||||
get {
|
||||
return conditionExpression;
|
||||
}
|
||||
set {
|
||||
conditionExpression = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string LastConditionValue {
|
||||
get {
|
||||
return lastConditionValue;
|
||||
}
|
||||
set {
|
||||
lastConditionValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool BreakIfConditionChanges {
|
||||
get {
|
||||
return breakIfConditionChanges;
|
||||
}
|
||||
set {
|
||||
breakIfConditionChanges = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NonUserBreakpoint is special kind of breakpoint that is not placed by user but by IDE/Add-In.
|
||||
/// This breakpoint is usually used by AddIn to execute code on debugee at certain point in application execution.
|
||||
/// IDE must hide this breakpoint from user. In breakpoints list and it must not stop execution(show breakpoint hit location).
|
||||
/// WARNING: Code that adds this breakpoint must also make sure to call session.Continue(); when breakpoint is hit.
|
||||
/// </summary>
|
||||
public bool NonUserBreakpoint {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commits changes done in the break event properties
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method must be called after doing changes in the break event properties.
|
||||
/// </remarks>
|
||||
public void CommitChanges ()
|
||||
{
|
||||
if (store != null)
|
||||
store.NotifyBreakEventChanged (this);
|
||||
}
|
||||
|
||||
internal void NotifyUpdate ()
|
||||
{
|
||||
if (store != null)
|
||||
store.NotifyBreakEventUpdated (this);
|
||||
}
|
||||
|
||||
public virtual bool Reset ()
|
||||
{
|
||||
bool changed = CurrentHitCount != 0;
|
||||
|
||||
CurrentHitCount = 0;
|
||||
lastConditionValue = null;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clone this instance.
|
||||
/// </summary>
|
||||
public BreakEvent Clone ()
|
||||
{
|
||||
return (BreakEvent) MemberwiseClone ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes a copy of this instance
|
||||
/// </summary>
|
||||
/// <param name='ev'>
|
||||
/// A break event from which to copy the data.
|
||||
/// </param>
|
||||
public virtual void CopyFrom (BreakEvent ev)
|
||||
{
|
||||
hitAction = ev.hitAction;
|
||||
customActionId = ev.customActionId;
|
||||
traceExpression = ev.traceExpression;
|
||||
hitCount = ev.hitCount;
|
||||
breakIfConditionChanges = ev.breakIfConditionChanges;
|
||||
conditionExpression = ev.conditionExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// BreakEventArgs.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class BreakEventArgs : EventArgs
|
||||
{
|
||||
public BreakEventArgs (BreakEvent be)
|
||||
{
|
||||
BreakEvent = be;
|
||||
}
|
||||
|
||||
public BreakEvent BreakEvent {
|
||||
get; private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
VisualPascalABCNETLinux/MonoDebugging/Client/BreakEventInfo.cs
Normal file
159
VisualPascalABCNETLinux/MonoDebugging/Client/BreakEventInfo.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
//
|
||||
// BreakEventInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// This class can be used to manage and get information about a breakpoint
|
||||
/// at debug-time. It is intended to be used by DebuggerSession subclasses.
|
||||
/// </summary>
|
||||
public class BreakEventInfo
|
||||
{
|
||||
DebuggerSession session;
|
||||
int adjustedColumn = -1;
|
||||
int adjustedLine = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the implementation specific handle of the breakpoint
|
||||
/// </summary>
|
||||
public object Handle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Break event that this instance represents
|
||||
/// </summary>
|
||||
public BreakEvent BreakEvent { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status of the break event
|
||||
/// </summary>
|
||||
public BreakEventStatus Status { get; private set; }
|
||||
|
||||
public Breakpoint Breakpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a description of the status
|
||||
/// </summary>
|
||||
public string StatusMessage { get; private set; }
|
||||
|
||||
internal void AttachSession (DebuggerSession s, BreakEvent ev)
|
||||
{
|
||||
session = s;
|
||||
BreakEvent = ev;
|
||||
session.NotifyBreakEventStatusChanged (BreakEvent);
|
||||
if (adjustedLine != -1 || adjustedColumn != -1)
|
||||
session.AdjustBreakpointLocation ((Breakpoint)BreakEvent, adjustedLine, adjustedColumn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the location of a breakpoint
|
||||
/// </summary>
|
||||
/// <param name='newLine'>
|
||||
/// New line.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This method can be used to temporarily change source code line of the breakpoint.
|
||||
/// This is useful, for example, when two adjacent lines are mapped to a single
|
||||
/// native offset. If the breakpoint is set to the first of those lines, the debugger
|
||||
/// might end stopping in the second line, because it has the same native offset.
|
||||
/// To avoid this confusion situation, the debugger implementation may decide to
|
||||
/// adjust the position of the breakpoint, and move it to the second line.
|
||||
/// This line adjustment has effect only during the debug session, and is automatically
|
||||
/// reset when it terminates.
|
||||
/// </remarks>
|
||||
public void AdjustBreakpointLocation (int newLine, int newColumn)
|
||||
{
|
||||
if (session != null) {
|
||||
session.AdjustBreakpointLocation ((Breakpoint)BreakEvent, newLine, newColumn);
|
||||
} else {
|
||||
adjustedColumn = newColumn;
|
||||
adjustedLine = newLine;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments the hit count.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the break event should trigger, or <c>false</c> otherwise.</returns>
|
||||
public bool HitCountReached
|
||||
{
|
||||
get {
|
||||
switch (BreakEvent.HitCountMode) {
|
||||
case HitCountMode.LessThan:
|
||||
return BreakEvent.CurrentHitCount < BreakEvent.HitCount;
|
||||
case HitCountMode.LessThanOrEqualTo:
|
||||
return BreakEvent.CurrentHitCount <= BreakEvent.HitCount;
|
||||
case HitCountMode.EqualTo:
|
||||
return BreakEvent.CurrentHitCount == BreakEvent.HitCount;
|
||||
case HitCountMode.GreaterThan:
|
||||
return BreakEvent.CurrentHitCount > BreakEvent.HitCount;
|
||||
case HitCountMode.GreaterThanOrEqualTo:
|
||||
return BreakEvent.CurrentHitCount >= BreakEvent.HitCount;
|
||||
case HitCountMode.MultipleOf:
|
||||
return (BreakEvent.CurrentHitCount % BreakEvent.HitCount) == 0;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void IncrementHitCount ()
|
||||
{
|
||||
if (BreakEvent.HitCountMode != HitCountMode.None) {
|
||||
BreakEvent.CurrentHitCount++;
|
||||
BreakEvent.NotifyUpdate ();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStatus (BreakEventStatus s, string statusMessage)
|
||||
{
|
||||
if (s != Status) {
|
||||
Status = s;
|
||||
StatusMessage = statusMessage;
|
||||
if (session != null)
|
||||
session.NotifyBreakEventStatusChanged (BreakEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public bool RunCustomBreakpointAction (string actionId)
|
||||
{
|
||||
var h = session.CustomBreakEventHitHandler;
|
||||
return h != null && h (actionId, BreakEvent);
|
||||
}
|
||||
|
||||
public void UpdateLastTraceValue (string value)
|
||||
{
|
||||
BreakEvent.LastTraceValue = value;
|
||||
BreakEvent.NotifyUpdate ();
|
||||
if (value != null) {
|
||||
if (session.BreakpointTraceHandler != null)
|
||||
session.BreakpointTraceHandler (BreakEvent, value);
|
||||
else
|
||||
session.OnTargetDebug (0, "", value + Environment.NewLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// BreakEventStatus.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public enum BreakEventStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The breakpoint is not connected to any debug session
|
||||
/// </summary>
|
||||
Disconnected = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The breakpoint is not yet bound to a valid location
|
||||
/// </summary>
|
||||
NotBound = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The breakpoint is bound
|
||||
/// </summary>
|
||||
Bound = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The breakpoint could not be bound because the breakpoint location is invalid
|
||||
/// </summary>
|
||||
Invalid = 4,
|
||||
|
||||
/// <summary>
|
||||
/// There was a debugger error while binding the breakpoint
|
||||
/// </summary>
|
||||
BindError = 5
|
||||
}
|
||||
}
|
||||
209
VisualPascalABCNETLinux/MonoDebugging/Client/Breakpoint.cs
Normal file
209
VisualPascalABCNETLinux/MonoDebugging/Client/Breakpoint.cs
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
// Breakpoint.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class Breakpoint: BreakEvent
|
||||
{
|
||||
int adjustedColumn = -1;
|
||||
int adjustedLine = -1;
|
||||
string fileName;
|
||||
int column;
|
||||
int line;
|
||||
|
||||
public Breakpoint (string fileName, int line, int column)
|
||||
{
|
||||
FileName = fileName;
|
||||
Column = column;
|
||||
Line = line;
|
||||
}
|
||||
|
||||
public Breakpoint (string fileName, int line) : this (fileName, line, 1)
|
||||
{
|
||||
}
|
||||
|
||||
internal Breakpoint (XmlElement elem, string baseDir) : base (elem, baseDir)
|
||||
{
|
||||
string s = elem.GetAttribute ("relfile");
|
||||
if (!string.IsNullOrEmpty (s) && baseDir != null) {
|
||||
fileName = Path.Combine (baseDir, s);
|
||||
} else {
|
||||
s = elem.GetAttribute ("file");
|
||||
if (!string.IsNullOrEmpty (s))
|
||||
fileName = s;
|
||||
}
|
||||
|
||||
s = elem.GetAttribute ("line");
|
||||
if (string.IsNullOrEmpty (s) || !int.TryParse (s, out line))
|
||||
line = 1;
|
||||
|
||||
s = elem.GetAttribute ("column");
|
||||
if (string.IsNullOrEmpty (s) || !int.TryParse (s, out column))
|
||||
column = 1;
|
||||
}
|
||||
|
||||
internal override XmlElement ToXml (XmlDocument doc, string baseDir)
|
||||
{
|
||||
XmlElement elem = base.ToXml (doc, baseDir);
|
||||
|
||||
if (!string.IsNullOrEmpty (fileName)) {
|
||||
elem.SetAttribute ("file", fileName);
|
||||
if (baseDir != null) {
|
||||
if (fileName.StartsWith (baseDir, StringComparison.Ordinal))
|
||||
elem.SetAttribute ("relfile", fileName.Substring (baseDir.Length).TrimStart (Path.DirectorySeparatorChar));
|
||||
}
|
||||
}
|
||||
|
||||
elem.SetAttribute ("line", line.ToString ());
|
||||
elem.SetAttribute ("column", column.ToString ());
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
public string FileName {
|
||||
get { return fileName; }
|
||||
protected set { fileName = value; }
|
||||
}
|
||||
|
||||
public int OriginalColumn {
|
||||
get { return column; }
|
||||
}
|
||||
|
||||
public int Column {
|
||||
get { return adjustedColumn == -1 ? column : adjustedColumn; }
|
||||
protected set { column = value; }
|
||||
}
|
||||
|
||||
public int OriginalLine {
|
||||
get { return line; }
|
||||
}
|
||||
|
||||
public int Line {
|
||||
get { return adjustedLine == -1 ? line : adjustedLine; }
|
||||
protected set { line = value; }
|
||||
}
|
||||
|
||||
public void SetColumn (int newColumn)
|
||||
{
|
||||
ResetAdjustedColumn ();
|
||||
column = newColumn;
|
||||
}
|
||||
|
||||
public bool UpdatedByEnC { get; set; }
|
||||
|
||||
public void SetLine (int newLine)
|
||||
{
|
||||
ResetAdjustedLine ();
|
||||
line = newLine;
|
||||
}
|
||||
|
||||
internal void SetFileName (string newFileName)
|
||||
{
|
||||
fileName = newFileName;
|
||||
}
|
||||
|
||||
internal void SetAdjustedColumn (int newColumn)
|
||||
{
|
||||
adjustedColumn = newColumn;
|
||||
}
|
||||
|
||||
internal void SetAdjustedLine (int newLine)
|
||||
{
|
||||
adjustedLine = newLine;
|
||||
}
|
||||
|
||||
// FIXME: make this private
|
||||
internal void ResetAdjustedColumn ()
|
||||
{
|
||||
adjustedColumn = -1;
|
||||
}
|
||||
|
||||
// FIXME: make this private
|
||||
internal void ResetAdjustedLine ()
|
||||
{
|
||||
adjustedLine = -1;
|
||||
}
|
||||
|
||||
public override bool Reset ()
|
||||
{
|
||||
bool changed = base.Reset () || HasAdjustedLine || HasAdjustedColumn;
|
||||
|
||||
adjustedColumn = -1;
|
||||
adjustedLine = -1;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
// FIXME: make this private
|
||||
internal bool HasAdjustedColumn {
|
||||
get { return adjustedColumn != -1; }
|
||||
}
|
||||
|
||||
// FIXME: make this private
|
||||
internal bool HasAdjustedLine {
|
||||
get { return adjustedLine != -1; }
|
||||
}
|
||||
|
||||
public override void CopyFrom (BreakEvent ev)
|
||||
{
|
||||
base.CopyFrom (ev);
|
||||
|
||||
Breakpoint bp = (Breakpoint) ev;
|
||||
|
||||
fileName = bp.fileName;
|
||||
column = bp.column;
|
||||
line = bp.line;
|
||||
}
|
||||
}
|
||||
|
||||
public enum HitCountMode {
|
||||
None,
|
||||
LessThan,
|
||||
LessThanOrEqualTo,
|
||||
EqualTo,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqualTo,
|
||||
MultipleOf
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HitAction
|
||||
{
|
||||
None = 0x0,
|
||||
Break = 0x1,
|
||||
PrintExpression = 0x2,
|
||||
CustomAction = 0x4,
|
||||
PrintTrace = 0x8
|
||||
}
|
||||
|
||||
public delegate bool BreakEventHitHandler (string actionId, BreakEvent be);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// BreakpointEventArgs.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class BreakpointEventArgs : EventArgs
|
||||
{
|
||||
public BreakpointEventArgs (Breakpoint bp)
|
||||
{
|
||||
Breakpoint = bp;
|
||||
}
|
||||
|
||||
public Breakpoint Breakpoint {
|
||||
get; private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
687
VisualPascalABCNETLinux/MonoDebugging/Client/BreakpointStore.cs
Normal file
687
VisualPascalABCNETLinux/MonoDebugging/Client/BreakpointStore.cs
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
// BreakpointStore.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public sealed class BreakpointStore: ICollection<BreakEvent>
|
||||
{
|
||||
static readonly StringComparer PathComparer;
|
||||
static readonly bool IsWindows;
|
||||
static readonly bool IsMac;
|
||||
|
||||
readonly object breakpointLock = new object ();
|
||||
List<BreakEvent> breakpoints = new List<BreakEvent>();
|
||||
|
||||
static BreakpointStore ()
|
||||
{
|
||||
IsWindows = Path.DirectorySeparatorChar == '\\';
|
||||
IsMac = !IsWindows && IsRunningOnMac ();
|
||||
|
||||
PathComparer = IsWindows || IsMac ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
|
||||
}
|
||||
|
||||
[DllImport ("libc")]
|
||||
static extern int uname (IntPtr buf);
|
||||
|
||||
//From Managed.Windows.Forms/XplatUI
|
||||
static bool IsRunningOnMac ()
|
||||
{
|
||||
var buf = IntPtr.Zero;
|
||||
|
||||
try {
|
||||
buf = Marshal.AllocHGlobal (8192);
|
||||
// This is a hacktastic way of getting sysname from uname ()
|
||||
if (uname (buf) == 0) {
|
||||
var os = Marshal.PtrToStringAnsi (buf);
|
||||
if (os == "Darwin")
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
} finally {
|
||||
if (buf != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal (buf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int Count {
|
||||
get {
|
||||
return InternalGetBreakpoints().Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly {
|
||||
get {
|
||||
var args = new ReadOnlyCheckEventArgs ();
|
||||
CheckingReadOnly?.Invoke (this, args);
|
||||
return args.IsReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
public Breakpoint Add (string filename, int line, int column)
|
||||
{
|
||||
return Add (filename, line, column, true);
|
||||
}
|
||||
|
||||
public Breakpoint Add (string filename, int line)
|
||||
{
|
||||
return Add (filename, line, 1, true);
|
||||
}
|
||||
|
||||
public Breakpoint Add (string filename, int line, int column, bool activate)
|
||||
{
|
||||
if (filename == null)
|
||||
throw new ArgumentNullException (nameof (filename));
|
||||
|
||||
if (line < 1)
|
||||
throw new ArgumentOutOfRangeException (nameof (line));
|
||||
|
||||
if (column < 1)
|
||||
throw new ArgumentOutOfRangeException (nameof (column));
|
||||
|
||||
if (IsReadOnly)
|
||||
return null;
|
||||
|
||||
var bp = new Breakpoint (filename, line, column);
|
||||
Add (bp);
|
||||
|
||||
return bp;
|
||||
}
|
||||
|
||||
void ICollection<BreakEvent>.Add (BreakEvent bp)
|
||||
{
|
||||
Add (bp);
|
||||
}
|
||||
|
||||
public bool Add (BreakEvent be)
|
||||
{
|
||||
if (be == null)
|
||||
throw new ArgumentNullException (nameof (be));
|
||||
|
||||
if (IsReadOnly)
|
||||
return false;
|
||||
|
||||
if (be is Breakpoint bp) {
|
||||
bp.SetFileName (ResolveFullPath(bp.FileName));
|
||||
}
|
||||
|
||||
lock (breakpointLock) {
|
||||
breakpoints.Add(be);
|
||||
SetBreakpoints(breakpoints);
|
||||
be.Store = this;
|
||||
}
|
||||
|
||||
OnBreakEventAdded (be);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Catchpoint AddCatchpoint (string exceptionName)
|
||||
{
|
||||
return AddCatchpoint (exceptionName, true);
|
||||
}
|
||||
|
||||
public Catchpoint AddCatchpoint (string exceptionName, bool includeSubclasses)
|
||||
{
|
||||
if (exceptionName == null)
|
||||
throw new ArgumentNullException (nameof (exceptionName));
|
||||
|
||||
if (IsReadOnly)
|
||||
return null;
|
||||
|
||||
var cp = new Catchpoint (exceptionName, includeSubclasses);
|
||||
Add (cp);
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
public bool Remove (string filename, int line, int column)
|
||||
{
|
||||
if (filename == null)
|
||||
throw new ArgumentNullException (nameof (filename));
|
||||
|
||||
if (IsReadOnly)
|
||||
return false;
|
||||
|
||||
filename = Path.GetFullPath (filename);
|
||||
|
||||
var breakpointsToRemove = new List<BreakEvent> ();
|
||||
foreach (var b in InternalGetBreakpoints ()) {
|
||||
if (b is Breakpoint bp && FileNameEquals(bp.FileName, filename) &&
|
||||
(bp.OriginalLine == line || bp.Line == line) &&
|
||||
(bp.OriginalColumn == column || bp.Column == column)) {
|
||||
breakpointsToRemove.Add (bp);
|
||||
}
|
||||
}
|
||||
|
||||
RemoveRange (breakpointsToRemove);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RemoveCatchpoint (string exceptionName)
|
||||
{
|
||||
if (exceptionName == null)
|
||||
throw new ArgumentNullException (nameof (exceptionName));
|
||||
|
||||
if (IsReadOnly)
|
||||
return false;
|
||||
|
||||
var breakpointsToRemove = new List<BreakEvent> ();
|
||||
foreach (var b in InternalGetBreakpoints ()) {
|
||||
if (b is Catchpoint cp && cp.ExceptionName == exceptionName) {
|
||||
breakpointsToRemove.Add (cp);
|
||||
}
|
||||
}
|
||||
|
||||
RemoveRange (breakpointsToRemove);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void RemoveRunToCursorBreakpoints ()
|
||||
{
|
||||
if (IsReadOnly)
|
||||
return;
|
||||
|
||||
var breakpointsToRemove = InternalGetBreakpoints ().OfType<RunToCursorBreakpoint> ().ToList ();
|
||||
|
||||
RemoveRange (breakpointsToRemove);
|
||||
}
|
||||
|
||||
public bool Remove (BreakEvent bp)
|
||||
{
|
||||
if (bp == null)
|
||||
throw new ArgumentNullException (nameof (bp));
|
||||
|
||||
|
||||
if (!IsReadOnly) {
|
||||
var wasRemoved = false;
|
||||
lock (breakpointLock) {
|
||||
if (breakpoints.Contains (bp)) {
|
||||
breakpoints.Remove(bp);
|
||||
SetBreakpoints(breakpoints);
|
||||
wasRemoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (wasRemoved) {
|
||||
OnBreakEventRemoved (bp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RemoveRange (IEnumerable<BreakEvent> breakEvents)
|
||||
{
|
||||
List<BreakEvent> oldEvents;
|
||||
|
||||
if (!IsReadOnly) {
|
||||
lock (breakpointLock) {
|
||||
foreach (var b in breakEvents)
|
||||
breakpoints.Remove(b);
|
||||
oldEvents = SetBreakpoints(breakpoints);
|
||||
}
|
||||
|
||||
List<BreakEvent> breakEventsRemoved = new List<BreakEvent> ();
|
||||
|
||||
foreach (var bp in breakEvents) {
|
||||
if (oldEvents.Contains(bp)) {
|
||||
breakEventsRemoved.Add (bp);
|
||||
}
|
||||
}
|
||||
|
||||
OnBreakEventsRemoved (breakEventsRemoved);
|
||||
}
|
||||
}
|
||||
|
||||
public Breakpoint Toggle (string filename, int line, int column)
|
||||
{
|
||||
if (filename == null)
|
||||
throw new ArgumentNullException (nameof (filename));
|
||||
|
||||
if (line < 1)
|
||||
throw new ArgumentOutOfRangeException (nameof (line));
|
||||
|
||||
if (column < 1)
|
||||
throw new ArgumentOutOfRangeException (nameof (column));
|
||||
|
||||
if (IsReadOnly)
|
||||
return null;
|
||||
|
||||
var col = GetBreakpointsAtFileLine (filename, line);
|
||||
if (col.Count > 0) {
|
||||
// Remove only the most-recently-added breakpoint on the specified line
|
||||
Remove (col[col.Count - 1]);
|
||||
return null;
|
||||
}
|
||||
|
||||
return Add (filename, line, column);
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<BreakEvent> GetBreakevents ()
|
||||
{
|
||||
return new ReadOnlyCollection<BreakEvent>(InternalGetBreakpoints ());
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<Breakpoint> GetBreakpoints ()
|
||||
{
|
||||
var list = new List<Breakpoint> ();
|
||||
|
||||
foreach (var bp in InternalGetBreakpoints ().OfType<Breakpoint> ()) {
|
||||
if (!(bp is RunToCursorBreakpoint))
|
||||
list.Add (bp);
|
||||
}
|
||||
|
||||
return list.AsReadOnly ();
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<Catchpoint> GetCatchpoints ()
|
||||
{
|
||||
return InternalGetBreakpoints ().OfType<Catchpoint> ().ToList ().AsReadOnly ();
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<Breakpoint> GetBreakpointsAtFile (string filename)
|
||||
{
|
||||
if (filename == null)
|
||||
throw new ArgumentNullException (nameof (filename));
|
||||
|
||||
var list = new List<Breakpoint> ();
|
||||
if (string.IsNullOrEmpty (filename))
|
||||
return list.AsReadOnly ();
|
||||
|
||||
try {
|
||||
filename = Path.GetFullPath (filename);
|
||||
} catch {
|
||||
return list.AsReadOnly ();
|
||||
}
|
||||
|
||||
foreach (var bp in InternalGetBreakpoints ().OfType<Breakpoint> ()) {
|
||||
if (!(bp is RunToCursorBreakpoint) && FileNameEquals(bp.FileName, filename))
|
||||
list.Add (bp);
|
||||
}
|
||||
|
||||
return list.AsReadOnly ();
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<Breakpoint> GetBreakpointsAtFileLine (string filename, int line)
|
||||
{
|
||||
if (filename == null)
|
||||
throw new ArgumentNullException (nameof (filename));
|
||||
|
||||
var list = new List<Breakpoint> ();
|
||||
|
||||
try {
|
||||
filename = Path.GetFullPath (filename);
|
||||
} catch {
|
||||
return list.AsReadOnly ();
|
||||
}
|
||||
|
||||
foreach (var bp in InternalGetBreakpoints ().OfType<Breakpoint> ()) {
|
||||
if (!(bp is RunToCursorBreakpoint) && FileNameEquals(bp.FileName, filename) && (bp.OriginalLine == line || bp.Line == line))
|
||||
list.Add (bp);
|
||||
}
|
||||
|
||||
return list.AsReadOnly ();
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator ()
|
||||
{
|
||||
return ((IEnumerable)InternalGetBreakpoints()).GetEnumerator ();
|
||||
}
|
||||
|
||||
IEnumerator<BreakEvent> IEnumerable<BreakEvent>.GetEnumerator ()
|
||||
{
|
||||
return ((IEnumerable<BreakEvent>)InternalGetBreakpoints ()).GetEnumerator ();
|
||||
}
|
||||
|
||||
public void Clear ()
|
||||
{
|
||||
Clear (true);
|
||||
}
|
||||
|
||||
public void Clear (bool clearNonUserBreakpoints)
|
||||
{
|
||||
var breakpointsToRemove = InternalGetBreakpoints ()
|
||||
.Where (bp => clearNonUserBreakpoints || !bp.NonUserBreakpoint);
|
||||
|
||||
RemoveRange (breakpointsToRemove);
|
||||
}
|
||||
|
||||
public void ClearBreakpoints ()
|
||||
{
|
||||
RemoveRange (GetBreakpoints ());
|
||||
}
|
||||
|
||||
public void ClearCatchpoints ()
|
||||
{
|
||||
RemoveRange (GetCatchpoints ());
|
||||
}
|
||||
|
||||
public bool Contains (BreakEvent item)
|
||||
{
|
||||
return InternalGetBreakpoints ().Contains (item);
|
||||
}
|
||||
|
||||
public void CopyTo (BreakEvent[] array, int arrayIndex)
|
||||
{
|
||||
InternalGetBreakpoints ().CopyTo (array, arrayIndex);
|
||||
}
|
||||
|
||||
public void UpdateBreakpointLine (Breakpoint bp, int newLine)
|
||||
{
|
||||
if (IsReadOnly)
|
||||
return;
|
||||
|
||||
bp.SetLine (newLine);
|
||||
NotifyBreakEventChanged (bp);
|
||||
}
|
||||
|
||||
internal void AdjustBreakpointLine (Breakpoint bp, int newLine, int newColumn)
|
||||
{
|
||||
if (IsReadOnly)
|
||||
return;
|
||||
|
||||
bp.SetAdjustedColumn (newColumn);
|
||||
bp.SetAdjustedLine (newLine);
|
||||
NotifyBreakEventChanged (bp);
|
||||
}
|
||||
|
||||
internal void ResetBreakpoints ()
|
||||
{
|
||||
if (IsReadOnly)
|
||||
return;
|
||||
|
||||
foreach (var bp in InternalGetBreakpoints ()) {
|
||||
if (bp.Reset ()) {
|
||||
NotifyBreakEventChanged (bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public XmlElement Save (string baseDir = null)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument ();
|
||||
XmlElement elem = doc.CreateElement ("BreakpointStore");
|
||||
foreach (BreakEvent ev in this) {
|
||||
if (ev.NonUserBreakpoint)
|
||||
continue;
|
||||
XmlElement be = ev.ToXml (doc, baseDir);
|
||||
elem.AppendChild (be);
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
public void Load (XmlElement rootElem, string baseDir = null)
|
||||
{
|
||||
Clear ();
|
||||
|
||||
var loadedBreakpoints = new List<BreakEvent> ();
|
||||
foreach (XmlNode n in rootElem.ChildNodes) {
|
||||
XmlElement elem = n as XmlElement;
|
||||
if (elem == null)
|
||||
continue;
|
||||
BreakEvent ev = BreakEvent.FromXml (elem, baseDir);
|
||||
if (ev != null) {
|
||||
loadedBreakpoints.Add (ev);
|
||||
ev.Store = this;
|
||||
}
|
||||
}
|
||||
|
||||
lock (breakpointLock) {
|
||||
SetBreakpoints (new List<BreakEvent> (loadedBreakpoints));
|
||||
}
|
||||
|
||||
// preserve behaviour by sending an event for each breakpoint that was loaded
|
||||
OnBreakEventsAdded (loadedBreakpoints);
|
||||
}
|
||||
|
||||
[DllImport("libc")]
|
||||
static extern string realpath(string path, IntPtr buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the full path of the given file
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <returns>The full path if a file is given, or returns the parameter if it is null or empty</returns>
|
||||
static string ResolveFullPath (string path)
|
||||
{
|
||||
// If there is no path given, return the same path back
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return path;
|
||||
|
||||
string result = null;
|
||||
try {
|
||||
result = realpath(path, IntPtr.Zero);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(result) ? Path.GetFullPath(path) : result;
|
||||
}
|
||||
|
||||
public static bool FileNameEquals (string file1, string file2)
|
||||
{
|
||||
if (file1 == null)
|
||||
return file2 == null;
|
||||
|
||||
if (file2 == null)
|
||||
return false;
|
||||
|
||||
return PathComparer.Compare (file1, file2) == 0;
|
||||
}
|
||||
|
||||
internal bool EnableBreakEvent (BreakEvent be, bool previouslyEnabled, bool enabled)
|
||||
{
|
||||
if (IsReadOnly)
|
||||
return false;
|
||||
|
||||
if (previouslyEnabled != enabled) {
|
||||
OnChanged ();
|
||||
BreakEventEnableStatusChanged?.Invoke (this, new BreakEventArgs (be));
|
||||
NotifyStatusChanged (be);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnBreakEventAdded (BreakEvent be)
|
||||
{
|
||||
BreakEventAdded?.Invoke (this, new BreakEventArgs (be));
|
||||
if (be is Breakpoint bp) {
|
||||
BreakpointAdded?.Invoke (this, new BreakpointEventArgs (bp));
|
||||
} else if (be is Catchpoint ce) {
|
||||
CatchpointAdded?.Invoke (this, new CatchpointEventArgs (ce));
|
||||
}
|
||||
OnChanged ();
|
||||
}
|
||||
|
||||
void OnBreakEventsAdded (List<BreakEvent> bes)
|
||||
{
|
||||
foreach (BreakEvent be in bes) {
|
||||
BreakEventAdded?.Invoke (this, new BreakEventArgs (be));
|
||||
if (be is Breakpoint bp) {
|
||||
BreakpointAdded?.Invoke (this, new BreakpointEventArgs (bp));
|
||||
} else if (be is Catchpoint ce) {
|
||||
CatchpointAdded?.Invoke (this, new CatchpointEventArgs (ce));
|
||||
}
|
||||
}
|
||||
|
||||
OnChanged ();
|
||||
}
|
||||
|
||||
void OnBreakEventRemoved (BreakEvent be)
|
||||
{
|
||||
BreakEventRemoved?.Invoke (this, new BreakEventArgs (be));
|
||||
if (be is Breakpoint bp) {
|
||||
BreakpointRemoved?.Invoke (this, new BreakpointEventArgs (bp));
|
||||
} else if (be is Catchpoint ce) {
|
||||
CatchpointRemoved?.Invoke (this, new CatchpointEventArgs (ce));
|
||||
}
|
||||
OnChanged ();
|
||||
}
|
||||
|
||||
void OnBreakEventsRemoved (List<BreakEvent> bes)
|
||||
{
|
||||
foreach (BreakEvent be in bes) {
|
||||
BreakEventRemoved?.Invoke (this, new BreakEventArgs (be));
|
||||
if (be is Breakpoint bp) {
|
||||
BreakpointRemoved?.Invoke (this, new BreakpointEventArgs (bp));
|
||||
} else if (be is Catchpoint ce) {
|
||||
CatchpointRemoved?.Invoke (this, new CatchpointEventArgs (ce));
|
||||
}
|
||||
}
|
||||
|
||||
OnChanged ();
|
||||
}
|
||||
|
||||
void OnChanged ()
|
||||
{
|
||||
Changed?.Invoke (this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal void NotifyStatusChanged (BreakEvent be)
|
||||
{
|
||||
try {
|
||||
BreakEventStatusChanged?.Invoke (this, new BreakEventArgs (be));
|
||||
if (be is Breakpoint bp) {
|
||||
BreakpointStatusChanged?.Invoke (this, new BreakpointEventArgs (bp));
|
||||
} else if (be is Catchpoint ce) {
|
||||
CatchpointStatusChanged?.Invoke (this, new CatchpointEventArgs (ce));
|
||||
}
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyBreakEventChanged (BreakEvent be)
|
||||
{
|
||||
try {
|
||||
BreakEventModified?.Invoke (this, new BreakEventArgs (be));
|
||||
if (be is Breakpoint bp) {
|
||||
BreakpointModified?.Invoke (this, new BreakpointEventArgs (bp));
|
||||
} else if (be is Catchpoint ce) {
|
||||
CatchpointModified?.Invoke (this, new CatchpointEventArgs (ce));
|
||||
}
|
||||
OnChanged ();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyBreakEventUpdated (BreakEvent be)
|
||||
{
|
||||
|
||||
try {
|
||||
BreakEventUpdated?.Invoke (this, new BreakEventArgs (be));
|
||||
if (be is Breakpoint bp) {
|
||||
BreakpointUpdated?.Invoke (this, new BreakpointEventArgs (bp));
|
||||
} else if (be is Catchpoint ce) {
|
||||
CatchpointUpdated?.Invoke (this, new CatchpointEventArgs (ce));
|
||||
}
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<BreakpointEventArgs> BreakpointAdded;
|
||||
public event EventHandler<BreakpointEventArgs> BreakpointRemoved;
|
||||
public event EventHandler<BreakpointEventArgs> BreakpointStatusChanged;
|
||||
public event EventHandler<BreakpointEventArgs> BreakpointModified;
|
||||
public event EventHandler<BreakpointEventArgs> BreakpointUpdated;
|
||||
public event EventHandler<CatchpointEventArgs> CatchpointAdded;
|
||||
public event EventHandler<CatchpointEventArgs> CatchpointRemoved;
|
||||
public event EventHandler<CatchpointEventArgs> CatchpointStatusChanged;
|
||||
public event EventHandler<CatchpointEventArgs> CatchpointModified;
|
||||
public event EventHandler<CatchpointEventArgs> CatchpointUpdated;
|
||||
public event EventHandler<BreakEventArgs> BreakEventAdded;
|
||||
public event EventHandler<BreakEventArgs> BreakEventRemoved;
|
||||
public event EventHandler<BreakEventArgs> BreakEventStatusChanged;
|
||||
public event EventHandler<BreakEventArgs> BreakEventModified;
|
||||
public event EventHandler<BreakEventArgs> BreakEventUpdated;
|
||||
public event EventHandler Changed;
|
||||
public event EventHandler<ReadOnlyCheckEventArgs> CheckingReadOnly;
|
||||
|
||||
internal event EventHandler<BreakEventArgs> BreakEventEnableStatusChanged;
|
||||
|
||||
public void FileRenamed (string oldPath, string newPath)
|
||||
{
|
||||
if (IsReadOnly)
|
||||
return;
|
||||
|
||||
foreach (var bp in GetBreakpointsAtFile (oldPath)) {
|
||||
Remove (bp);
|
||||
bp.SetFileName (newPath);
|
||||
Add (bp);
|
||||
}
|
||||
}
|
||||
|
||||
List<BreakEvent> SetBreakpoints (List<BreakEvent> newBreakpoints)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert (System.Threading.Monitor.IsEntered (breakpointLock), "SetBreakpoints must be called during a lock");
|
||||
|
||||
foreach (BreakEvent be in newBreakpoints) {
|
||||
if (be is Breakpoint bp) {
|
||||
bp.SetFileName (ResolveFullPath(bp.FileName));
|
||||
}
|
||||
}
|
||||
|
||||
var oldEvents = breakpoints;
|
||||
breakpoints = newBreakpoints;
|
||||
return oldEvents;
|
||||
}
|
||||
|
||||
List<BreakEvent> InternalGetBreakpoints ()
|
||||
{
|
||||
lock (breakpointLock) {
|
||||
return breakpoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ReadOnlyCheckEventArgs: EventArgs
|
||||
{
|
||||
internal bool IsReadOnly;
|
||||
|
||||
public void SetReadOnly (bool isReadOnly)
|
||||
{
|
||||
IsReadOnly = IsReadOnly || isReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
VisualPascalABCNETLinux/MonoDebugging/Client/Catchpoint.cs
Normal file
126
VisualPascalABCNETLinux/MonoDebugging/Client/Catchpoint.cs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
// Catchpoint.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class Catchpoint: BreakEvent
|
||||
{
|
||||
string exceptionName;
|
||||
bool includeSubclasses;
|
||||
|
||||
public Catchpoint (string exceptionName) : this (exceptionName, true)
|
||||
{
|
||||
}
|
||||
|
||||
public Catchpoint (string exceptionName, bool includeSubclasses)
|
||||
{
|
||||
this.exceptionName = exceptionName;
|
||||
this.includeSubclasses = includeSubclasses;
|
||||
}
|
||||
|
||||
internal Catchpoint (XmlElement elem, string baseDir): base (elem, baseDir)
|
||||
{
|
||||
exceptionName = elem.GetAttribute ("exceptionName");
|
||||
|
||||
var str = elem.GetAttribute ("includeSubclasses");
|
||||
if (string.IsNullOrEmpty (str) || !bool.TryParse (str, out includeSubclasses)) {
|
||||
// fall back to the old default behavior
|
||||
includeSubclasses = true;
|
||||
}
|
||||
foreach (var child in elem.ChildNodes.OfType<XmlElement>()) {
|
||||
Ignored.Add (child.InnerText);
|
||||
}
|
||||
}
|
||||
|
||||
internal override XmlElement ToXml (XmlDocument doc, string baseDir)
|
||||
{
|
||||
var elem = base.ToXml (doc, baseDir);
|
||||
elem.SetAttribute ("exceptionName", exceptionName);
|
||||
elem.SetAttribute ("includeSubclasses", includeSubclasses.ToString ());
|
||||
foreach (var item in Ignored.OrderBy(s => s)) {
|
||||
var newChild = doc.CreateElement ("Ignore");
|
||||
newChild.InnerText = item;
|
||||
elem.AppendChild (newChild);
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
public string ExceptionName {
|
||||
get { return exceptionName; }
|
||||
set { exceptionName = value; }
|
||||
}
|
||||
|
||||
public bool IncludeSubclasses {
|
||||
get { return includeSubclasses; }
|
||||
set { includeSubclasses = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When an exception first happens, we are given the frame of the exception.
|
||||
/// However by the time the user chooses "Ignore this location" in the exception dialog,
|
||||
/// the current frame might be a different frame (the one with source code),
|
||||
/// and not necessarily the bottom frame of the stack.
|
||||
/// Make sure we remember the original frame where the exception happened
|
||||
/// so that when it happens next time, we use the same frame signature to compare
|
||||
/// against.
|
||||
/// </summary>
|
||||
public string CurrentLocationSignature { get; set; }
|
||||
|
||||
public HashSet<string> Ignored { get; private set; } = new HashSet<string> (StringComparer.Ordinal);
|
||||
|
||||
public bool ShouldIgnore(string type, string locationSignature)
|
||||
{
|
||||
return Ignored.Contains (type) || Ignored.Contains (locationSignature);
|
||||
}
|
||||
|
||||
public override void CopyFrom (BreakEvent ev)
|
||||
{
|
||||
base.CopyFrom (ev);
|
||||
|
||||
var cp = (Catchpoint) ev;
|
||||
exceptionName = cp.exceptionName;
|
||||
includeSubclasses = cp.includeSubclasses;
|
||||
Ignored = cp.Ignored;
|
||||
}
|
||||
|
||||
public void AddIgnore (string ignore)
|
||||
{
|
||||
Ignored.Add (ignore);
|
||||
}
|
||||
|
||||
public void RemoveIgnore (string ignore)
|
||||
{
|
||||
Ignored.Remove (ignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// CatchpointEventArgs.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class CatchpointEventArgs : EventArgs
|
||||
{
|
||||
public CatchpointEventArgs (Catchpoint cp)
|
||||
{
|
||||
Catchpoint = cp;
|
||||
}
|
||||
|
||||
public Catchpoint Catchpoint {
|
||||
get; private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// CompletionData.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class CompletionData
|
||||
{
|
||||
int expressionLength;
|
||||
List<CompletionItem> items = new List<CompletionItem> ();
|
||||
|
||||
public int ExpressionLength {
|
||||
get {
|
||||
return expressionLength;
|
||||
}
|
||||
set {
|
||||
expressionLength = value;
|
||||
}
|
||||
}
|
||||
|
||||
public List<CompletionItem> Items {
|
||||
get { return items; }
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class CompletionItem
|
||||
{
|
||||
string name;
|
||||
ObjectValueFlags flags;
|
||||
|
||||
public CompletionItem (string name, ObjectValueFlags flags)
|
||||
{
|
||||
this.name = name;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectValueFlags Flags {
|
||||
get {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// DebuggerException.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class DebuggerException: Exception
|
||||
{
|
||||
public DebuggerException (SerializationInfo info, StreamingContext ctx): base (info, ctx)
|
||||
{
|
||||
}
|
||||
|
||||
public DebuggerException (string message): base (message)
|
||||
{
|
||||
}
|
||||
|
||||
public DebuggerException (string message, Exception inner): base (message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// DebuggerFeatures.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Flags]
|
||||
public enum DebuggerFeatures: uint
|
||||
{
|
||||
None = 0,
|
||||
ConditionalBreakpoints = 1,
|
||||
Tracepoints = 1 << 1,
|
||||
Catchpoints = 1 << 2,
|
||||
Attaching = 1 << 3,
|
||||
DebugFile = 1 << 4,
|
||||
Stepping = 1 << 5,
|
||||
Pause = 1 << 6,
|
||||
Breakpoints = 1 << 7,
|
||||
Disassembly = 1 << 8,
|
||||
All = 0xffffffff
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// DebuggerLoggingService.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Hutchinson <mhutchinson@novell.com>
|
||||
//
|
||||
// Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a simple abstraction so that MD can plug in its own logging service to handle the Mono.Debugging.Soft
|
||||
/// error logging, without Mono.Debugging.Soft depending on MonoDevelop.Core.
|
||||
/// In the absence of a custom logger, it writes to Console.
|
||||
/// </summary>
|
||||
public static class DebuggerLoggingService
|
||||
{
|
||||
public static ICustomLogger CustomLogger { get; set; }
|
||||
|
||||
public static void LogError (string message, Exception ex)
|
||||
{
|
||||
if (CustomLogger != null)
|
||||
CustomLogger.LogError (message, ex);
|
||||
else
|
||||
Console.WriteLine (message + (ex != null? System.Environment.NewLine + ex.ToString () : string.Empty));
|
||||
}
|
||||
|
||||
public static void LogMessage (string messageFormat, params object[] args)
|
||||
{
|
||||
if (CustomLogger != null)
|
||||
CustomLogger.LogMessage (messageFormat, args);
|
||||
else
|
||||
Console.WriteLine (messageFormat, args);
|
||||
}
|
||||
|
||||
//this is meant to show a GUI if possible
|
||||
public static void LogAndShowException (string message, Exception ex)
|
||||
{
|
||||
if (CustomLogger != null)
|
||||
CustomLogger.LogAndShowException (message, ex);
|
||||
else
|
||||
LogError (message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICustomLogger
|
||||
{
|
||||
void LogError (string message, System.Exception ex);
|
||||
void LogAndShowException (string message, System.Exception ex);
|
||||
void LogMessage (string messageFormat, params object[] args);
|
||||
/// <summary>
|
||||
/// Gets the new debugger log filename. It may return null which means disable logging.
|
||||
/// </summary>
|
||||
/// <returns>The new debugger log filename or null.</returns>
|
||||
string GetNewDebuggerLogFilename ();
|
||||
}
|
||||
}
|
||||
1859
VisualPascalABCNETLinux/MonoDebugging/Client/DebuggerSession.cs
Normal file
1859
VisualPascalABCNETLinux/MonoDebugging/Client/DebuggerSession.cs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// DebuggerSessionOptions.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public enum AutomaticSourceDownload
|
||||
{
|
||||
Ask,
|
||||
Always,
|
||||
Never
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class DebuggerSessionOptions
|
||||
{
|
||||
public EvaluationOptions EvaluationOptions { get; set; }
|
||||
public bool StepOverPropertiesAndOperators { get; set; }
|
||||
public bool ProjectAssembliesOnly { get; set; }
|
||||
public AutomaticSourceDownload AutomaticSourceLinkDownload { get; set; }
|
||||
public bool DebugSubprocesses { get; set; }
|
||||
public List<SymbolSource> SymbolSearchPaths { get; set; } = new List<SymbolSource>();
|
||||
public bool SearchMicrosoftSymbolServer { get; set; }
|
||||
public bool SearchNuGetSymbolServer { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SymbolSource
|
||||
{
|
||||
public SymbolSource ()
|
||||
{
|
||||
// For deserialization
|
||||
}
|
||||
|
||||
public SymbolSource (string path, string name, bool isEnabled)
|
||||
{
|
||||
Path = path;
|
||||
Name = name;
|
||||
IsEnabled = isEnabled;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Path { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
// DebuggerStartInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class DebuggerStartInfo
|
||||
{
|
||||
string command;
|
||||
string arguments;
|
||||
string runtimeArguments;
|
||||
string workingDirectory;
|
||||
Dictionary<string, string> environmentVariables;
|
||||
|
||||
public string Command {
|
||||
get {
|
||||
return command;
|
||||
}
|
||||
set {
|
||||
command = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Arguments {
|
||||
get {
|
||||
return arguments;
|
||||
}
|
||||
set {
|
||||
arguments = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string RuntimeArguments {
|
||||
get {
|
||||
return runtimeArguments;
|
||||
}
|
||||
set {
|
||||
runtimeArguments = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string WorkingDirectory {
|
||||
get {
|
||||
return workingDirectory;
|
||||
}
|
||||
set {
|
||||
workingDirectory = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, string> EnvironmentVariables {
|
||||
get {
|
||||
if (environmentVariables == null)
|
||||
environmentVariables = new Dictionary<string,string> ();
|
||||
return environmentVariables;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseExternalConsole { get; set; }
|
||||
|
||||
public bool CloseExternalConsoleOnExit { get; set; }
|
||||
|
||||
public bool RequiresManualStart { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
//
|
||||
// DebuggerStatistics.cs
|
||||
//
|
||||
// Author:
|
||||
// Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||
//
|
||||
// Copyright (c) 2019 Microsoft Corp.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class DebuggerStatistics
|
||||
{
|
||||
static readonly int[] UpperTimeLimits = { 10, 50, 100, 250, 500, 1000, 1500, 2000, 5000, 10000 };
|
||||
|
||||
readonly int[] buckets = new int[UpperTimeLimits.Length + 1];
|
||||
readonly object mutex = new object ();
|
||||
TimeSpan minTime = TimeSpan.MaxValue;
|
||||
TimeSpan maxTime, totalTime;
|
||||
|
||||
public DebuggerStatistics(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public double MaxTime {
|
||||
get { return maxTime.TotalMilliseconds; }
|
||||
}
|
||||
|
||||
public double MinTime {
|
||||
get { return minTime.TotalMilliseconds; }
|
||||
}
|
||||
|
||||
public double AverageTime {
|
||||
get {
|
||||
if (TimingsCount > 0)
|
||||
return totalTime.TotalMilliseconds / TimingsCount;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int TimingsCount { get; private set; }
|
||||
|
||||
public int FailureCount { get; private set; }
|
||||
public string Name { get; }
|
||||
|
||||
public DebuggerTimer StartTimer (string name)
|
||||
{
|
||||
return new DebuggerTimer (this, name);
|
||||
}
|
||||
|
||||
int GetBucketIndex (TimeSpan duration)
|
||||
{
|
||||
var ms = (long) duration.TotalMilliseconds;
|
||||
|
||||
for (var bucket = 0; bucket < UpperTimeLimits.Length; bucket++) {
|
||||
if (ms <= UpperTimeLimits[bucket])
|
||||
return bucket;
|
||||
}
|
||||
|
||||
return buckets.Length - 1;
|
||||
}
|
||||
|
||||
public void AddTime (TimeSpan duration)
|
||||
{
|
||||
lock (mutex) {
|
||||
if (duration > maxTime)
|
||||
maxTime = duration;
|
||||
|
||||
if (duration < minTime)
|
||||
minTime = duration;
|
||||
|
||||
buckets[GetBucketIndex (duration)]++;
|
||||
|
||||
totalTime += duration;
|
||||
TimingsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
public void IncrementFailureCount ()
|
||||
{
|
||||
lock (mutex) {
|
||||
FailureCount++;
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize (Dictionary<string, object> metadata)
|
||||
{
|
||||
metadata["AverageDuration"] = AverageTime;
|
||||
metadata["MaximumDuration"] = MaxTime;
|
||||
metadata["MinimumDuration"] = MinTime;
|
||||
metadata["FailureCount"] = FailureCount;
|
||||
metadata["SuccessCount"] = TimingsCount;
|
||||
|
||||
for (int i = 0; i < buckets.Length; i++)
|
||||
metadata[$"Bucket{i}"] = buckets[i];
|
||||
}
|
||||
}
|
||||
|
||||
public class DebuggerTimer : IDisposable
|
||||
{
|
||||
readonly DebuggerStatistics stats;
|
||||
readonly Stopwatch stopwatch;
|
||||
|
||||
static readonly TraceListener traceListener = new TraceSource (nameof (DebuggerTimer)).Listeners.OfType<TraceListener> ().FirstOrDefault (l => l.Name == nameof (DebuggerTimer));
|
||||
static int traceSeq = 0;
|
||||
int traceId;
|
||||
|
||||
public DebuggerTimer (DebuggerStatistics stats, string name)
|
||||
{
|
||||
stopwatch = Stopwatch.StartNew ();
|
||||
this.stats = stats;
|
||||
if (stats != null && traceListener != null) {
|
||||
traceId = Interlocked.Increment (ref traceSeq);
|
||||
traceListener.TraceEvent (null, stats.Name, TraceEventType.Start, traceId, name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the debugger operation was successful. If this is false the
|
||||
/// timing will not be reported and a failure will be indicated.
|
||||
/// </summary>
|
||||
public bool Success { get; set; }
|
||||
|
||||
public TimeSpan Elapsed {
|
||||
get { return stopwatch.Elapsed; }
|
||||
}
|
||||
|
||||
public void Stop (bool success)
|
||||
{
|
||||
stopwatch.Stop ();
|
||||
Success = success;
|
||||
|
||||
if (stats == null)
|
||||
return;
|
||||
traceListener?.TraceEvent (null, stats.Name, TraceEventType.Stop, traceId, "Stop1");
|
||||
|
||||
if (success)
|
||||
stats.AddTime (stopwatch.Elapsed);
|
||||
else
|
||||
stats.IncrementFailureCount ();
|
||||
}
|
||||
|
||||
public void Stop (ObjectValue val)
|
||||
{
|
||||
stopwatch.Stop ();
|
||||
if (stats == null)
|
||||
return;
|
||||
traceListener?.TraceEvent (null, stats.Name, TraceEventType.Stop, traceId, "Stop2");
|
||||
|
||||
if (val.IsEvaluating || val.IsEvaluatingGroup) {
|
||||
// Do not capture timing - evaluation not finished.
|
||||
} else if (val.IsError || val.IsImplicitNotSupported || val.IsNotSupported || val.IsUnknown) {
|
||||
stats.IncrementFailureCount ();
|
||||
} else {
|
||||
// Success
|
||||
stats.AddTime (stopwatch.Elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
if (stopwatch.IsRunning) {
|
||||
stopwatch.Stop ();
|
||||
|
||||
if (stats == null)
|
||||
return;
|
||||
traceListener?.TraceEvent (null, stats.Name, TraceEventType.Stop, traceId, "Dispose");
|
||||
|
||||
if (Success)
|
||||
stats.AddTime (stopwatch.Elapsed);
|
||||
else
|
||||
stats.IncrementFailureCount ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
//
|
||||
// EvaluationOptions.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class EvaluationOptions
|
||||
{
|
||||
bool allowMethodEvaluation;
|
||||
bool allowToStringCalls;
|
||||
|
||||
public const char Ellipsis = '…';
|
||||
|
||||
public static EvaluationOptions DefaultOptions {
|
||||
get {
|
||||
EvaluationOptions ops = new EvaluationOptions ();
|
||||
ops.EvaluationTimeout = 1000;
|
||||
ops.MemberEvaluationTimeout = 5000;
|
||||
ops.AllowTargetInvoke = true;
|
||||
ops.AllowMethodEvaluation = true;
|
||||
ops.AllowToStringCalls = true;
|
||||
ops.FlattenHierarchy = true;
|
||||
ops.GroupPrivateMembers = true;
|
||||
ops.GroupStaticMembers = true;
|
||||
ops.UseExternalTypeResolver = true;
|
||||
ops.IntegerDisplayFormat = IntegerDisplayFormat.Decimal;
|
||||
ops.CurrentExceptionTag = "$exception";
|
||||
ops.EllipsizeStrings = true;
|
||||
ops.EllipsizedLength = 100;
|
||||
ops.ChunkRawStrings = false;
|
||||
ops.StackFrameFormat = new StackFrameFormat ();
|
||||
return ops;
|
||||
}
|
||||
}
|
||||
|
||||
public EvaluationOptions Clone ()
|
||||
{
|
||||
var clone = (EvaluationOptions)MemberwiseClone ();
|
||||
clone.StackFrameFormat = new StackFrameFormat (StackFrameFormat);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public bool ChunkRawStrings { get; set; }
|
||||
|
||||
public bool EllipsizeStrings { get; set; }
|
||||
public int EllipsizedLength { get; set; }
|
||||
|
||||
public int EvaluationTimeout { get; set; }
|
||||
public int MemberEvaluationTimeout { get; set; }
|
||||
public bool AllowTargetInvoke { get; set; }
|
||||
|
||||
public bool AllowMethodEvaluation {
|
||||
get { return allowMethodEvaluation && AllowTargetInvoke; }
|
||||
set { allowMethodEvaluation = value; }
|
||||
}
|
||||
|
||||
public bool AllowToStringCalls {
|
||||
get { return allowToStringCalls && AllowTargetInvoke; }
|
||||
set { allowToStringCalls = value; }
|
||||
}
|
||||
|
||||
public bool AllowDisplayStringEvaluation {
|
||||
get { return AllowTargetInvoke; }
|
||||
}
|
||||
|
||||
public bool AllowDebuggerProxy {
|
||||
get { return AllowTargetInvoke; }
|
||||
}
|
||||
|
||||
public bool FlattenHierarchy { get; set; }
|
||||
|
||||
public bool GroupPrivateMembers { get; set; }
|
||||
|
||||
public bool GroupStaticMembers { get; set; }
|
||||
|
||||
public bool UseExternalTypeResolver { get; set; }
|
||||
|
||||
public IntegerDisplayFormat IntegerDisplayFormat { get; set; }
|
||||
|
||||
public string CurrentExceptionTag { get; set; }
|
||||
|
||||
public bool IEnumerable { get; set; }
|
||||
|
||||
public StackFrameFormat StackFrameFormat { get; set; }
|
||||
}
|
||||
|
||||
public class StackFrameFormat
|
||||
{
|
||||
public bool Line { get; set; } = true;
|
||||
|
||||
public bool Module { get; set; } = false;
|
||||
|
||||
public bool ParameterNames { get; set; } = true;
|
||||
|
||||
public bool ParameterTypes { get; set; } = true;
|
||||
|
||||
public bool ParameterValues { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Default is null. Which means do same as "ProjectAssembliesOnly" setting.
|
||||
/// </summary>
|
||||
public bool? ExternalCode { get; set; } = null;
|
||||
|
||||
public StackFrameFormat ()
|
||||
{
|
||||
}
|
||||
|
||||
public StackFrameFormat (StackFrameFormat copy)
|
||||
{
|
||||
Line = copy.Line;
|
||||
Module = copy.Module;
|
||||
ParameterNames = copy.ParameterNames;
|
||||
ParameterTypes = copy.ParameterTypes;
|
||||
ParameterValues = copy.ParameterValues;
|
||||
ExternalCode = copy.ExternalCode;
|
||||
}
|
||||
}
|
||||
|
||||
public enum IntegerDisplayFormat
|
||||
{
|
||||
Decimal,
|
||||
Hexadecimal
|
||||
}
|
||||
}
|
||||
320
VisualPascalABCNETLinux/MonoDebugging/Client/ExceptionInfo.cs
Normal file
320
VisualPascalABCNETLinux/MonoDebugging/Client/ExceptionInfo.cs
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
//
|
||||
// ExceptionInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class ExceptionInfo
|
||||
{
|
||||
ObjectValue exception;
|
||||
ObjectValue messageObject;
|
||||
|
||||
[NonSerialized]
|
||||
ExceptionStackFrame[] frames;
|
||||
|
||||
[NonSerialized]
|
||||
ExceptionInfo innerException;
|
||||
|
||||
[NonSerialized]
|
||||
ObjectValue instance;
|
||||
|
||||
/// <summary>
|
||||
/// The provided value can have the following members:
|
||||
/// Type of the object: type of the exception
|
||||
/// Message: Message of the exception
|
||||
/// Instance: Raw instance of the exception
|
||||
/// StackTrace: an array of frames. Each frame must have:
|
||||
/// Value of the object: display text of the frame
|
||||
/// File: name of the file
|
||||
/// Line: line
|
||||
/// Column: column
|
||||
/// InnerException: inner exception, following the same format described above.
|
||||
/// </summary>
|
||||
public ExceptionInfo (ObjectValue exception)
|
||||
{
|
||||
this.exception = exception;
|
||||
if (exception.IsEvaluating || exception.IsEvaluatingGroup)
|
||||
exception.ValueChanged += HandleExceptionValueChanged;
|
||||
}
|
||||
|
||||
void LoadMessage ()
|
||||
{
|
||||
if (messageObject == null) {
|
||||
messageObject = exception.GetChild ("Message");
|
||||
if (messageObject != null && messageObject.IsEvaluating)
|
||||
messageObject.ValueChanged += HandleMessageValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleMessageValueChanged (object sender, EventArgs e)
|
||||
{
|
||||
frames = null;
|
||||
NotifyChanged ();
|
||||
}
|
||||
|
||||
void HandleExceptionValueChanged (object sender, EventArgs e)
|
||||
{
|
||||
frames = null;
|
||||
if (exception.IsEvaluatingGroup)
|
||||
exception = exception.GetArrayItem (0);
|
||||
LoadMessage ();
|
||||
NotifyChanged ();
|
||||
}
|
||||
|
||||
void NotifyChanged ()
|
||||
{
|
||||
EventHandler evnt = Changed;
|
||||
if (evnt != null)
|
||||
evnt (this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public string Type {
|
||||
get { return exception.TypeName; }
|
||||
}
|
||||
|
||||
public string Message {
|
||||
get {
|
||||
LoadMessage ();
|
||||
if (messageObject != null && messageObject.IsEvaluating)
|
||||
return "Loading...";
|
||||
return messageObject != null ? messageObject.Value : null;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectValue helpLinkObject;
|
||||
public string HelpLink {
|
||||
get {
|
||||
if (helpLinkObject == null) {
|
||||
helpLinkObject = exception.GetChild ("HelpLink");
|
||||
if (helpLinkObject != null && helpLinkObject.IsEvaluating) {
|
||||
helpLinkObject.ValueChanged += delegate {
|
||||
NotifyChanged ();
|
||||
};
|
||||
}
|
||||
}
|
||||
return helpLinkObject != null ? helpLinkObject.Value : null;
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectValue Instance {
|
||||
get {
|
||||
if (instance == null)
|
||||
instance = exception.GetChild ("Instance");
|
||||
if (instance == null)
|
||||
return exception;
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEvaluating {
|
||||
get { return exception.IsEvaluating || exception.IsEvaluatingGroup; }
|
||||
}
|
||||
|
||||
public bool StackIsEvaluating {
|
||||
get {
|
||||
ObjectValue stackTrace = exception.GetChild ("StackTrace");
|
||||
if (stackTrace != null)
|
||||
return stackTrace.IsEvaluating;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public ExceptionStackFrame[] StackTrace {
|
||||
get {
|
||||
if (frames != null)
|
||||
return frames;
|
||||
|
||||
var stackTrace = exception.GetChild ("StackTrace");
|
||||
if (stackTrace == null || stackTrace.IsNull)
|
||||
return frames = new ExceptionStackFrame [0];
|
||||
|
||||
if (stackTrace.IsEvaluating) {
|
||||
frames = new ExceptionStackFrame [0];
|
||||
stackTrace.ValueChanged += HandleExceptionValueChanged;
|
||||
return frames;
|
||||
}
|
||||
|
||||
if (stackTrace.TypeName == "string") {
|
||||
stackTrace = Debugging.Evaluation.ExceptionInfoSource.GetStackTrace (stackTrace.Value);
|
||||
}
|
||||
|
||||
if (!stackTrace.IsArray) {
|
||||
return frames = new ExceptionStackFrame [0];
|
||||
}
|
||||
|
||||
var list = new List<ExceptionStackFrame> ();
|
||||
for (int i = 0; i < stackTrace.ArrayCount; i++)
|
||||
list.Add (new ExceptionStackFrame (stackTrace.GetArrayItem (i, EvaluationOptions.DefaultOptions)));
|
||||
|
||||
frames = list.ToArray ();
|
||||
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
|
||||
public ExceptionInfo InnerException {
|
||||
get {
|
||||
if (innerException == null) {
|
||||
ObjectValue innerVal = exception.GetChild ("InnerException");
|
||||
if (innerVal == null || innerVal.IsNull || innerVal.IsError || innerVal.IsUnknown)
|
||||
return null;
|
||||
if (innerVal.IsEvaluating) {
|
||||
innerVal.ValueChanged += delegate { NotifyChanged (); };
|
||||
return null;
|
||||
}
|
||||
innerException = new ExceptionInfo (innerVal);
|
||||
innerException.Changed += delegate {
|
||||
NotifyChanged ();
|
||||
};
|
||||
}
|
||||
return innerException;
|
||||
}
|
||||
}
|
||||
|
||||
List<ExceptionInfo> innerExceptions;
|
||||
public List<ExceptionInfo> InnerExceptions {
|
||||
get {
|
||||
if (innerExceptions == null) {
|
||||
ObjectValue innerVal = exception.GetChild ("InnerExceptions");
|
||||
if (innerVal == null || innerVal.IsError || innerVal.IsUnknown)
|
||||
return null;
|
||||
if (innerVal.IsEvaluating) {
|
||||
innerVal.ValueChanged += delegate { NotifyChanged (); };
|
||||
return null;
|
||||
}
|
||||
innerExceptions = new List<ExceptionInfo> ();
|
||||
foreach (var inner in innerVal.GetAllChildren ()) {
|
||||
var innerObj = new ExceptionInfo (inner);
|
||||
innerObj.Changed += delegate {
|
||||
NotifyChanged ();
|
||||
};
|
||||
innerExceptions.Add (innerObj);
|
||||
}
|
||||
}
|
||||
return innerExceptions;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler Changed;
|
||||
|
||||
internal void ConnectCallback (StackFrame parentFrame)
|
||||
{
|
||||
ObjectValue.ConnectCallbacks (parentFrame, exception);
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var sb = new StringBuilder ();
|
||||
var chain = new List<ExceptionInfo> ();
|
||||
var e = this;
|
||||
|
||||
while (e != null) {
|
||||
chain.Insert (0, e);
|
||||
if (sb.Length > 0)
|
||||
sb.Append (" ---> ");
|
||||
sb.Append (e.Type).Append (": ").Append (e.Message);
|
||||
e = e.InnerException;
|
||||
}
|
||||
|
||||
sb.AppendLine ();
|
||||
|
||||
foreach (var ex in chain) {
|
||||
if (ex != chain[0])
|
||||
sb.AppendLine (" --- End of inner exception stack trace ---");
|
||||
|
||||
foreach (var frame in ex.StackTrace) {
|
||||
sb.Append (" at ").Append (frame.DisplayText);
|
||||
|
||||
if (!string.IsNullOrEmpty (frame.File)) {
|
||||
sb.Append (" in ").Append (frame.File).Append (':').Append (frame.Line);
|
||||
if (frame.Column != 0)
|
||||
sb.Append (',').Append (frame.Column);
|
||||
}
|
||||
|
||||
sb.AppendLine ();
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public class ExceptionStackFrame
|
||||
{
|
||||
readonly ObjectValue frame;
|
||||
|
||||
/// <summary>
|
||||
/// The provided value must have a specific structure.
|
||||
/// The Value property is the display text.
|
||||
/// A child "File" member must be the name of the file.
|
||||
/// A child "Line" member must be the line.
|
||||
/// A child "Column" member must be the column.
|
||||
/// </summary>
|
||||
public ExceptionStackFrame (ObjectValue value)
|
||||
{
|
||||
frame = value;
|
||||
}
|
||||
|
||||
public string File {
|
||||
get {
|
||||
var file = frame.GetChild ("File", EvaluationOptions.DefaultOptions);
|
||||
if (file != null)
|
||||
return file.Value;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int Line {
|
||||
get {
|
||||
var val = frame.GetChild ("Line", EvaluationOptions.DefaultOptions);
|
||||
if (val != null)
|
||||
return int.Parse (val.Value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int Column {
|
||||
get {
|
||||
var val = frame.GetChild ("Column", EvaluationOptions.DefaultOptions);
|
||||
if (val != null)
|
||||
return int.Parse (val.Value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public string DisplayText {
|
||||
get { return frame.Value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
//
|
||||
// FunctionBreakpoint.cs
|
||||
//
|
||||
// Author: Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2012 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
|
||||
[Serializable]
|
||||
public class FunctionBreakpoint : Breakpoint
|
||||
{
|
||||
public FunctionBreakpoint (string functionName, string language) : base (null, 1, 1)
|
||||
{
|
||||
Language = language;
|
||||
ParseTypeAndMethodName (functionName);
|
||||
}
|
||||
|
||||
private void ParseTypeAndMethodName (string functionName)
|
||||
{
|
||||
FunctionName = functionName;
|
||||
var bracket = functionName.IndexOf ('(');
|
||||
int dot;
|
||||
if (bracket != -1) {
|
||||
//Handle stuff like SomeNamespace.SomeType.Method(SomeOtherNamespace.SomeOtherType)
|
||||
dot = functionName.LastIndexOf('.', bracket);
|
||||
} else {
|
||||
dot = functionName.LastIndexOf('.');
|
||||
}
|
||||
if (dot == -1 || dot + 1 == functionName.Length)
|
||||
return;
|
||||
|
||||
// FIXME: handle types like GenericType<>, GenericType<SomeOtherType>, and GenericType<...>+NestedGenricType<...>
|
||||
string methodName;
|
||||
string typeName = functionName.Substring (0, dot);
|
||||
if (bracket == -1) {
|
||||
methodName = functionName.Substring (dot + 1);
|
||||
} else {
|
||||
methodName = functionName.Substring (dot + 1, bracket - (dot + 1));
|
||||
}
|
||||
TypeName = typeName;
|
||||
MethodName = methodName;
|
||||
}
|
||||
|
||||
public FunctionBreakpoint (string typeName, string methodName, string language) : base (null, 1, 1)
|
||||
{
|
||||
Language = language;
|
||||
TypeName = typeName;
|
||||
MethodName = methodName;
|
||||
FunctionName = TypeName + "." + MethodName;
|
||||
}
|
||||
|
||||
static bool SkipArrayRank (string text, ref int index, int endIndex)
|
||||
{
|
||||
char c;
|
||||
|
||||
while (index < endIndex) {
|
||||
if ((c = text[index++]) == ']')
|
||||
return true;
|
||||
|
||||
if (c != ',' && !char.IsWhiteSpace (c) && !char.IsDigit (c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SkipGenericArgs (string text, ref int index, int endIndex)
|
||||
{
|
||||
char c;
|
||||
|
||||
while (index < endIndex) {
|
||||
if ((c = text[index++]) == '>')
|
||||
return true;
|
||||
|
||||
if (c == '<') {
|
||||
if (!SkipGenericArgs (text, ref index, endIndex))
|
||||
return false;
|
||||
|
||||
while (index < endIndex && !char.IsWhiteSpace (text[index]))
|
||||
index++;
|
||||
|
||||
// the only chars allowed after a '>' are: '>', '[', and ','
|
||||
if (">[,".IndexOf (text[index]) == -1)
|
||||
return false;
|
||||
} else if (c == '[') {
|
||||
if (!SkipArrayRank (text, ref index, endIndex))
|
||||
return false;
|
||||
|
||||
while (index < endIndex && !char.IsWhiteSpace (text[index]))
|
||||
index++;
|
||||
|
||||
// the only chars allowed after a ']' are: '>', '[', and ','
|
||||
if (">[,".IndexOf (text[index]) == -1)
|
||||
return false;
|
||||
} else if (c != '.' && c != '+' && c != ',' && !char.IsWhiteSpace (c) && !char.IsLetterOrDigit (c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryParseParameters (string text, int startIndex, int endIndex, out string[] paramTypes)
|
||||
{
|
||||
List<string> parsedParamTypes = new List<string> ();
|
||||
int index = startIndex;
|
||||
int start;
|
||||
char c;
|
||||
|
||||
paramTypes = null;
|
||||
|
||||
while (index < endIndex) {
|
||||
while (char.IsWhiteSpace (text[index]))
|
||||
index++;
|
||||
|
||||
start = index;
|
||||
while (index < endIndex) {
|
||||
if ((c = text[index]) == ',')
|
||||
break;
|
||||
|
||||
index++;
|
||||
|
||||
if (c == '<') {
|
||||
if (!SkipGenericArgs (text, ref index, endIndex))
|
||||
return false;
|
||||
} else if (c == '[') {
|
||||
if (!SkipArrayRank (text, ref index, endIndex))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parsedParamTypes.Add (text.Substring (start, index - start).TrimEnd ());
|
||||
|
||||
if (index < endIndex)
|
||||
index++;
|
||||
}
|
||||
|
||||
paramTypes = parsedParamTypes.ToArray ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal FunctionBreakpoint (XmlElement elem, string baseDir) : base (elem, baseDir)
|
||||
{
|
||||
var functionName = elem.GetAttribute ("function");
|
||||
ParseTypeAndMethodName (functionName);
|
||||
string text = elem.GetAttribute ("language");
|
||||
if (string.IsNullOrEmpty (text))
|
||||
Language = "C#";
|
||||
else
|
||||
Language = text;
|
||||
|
||||
if (elem.HasAttribute ("params")) {
|
||||
string[] paramTypes;
|
||||
|
||||
text = elem.GetAttribute ("params").Trim ();
|
||||
if (text.Length > 0 && TryParseParameters (text, 0, text.Length, out paramTypes))
|
||||
ParamTypes = paramTypes;
|
||||
else
|
||||
ParamTypes = new string[0];
|
||||
}
|
||||
|
||||
FileName = null;
|
||||
}
|
||||
|
||||
internal override XmlElement ToXml (XmlDocument doc, string baseDir)
|
||||
{
|
||||
XmlElement elem = base.ToXml (doc, baseDir);
|
||||
|
||||
elem.SetAttribute ("function", FunctionName);
|
||||
elem.SetAttribute ("language", Language);
|
||||
|
||||
if (ParamTypes != null)
|
||||
elem.SetAttribute ("params", string.Join (", ", ParamTypes));
|
||||
|
||||
return elem;
|
||||
}
|
||||
public string FunctionName {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string TypeName {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string MethodName {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Language {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string[] ParamTypes {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public override void CopyFrom (BreakEvent ev)
|
||||
{
|
||||
base.CopyFrom (ev);
|
||||
|
||||
var bp = (FunctionBreakpoint) ev;
|
||||
FunctionName = bp.FunctionName;
|
||||
MethodName = bp.MethodName;
|
||||
TypeName = bp.TypeName;
|
||||
ParamTypes = bp.ParamTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// IExpressionEvaluator.cs
|
||||
//
|
||||
// Author:
|
||||
// Carlo kok <ck@remobjects.com>
|
||||
//
|
||||
// Copyright (c) 2010 RemObjects Software
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using Mono.Debugging.Evaluation;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public interface IExpressionEvaluator
|
||||
{
|
||||
ExpressionEvaluator Evaluator { get; }
|
||||
ObjectValue[] GetLocals (StackFrame sf);
|
||||
}
|
||||
}
|
||||
101
VisualPascalABCNETLinux/MonoDebugging/Client/ObjectPath.cs
Normal file
101
VisualPascalABCNETLinux/MonoDebugging/Client/ObjectPath.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
// ObjectPath.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public struct ObjectPath
|
||||
{
|
||||
string[] path;
|
||||
|
||||
public ObjectPath (params string[] path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public string this [int n] {
|
||||
get {
|
||||
if (path == null)
|
||||
throw new IndexOutOfRangeException ();
|
||||
return path [n];
|
||||
}
|
||||
}
|
||||
|
||||
public int Length {
|
||||
get { return path != null ? path.Length : 0; }
|
||||
}
|
||||
|
||||
public IEnumerable GetEnumerator ()
|
||||
{
|
||||
if (path != null)
|
||||
return path;
|
||||
|
||||
return new string [0];
|
||||
}
|
||||
|
||||
public ObjectPath GetSubpath (int start)
|
||||
{
|
||||
if (start == 0)
|
||||
return this;
|
||||
|
||||
var newPath = new string [path.Length - start];
|
||||
Array.Copy (path, start, newPath, 0, newPath.Length);
|
||||
|
||||
return new ObjectPath (newPath);
|
||||
}
|
||||
|
||||
public ObjectPath Append (string name)
|
||||
{
|
||||
var newPath = new string [path.Length + 1];
|
||||
Array.Copy (path, newPath, path.Length);
|
||||
newPath [path.Length] = name;
|
||||
return new ObjectPath (newPath);
|
||||
}
|
||||
|
||||
public string LastName {
|
||||
get {
|
||||
if (Length == 0)
|
||||
return "";
|
||||
|
||||
return path[path.Length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public string Join (string separator)
|
||||
{
|
||||
return string.Join (separator, path);
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return Join ("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
882
VisualPascalABCNETLinux/MonoDebugging/Client/ObjectValue.cs
Normal file
882
VisualPascalABCNETLinux/MonoDebugging/Client/ObjectValue.cs
Normal file
|
|
@ -0,0 +1,882 @@
|
|||
// ObjectValue.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class ObjectValue
|
||||
{
|
||||
ObjectPath path;
|
||||
int arrayCount = -1;
|
||||
bool isNull;
|
||||
string name;
|
||||
string value;
|
||||
string typeName;
|
||||
string displayValue;
|
||||
string childSelector;
|
||||
ObjectValueFlags flags;
|
||||
IObjectValueSource source;
|
||||
IObjectValueUpdater updater;
|
||||
List<ObjectValue> children;
|
||||
ManualResetEvent evaluatedEvent;
|
||||
|
||||
[NonSerialized]
|
||||
readonly object mutex = new object ();
|
||||
|
||||
[NonSerialized]
|
||||
UpdateCallback updateCallback;
|
||||
|
||||
[NonSerialized]
|
||||
EventHandler valueChanged;
|
||||
|
||||
[NonSerialized]
|
||||
StackFrame parentFrame;
|
||||
|
||||
static ObjectValue Create (IObjectValueSource source, ObjectPath path, string typeName)
|
||||
{
|
||||
var val = new ObjectValue ();
|
||||
val.typeName = typeName;
|
||||
val.source = source;
|
||||
val.path = path;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateObject (IObjectValueSource source, ObjectPath path, string typeName, string value, ObjectValueFlags flags, ObjectValue[] children)
|
||||
{
|
||||
return CreateObject (source, path, typeName, new EvaluationResult (value), flags, children);
|
||||
}
|
||||
|
||||
public static ObjectValue CreateObject (IObjectValueSource source, ObjectPath path, string typeName, EvaluationResult value, ObjectValueFlags flags, ObjectValue[] children)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = flags | ObjectValueFlags.Object;
|
||||
val.displayValue = value.DisplayValue;
|
||||
val.value = value.Value;
|
||||
|
||||
if (children != null) {
|
||||
val.children = new List<ObjectValue> ();
|
||||
val.children.AddRange (children);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateNullObject (IObjectValueSource source, string name, string typeName, ObjectValueFlags flags)
|
||||
{
|
||||
return CreateNullObject (source, new ObjectPath (name), typeName, flags);
|
||||
}
|
||||
|
||||
public static ObjectValue CreateNullObject (IObjectValueSource source, ObjectPath path, string typeName, ObjectValueFlags flags)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = flags | ObjectValueFlags.Object;
|
||||
val.value = "(null)";
|
||||
val.isNull = true;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreatePrimitive (IObjectValueSource source, ObjectPath path, string typeName, EvaluationResult value, ObjectValueFlags flags)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = flags | ObjectValueFlags.Primitive;
|
||||
val.displayValue = value.DisplayValue;
|
||||
val.value = value.Value;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateArray (IObjectValueSource source, ObjectPath path, string typeName, int arrayCount, ObjectValueFlags flags, ObjectValue[] children)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = flags | ObjectValueFlags.Array;
|
||||
val.value = "[" + arrayCount + "]";
|
||||
val.arrayCount = arrayCount;
|
||||
|
||||
if (children != null && children.Length > 0) {
|
||||
val.children = new List<ObjectValue> ();
|
||||
val.children.AddRange (children);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateUnknown (IObjectValueSource source, ObjectPath path, string typeName)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = ObjectValueFlags.Unknown | ObjectValueFlags.ReadOnly;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateUnknown (string name)
|
||||
{
|
||||
return CreateUnknown (null, new ObjectPath (name), "");
|
||||
}
|
||||
|
||||
public static ObjectValue CreateError (IObjectValueSource source, ObjectPath path, string typeName, string value, ObjectValueFlags flags)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = flags | ObjectValueFlags.Error;
|
||||
val.value = value;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateImplicitNotSupported (IObjectValueSource source, ObjectPath path, string typeName, ObjectValueFlags flags)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = flags | ObjectValueFlags.ImplicitNotSupported;
|
||||
val.value = "Implicit evaluation is disabled";
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateNotSupported (IObjectValueSource source, ObjectPath path, string typeName, string message, ObjectValueFlags flags)
|
||||
{
|
||||
var val = Create (source, path, typeName);
|
||||
val.flags = flags | ObjectValueFlags.NotSupported;
|
||||
val.value = message;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateFatalError (string name, string message, ObjectValueFlags flags)
|
||||
{
|
||||
var val = new ObjectValue ();
|
||||
val.flags = flags | ObjectValueFlags.Error;
|
||||
val.value = message;
|
||||
val.name = name;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateEvaluating (IObjectValueUpdater updater, ObjectPath path, ObjectValueFlags flags)
|
||||
{
|
||||
var val = Create (null, path, null);
|
||||
val.flags = flags | ObjectValueFlags.Evaluating;
|
||||
val.updater = updater;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateShowMore ()
|
||||
{
|
||||
return new ObjectValue () {
|
||||
flags = ObjectValueFlags.IEnumerable,
|
||||
name = ""
|
||||
};
|
||||
}
|
||||
|
||||
public DebuggerSession DebuggerSession {
|
||||
get {
|
||||
return parentFrame?.DebuggerSession;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the flags of the value
|
||||
/// </summary>
|
||||
public ObjectValueFlags Flags {
|
||||
get { return flags; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the value (for example, the property name)
|
||||
/// </summary>
|
||||
public string Name {
|
||||
get { return name ?? path[path.Length - 1]; }
|
||||
set { name = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the object
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The value.
|
||||
/// </value>
|
||||
/// <exception cref='InvalidOperationException'>
|
||||
/// Is thrown when trying to set a value on a read-only ObjectValue
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// This value is a string representation of the ObjectValue. The content depends on several evaluation
|
||||
/// options. For example, if ToString calls are enabled, this value will be the result of calling
|
||||
/// ToString.
|
||||
/// If the object is a primitive type, in general the Value will be an expression that represents the
|
||||
/// value in the target language. For example, when debugging C#, if the property is an string, the value
|
||||
/// will include the quotation marks and chars like '\' will be properly escaped.
|
||||
/// If you need to get the real CLR value of the object, use GetRawValue.
|
||||
/// </remarks>
|
||||
public virtual string Value {
|
||||
get {
|
||||
return value;
|
||||
}
|
||||
set {
|
||||
if (IsReadOnly || source == null)
|
||||
throw new InvalidOperationException ("Value is not editable");
|
||||
|
||||
var res = source.SetValue (path, value, null);
|
||||
if (res != null) {
|
||||
this.value = res.Value;
|
||||
displayValue = res.DisplayValue;
|
||||
isNull = value == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display value of this object
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method returns a string to be used when showing the value of this object.
|
||||
/// In most cases, the Value and DisplayValue properties return the same text, but there are some cases
|
||||
/// in which DisplayValue may return a more convenient textual representation of the value, which
|
||||
/// may not be a valid target language expression.
|
||||
/// For example in C#, an enum Value includes the full enum type name (e.g. "Gtk.ResponseType.OK"),
|
||||
/// while DisplayValue only has the enum value name ("OK").
|
||||
/// </remarks>
|
||||
public string DisplayValue {
|
||||
get { return displayValue ?? Value; }
|
||||
set { displayValue = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of this object, using the default evaluation options
|
||||
/// </summary>
|
||||
public void SetValue (string value)
|
||||
{
|
||||
SetValue (value, parentFrame.DebuggerSession.EvaluationOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of this object, using the specified evaluation options
|
||||
/// </summary>
|
||||
/// <param name='value'>
|
||||
/// The value
|
||||
/// </param>
|
||||
/// <param name='options'>
|
||||
/// The options
|
||||
/// </param>
|
||||
/// <exception cref='InvalidOperationException'>
|
||||
/// Is thrown if the value is read-only
|
||||
/// </exception>
|
||||
public void SetValue (string value, EvaluationOptions options)
|
||||
{
|
||||
if (IsReadOnly || source == null)
|
||||
throw new InvalidOperationException ("Value is not editable");
|
||||
|
||||
var res = source.SetValue (path, value, options);
|
||||
if (res != null) {
|
||||
this.value = res.Value;
|
||||
displayValue = res.DisplayValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw value of this object
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The raw value.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method can be used to get the CLR value of the object. For example, if this ObjectValue is
|
||||
/// a property of type String, this method will return the System.String value of the property.
|
||||
/// If this ObjectValue refers to an object instead of a primitive value, then a RawValue object
|
||||
/// will be returned. RawValue can be used to get and set members of an object, and to call methods.
|
||||
/// If this ObjectValue refers to an array, then a RawValueArray object will be returned.
|
||||
/// </remarks>
|
||||
public object GetRawValue ()
|
||||
{
|
||||
var ops = parentFrame.DebuggerSession.EvaluationOptions.Clone ();
|
||||
ops.EllipsizeStrings = false;
|
||||
|
||||
return GetRawValue (ops);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw value of this object
|
||||
/// </summary>
|
||||
/// <param name='options'>
|
||||
/// The evaluation options
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The raw value.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method can be used to get the CLR value of the object. For example, if this ObjectValue is
|
||||
/// a property of type String, this method will return the System.String value of the property.
|
||||
/// If this ObjectValue refers to an object instead of a primitive value, then a RawValue object
|
||||
/// will be returned. RawValue can be used to get and set members of an object, and to call methods.
|
||||
/// If this ObjectValue refers to an array, then a RawValueArray object will be returned.
|
||||
/// </remarks>
|
||||
public object GetRawValue (EvaluationOptions options)
|
||||
{
|
||||
if (source == null && (IsEvaluating || IsEvaluatingGroup)) {
|
||||
if (!WaitHandle.WaitOne (options.EvaluationTimeout)) {
|
||||
throw new Evaluation.TimeOutException ();
|
||||
}
|
||||
}
|
||||
|
||||
var res = source.GetRawValue (path, options);
|
||||
if (res is IRawObject raw)
|
||||
raw.Connect (parentFrame.DebuggerSession, options);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the raw value of this object
|
||||
/// </summary>
|
||||
/// <param name='value'>
|
||||
/// The value
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// The provided value can be a primitive type, a RawValue object or a RawValueArray object.
|
||||
/// </remarks>
|
||||
public void SetRawValue (object value)
|
||||
{
|
||||
SetRawValue (value, parentFrame.DebuggerSession.EvaluationOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the raw value of this object
|
||||
/// </summary>
|
||||
/// <param name='value'>
|
||||
/// The value
|
||||
/// </param>
|
||||
/// <param name='options'>
|
||||
/// The evaluation options
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// The provided value can be a primitive type, a RawValue object or a RawValueArray object.
|
||||
/// </remarks>
|
||||
public void SetRawValue (object value, EvaluationOptions options)
|
||||
{
|
||||
if (source == null && (IsEvaluating || IsEvaluatingGroup)) {
|
||||
if (!WaitHandle.WaitOne (options.EvaluationTimeout)) {
|
||||
throw new Evaluation.TimeOutException ();
|
||||
}
|
||||
}
|
||||
source.SetRawValue (path, value, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Full name of the type of the object
|
||||
/// </summary>
|
||||
public string TypeName {
|
||||
get { return typeName; }
|
||||
set { typeName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child selector.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The child selector is an expression which can be concatenated to a parent expression to get this child.
|
||||
/// For example, if this object is a reference to a field named 'foo' of an object, the child
|
||||
/// selector is '.foo'.
|
||||
/// </remarks>
|
||||
public string ChildSelector {
|
||||
get {
|
||||
if (childSelector != null)
|
||||
return childSelector;
|
||||
|
||||
if ((flags & ObjectValueFlags.ArrayElement) != 0)
|
||||
return Name;
|
||||
|
||||
return "." + Name;
|
||||
}
|
||||
set { childSelector = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this object has children.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has children; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool HasChildren {
|
||||
get {
|
||||
if (isNull)
|
||||
return false;
|
||||
if (IsEvaluating)
|
||||
return false;
|
||||
if (children != null)
|
||||
return children.Count > 0;
|
||||
if (source == null)
|
||||
return false;
|
||||
if (IsArray)
|
||||
return arrayCount > 0;
|
||||
if (IsObject)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a child value
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The child.
|
||||
/// </returns>
|
||||
/// <param name='name'>
|
||||
/// Name of the member
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This method can be used to get a member of an object (such as a field or property)
|
||||
/// </remarks>
|
||||
public ObjectValue GetChild (string name)
|
||||
{
|
||||
return GetChild (name, parentFrame?.DebuggerSession.EvaluationOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a child value
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The child.
|
||||
/// </returns>
|
||||
/// <param name='name'>
|
||||
/// Name of the member
|
||||
/// </param>
|
||||
/// <param name='options'>
|
||||
/// Options to be used to evaluate the child
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This method can be used to get a member of an object (such as a field or property)
|
||||
/// </remarks>
|
||||
public ObjectValue GetChild (string name, EvaluationOptions options)
|
||||
{
|
||||
if (IsArray)
|
||||
throw new InvalidOperationException ("Object is an array.");
|
||||
if (IsEvaluating)
|
||||
return null;
|
||||
|
||||
if (children == null) {
|
||||
children = new List<ObjectValue> ();
|
||||
if (source != null) {
|
||||
try {
|
||||
var cs = source.GetChildren (path, -1, -1, options);
|
||||
ConnectCallbacks (parentFrame, cs);
|
||||
children.AddRange (cs);
|
||||
} catch (Exception ex) {
|
||||
children = null;
|
||||
return CreateFatalError ("", ex.Message, ObjectValueFlags.ReadOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var child in children) {
|
||||
if (child.Name == name)
|
||||
return child;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all children of the object
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An array of all child values
|
||||
/// </returns>
|
||||
public ObjectValue[] GetAllChildren ()
|
||||
{
|
||||
return GetAllChildren (parentFrame.DebuggerSession.EvaluationOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all children of the object
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An array of all child values
|
||||
/// </returns>
|
||||
/// <param name='options'>
|
||||
/// Options to be used to evaluate the children
|
||||
/// </param>
|
||||
public ObjectValue[] GetAllChildren (EvaluationOptions options)
|
||||
{
|
||||
if (IsEvaluating)
|
||||
return new ObjectValue[0];
|
||||
|
||||
if (IsArray) {
|
||||
GetArrayItem (arrayCount - 1);
|
||||
return children.ToArray ();
|
||||
}
|
||||
|
||||
if (children == null) {
|
||||
children = new List<ObjectValue> ();
|
||||
if (source != null) {
|
||||
try {
|
||||
var cs = source.GetChildren (path, -1, -1, options);
|
||||
ConnectCallbacks (parentFrame, cs);
|
||||
children.AddRange (cs);
|
||||
} catch (Exception ex) {
|
||||
if (parentFrame != null)
|
||||
parentFrame.DebuggerSession.OnDebuggerOutput (true, ex.ToString ());
|
||||
children.Add (CreateFatalError ("", ex.Message, ObjectValueFlags.ReadOnly));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return children.ToArray ();
|
||||
}
|
||||
|
||||
public ObjectValue[] GetRangeOfChildren (int index, int count)
|
||||
{
|
||||
return GetRangeOfChildren (index, count, parentFrame.DebuggerSession.EvaluationOptions);
|
||||
}
|
||||
|
||||
public ObjectValue[] GetRangeOfChildren (int index, int count, EvaluationOptions options)
|
||||
{
|
||||
if (IsEvaluating)
|
||||
return new ObjectValue[0];
|
||||
|
||||
if (IsArray) {
|
||||
GetArrayItem (arrayCount - 1);
|
||||
if (index >= ArrayCount)
|
||||
return new ObjectValue[0];
|
||||
return children.Skip (index).Take (Math.Min (count, ArrayCount - index)).ToArray ();
|
||||
}
|
||||
|
||||
if (children == null) {
|
||||
children = new List<ObjectValue> ();
|
||||
}
|
||||
if (children.Count < index + count) {
|
||||
if (source != null) {
|
||||
try {
|
||||
ObjectValue[] cs = source.GetChildren (path, children.Count, index + count, options);
|
||||
ConnectCallbacks (parentFrame, cs);
|
||||
children.AddRange (cs);
|
||||
} catch (Exception ex) {
|
||||
if (parentFrame != null)
|
||||
parentFrame.DebuggerSession.OnDebuggerOutput (true, ex.ToString ());
|
||||
children.Add (CreateFatalError ("", ex.Message, ObjectValueFlags.ReadOnly));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= children.Count)
|
||||
return new ObjectValue[0];
|
||||
|
||||
return children.Skip (index).Take (Math.Min (count, children.Count - index)).ToArray ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an item of an array
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The array item.
|
||||
/// </returns>
|
||||
/// <param name='index'>
|
||||
/// Item index
|
||||
/// </param>
|
||||
/// <exception cref='InvalidOperationException'>
|
||||
/// Is thrown if this object is not an array (IsArray returns false)
|
||||
/// </exception>
|
||||
public ObjectValue GetArrayItem (int index)
|
||||
{
|
||||
return GetArrayItem (index, parentFrame.DebuggerSession.EvaluationOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an item of an array
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The array item.
|
||||
/// </returns>
|
||||
/// <param name='index'>
|
||||
/// Item index
|
||||
/// </param>
|
||||
/// <param name='options'>
|
||||
/// Options to be used to evaluate the item
|
||||
/// </param>
|
||||
/// <exception cref='InvalidOperationException'>
|
||||
/// Is thrown if this object is not an array (IsArray returns false)
|
||||
/// </exception>
|
||||
public ObjectValue GetArrayItem (int index, EvaluationOptions options)
|
||||
{
|
||||
if (!IsArray)
|
||||
throw new InvalidOperationException ("Object is not an array.");
|
||||
|
||||
if (index >= arrayCount || index < 0 || IsEvaluating)
|
||||
throw new IndexOutOfRangeException ();
|
||||
|
||||
if (children == null)
|
||||
children = new List<ObjectValue> ();
|
||||
|
||||
if (index >= children.Count) {
|
||||
int nc = (index + 50);
|
||||
|
||||
if (nc > arrayCount)
|
||||
nc = arrayCount;
|
||||
|
||||
nc = nc - children.Count;
|
||||
|
||||
try {
|
||||
var items = source.GetChildren (path, children.Count, nc, options);
|
||||
ConnectCallbacks (parentFrame, items);
|
||||
children.AddRange (items);
|
||||
} catch (Exception ex) {
|
||||
return CreateFatalError ("", ex.Message, ObjectValueFlags.ArrayElement | ObjectValueFlags.ReadOnly);
|
||||
}
|
||||
}
|
||||
|
||||
return children [index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of items of an array
|
||||
/// </summary>
|
||||
/// <exception cref='InvalidOperationException'>
|
||||
/// Is thrown if this object is not an array (IsArray returns false)
|
||||
/// </exception>
|
||||
public int ArrayCount {
|
||||
get {
|
||||
if (!IsArray)
|
||||
throw new InvalidOperationException ("Object is not an array.");
|
||||
|
||||
if (IsEvaluating)
|
||||
return 0;
|
||||
|
||||
return arrayCount;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsNull {
|
||||
get { return isNull; }
|
||||
}
|
||||
|
||||
public bool IsReadOnly {
|
||||
get { return HasFlag (ObjectValueFlags.ReadOnly); }
|
||||
}
|
||||
|
||||
public bool IsArray {
|
||||
get { return HasFlag (ObjectValueFlags.Array); }
|
||||
}
|
||||
|
||||
public bool IsObject {
|
||||
get { return HasFlag (ObjectValueFlags.Object); }
|
||||
}
|
||||
|
||||
public bool IsPrimitive {
|
||||
get { return HasFlag (ObjectValueFlags.Primitive); }
|
||||
}
|
||||
|
||||
public bool IsUnknown {
|
||||
get { return HasFlag (ObjectValueFlags.Unknown); }
|
||||
}
|
||||
|
||||
public bool IsNotSupported {
|
||||
get { return HasFlag (ObjectValueFlags.NotSupported); }
|
||||
}
|
||||
|
||||
public bool IsImplicitNotSupported {
|
||||
get { return HasFlag (ObjectValueFlags.ImplicitNotSupported); }
|
||||
}
|
||||
|
||||
public bool IsError {
|
||||
get { return HasFlag (ObjectValueFlags.Error); }
|
||||
}
|
||||
|
||||
public bool IsEvaluating {
|
||||
get { return HasFlag (ObjectValueFlags.Evaluating); }
|
||||
}
|
||||
|
||||
public bool IsEvaluatingGroup {
|
||||
get { return HasFlag (ObjectValueFlags.EvaluatingGroup); }
|
||||
}
|
||||
|
||||
public bool CanRefresh {
|
||||
get { return source != null && !HasFlag (ObjectValueFlags.NoRefresh); }
|
||||
}
|
||||
|
||||
public bool HasFlag (ObjectValueFlags flag)
|
||||
{
|
||||
return (flags & flag) != 0;
|
||||
}
|
||||
|
||||
public event EventHandler ValueChanged {
|
||||
add {
|
||||
lock (mutex) {
|
||||
valueChanged += value;
|
||||
if (!IsEvaluating)
|
||||
value (this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
remove {
|
||||
lock (mutex) {
|
||||
valueChanged -= value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the value of this object
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method can be called to get a more up-to-date value for this object.
|
||||
/// </remarks>
|
||||
public void Refresh ()
|
||||
{
|
||||
Refresh (parentFrame.DebuggerSession.EvaluationOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the value of this object
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method can be called to get a more up-to-date value for this object.
|
||||
/// </remarks>
|
||||
public void Refresh (EvaluationOptions options)
|
||||
{
|
||||
if (!CanRefresh)
|
||||
return;
|
||||
|
||||
var val = source.GetValue (path, options);
|
||||
UpdateFrom (val, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a wait handle which can be used to wait for the evaluation of this object to end
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The wait handle.
|
||||
/// </value>
|
||||
public WaitHandle WaitHandle {
|
||||
get {
|
||||
lock (mutex) {
|
||||
if (evaluatedEvent == null)
|
||||
evaluatedEvent = new ManualResetEvent (!IsEvaluating);
|
||||
return evaluatedEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal IObjectValueUpdater Updater {
|
||||
get { return updater; }
|
||||
}
|
||||
|
||||
internal void UpdateFrom (ObjectValue val, bool notify)
|
||||
{
|
||||
lock (mutex) {
|
||||
arrayCount = val.arrayCount;
|
||||
if (val.name != null)
|
||||
name = val.name;
|
||||
value = val.value;
|
||||
displayValue = val.displayValue;
|
||||
typeName = val.typeName;
|
||||
flags = val.flags;
|
||||
source = val.source;
|
||||
children = val.children;
|
||||
path = val.path;
|
||||
updater = val.updater;
|
||||
ConnectCallbacks (parentFrame, this);
|
||||
if (evaluatedEvent != null)
|
||||
evaluatedEvent.Set ();
|
||||
if (notify && valueChanged != null)
|
||||
valueChanged (this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
internal UpdateCallback GetUpdateCallback ()
|
||||
{
|
||||
if (IsEvaluating) {
|
||||
if (updateCallback == null)
|
||||
updateCallback = new UpdateCallback (new UpdateCallbackProxy (this), path);
|
||||
return updateCallback;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
~ObjectValue ()
|
||||
{
|
||||
#if !NETCOREAPP
|
||||
if (updateCallback != null)
|
||||
System.Runtime.Remoting.RemotingServices.Disconnect ((UpdateCallbackProxy)updateCallback.Callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void ConnectCallbacks (StackFrame parentFrame, params ObjectValue[] values)
|
||||
{
|
||||
Dictionary<IObjectValueUpdater, List<UpdateCallback>> callbacks = null;
|
||||
var valueList = new List<ObjectValue> (values);
|
||||
|
||||
for (int n = 0; n < valueList.Count; n++) {
|
||||
var val = valueList [n];
|
||||
val.source = parentFrame.DebuggerSession.WrapDebuggerObject (val.source);
|
||||
val.updater = parentFrame.DebuggerSession.WrapDebuggerObject (val.updater);
|
||||
val.parentFrame = parentFrame;
|
||||
|
||||
var cb = val.GetUpdateCallback ();
|
||||
if (cb != null) {
|
||||
if (callbacks == null)
|
||||
callbacks = new Dictionary<IObjectValueUpdater, List<UpdateCallback>> ();
|
||||
|
||||
List<UpdateCallback> list;
|
||||
if (!callbacks.TryGetValue (val.Updater, out list)) {
|
||||
list = new List<UpdateCallback> ();
|
||||
callbacks [val.Updater] = list;
|
||||
}
|
||||
|
||||
list.Add (cb);
|
||||
}
|
||||
|
||||
if (val.children != null)
|
||||
valueList.AddRange (val.children);
|
||||
}
|
||||
|
||||
if (callbacks != null) {
|
||||
// Do the callback connection in a background thread
|
||||
ThreadPool.QueueUserWorkItem (delegate {
|
||||
foreach (KeyValuePair<IObjectValueUpdater, List<UpdateCallback>> cbs in callbacks) {
|
||||
cbs.Key.RegisterUpdateCallbacks (cbs.Value.ToArray ());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateCallbackProxy: MarshalByRefObject, IObjectValueUpdateCallback
|
||||
{
|
||||
readonly WeakReference valRef;
|
||||
|
||||
public void UpdateValue (ObjectValue newValue)
|
||||
{
|
||||
var val = valRef.Target as ObjectValue;
|
||||
|
||||
if (val != null)
|
||||
val.UpdateFrom (newValue, true);
|
||||
}
|
||||
|
||||
public UpdateCallbackProxy (ObjectValue val)
|
||||
{
|
||||
valRef = new WeakReference (val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// ObjectValueKind.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Flags]
|
||||
public enum ObjectValueFlags: uint {
|
||||
None = 0,
|
||||
Object = 1, // The value is an object
|
||||
Array = 1 << 1, // The value is an array
|
||||
Primitive = 1 << 2, // The value is a primitive value
|
||||
Unknown = 1 << 3, // The evaluated identifier is unknown
|
||||
Error = 1 << 4, // The expression evaluation returned an error
|
||||
NotSupported = 1 << 5, // The expression is valid but its evaluation is not supported
|
||||
Evaluating = 1 << 6, // The expression is being evaluated. The value will be updated when done.
|
||||
ImplicitNotSupported = 1 << 7, // The expression is valid but it can't be performed implicitly.
|
||||
KindMask = 0x000000ff,
|
||||
|
||||
Field = 1 << 8,
|
||||
Property = 1 << 9,
|
||||
Parameter = 1 << 10,
|
||||
Variable = 1 << 11,
|
||||
ArrayElement = 1 << 12,
|
||||
Method = 1 << 13,
|
||||
Literal = 1 << 14,
|
||||
Type = 1 << 15,
|
||||
Namespace = 1 << 16,
|
||||
Group = 1 << 17,
|
||||
OriginMask = 0x0003ff00,
|
||||
|
||||
Global = 1 << 18, // For fields, it means static
|
||||
ReadOnly = 1 << 19,
|
||||
NoRefresh = 1 << 20, // When set, this value can't be refreshed
|
||||
EvaluatingGroup = 1 << 21, // When set, this value represents a set of values being evaluated
|
||||
// When evaluation ends, the value is updated, and the children are the
|
||||
// values represented by this group
|
||||
IEnumerable = 1 << 22,
|
||||
|
||||
// For field and property
|
||||
Public = 1 << 24,
|
||||
Protected = 1 << 25,
|
||||
Internal = 1 << 26,
|
||||
Private = 1 << 27,
|
||||
InternalProtected = Internal | Protected,
|
||||
AccessMask = Public | Protected | Internal | Private
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class OutputOptions
|
||||
{
|
||||
public bool ModuleLoaded { get; set; }
|
||||
public bool ModuleUnoaded { get; set; }
|
||||
public bool ExceptionMessage { get; set; }
|
||||
public bool SymbolSearch { get; set; }
|
||||
public bool ThreadExited { get; set; }
|
||||
public bool ProcessExited { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// ProcessEventArgs.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class ProcessEventArgs : EventArgs
|
||||
{
|
||||
public ProcessEventArgs (int processId)
|
||||
{
|
||||
ProcessId = processId;
|
||||
}
|
||||
|
||||
public int ProcessId {
|
||||
get; private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
VisualPascalABCNETLinux/MonoDebugging/Client/ProcessInfo.cs
Normal file
90
VisualPascalABCNETLinux/MonoDebugging/Client/ProcessInfo.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// ProcessInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class ProcessInfo
|
||||
{
|
||||
long id;
|
||||
string name;
|
||||
string description;
|
||||
|
||||
[NonSerialized]
|
||||
DebuggerSession session;
|
||||
|
||||
internal void Attach (DebuggerSession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public long Id {
|
||||
get {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public string Description {
|
||||
get {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
public ProcessInfo (string name, string description)
|
||||
{
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public ProcessInfo (long id, string name)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ThreadInfo[] GetThreads ()
|
||||
{
|
||||
return session.GetThreads (id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets assemblies from the debugger session that matches the process ID.
|
||||
/// </summary>
|
||||
public Assembly[] GetAssemblies ()
|
||||
{
|
||||
return session.GetAssemblies (id);
|
||||
}
|
||||
}
|
||||
}
|
||||
311
VisualPascalABCNETLinux/MonoDebugging/Client/RawValue.cs
Normal file
311
VisualPascalABCNETLinux/MonoDebugging/Client/RawValue.cs
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
//
|
||||
// RawValue.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an object in the process being debugged
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class RawValue : IRawObject
|
||||
{
|
||||
IRawValue source;
|
||||
EvaluationOptions options;
|
||||
DebuggerSession session;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mono.Debugging.Client.RawValue"/> class.
|
||||
/// </summary>
|
||||
/// <param name='source'>
|
||||
/// Value source
|
||||
/// </param>
|
||||
public RawValue (IRawValue source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
void IRawObject.Connect (DebuggerSession session, EvaluationOptions options)
|
||||
{
|
||||
this.options = options;
|
||||
this.session = session;
|
||||
source = session.WrapDebuggerObject (source);
|
||||
}
|
||||
|
||||
internal IRawValue Source {
|
||||
get { return this.source; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Full name of the type of the object
|
||||
/// </summary>
|
||||
public string TypeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a method on the object
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The result of the invocation
|
||||
/// </returns>
|
||||
/// <param name='methodName'>
|
||||
/// The name of the method
|
||||
/// </param>
|
||||
/// <param name='parameters'>
|
||||
/// The parameters (primitive type values, RawValue instances or RawValueArray instances)
|
||||
/// </param>
|
||||
public object CallMethod (string methodName, params object [] parameters)
|
||||
{
|
||||
object res = source.CallMethod (methodName, parameters, options);
|
||||
RawValue val = res as RawValue;
|
||||
if (val != null)
|
||||
val.options = options;
|
||||
IRawObject raw = res as IRawObject;
|
||||
if (raw != null)
|
||||
raw.Connect (session, options);
|
||||
return res;
|
||||
}
|
||||
|
||||
public object CallMethod (string methodName, out object [] outArgs, params object [] parameters)
|
||||
{
|
||||
object res = source.CallMethod (methodName, parameters, out outArgs, options);
|
||||
RawValue val = res as RawValue;
|
||||
if (val != null)
|
||||
val.options = options;
|
||||
IRawObject raw = res as IRawObject;
|
||||
if (raw != null)
|
||||
raw.Connect (session, options);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a field or property
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The value (a primitive type value, a RawValue instance or a RawValueArray instance)
|
||||
/// </returns>
|
||||
/// <param name='name'>
|
||||
/// Name of the field or property
|
||||
/// </param>
|
||||
public object GetMemberValue (string name)
|
||||
{
|
||||
object res = source.GetMemberValue (name, options);
|
||||
RawValue val = res as RawValue;
|
||||
if (val != null)
|
||||
val.options = options;
|
||||
IRawObject raw = res as IRawObject;
|
||||
if (raw != null)
|
||||
raw.Connect (session, options);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of a field or property
|
||||
/// </summary>
|
||||
/// <param name='name'>
|
||||
/// Name of the field or property
|
||||
/// </param>
|
||||
/// <param name='value'>
|
||||
/// The value (a primitive type value, a RawValue instance or a RawValueArray instance)
|
||||
/// </param>
|
||||
public void SetMemberValue (string name, object value)
|
||||
{
|
||||
source.SetMemberValue (name, value, options);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of objects in the process being debugged
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class RawValueArray : IRawObject
|
||||
{
|
||||
IRawValueArray source;
|
||||
EvaluationOptions options;
|
||||
DebuggerSession session;
|
||||
int [] dimensions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mono.Debugging.Client.RawValueArray"/> class.
|
||||
/// </summary>
|
||||
/// <param name='source'>
|
||||
/// Value source.
|
||||
/// </param>
|
||||
public RawValueArray (IRawValueArray source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
void IRawObject.Connect (DebuggerSession session, EvaluationOptions options)
|
||||
{
|
||||
this.options = options;
|
||||
this.session = session;
|
||||
source = session.WrapDebuggerObject (source);
|
||||
}
|
||||
|
||||
internal IRawValueArray Source {
|
||||
get { return this.source; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Full type name of the array items
|
||||
/// </summary>
|
||||
public string ElementTypeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item at the specified index.
|
||||
/// </summary>
|
||||
/// <param name='index'>
|
||||
/// The index
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// The item value can be a primitive type value, a RawValue instance or a RawValueArray instance.
|
||||
/// </remarks>
|
||||
public object this [int index] {
|
||||
get {
|
||||
return source.GetValue (new int [] { index });
|
||||
}
|
||||
set {
|
||||
source.SetValue (new int [] { index }, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values.
|
||||
/// </summary>
|
||||
/// <returns>The items.</returns>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <param name="count">The number of items to get.</param>
|
||||
/// <remarks>
|
||||
/// This method is useful for incrementally fetching an array in order to avoid
|
||||
/// long waiting periods when the array is too large for ToArray().
|
||||
/// </remarks>
|
||||
public Array GetValues (int index, int count)
|
||||
{
|
||||
return source.GetValues (new int [] { index }, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array with all items of the RawValueArray
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is useful to avoid unnecessary debugger-debuggee roundtrips
|
||||
/// when processing all items of an array. For example, if a RawValueArray
|
||||
/// represents an image encoded in a byte[], getting the values one by one
|
||||
/// using the indexer is very slow. The ToArray() will return the whole byte[]
|
||||
/// in a single call.
|
||||
/// </remarks>
|
||||
public Array ToArray ()
|
||||
{
|
||||
var array = source.ToArray ();
|
||||
for (int i = 0; i < array.Length; i++) {
|
||||
var val = array.GetValue (i) as IRawObject;
|
||||
if (val != null) {
|
||||
val.Connect (session, options);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the array
|
||||
/// </summary>
|
||||
public int Length {
|
||||
get {
|
||||
if (dimensions == null)
|
||||
dimensions = source.Dimensions;
|
||||
return dimensions [0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a string object in the process being debugged
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class RawValueString : IRawObject
|
||||
{
|
||||
IRawValueString source;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mono.Debugging.Client.RawValueString"/> class.
|
||||
/// </summary>
|
||||
/// <param name='source'>
|
||||
/// Value source.
|
||||
/// </param>
|
||||
public RawValueString (IRawValueString source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
void IRawObject.Connect (DebuggerSession session, EvaluationOptions options)
|
||||
{
|
||||
source = session.WrapDebuggerObject (source);
|
||||
}
|
||||
|
||||
internal IRawValueString Source {
|
||||
get { return source; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the string
|
||||
/// </summary>
|
||||
public int Length {
|
||||
get { return source.Length; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a substring of the string
|
||||
/// </summary>
|
||||
/// <param name='index'>
|
||||
/// The starting index of the requested substring.
|
||||
/// </param>
|
||||
/// <param name='length'>
|
||||
/// The length of the requested substring.
|
||||
/// </param>
|
||||
public string Substring (int index, int length)
|
||||
{
|
||||
return source.Substring (index, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The value.
|
||||
/// </value>
|
||||
public string Value {
|
||||
get { return source.Value; }
|
||||
}
|
||||
}
|
||||
|
||||
interface IRawObject
|
||||
{
|
||||
void Connect (DebuggerSession session, EvaluationOptions options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// RunToCursorBreakpoint.cs
|
||||
//
|
||||
// Author: Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2014 Xamarin Inc. (www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public sealed class RunToCursorBreakpoint : Breakpoint
|
||||
{
|
||||
public RunToCursorBreakpoint (string fileName, int line, int column) : base (fileName, line, column)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
25
VisualPascalABCNETLinux/MonoDebugging/Client/SourceLink.cs
Normal file
25
VisualPascalABCNETLinux/MonoDebugging/Client/SourceLink.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class SourceLink
|
||||
{
|
||||
public string Uri { get; }
|
||||
|
||||
public string RelativeFilePath { get; }
|
||||
|
||||
public SourceLink (string uri, string relativeFilePath)
|
||||
{
|
||||
RelativeFilePath = relativeFilePath;
|
||||
Uri = uri;
|
||||
}
|
||||
|
||||
public string GetDownloadLocation (string cachePath)
|
||||
{
|
||||
var uri = new Uri (Uri);
|
||||
return Path.Combine (cachePath, uri.Host + uri.PathAndQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
190
VisualPascalABCNETLinux/MonoDebugging/Client/SourceLocation.cs
Normal file
190
VisualPascalABCNETLinux/MonoDebugging/Client/SourceLocation.cs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class SourceLocation
|
||||
{
|
||||
public string MethodName { get; private set; }
|
||||
public string FileName { get; private set; }
|
||||
public int Line { get; private set; }
|
||||
public int Column { get; private set; }
|
||||
public int EndLine { get; private set; }
|
||||
public int EndColumn { get; private set; }
|
||||
public byte[] FileHash { get; private set; }
|
||||
public SourceLink SourceLink { get; private set; }
|
||||
|
||||
[Obsolete]
|
||||
public SourceLocation (string methodName, string fileName, int line)
|
||||
: this (methodName, fileName, line, -1, -1, -1, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SourceLocation (string methodName, string fileName, int line, int column, int endLine, int endColumn)
|
||||
: this (methodName, fileName, line, column, endLine, endColumn, null, null)
|
||||
{
|
||||
|
||||
}
|
||||
public SourceLocation (string methodName, string fileName, int line, int column, int endLine, int endColumn, byte [] hash = null)
|
||||
: this (methodName, fileName, line, column, endLine, endColumn, hash, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SourceLocation (string methodName, string fileName, int line, int column, int endLine, int endColumn, byte[] hash = null, SourceLink sourceLink = null)
|
||||
{
|
||||
this.MethodName = methodName;
|
||||
this.FileName = fileName;
|
||||
this.Line = line;
|
||||
this.Column = column;
|
||||
this.EndLine = endLine;
|
||||
this.EndColumn = endColumn;
|
||||
this.FileHash = hash;
|
||||
this.SourceLink = sourceLink;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return string.Format("[SourceLocation Method={0}, Filename={1}, Line={2}, Column={3}]", MethodName, FileName, Line, Column);
|
||||
}
|
||||
|
||||
static void ComputeHashes (Stream stream, HashAlgorithm hash, HashAlgorithm dos, HashAlgorithm unix)
|
||||
{
|
||||
var unixBuffer = new byte[4096 + 1];
|
||||
var dosBuffer = new byte[8192 + 1];
|
||||
var buffer = new byte[4096];
|
||||
byte pc = 0;
|
||||
int count;
|
||||
|
||||
try {
|
||||
while ((count = stream.Read (buffer, 0, buffer.Length)) > 0) {
|
||||
int unixIndex = 0, dosIndex = 0;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
var c = buffer[i];
|
||||
|
||||
if (c == (byte) '\r') {
|
||||
if (pc == (byte) '\r')
|
||||
unixBuffer[unixIndex++] = pc;
|
||||
dosBuffer[dosIndex++] = c;
|
||||
} else if (c == (byte) '\n') {
|
||||
if (pc != (byte) '\r')
|
||||
dosBuffer[dosIndex++] = (byte) '\r';
|
||||
unixBuffer[unixIndex++] = c;
|
||||
dosBuffer[dosIndex++] = c;
|
||||
} else {
|
||||
if (pc == (byte) '\r')
|
||||
unixBuffer[unixIndex++] = pc;
|
||||
unixBuffer[unixIndex++] = c;
|
||||
dosBuffer[dosIndex++] = c;
|
||||
}
|
||||
|
||||
pc = c;
|
||||
}
|
||||
|
||||
hash.TransformBlock (buffer, 0, count, outputBuffer: null, outputOffset: 0);
|
||||
dos.TransformBlock (dosBuffer, 0, dosIndex, outputBuffer: null, outputOffset: 0);
|
||||
unix.TransformBlock (unixBuffer, 0, unixIndex, outputBuffer: null, outputOffset: 0);
|
||||
}
|
||||
|
||||
hash.TransformFinalBlock (buffer, 0, 0);
|
||||
dos.TransformFinalBlock (buffer, 0, 0);
|
||||
unix.TransformFinalBlock (buffer, 0, 0);
|
||||
} finally {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static List<byte[]> ComputeChecksums (string path, string algorithm)
|
||||
{
|
||||
using (var stream = File.OpenRead (path)) {
|
||||
using (var hash = HashAlgorithm.Create (algorithm)) {
|
||||
using (var dos = HashAlgorithm.Create (algorithm)) {
|
||||
using (var unix = HashAlgorithm.Create (algorithm)) {
|
||||
ComputeHashes (stream, hash, dos, unix);
|
||||
|
||||
var checksums = new List<byte[]> (3);
|
||||
checksums.Add (hash.Hash);
|
||||
checksums.Add (dos.Hash);
|
||||
checksums.Add (unix.Hash);
|
||||
return checksums;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool ChecksumsEqual (byte[] calculated, byte[] checksum, int skip = 0)
|
||||
{
|
||||
if (skip > 0) {
|
||||
if (calculated.Length < checksum.Length - skip)
|
||||
return false;
|
||||
} else {
|
||||
if (calculated.Length != checksum.Length)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0, csi = skip; csi < checksum.Length; i++, csi++) {
|
||||
if (calculated[i] != checksum[csi])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CheckHash (Stream stream, string algorithm, byte[] checksum)
|
||||
{
|
||||
using (var hash = HashAlgorithm.Create (algorithm)) {
|
||||
int size = hash.HashSize / 8;
|
||||
|
||||
using (var dos = HashAlgorithm.Create (algorithm)) {
|
||||
using (var unix = HashAlgorithm.Create (algorithm)) {
|
||||
stream.Position = 0;
|
||||
|
||||
ComputeHashes (stream, hash, dos, unix);
|
||||
|
||||
if (checksum [0] == size && checksum.Length < size) {
|
||||
return ChecksumsEqual (hash.Hash, checksum, 1) ||
|
||||
ChecksumsEqual (unix.Hash, checksum, 1) ||
|
||||
ChecksumsEqual (dos.Hash, checksum, 1);
|
||||
}
|
||||
|
||||
return ChecksumsEqual (hash.Hash, checksum) ||
|
||||
ChecksumsEqual (unix.Hash, checksum) ||
|
||||
ChecksumsEqual (dos.Hash, checksum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckFileHash (string path, byte[] checksum)
|
||||
{
|
||||
if (checksum == null || checksum.Length == 0 || !File.Exists (path))
|
||||
return false;
|
||||
|
||||
using (var stream = File.OpenRead (path)) {
|
||||
if (checksum.Length == 16) {
|
||||
// Note: Roslyn SHA1 hashes are 16 bytes and start w/ 20
|
||||
if (checksum[0] == 20 && CheckHash (stream, "SHA1", checksum))
|
||||
return true;
|
||||
|
||||
// Note: Roslyn SHA256 hashes are 16 bytes and start w/ 32
|
||||
if (checksum[0] == 32 && CheckHash (stream, "SHA256", checksum))
|
||||
return true;
|
||||
|
||||
return CheckHash (stream, "MD5", checksum);
|
||||
}
|
||||
|
||||
if (checksum.Length == 20)
|
||||
return CheckHash (stream, "SHA1", checksum);
|
||||
|
||||
if (checksum.Length == 32)
|
||||
return CheckHash (stream, "SHA256", checksum);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
475
VisualPascalABCNETLinux/MonoDebugging/Client/StackFrame.cs
Normal file
475
VisualPascalABCNETLinux/MonoDebugging/Client/StackFrame.cs
Normal file
|
|
@ -0,0 +1,475 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class StackFrame
|
||||
{
|
||||
long address;
|
||||
string addressSpace;
|
||||
SourceLocation location;
|
||||
IBacktrace sourceBacktrace;
|
||||
string language;
|
||||
int index;
|
||||
bool isExternalCode;
|
||||
bool isDebuggerHidden;
|
||||
bool hasDebugInfo;
|
||||
string fullTypeName;
|
||||
|
||||
[NonSerialized]
|
||||
DebuggerSession session;
|
||||
[NonSerialized]
|
||||
bool haveParameterValues;
|
||||
[NonSerialized]
|
||||
ObjectValue[] parameters;
|
||||
|
||||
public StackFrame (long address, string addressSpace, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo, bool isDebuggerHidden, string fullModuleName, string fullTypeName)
|
||||
{
|
||||
this.address = address;
|
||||
this.addressSpace = addressSpace;
|
||||
this.location = location;
|
||||
this.language = language;
|
||||
this.isExternalCode = isExternalCode;
|
||||
this.isDebuggerHidden = isDebuggerHidden;
|
||||
this.hasDebugInfo = hasDebugInfo;
|
||||
this.FullModuleName = fullModuleName;
|
||||
this.fullTypeName = fullTypeName;
|
||||
}
|
||||
|
||||
public StackFrame (long address, string addressSpace, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo, string fullModuleName, string fullTypeName)
|
||||
: this (address, addressSpace, location, language, isExternalCode, hasDebugInfo, false, fullModuleName, fullTypeName)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public StackFrame (long address, string addressSpace, SourceLocation location, string language)
|
||||
: this (address, addressSpace, location, language, string.IsNullOrEmpty (location.FileName), true, "", "")
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public StackFrame (long address, string addressSpace, string module, string method, string filename, int line, string language)
|
||||
: this (address, addressSpace, new SourceLocation (method, filename, line), language)
|
||||
{
|
||||
}
|
||||
|
||||
public StackFrame (long address, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo)
|
||||
: this (address, "", location, language, string.IsNullOrEmpty (location.FileName) || isExternalCode, hasDebugInfo, "", "")
|
||||
{
|
||||
}
|
||||
|
||||
public StackFrame (long address, SourceLocation location, string language)
|
||||
: this (address, "", location, language, string.IsNullOrEmpty (location.FileName), true, "", "")
|
||||
{
|
||||
}
|
||||
|
||||
internal void Attach (DebuggerSession debugSession)
|
||||
{
|
||||
session = debugSession;
|
||||
}
|
||||
|
||||
public DebuggerSession DebuggerSession {
|
||||
get { return session; }
|
||||
}
|
||||
|
||||
public SourceLocation SourceLocation {
|
||||
get { return location; }
|
||||
}
|
||||
|
||||
public long Address {
|
||||
get { return address; }
|
||||
}
|
||||
|
||||
public string AddressSpace {
|
||||
get { return addressSpace; }
|
||||
}
|
||||
|
||||
internal IBacktrace SourceBacktrace {
|
||||
get { return sourceBacktrace; }
|
||||
set { sourceBacktrace = value; }
|
||||
}
|
||||
|
||||
public int Index {
|
||||
get { return index; }
|
||||
internal set { index = value; }
|
||||
}
|
||||
|
||||
public string Language {
|
||||
get { return language; }
|
||||
}
|
||||
|
||||
public bool IsExternalCode {
|
||||
get { return isExternalCode; }
|
||||
}
|
||||
|
||||
public bool IsDebuggerHidden {
|
||||
get { return isDebuggerHidden; }
|
||||
}
|
||||
|
||||
public bool HasDebugInfo {
|
||||
get { return hasDebugInfo; }
|
||||
}
|
||||
|
||||
public string FullModuleName { get; protected set; }
|
||||
|
||||
public string FullTypeName {
|
||||
get { return fullTypeName; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full name of the stackframe. Which respects Session.EvaluationOptions.StackFrameFormat
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public string FullStackframeText {
|
||||
get { return GetFullStackFrameText (); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to ignore a first-chance exception in the given location (module, type, method and IL offset).
|
||||
/// </summary>
|
||||
public string GetLocationSignature ()
|
||||
{
|
||||
string methodName = this.SourceLocation.MethodName;
|
||||
if (methodName != null && !methodName.Contains("!")) {
|
||||
methodName = $"{Path.GetFileName (this.FullModuleName)}!{methodName}";
|
||||
}
|
||||
|
||||
if (this.Address != 0) {
|
||||
methodName = $"{methodName}:{Address}";
|
||||
}
|
||||
|
||||
return methodName;
|
||||
}
|
||||
|
||||
public string GetFullStackFrameText ()
|
||||
{
|
||||
return GetFullStackFrameText (session.EvaluationOptions);
|
||||
}
|
||||
|
||||
public virtual string GetFullStackFrameText (EvaluationOptions options)
|
||||
{
|
||||
using (var cts = new CancellationTokenSource (options.MemberEvaluationTimeout))
|
||||
return GetFullStackFrameTextAsync (options, false, cts.Token).GetAwaiter ().GetResult ();
|
||||
}
|
||||
|
||||
public Task<string> GetFullStackFrameTextAsync (CancellationToken cancellationToken = default (CancellationToken))
|
||||
{
|
||||
return GetFullStackFrameTextAsync (session.EvaluationOptions, true, cancellationToken);
|
||||
}
|
||||
|
||||
public virtual Task<string> GetFullStackFrameTextAsync (EvaluationOptions options, CancellationToken cancellationToken = default (CancellationToken))
|
||||
{
|
||||
return GetFullStackFrameTextAsync (options, true, cancellationToken);
|
||||
}
|
||||
|
||||
async Task<string> GetFullStackFrameTextAsync (EvaluationOptions options, bool doAsync, CancellationToken cancellationToken)
|
||||
{
|
||||
// If MethodName starts with "[", then it's something like [ExternalCode]
|
||||
if (SourceLocation.MethodName.StartsWith ("[", StringComparison.Ordinal))
|
||||
return SourceLocation.MethodName;
|
||||
|
||||
options = options.Clone ();
|
||||
if (options.StackFrameFormat.ParameterValues) {
|
||||
options.AllowMethodEvaluation = true;
|
||||
options.AllowToStringCalls = true;
|
||||
options.AllowTargetInvoke = true;
|
||||
} else {
|
||||
options.AllowMethodEvaluation = false;
|
||||
options.AllowToStringCalls = false;
|
||||
options.AllowTargetInvoke = false;
|
||||
}
|
||||
|
||||
// Cache the method parameters. Only refresh the method params iff the cached args do not
|
||||
// already have parameter values. Once we have parameter values, we never have to
|
||||
// refresh the cached parameters because we can just omit the parameter values when
|
||||
// constructing the display string.
|
||||
if (parameters == null || (options.StackFrameFormat.ParameterValues && !haveParameterValues)) {
|
||||
haveParameterValues = options.StackFrameFormat.ParameterValues;
|
||||
parameters = GetParameters (options);
|
||||
}
|
||||
|
||||
var methodNameBuilder = new StringBuilder ();
|
||||
|
||||
if (options.StackFrameFormat.Module && !string.IsNullOrEmpty (FullModuleName)) {
|
||||
methodNameBuilder.Append (Path.GetFileName (FullModuleName));
|
||||
methodNameBuilder.Append ('!');
|
||||
}
|
||||
|
||||
methodNameBuilder.Append (SourceLocation.MethodName);
|
||||
|
||||
if (options.StackFrameFormat.ParameterTypes || options.StackFrameFormat.ParameterNames || options.StackFrameFormat.ParameterValues) {
|
||||
methodNameBuilder.Append ('(');
|
||||
for (int n = 0; n < parameters.Length; n++) {
|
||||
if (parameters[n].IsEvaluating) {
|
||||
var tcs = new TaskCompletionSource<bool> ();
|
||||
EventHandler updated = (s, e) => {
|
||||
tcs.TrySetResult (true);
|
||||
};
|
||||
parameters[n].ValueChanged += updated;
|
||||
try {
|
||||
using (var registration = cancellationToken.Register (() => tcs.TrySetCanceled ())) {
|
||||
if (parameters[n].IsEvaluating) {
|
||||
if (doAsync) {
|
||||
await tcs.Task.ConfigureAwait (false);
|
||||
} else {
|
||||
tcs.Task.Wait (cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
parameters[n].ValueChanged -= updated;
|
||||
}
|
||||
}
|
||||
if (n > 0)
|
||||
methodNameBuilder.Append (", ");
|
||||
if (options.StackFrameFormat.ParameterTypes) {
|
||||
methodNameBuilder.Append (parameters[n].TypeName);
|
||||
if (options.StackFrameFormat.ParameterNames)
|
||||
methodNameBuilder.Append (' ');
|
||||
}
|
||||
if (options.StackFrameFormat.ParameterNames)
|
||||
methodNameBuilder.Append (parameters[n].Name);
|
||||
if (options.StackFrameFormat.ParameterValues) {
|
||||
if (options.StackFrameFormat.ParameterTypes || options.StackFrameFormat.ParameterNames)
|
||||
methodNameBuilder.Append (" = ");
|
||||
var val = parameters[n].Value ?? string.Empty;
|
||||
methodNameBuilder.Append (val.Replace ("\r\n", " ").Replace ("\n", " "));
|
||||
}
|
||||
}
|
||||
methodNameBuilder.Append (')');
|
||||
}
|
||||
|
||||
return methodNameBuilder.ToString ();
|
||||
}
|
||||
|
||||
public ObjectValue[] GetLocalVariables ()
|
||||
{
|
||||
return GetLocalVariables (session.EvaluationOptions);
|
||||
}
|
||||
|
||||
public ObjectValue[] GetLocalVariables (EvaluationOptions options)
|
||||
{
|
||||
if (!hasDebugInfo) {
|
||||
DebuggerLoggingService.LogMessage ("Cannot get local variables: no debugging symbols for frame: {0}", this);
|
||||
return new ObjectValue [0];
|
||||
}
|
||||
|
||||
var values = sourceBacktrace.GetLocalVariables (index, options);
|
||||
ObjectValue.ConnectCallbacks (this, values);
|
||||
return values;
|
||||
}
|
||||
|
||||
public ObjectValue[] GetParameters ()
|
||||
{
|
||||
return GetParameters (session.EvaluationOptions);
|
||||
}
|
||||
|
||||
public ObjectValue[] GetParameters (EvaluationOptions options)
|
||||
{
|
||||
if (!hasDebugInfo) {
|
||||
DebuggerLoggingService.LogMessage ("Cannot get parameters: no debugging symbols for frame: {0}", this);
|
||||
return new ObjectValue [0];
|
||||
}
|
||||
|
||||
var values = sourceBacktrace.GetParameters (index, options);
|
||||
ObjectValue.ConnectCallbacks (this, values);
|
||||
return values;
|
||||
}
|
||||
|
||||
public ObjectValue[] GetAllLocals ()
|
||||
{
|
||||
if (!hasDebugInfo) {
|
||||
DebuggerLoggingService.LogMessage ("Cannot get local variables: no debugging symbols for frame: {0}", this);
|
||||
return new ObjectValue [0];
|
||||
}
|
||||
|
||||
var evaluator = session.FindExpressionEvaluator (this);
|
||||
|
||||
return evaluator != null ? evaluator.GetLocals (this) : GetAllLocals (session.EvaluationOptions);
|
||||
}
|
||||
|
||||
public ObjectValue[] GetAllLocals (EvaluationOptions options)
|
||||
{
|
||||
if (!hasDebugInfo) {
|
||||
DebuggerLoggingService.LogMessage ("Cannot get local variables: no debugging symbols for frame: {0}", this);
|
||||
return new ObjectValue [0];
|
||||
}
|
||||
|
||||
var values = sourceBacktrace.GetAllLocals (index, options);
|
||||
ObjectValue.ConnectCallbacks (this, values);
|
||||
return values;
|
||||
}
|
||||
|
||||
public ObjectValue GetThisReference ()
|
||||
{
|
||||
return GetThisReference (session.EvaluationOptions);
|
||||
}
|
||||
|
||||
public ObjectValue GetThisReference (EvaluationOptions options)
|
||||
{
|
||||
if (!hasDebugInfo) {
|
||||
DebuggerLoggingService.LogMessage ("Cannot get `this' reference: no debugging symbols for frame: {0}", this);
|
||||
return null;
|
||||
}
|
||||
|
||||
var value = sourceBacktrace.GetThisReference (index, options);
|
||||
if (value != null)
|
||||
ObjectValue.ConnectCallbacks (this, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public ExceptionInfo GetException ()
|
||||
{
|
||||
return GetException (session.EvaluationOptions);
|
||||
}
|
||||
|
||||
public ExceptionInfo GetException (EvaluationOptions options)
|
||||
{
|
||||
var value = sourceBacktrace.GetException (index, options);
|
||||
if (value != null)
|
||||
value.ConnectCallback (this);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public string ResolveExpression (string exp)
|
||||
{
|
||||
return session.ResolveExpression (exp, location);
|
||||
}
|
||||
|
||||
public ObjectValue[] GetExpressionValues (string[] expressions, bool evaluateMethods)
|
||||
{
|
||||
var options = session.EvaluationOptions.Clone ();
|
||||
options.AllowMethodEvaluation = evaluateMethods;
|
||||
return GetExpressionValues (expressions, options);
|
||||
}
|
||||
|
||||
public ObjectValue[] GetExpressionValues (string[] expressions, EvaluationOptions options)
|
||||
{
|
||||
if (!hasDebugInfo) {
|
||||
DebuggerLoggingService.LogMessage ("Cannot get expression values: no debugging symbols for frame: {0}", this);
|
||||
|
||||
var vals = new ObjectValue [expressions.Length];
|
||||
for (int n = 0; n < expressions.Length; n++)
|
||||
vals[n] = ObjectValue.CreateUnknown (expressions[n]);
|
||||
|
||||
return vals;
|
||||
}
|
||||
|
||||
if (options.UseExternalTypeResolver) {
|
||||
var resolved = new string [expressions.Length];
|
||||
for (int n = 0; n < expressions.Length; n++)
|
||||
resolved[n] = ResolveExpression (expressions[n]);
|
||||
|
||||
expressions = resolved;
|
||||
}
|
||||
|
||||
var values = sourceBacktrace.GetExpressionValues (index, expressions, options);
|
||||
ObjectValue.ConnectCallbacks (this, values);
|
||||
return values;
|
||||
}
|
||||
|
||||
public ObjectValue GetExpressionValue (string expression, bool evaluateMethods)
|
||||
{
|
||||
var options = session.EvaluationOptions.Clone ();
|
||||
options.AllowMethodEvaluation = evaluateMethods;
|
||||
return GetExpressionValue (expression, options);
|
||||
}
|
||||
|
||||
public ObjectValue GetExpressionValue (string expression, EvaluationOptions options)
|
||||
{
|
||||
if (!hasDebugInfo) {
|
||||
DebuggerLoggingService.LogMessage ("Cannot get expression value: no debugging symbols for frame: {0}", this);
|
||||
return ObjectValue.CreateUnknown (expression);
|
||||
}
|
||||
|
||||
if (options.UseExternalTypeResolver)
|
||||
expression = ResolveExpression (expression);
|
||||
|
||||
var values = sourceBacktrace.GetExpressionValues (index, new [] { expression }, options);
|
||||
ObjectValue.ConnectCallbacks (this, values);
|
||||
return values [0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns True if the expression is valid and can be evaluated for this frame.
|
||||
/// </summary>
|
||||
public bool ValidateExpression (string expression)
|
||||
{
|
||||
return ValidateExpression (expression, session.EvaluationOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns True if the expression is valid and can be evaluated for this frame.
|
||||
/// </summary>
|
||||
public ValidationResult ValidateExpression (string expression, EvaluationOptions options)
|
||||
{
|
||||
if (options.UseExternalTypeResolver)
|
||||
expression = ResolveExpression (expression);
|
||||
|
||||
return sourceBacktrace.ValidateExpression (index, expression, options);
|
||||
}
|
||||
|
||||
public CompletionData GetExpressionCompletionData (string exp)
|
||||
{
|
||||
return hasDebugInfo ? sourceBacktrace.GetExpressionCompletionData (index, exp) : null;
|
||||
}
|
||||
|
||||
// Returns disassembled code for this stack frame.
|
||||
// firstLine is the relative code line. It can be negative.
|
||||
public AssemblyLine[] Disassemble (int firstLine, int count)
|
||||
{
|
||||
return sourceBacktrace.Disassemble (index, firstLine, count);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string loc;
|
||||
|
||||
if (location.Line != -1 && !string.IsNullOrEmpty (location.FileName)) {
|
||||
loc = " at " + location.FileName + ":" + location.Line;
|
||||
if (location.Column != 0)
|
||||
loc += "," + location.Column;
|
||||
} else if (!string.IsNullOrEmpty (location.FileName)) {
|
||||
loc = " at " + location.FileName;
|
||||
} else {
|
||||
loc = string.Empty;
|
||||
}
|
||||
|
||||
return string.Format ("0x{0:X} in {1}{2}", address, location.MethodName, loc);
|
||||
}
|
||||
|
||||
public void UpdateSourceFile (string newFilePath)
|
||||
{
|
||||
location = new SourceLocation (location.MethodName, newFilePath, location.Line, location.Column, location.EndLine, location.EndColumn, location.FileHash, location.SourceLink);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct ValidationResult
|
||||
{
|
||||
readonly string message;
|
||||
readonly bool isValid;
|
||||
|
||||
public ValidationResult (bool isValid, string message)
|
||||
{
|
||||
this.isValid = isValid;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public bool IsValid { get { return isValid; } }
|
||||
public string Message { get { return message; } }
|
||||
|
||||
public static implicit operator bool (ValidationResult result)
|
||||
{
|
||||
return result.isValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class TargetEventArgs: EventArgs
|
||||
{
|
||||
TargetEventType type;
|
||||
Backtrace backtrace;
|
||||
ProcessInfo process;
|
||||
ThreadInfo thread;
|
||||
|
||||
public TargetEventArgs (TargetEventType type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public TargetEventType Type
|
||||
{
|
||||
get { return type; }
|
||||
set { type = value; }
|
||||
}
|
||||
|
||||
public Backtrace Backtrace
|
||||
{
|
||||
get { return backtrace; }
|
||||
set { backtrace = value; }
|
||||
}
|
||||
|
||||
public ThreadInfo Thread {
|
||||
get {
|
||||
return thread;
|
||||
}
|
||||
set {
|
||||
thread = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ProcessInfo Process {
|
||||
get {
|
||||
return process;
|
||||
}
|
||||
set {
|
||||
process = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsStopEvent {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public BreakEvent BreakEvent {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public int? ExitCode {
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public enum TargetEventType
|
||||
{
|
||||
TargetReady,
|
||||
TargetStopped,
|
||||
TargetInterrupted,
|
||||
TargetHitBreakpoint,
|
||||
TargetSignaled,
|
||||
TargetExited,
|
||||
ExceptionThrown,
|
||||
UnhandledException,
|
||||
ThreadStarted,
|
||||
ThreadStopped
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// ThreadEventArgs.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class ThreadEventArgs : EventArgs
|
||||
{
|
||||
public ThreadEventArgs (int threadId)
|
||||
{
|
||||
ThreadId = threadId;
|
||||
}
|
||||
|
||||
public int ThreadId {
|
||||
get; private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
146
VisualPascalABCNETLinux/MonoDebugging/Client/ThreadInfo.cs
Normal file
146
VisualPascalABCNETLinux/MonoDebugging/Client/ThreadInfo.cs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
// ThreadInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
[Serializable]
|
||||
public class ThreadInfo
|
||||
{
|
||||
long id;
|
||||
string name;
|
||||
long processId;
|
||||
string location;
|
||||
Backtrace backtrace;
|
||||
|
||||
[NonSerialized]
|
||||
DebuggerSession session;
|
||||
|
||||
internal void Attach (DebuggerSession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public long Id {
|
||||
get {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public string Location {
|
||||
get {
|
||||
if (location == null) {
|
||||
PrefetchBacktrace ();
|
||||
if (backtrace != null && backtrace.FrameCount > 0)
|
||||
location = backtrace.GetFrame (0).ToString ();
|
||||
}
|
||||
return location;
|
||||
}
|
||||
}
|
||||
|
||||
internal long ProcessId {
|
||||
get { return processId; }
|
||||
}
|
||||
|
||||
public Backtrace Backtrace {
|
||||
get {
|
||||
PrefetchBacktrace ();
|
||||
return backtrace;
|
||||
}
|
||||
}
|
||||
|
||||
public long ElapsedTime {
|
||||
get {
|
||||
var elapsedTime = session.GetElapsedTime (processId, id);
|
||||
return elapsedTime;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetActive ()
|
||||
{
|
||||
session.ActiveThread = this;
|
||||
}
|
||||
|
||||
public void PrefetchBacktrace ()
|
||||
{
|
||||
if (backtrace == null)
|
||||
backtrace = session.GetBacktrace (processId, id);
|
||||
}
|
||||
|
||||
public ThreadInfo (long processId, long id, string name, string location): this (processId, id, name, location, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ThreadInfo (long processId, long id, string name, string location, Backtrace backtrace)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.processId = processId;
|
||||
this.location = location;
|
||||
this.backtrace = backtrace;
|
||||
}
|
||||
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (obj is ThreadInfo ot)
|
||||
return id == ot.id && processId == ot.processId && session == ot.session;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
unchecked {
|
||||
return (int) (id + processId*1000);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator == (ThreadInfo t1, ThreadInfo t2)
|
||||
{
|
||||
if (object.ReferenceEquals (t1, t2))
|
||||
return true;
|
||||
if ((object)t1 == null || (object)t2 == null)
|
||||
return false;
|
||||
return t1.Equals (t2);
|
||||
}
|
||||
|
||||
public static bool operator != (ThreadInfo t1, ThreadInfo t2)
|
||||
{
|
||||
if (object.ReferenceEquals (t1, t2))
|
||||
return false;
|
||||
if (t1 == null || t2 == null)
|
||||
return true;
|
||||
return !t1.Equals (t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
VisualPascalABCNETLinux/MonoDebugging/Client/UsageCounter.cs
Normal file
55
VisualPascalABCNETLinux/MonoDebugging/Client/UsageCounter.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// UsageCounter.cs
|
||||
//
|
||||
// Author:
|
||||
// Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||
//
|
||||
// Copyright (c) 2020 Microsoft Corp.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Client
|
||||
{
|
||||
public class UsageCounter
|
||||
{
|
||||
readonly Dictionary<string, int> stats = new Dictionary<string, int> ();
|
||||
|
||||
public UsageCounter ()
|
||||
{
|
||||
}
|
||||
|
||||
public bool HasUsageStats {
|
||||
get { return stats.Count > 0; }
|
||||
}
|
||||
|
||||
public void IncrementUsage (string action)
|
||||
{
|
||||
stats.TryGetValue (action, out var value);
|
||||
stats[action] = value + 1;
|
||||
}
|
||||
|
||||
public void Serialize (Dictionary<string, object> metadata)
|
||||
{
|
||||
foreach (var kvp in stats)
|
||||
metadata[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
// ArrayElementGroup.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class ArrayElementGroup: RemoteFrameObject, IObjectValueSource
|
||||
{
|
||||
readonly ICollectionAdaptor array;
|
||||
readonly EvaluationContext ctx;
|
||||
int[] baseIndices;
|
||||
int[] dimensions;
|
||||
int firstIndex;
|
||||
int lastIndex;
|
||||
|
||||
const int MaxChildCount = 150;
|
||||
|
||||
public ArrayElementGroup (EvaluationContext ctx, ICollectionAdaptor array)
|
||||
: this (ctx, array, new int [0])
|
||||
{
|
||||
}
|
||||
|
||||
public ArrayElementGroup (EvaluationContext ctx, ICollectionAdaptor array, int[] baseIndices)
|
||||
: this (ctx, array, baseIndices, 0, -1)
|
||||
{
|
||||
}
|
||||
|
||||
public ArrayElementGroup (EvaluationContext ctx, ICollectionAdaptor array, int[] baseIndices, int firstIndex, int lastIndex)
|
||||
{
|
||||
this.array = array;
|
||||
this.ctx = ctx;
|
||||
this.dimensions = array.GetDimensions ();
|
||||
this.baseIndices = baseIndices;
|
||||
this.firstIndex = firstIndex;
|
||||
this.lastIndex = lastIndex;
|
||||
}
|
||||
|
||||
public bool IsRange {
|
||||
get { return lastIndex != -1; }
|
||||
}
|
||||
|
||||
public ObjectValue CreateObjectValue ()
|
||||
{
|
||||
Connect ();
|
||||
|
||||
var sb = new StringBuilder ("[");
|
||||
|
||||
for (int i = 0; i < baseIndices.Length; i++) {
|
||||
if (i > 0)
|
||||
sb.Append (", ");
|
||||
sb.Append (baseIndices[i].ToString ());
|
||||
}
|
||||
|
||||
if (IsRange) {
|
||||
if (baseIndices.Length > 0)
|
||||
sb.Append (", ");
|
||||
|
||||
sb.Append (firstIndex.ToString ()).Append ("..").Append (lastIndex.ToString ());
|
||||
}
|
||||
|
||||
if (dimensions.Length > 1 && baseIndices.Length < dimensions.Length)
|
||||
sb.Append (", ...");
|
||||
|
||||
sb.Append ("]");
|
||||
|
||||
ObjectValue res = ObjectValue.CreateObject (this, new ObjectPath (sb.ToString ()), "", "", ObjectValueFlags.ArrayElement|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
|
||||
res.ChildSelector = "";
|
||||
return res;
|
||||
}
|
||||
|
||||
public ObjectValue[] GetChildren (EvaluationOptions options)
|
||||
{
|
||||
return GetChildren (new ObjectPath ("this"), -1, -1, options);
|
||||
}
|
||||
|
||||
public ObjectValue[] GetChildren (ObjectPath path, int firstItemIndex, int count, EvaluationOptions options)
|
||||
{
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
if (path.Length > 1) {
|
||||
// Looking for children of an array element
|
||||
int[] idx = StringToIndices (path [1]);
|
||||
object obj = array.GetElement (idx);
|
||||
return cctx.Adapter.GetObjectValueChildren (cctx, new ArrayObjectSource (array, path[1]), obj, firstItemIndex, count);
|
||||
}
|
||||
|
||||
int lowerBound;
|
||||
int upperBound;
|
||||
bool isLastDimension;
|
||||
|
||||
if (dimensions.Length > 1) {
|
||||
int rank = baseIndices.Length;
|
||||
lowerBound = array.GetLowerBounds () [rank];
|
||||
upperBound = lowerBound + dimensions [rank] - 1;
|
||||
isLastDimension = rank == dimensions.Length - 1;
|
||||
} else {
|
||||
lowerBound = array.GetLowerBounds () [0];
|
||||
upperBound = lowerBound + dimensions [0] - 1;
|
||||
isLastDimension = true;
|
||||
}
|
||||
|
||||
int len;
|
||||
int initalIndex;
|
||||
|
||||
if (!IsRange) {
|
||||
initalIndex = lowerBound;
|
||||
len = upperBound + 1 - lowerBound;
|
||||
} else {
|
||||
initalIndex = firstIndex;
|
||||
len = lastIndex - firstIndex + 1;
|
||||
}
|
||||
|
||||
if (firstItemIndex == -1) {
|
||||
firstItemIndex = 0;
|
||||
count = len;
|
||||
}
|
||||
|
||||
// Make sure the group doesn't have too many elements. If so, divide
|
||||
int div = 1;
|
||||
while (len / div > MaxChildCount)
|
||||
div *= 10;
|
||||
|
||||
if (div == 1 && isLastDimension) {
|
||||
// Return array elements
|
||||
|
||||
ObjectValue[] values = new ObjectValue [count];
|
||||
ObjectPath newPath = new ObjectPath ("this");
|
||||
|
||||
int[] curIndex = new int [baseIndices.Length + 1];
|
||||
Array.Copy (baseIndices, curIndex, baseIndices.Length);
|
||||
string curIndexStr = IndicesToString (baseIndices);
|
||||
if (baseIndices.Length > 0)
|
||||
curIndexStr += ",";
|
||||
curIndex [curIndex.Length - 1] = initalIndex + firstItemIndex;
|
||||
var elems = array.GetElements (curIndex, System.Math.Min (values.Length, upperBound - lowerBound + 1));
|
||||
|
||||
for (int n = 0; n < values.Length; n++) {
|
||||
int index = n + initalIndex + firstItemIndex;
|
||||
string sidx = curIndexStr + index;
|
||||
ObjectValue val;
|
||||
string ename = "[" + sidx.Replace (",", ", ") + "]";
|
||||
if (index > upperBound)
|
||||
val = ObjectValue.CreateUnknown (sidx);
|
||||
else {
|
||||
curIndex [curIndex.Length - 1] = index;
|
||||
val = cctx.Adapter.CreateObjectValue (cctx, this, newPath.Append (sidx), elems.GetValue (n), ObjectValueFlags.ArrayElement);
|
||||
if (elems.GetValue (n) != null && !cctx.Adapter.IsNull (cctx, elems.GetValue (n))) {
|
||||
TypeDisplayData tdata = cctx.Adapter.GetTypeDisplayData (cctx, cctx.Adapter.GetValueType (cctx, elems.GetValue (n)));
|
||||
if (!string.IsNullOrEmpty (tdata.NameDisplayString)) {
|
||||
try {
|
||||
ename = cctx.Adapter.EvaluateDisplayString (cctx, elems.GetValue (n), tdata.NameDisplayString);
|
||||
} catch (MissingMemberException) {
|
||||
// missing property or otherwise malformed DebuggerDisplay string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val.Name = ename;
|
||||
values [n] = val;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
if (!isLastDimension && div == 1) {
|
||||
// Return an array element group for each index
|
||||
|
||||
var list = new List<ObjectValue> ();
|
||||
for (int i=0; i<count; i++) {
|
||||
int index = i + initalIndex + firstItemIndex;
|
||||
ObjectValue val;
|
||||
|
||||
// This array must be created at every call to avoid sharing
|
||||
// changes with all array groups
|
||||
int[] curIndex = new int [baseIndices.Length + 1];
|
||||
Array.Copy (baseIndices, curIndex, baseIndices.Length);
|
||||
curIndex [curIndex.Length - 1] = index;
|
||||
|
||||
if (index > upperBound)
|
||||
val = ObjectValue.CreateUnknown ("");
|
||||
else {
|
||||
ArrayElementGroup grp = new ArrayElementGroup (cctx, array, curIndex);
|
||||
val = grp.CreateObjectValue ();
|
||||
}
|
||||
list.Add (val);
|
||||
}
|
||||
return list.ToArray ();
|
||||
} else {
|
||||
// Too many elements. Split the array.
|
||||
|
||||
// Don't make divisions of 10 elements, min is 100
|
||||
if (div == 10)
|
||||
div = 100;
|
||||
|
||||
// Create the child groups
|
||||
int i = initalIndex + firstItemIndex;
|
||||
len += i;
|
||||
var list = new List<ObjectValue> ();
|
||||
while (i < len) {
|
||||
int end = i + div - 1;
|
||||
if (end >= len)
|
||||
end = len - 1;
|
||||
ArrayElementGroup grp = new ArrayElementGroup (cctx, array, baseIndices, i, end);
|
||||
list.Add (grp.CreateObjectValue ());
|
||||
i += div;
|
||||
}
|
||||
return list.ToArray ();
|
||||
}
|
||||
}
|
||||
|
||||
internal static string IndicesToString (int[] indices)
|
||||
{
|
||||
var sb = new StringBuilder ();
|
||||
|
||||
for (int i = 0; i < indices.Length; i++) {
|
||||
if (i > 0)
|
||||
sb.Append (',');
|
||||
sb.Append (indices[i].ToString ());
|
||||
}
|
||||
|
||||
return sb.ToString ();
|
||||
}
|
||||
|
||||
internal static int[] StringToIndices (string str)
|
||||
{
|
||||
var sidx = str.Split (',');
|
||||
var idx = new int [sidx.Length];
|
||||
|
||||
for (int i = 0; i < sidx.Length; i++)
|
||||
idx[i] = int.Parse (sidx[i]);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
public static string GetArrayDescription (int[] bounds)
|
||||
{
|
||||
if (bounds.Length == 0)
|
||||
return "[...]";
|
||||
|
||||
var sb = new StringBuilder ("[");
|
||||
|
||||
for (int i = 0; i < bounds.Length; i++) {
|
||||
if (i > 0)
|
||||
sb.Append (", ");
|
||||
sb.Append (bounds [i].ToString ());
|
||||
}
|
||||
|
||||
sb.Append ("]");
|
||||
|
||||
return sb.ToString ();
|
||||
}
|
||||
|
||||
public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
|
||||
{
|
||||
if (path.Length != 2)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
int[] idx = StringToIndices (path [1]);
|
||||
|
||||
object val;
|
||||
try {
|
||||
EvaluationContext cctx = ctx.Clone ();
|
||||
EvaluationOptions ops = options ?? cctx.Options;
|
||||
ops.AllowMethodEvaluation = true;
|
||||
ops.AllowTargetInvoke = true;
|
||||
cctx.Options = ops;
|
||||
ValueReference var = ctx.Evaluator.Evaluate (ctx, value, array.ElementType);
|
||||
val = var.Value;
|
||||
val = ctx.Adapter.Convert (ctx, val, array.ElementType);
|
||||
array.SetElement (idx, val);
|
||||
} catch {
|
||||
val = array.GetElement (idx);
|
||||
}
|
||||
try {
|
||||
return ctx.Evaluator.TargetObjectToExpression (ctx, val);
|
||||
} catch (Exception ex) {
|
||||
ctx.WriteDebuggerError (ex);
|
||||
return new EvaluationResult ("? (" + ex.Message + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
if (path.Length != 2)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
int[] idx = StringToIndices (path [1]);
|
||||
object elem = array.GetElement (idx);
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
ObjectValue val = cctx.Adapter.CreateObjectValue (cctx, this, path, elem, ObjectValueFlags.ArrayElement);
|
||||
if (elem != null && !cctx.Adapter.IsNull (cctx, elem)) {
|
||||
TypeDisplayData tdata = cctx.Adapter.GetTypeDisplayData (cctx, cctx.Adapter.GetValueType (cctx, elem));
|
||||
if (!string.IsNullOrEmpty (tdata.NameDisplayString)) {
|
||||
try {
|
||||
val.Name = cctx.Adapter.EvaluateDisplayString (cctx, elem, tdata.NameDisplayString);
|
||||
} catch (MissingMemberException) {
|
||||
// missing property or otherwise malformed DebuggerDisplay string
|
||||
}
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public object GetRawValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
if (path.Length != 2)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
int[] idx = StringToIndices (path [1]);
|
||||
object elem = array.GetElement (idx);
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
return cctx.Adapter.ToRawValue (cctx, new ArrayObjectSource (array, idx), elem);
|
||||
}
|
||||
|
||||
public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
if (path.Length != 2)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
int[] idx = StringToIndices (path [1]);
|
||||
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
object val = cctx.Adapter.FromRawValue (cctx, value);
|
||||
array.SetElement (idx, val);
|
||||
}
|
||||
}
|
||||
|
||||
class ArrayObjectSource: IObjectSource
|
||||
{
|
||||
readonly ICollectionAdaptor source;
|
||||
readonly string path;
|
||||
|
||||
public ArrayObjectSource (ICollectionAdaptor source, string path)
|
||||
{
|
||||
this.source = source;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public ArrayObjectSource (ICollectionAdaptor source, int[] index)
|
||||
{
|
||||
this.source = source;
|
||||
this.path = ArrayElementGroup.IndicesToString (index);
|
||||
}
|
||||
|
||||
public object Value {
|
||||
get {
|
||||
return source.GetElement (ArrayElementGroup.StringToIndices (path));
|
||||
}
|
||||
set {
|
||||
source.SetElement (ArrayElementGroup.StringToIndices (path), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
// ArrayValueReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class ArrayValueReference: ValueReference
|
||||
{
|
||||
readonly ICollectionAdaptor adaptor;
|
||||
readonly int[] indices;
|
||||
|
||||
public ArrayValueReference (EvaluationContext ctx, object arr, int[] indices) : base (ctx)
|
||||
{
|
||||
this.indices = indices;
|
||||
adaptor = ctx.Adapter.CreateArrayAdaptor (ctx, arr);
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
return adaptor.GetElement (indices);
|
||||
}
|
||||
set {
|
||||
adaptor.SetElement (indices, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
var name = new StringBuilder ();
|
||||
|
||||
name.Append ('[');
|
||||
for (int n = 0; n < indices.Length; n++) {
|
||||
if (n > 0)
|
||||
name.Append (", ");
|
||||
name.Append (indices[n]);
|
||||
}
|
||||
name.Append (']');
|
||||
|
||||
return name.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
return adaptor.ElementType;
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return ObjectValueFlags.ArrayElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
// AsyncEvaluationTracker.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public delegate ObjectValue ObjectEvaluatorDelegate ();
|
||||
|
||||
/// <summary>
|
||||
/// This class can be used to generate an ObjectValue using a provided evaluation delegate.
|
||||
/// The value is initialy evaluated synchronously (blocking the caller). If no result
|
||||
/// is obtained after a short period (provided in the WaitTime property), evaluation
|
||||
/// will then be made asynchronous and the Run method will immediately return an ObjectValue
|
||||
/// with the Evaluating state.
|
||||
/// </summary>
|
||||
public class AsyncEvaluationTracker: RemoteFrameObject, IObjectValueUpdater, IDisposable
|
||||
{
|
||||
Dictionary<string, UpdateCallback> asyncCallbacks = new Dictionary<string, UpdateCallback> ();
|
||||
Dictionary<string, ObjectValue> asyncResults = new Dictionary<string, ObjectValue> ();
|
||||
int asyncCounter = 0;
|
||||
int cancelTimestamp = 0;
|
||||
TimedEvaluator runner = new TimedEvaluator ();
|
||||
|
||||
public int WaitTime {
|
||||
get { return runner.RunTimeout; }
|
||||
set { runner.RunTimeout = value; }
|
||||
}
|
||||
|
||||
public bool IsEvaluating {
|
||||
get { return runner.IsEvaluating; }
|
||||
}
|
||||
|
||||
internal DebuggerSession Session { get; set; }
|
||||
|
||||
public ObjectValue Run (string name, ObjectValueFlags flags, ObjectEvaluatorDelegate evaluator)
|
||||
{
|
||||
string id;
|
||||
int tid;
|
||||
lock (asyncCallbacks) {
|
||||
tid = asyncCounter++;
|
||||
id = tid.ToString ();
|
||||
}
|
||||
|
||||
ObjectValue val = null;
|
||||
bool done = runner.Run (delegate {
|
||||
if (tid >= cancelTimestamp) {
|
||||
var session = Session;
|
||||
if (session == null || (flags == ObjectValueFlags.EvaluatingGroup)) {
|
||||
// Cannot report timing if session is null. If a group is being
|
||||
// evaluated then individual timings are not possible and must
|
||||
// be done elsewhere.
|
||||
val = evaluator ();
|
||||
} else {
|
||||
using (var timer = session.EvaluationStats.StartTimer (name)) {
|
||||
val = evaluator ();
|
||||
timer.Stop (val);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
delegate {
|
||||
if (tid >= cancelTimestamp)
|
||||
OnEvaluationDone (id, val);
|
||||
});
|
||||
|
||||
if (done) {
|
||||
// 'val' may be null if the timed evaluator is disposed while evaluating
|
||||
return val ?? ObjectValue.CreateUnknown (name);
|
||||
}
|
||||
|
||||
return ObjectValue.CreateEvaluating (this, new ObjectPath (id, name), flags);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
runner.Dispose ();
|
||||
}
|
||||
|
||||
|
||||
public void Stop ()
|
||||
{
|
||||
lock (asyncCallbacks) {
|
||||
cancelTimestamp = asyncCounter;
|
||||
runner.CancelAll ();
|
||||
foreach (var cb in asyncCallbacks.Values) {
|
||||
try {
|
||||
cb.UpdateValue (ObjectValue.CreateFatalError ("", "Canceled", ObjectValueFlags.None));
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
asyncCallbacks.Clear ();
|
||||
asyncResults.Clear ();
|
||||
}
|
||||
}
|
||||
|
||||
public void WaitForStopped ()
|
||||
{
|
||||
runner.WaitForStopped ();
|
||||
}
|
||||
|
||||
void OnEvaluationDone (string id, ObjectValue val)
|
||||
{
|
||||
if (val == null)
|
||||
val = ObjectValue.CreateUnknown (null);
|
||||
UpdateCallback cb = null;
|
||||
lock (asyncCallbacks) {
|
||||
if (asyncCallbacks.TryGetValue (id, out cb)) {
|
||||
try {
|
||||
cb.UpdateValue (val);
|
||||
} catch {}
|
||||
asyncCallbacks.Remove (id);
|
||||
}
|
||||
else
|
||||
asyncResults [id] = val;
|
||||
}
|
||||
}
|
||||
|
||||
void IObjectValueUpdater.RegisterUpdateCallbacks (UpdateCallback[] callbacks)
|
||||
{
|
||||
foreach (UpdateCallback c in callbacks) {
|
||||
lock (asyncCallbacks) {
|
||||
ObjectValue val;
|
||||
string id = c.Path[0];
|
||||
if (asyncResults.TryGetValue (id, out val)) {
|
||||
c.UpdateValue (val);
|
||||
asyncResults.Remove (id);
|
||||
} else {
|
||||
asyncCallbacks [id] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
// RuntimeInvokeManager.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ST = System.Threading;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class AsyncOperationManager: IDisposable
|
||||
{
|
||||
readonly List<AsyncOperation> operationsToCancel = new List<AsyncOperation> ();
|
||||
internal bool Disposing;
|
||||
|
||||
public void Invoke (AsyncOperation methodCall, int timeout)
|
||||
{
|
||||
methodCall.Aborted = false;
|
||||
methodCall.Manager = this;
|
||||
|
||||
lock (operationsToCancel) {
|
||||
operationsToCancel.Add (methodCall);
|
||||
methodCall.Invoke ();
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
if (!methodCall.WaitForCompleted (timeout)) {
|
||||
var wasAborted = methodCall.Aborted;
|
||||
|
||||
methodCall.InternalAbort ();
|
||||
|
||||
lock (operationsToCancel) {
|
||||
operationsToCancel.Remove (methodCall);
|
||||
ST.Monitor.PulseAll (operationsToCancel);
|
||||
}
|
||||
|
||||
if (wasAborted)
|
||||
throw new EvaluatorAbortedException ();
|
||||
|
||||
throw new TimeOutException ();
|
||||
}
|
||||
}
|
||||
else {
|
||||
methodCall.WaitForCompleted (System.Threading.Timeout.Infinite);
|
||||
}
|
||||
|
||||
lock (operationsToCancel) {
|
||||
operationsToCancel.Remove (methodCall);
|
||||
ST.Monitor.PulseAll (operationsToCancel);
|
||||
if (methodCall.Aborted) {
|
||||
throw new EvaluatorAbortedException ();
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty (methodCall.ExceptionMessage)) {
|
||||
throw new Exception (methodCall.ExceptionMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Disposing = true;
|
||||
lock (operationsToCancel) {
|
||||
foreach (var op in operationsToCancel) {
|
||||
op.InternalShutdown ();
|
||||
}
|
||||
operationsToCancel.Clear ();
|
||||
}
|
||||
}
|
||||
|
||||
public void AbortAll ()
|
||||
{
|
||||
lock (operationsToCancel) {
|
||||
foreach (var op in operationsToCancel)
|
||||
op.InternalAbort ();
|
||||
}
|
||||
}
|
||||
|
||||
public void EnterBusyState (AsyncOperation oper)
|
||||
{
|
||||
var args = new BusyStateEventArgs {
|
||||
IsBusy = true,
|
||||
Description = oper.Description,
|
||||
EvaluationContext = oper.EvaluationContext
|
||||
};
|
||||
|
||||
BusyStateChanged?.Invoke (this, args);
|
||||
}
|
||||
|
||||
public void LeaveBusyState (AsyncOperation oper)
|
||||
{
|
||||
var args = new BusyStateEventArgs {
|
||||
IsBusy = false,
|
||||
Description = oper.Description,
|
||||
EvaluationContext = oper.EvaluationContext
|
||||
};
|
||||
|
||||
BusyStateChanged?.Invoke (this, args);
|
||||
}
|
||||
|
||||
public event EventHandler<BusyStateEventArgs> BusyStateChanged;
|
||||
}
|
||||
|
||||
public abstract class AsyncOperation
|
||||
{
|
||||
internal AsyncOperationManager Manager;
|
||||
internal bool Aborted;
|
||||
|
||||
public bool Aborting { get; internal set; }
|
||||
|
||||
public EvaluationContext EvaluationContext {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
protected AsyncOperation (EvaluationContext ctx)
|
||||
{
|
||||
EvaluationContext = ctx;
|
||||
}
|
||||
|
||||
internal void InternalAbort ()
|
||||
{
|
||||
ST.Monitor.Enter (this);
|
||||
if (Aborted) {
|
||||
ST.Monitor.Exit (this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Aborting) {
|
||||
// Somebody else is aborting this. Just wait for it to finish.
|
||||
ST.Monitor.Exit (this);
|
||||
WaitForCompleted (ST.Timeout.Infinite);
|
||||
return;
|
||||
}
|
||||
|
||||
Aborting = true;
|
||||
|
||||
int abortState = 0;
|
||||
int abortRetryWait = 100;
|
||||
bool abortRequested = false;
|
||||
|
||||
do {
|
||||
if (abortState > 0)
|
||||
ST.Monitor.Enter (this);
|
||||
|
||||
try {
|
||||
if (!Aborted && !abortRequested) {
|
||||
// The Abort() call doesn't block. WaitForCompleted is used below to wait for the abort to succeed
|
||||
Abort ();
|
||||
abortRequested = true;
|
||||
}
|
||||
// Short wait for the Abort to finish. If this wait is not enough, it will wait again in the next loop
|
||||
if (WaitForCompleted (100)) {
|
||||
ST.Monitor.Exit (this);
|
||||
break;
|
||||
}
|
||||
} catch {
|
||||
// If abort fails, try again after a short wait
|
||||
}
|
||||
abortState++;
|
||||
if (abortState == 6) {
|
||||
// Several abort calls have failed. Inform the user that the debugger is busy
|
||||
abortRetryWait = 500;
|
||||
try {
|
||||
Manager.EnterBusyState (this);
|
||||
} catch (Exception ex) {
|
||||
Console.WriteLine (ex);
|
||||
}
|
||||
}
|
||||
ST.Monitor.Exit (this);
|
||||
} while (!Aborted && !WaitForCompleted (abortRetryWait) && !Manager.Disposing);
|
||||
|
||||
if (Manager.Disposing) {
|
||||
InternalShutdown ();
|
||||
}
|
||||
else {
|
||||
lock (this) {
|
||||
Aborted = true;
|
||||
if (abortState >= 6)
|
||||
Manager.LeaveBusyState (this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void InternalShutdown ()
|
||||
{
|
||||
lock (this) {
|
||||
if (Aborted)
|
||||
return;
|
||||
try {
|
||||
Aborted = true;
|
||||
Shutdown ();
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message of the exception, if the execution failed.
|
||||
/// </summary>
|
||||
public string ExceptionMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a short description of the operation, to be shown in the Debugger Busy Dialog
|
||||
/// when it blocks the execution of the debugger.
|
||||
/// </summary>
|
||||
public abstract string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Called to invoke the operation. The execution must be asynchronous (it must return immediatelly).
|
||||
/// </summary>
|
||||
public abstract void Invoke ( );
|
||||
|
||||
/// <summary>
|
||||
/// Called to abort the execution of the operation. It has to throw an exception
|
||||
/// if the operation can't be aborted. This operation must not block. The engine
|
||||
/// will wait for the operation to be aborted by calling WaitForCompleted.
|
||||
/// </summary>
|
||||
public abstract void Abort ();
|
||||
|
||||
/// <summary>
|
||||
/// Waits until the operation has been completed or aborted.
|
||||
/// </summary>
|
||||
public abstract bool WaitForCompleted (int timeout);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the debugging session has been disposed.
|
||||
/// I must cause any call to WaitForCompleted to exit, even if the operation
|
||||
/// has not been completed or can't be aborted.
|
||||
/// </summary>
|
||||
public abstract void Shutdown ();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
//
|
||||
// Backtrace.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public abstract class BaseBacktrace: RemoteFrameObject, IBacktrace
|
||||
{
|
||||
readonly Dictionary<int, FrameInfo> frameInfo = new Dictionary<int, FrameInfo> ();
|
||||
|
||||
protected BaseBacktrace (ObjectValueAdaptor adaptor)
|
||||
{
|
||||
Adaptor = adaptor;
|
||||
}
|
||||
|
||||
public abstract StackFrame[] GetStackFrames (int firstIndex, int lastIndex);
|
||||
|
||||
public ObjectValueAdaptor Adaptor { get; set; }
|
||||
|
||||
protected abstract EvaluationContext GetEvaluationContext (int frameIndex, EvaluationOptions options);
|
||||
|
||||
public abstract int FrameCount { get; }
|
||||
|
||||
public virtual ObjectValue[] GetLocalVariables (int frameIndex, EvaluationOptions options)
|
||||
{
|
||||
var frame = GetFrameInfo (frameIndex, options, false);
|
||||
var list = new List<ObjectValue> ();
|
||||
|
||||
if (frame == null) {
|
||||
var val = Adaptor.CreateObjectValueAsync ("Local Variables", ObjectValueFlags.EvaluatingGroup, delegate {
|
||||
frame = GetFrameInfo (frameIndex, options, true);
|
||||
foreach (var local in frame.LocalVariables) {
|
||||
using (var timer = StartEvaluationTimer (local.Name)) {
|
||||
var localValue = local.CreateObjectValue (false, options);
|
||||
timer.Stop (localValue);
|
||||
list.Add (localValue);
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectValue.CreateArray (null, new ObjectPath ("Local Variables"), "", list.Count, ObjectValueFlags.EvaluatingGroup, list.ToArray ());
|
||||
});
|
||||
|
||||
return new [] { val };
|
||||
}
|
||||
|
||||
foreach (var local in frame.LocalVariables)
|
||||
list.Add (local.CreateObjectValue (true, options));
|
||||
|
||||
return list.ToArray ();
|
||||
}
|
||||
|
||||
public virtual ObjectValue[] GetParameters (int frameIndex, EvaluationOptions options)
|
||||
{
|
||||
var frame = GetFrameInfo (frameIndex, options, false);
|
||||
var values = new List<ObjectValue> ();
|
||||
|
||||
if (frame == null) {
|
||||
var value = Adaptor.CreateObjectValueAsync ("Parameters", ObjectValueFlags.EvaluatingGroup, delegate {
|
||||
frame = GetFrameInfo (frameIndex, options, true);
|
||||
foreach (var param in frame.Parameters) {
|
||||
using (var timer = StartEvaluationTimer (param.Name)) {
|
||||
var paramValue = param.CreateObjectValue (false, options);
|
||||
timer.Stop (paramValue);
|
||||
values.Add (paramValue);
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectValue.CreateArray (null, new ObjectPath ("Parameters"), "", values.Count, ObjectValueFlags.EvaluatingGroup, values.ToArray ());
|
||||
});
|
||||
|
||||
return new [] { value };
|
||||
}
|
||||
|
||||
foreach (var param in frame.Parameters)
|
||||
values.Add (param.CreateObjectValue (true, options));
|
||||
|
||||
return values.ToArray ();
|
||||
}
|
||||
|
||||
public virtual ObjectValue GetThisReference (int frameIndex, EvaluationOptions options)
|
||||
{
|
||||
var frame = GetFrameInfo (frameIndex, options, false);
|
||||
|
||||
if (frame == null) {
|
||||
return Adaptor.CreateObjectValueAsync ("this", ObjectValueFlags.EvaluatingGroup, delegate {
|
||||
frame = GetFrameInfo (frameIndex, options, true);
|
||||
ObjectValue[] values;
|
||||
|
||||
if (frame.This != null) {
|
||||
using (var timer = StartEvaluationTimer ("this")) {
|
||||
var thisValue = frame.This.CreateObjectValue (false, options);
|
||||
timer.Stop (thisValue);
|
||||
values = new [] { thisValue };
|
||||
}
|
||||
} else
|
||||
values = new ObjectValue [0];
|
||||
|
||||
return ObjectValue.CreateArray (null, new ObjectPath ("this"), "", values.Length, ObjectValueFlags.EvaluatingGroup, values);
|
||||
});
|
||||
}
|
||||
|
||||
return frame.This != null ? frame.This.CreateObjectValue (true, options) : null;
|
||||
}
|
||||
|
||||
public virtual ExceptionInfo GetException (int frameIndex, EvaluationOptions options)
|
||||
{
|
||||
var frame = GetFrameInfo (frameIndex, options, false);
|
||||
ObjectValue value;
|
||||
|
||||
if (frame == null) {
|
||||
value = Adaptor.CreateObjectValueAsync (options.CurrentExceptionTag, ObjectValueFlags.EvaluatingGroup, delegate {
|
||||
frame = GetFrameInfo (frameIndex, options, true);
|
||||
ObjectValue[] values;
|
||||
|
||||
if (frame.Exception != null) {
|
||||
using (var timer = StartEvaluationTimer ("Exception")) {
|
||||
var exceptionValue = frame.Exception.CreateObjectValue (false, options);
|
||||
timer.Stop (exceptionValue);
|
||||
values = new [] { exceptionValue };
|
||||
}
|
||||
} else
|
||||
values = new ObjectValue [0];
|
||||
|
||||
return ObjectValue.CreateArray (null, new ObjectPath (options.CurrentExceptionTag), "", values.Length, ObjectValueFlags.EvaluatingGroup, values);
|
||||
});
|
||||
} else if (frame.Exception != null) {
|
||||
value = frame.Exception.CreateObjectValue (true, options);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ExceptionInfo (value);
|
||||
}
|
||||
|
||||
public virtual ObjectValue GetExceptionInstance (int frameIndex, EvaluationOptions options)
|
||||
{
|
||||
var frame = GetFrameInfo (frameIndex, options, false);
|
||||
|
||||
if (frame == null) {
|
||||
return Adaptor.CreateObjectValueAsync (options.CurrentExceptionTag, ObjectValueFlags.EvaluatingGroup, delegate {
|
||||
frame = GetFrameInfo (frameIndex, options, true);
|
||||
ObjectValue[] values;
|
||||
|
||||
if (frame.Exception != null) {
|
||||
using (var timer = StartEvaluationTimer ("Exception")) {
|
||||
var exceptionValue = frame.Exception.Exception.CreateObjectValue (false, options);
|
||||
timer.Stop (exceptionValue);
|
||||
values = new [] { exceptionValue };
|
||||
}
|
||||
} else
|
||||
values = new ObjectValue [0];
|
||||
|
||||
return ObjectValue.CreateArray (null, new ObjectPath (options.CurrentExceptionTag), "", values.Length, ObjectValueFlags.EvaluatingGroup, values);
|
||||
});
|
||||
}
|
||||
|
||||
return frame.Exception != null ? frame.Exception.Exception.CreateObjectValue (true, options) : null;
|
||||
}
|
||||
|
||||
public virtual ObjectValue[] GetAllLocals (int frameIndex, EvaluationOptions options)
|
||||
{
|
||||
var locals = new List<ObjectValue> ();
|
||||
|
||||
var excObj = GetExceptionInstance (frameIndex, options);
|
||||
if (excObj != null)
|
||||
locals.Insert (0, excObj);
|
||||
|
||||
locals.AddRange (GetLocalVariables (frameIndex, options));
|
||||
locals.AddRange (GetParameters (frameIndex, options));
|
||||
|
||||
locals.Sort ((v1, v2) => StringComparer.InvariantCulture.Compare (v1.Name, v2.Name));
|
||||
|
||||
var thisObj = GetThisReference (frameIndex, options);
|
||||
if (thisObj != null)
|
||||
locals.Insert (0, thisObj);
|
||||
|
||||
return locals.ToArray ();
|
||||
}
|
||||
|
||||
public virtual ObjectValue[] GetExpressionValues (int frameIndex, string[] expressions, EvaluationOptions options)
|
||||
{
|
||||
if (Adaptor.IsEvaluating) {
|
||||
var values = new List<ObjectValue> ();
|
||||
|
||||
foreach (var expression in expressions) {
|
||||
string tmpExp = expression;
|
||||
|
||||
var value = Adaptor.CreateObjectValueAsync (tmpExp, ObjectValueFlags.Field, delegate {
|
||||
var cctx = GetEvaluationContext (frameIndex, options);
|
||||
return Adaptor.GetExpressionValue (cctx, tmpExp);
|
||||
});
|
||||
value.Name = expression;
|
||||
|
||||
values.Add (value);
|
||||
}
|
||||
|
||||
return values.ToArray ();
|
||||
}
|
||||
|
||||
var ctx = GetEvaluationContext (frameIndex, options);
|
||||
|
||||
return ctx.Adapter.GetExpressionValuesAsync (ctx, expressions);
|
||||
}
|
||||
|
||||
public virtual CompletionData GetExpressionCompletionData (int frameIndex, string exp)
|
||||
{
|
||||
var ctx = GetEvaluationContext (frameIndex, EvaluationOptions.DefaultOptions);
|
||||
return ctx.Adapter.GetExpressionCompletionData (ctx, exp);
|
||||
}
|
||||
|
||||
public virtual AssemblyLine[] Disassemble (int frameIndex, int firstLine, int count)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public virtual ValidationResult ValidateExpression (int frameIndex, string expression, EvaluationOptions options)
|
||||
{
|
||||
var ctx = GetEvaluationContext (frameIndex, options);
|
||||
return Adaptor.ValidateExpression (ctx, expression);
|
||||
}
|
||||
|
||||
FrameInfo GetFrameInfo (int frameIndex, EvaluationOptions options, bool ignoreEvalStatus)
|
||||
{
|
||||
FrameInfo finfo;
|
||||
|
||||
lock (frameInfo) {
|
||||
if (frameInfo.TryGetValue (frameIndex, out finfo))
|
||||
return finfo;
|
||||
|
||||
if (!ignoreEvalStatus && Adaptor.IsEvaluating)
|
||||
return null;
|
||||
|
||||
var ctx = GetEvaluationContext (frameIndex, options);
|
||||
if (ctx == null)
|
||||
return null;
|
||||
|
||||
finfo = new FrameInfo ();
|
||||
finfo.Context = ctx;
|
||||
//Don't try to optimize lines below with lazy loading, you won't gain anything(in communication with runtime)
|
||||
finfo.LocalVariables.AddRange (ctx.Evaluator.GetLocalVariables (ctx));
|
||||
finfo.Parameters.AddRange (ctx.Evaluator.GetParameters (ctx));
|
||||
finfo.This = ctx.Evaluator.GetThisReference (ctx);
|
||||
|
||||
var ex = ctx.Evaluator.GetCurrentException (ctx);
|
||||
if (ex != null)
|
||||
finfo.Exception = new ExceptionInfoSource (ctx, ex);
|
||||
|
||||
frameInfo[frameIndex] = finfo;
|
||||
}
|
||||
|
||||
return finfo;
|
||||
}
|
||||
|
||||
DebuggerTimer StartEvaluationTimer (string name)
|
||||
{
|
||||
return new DebuggerTimer (Adaptor.DebuggerSession?.EvaluationStats, name);
|
||||
}
|
||||
}
|
||||
|
||||
class FrameInfo
|
||||
{
|
||||
public EvaluationContext Context;
|
||||
public List<ValueReference> LocalVariables = new List<ValueReference> ();
|
||||
public List<ValueReference> Parameters = new List<ValueReference> ();
|
||||
public ValueReference This;
|
||||
public ExceptionInfoSource Exception;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// BaseTypeViewSource.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Backend;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class BaseTypeViewSource: RemoteFrameObject, IObjectValueSource
|
||||
{
|
||||
EvaluationContext ctx;
|
||||
object type;
|
||||
object obj;
|
||||
IObjectSource objectSource;
|
||||
|
||||
public BaseTypeViewSource (EvaluationContext ctx, IObjectSource objectSource, object type, object obj)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
this.type = type;
|
||||
this.obj = obj;
|
||||
this.objectSource = objectSource;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateBaseTypeView (EvaluationContext ctx, IObjectSource objectSource, object type, object obj)
|
||||
{
|
||||
BaseTypeViewSource src = new BaseTypeViewSource (ctx, objectSource, type, obj);
|
||||
src.Connect ();
|
||||
string tname = ctx.Adapter.GetDisplayTypeName (ctx, type);
|
||||
ObjectValue val = ObjectValue.CreateObject (src, new ObjectPath ("base"), tname, "{" + tname + "}", ObjectValueFlags.Type|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
|
||||
val.ChildSelector = "";
|
||||
return val;
|
||||
}
|
||||
|
||||
#region IObjectValueSource implementation
|
||||
|
||||
public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
return cctx.Adapter.GetObjectValueChildren (cctx, objectSource, type, obj, index, count, false);
|
||||
}
|
||||
|
||||
public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public object GetRawValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
//
|
||||
// IEnumerableSource.cs
|
||||
//
|
||||
// Author:
|
||||
// David Karlaš <david.karlas@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Mono.Debugging.Backend;
|
||||
using Mono.Debugging.Client;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
class EnumerableSource : IObjectValueSource
|
||||
{
|
||||
object obj;
|
||||
object objType;
|
||||
EvaluationContext ctx;
|
||||
List<ObjectValue> elements;
|
||||
List<object> values;
|
||||
int currentIndex = 0;
|
||||
object enumerator;
|
||||
object enumeratorType;
|
||||
|
||||
public EnumerableSource (object source, object type, EvaluationContext ctx)
|
||||
{
|
||||
this.obj = source;
|
||||
this.objType = type;
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
bool MoveNext ()
|
||||
{
|
||||
return (bool)ctx.Adapter.TargetObjectToObject (ctx, ctx.Adapter.RuntimeInvoke (ctx, enumeratorType, enumerator, "MoveNext", new object[0], new object[0]));
|
||||
}
|
||||
|
||||
void Fetch (int maxIndex)
|
||||
{
|
||||
if (elements == null) {
|
||||
elements = new List<ObjectValue> ();
|
||||
values = new List<object> ();
|
||||
enumerator = ctx.Adapter.RuntimeInvoke (ctx, objType, obj, "GetEnumerator", new object[0], new object[0]);
|
||||
enumeratorType = ctx.Adapter.GetImplementedInterfaces (ctx, ctx.Adapter.GetValueType (ctx, enumerator)).First (f => ctx.Adapter.GetTypeName (ctx, f) == "System.Collections.IEnumerator");
|
||||
}
|
||||
while (maxIndex > elements.Count && MoveNext ()) {
|
||||
var valCurrent = ctx.Adapter.GetMember (ctx, null, enumeratorType, enumerator, "Current");
|
||||
var val = valCurrent.Value;
|
||||
values.Add (val);
|
||||
if (val != null) {
|
||||
elements.Add (ctx.Adapter.CreateObjectValue (ctx, valCurrent, new ObjectPath ("[" + currentIndex + "]"), val, ObjectValueFlags.ReadOnly));
|
||||
} else {
|
||||
elements.Add (Mono.Debugging.Client.ObjectValue.CreateNullObject (this, "[" + currentIndex + "]", ctx.Adapter.GetDisplayTypeName (ctx.Adapter.GetTypeName (ctx, valCurrent.Type)), ObjectValueFlags.ReadOnly));
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public object GetElement (int idx)
|
||||
{
|
||||
return values [idx];
|
||||
}
|
||||
|
||||
public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
int idx;
|
||||
if (int.TryParse (path.LastName.Replace ("[", "").Replace ("]", ""), out idx)) {
|
||||
return ctx.Adapter.GetObjectValueChildren (ctx, null, values [idx], -1, -1);
|
||||
}
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
if (count == 0)
|
||||
return new ObjectValue[0];
|
||||
if (count == -1)
|
||||
count = int.MaxValue;
|
||||
Fetch (index + count);
|
||||
if (count < 0 || index + count > elements.Count) {
|
||||
return elements.Skip (index).ToArray ();
|
||||
} else {
|
||||
if (index < elements.Count) {
|
||||
return elements.Skip (index).Take (System.Math.Min (count, elements.Count - index)).ToArray ();
|
||||
} else {
|
||||
return new ObjectValue[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
|
||||
{
|
||||
throw new InvalidOperationException ("Elements of IEnumerable can not be set");
|
||||
}
|
||||
|
||||
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
int idx;
|
||||
if (int.TryParse (path.LastName.Replace ("[", "").Replace ("]", ""), out idx)) {
|
||||
var element = elements [idx];
|
||||
element.Refresh (options);
|
||||
return element;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object GetRawValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
int idx = int.Parse (path.LastName.Replace ("[", "").Replace ("]", ""));
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
return cctx.Adapter.ToRawValue (cctx, new EnumerableObjectSource (this, idx), GetElement (idx));
|
||||
}
|
||||
|
||||
public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
throw new InvalidOperationException ("Elements of IEnumerable can not be set");
|
||||
}
|
||||
}
|
||||
|
||||
class EnumerableObjectSource : IObjectSource
|
||||
{
|
||||
EnumerableSource enumerableSource;
|
||||
int idx;
|
||||
|
||||
public EnumerableObjectSource (EnumerableSource enumerableSource, int idx)
|
||||
{
|
||||
this.enumerableSource = enumerableSource;
|
||||
this.idx = idx;
|
||||
|
||||
}
|
||||
|
||||
#region IObjectSource implementation
|
||||
|
||||
public object Value {
|
||||
get {
|
||||
return enumerableSource.GetElement (idx);
|
||||
}
|
||||
set {
|
||||
throw new InvalidOperationException ("Elements of IEnumerable can not be set");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
// EvaluationContext.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class EvaluationContext
|
||||
{
|
||||
public ExpressionEvaluator Evaluator { get; set; }
|
||||
public ObjectValueAdaptor Adapter { get; set; }
|
||||
|
||||
public EvaluationOptions Options {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public bool CaseSensitive {
|
||||
get { return Evaluator.CaseSensitive; }
|
||||
}
|
||||
|
||||
public virtual void WriteDebuggerError (Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void WriteDebuggerOutput (string message, params object[] values)
|
||||
{
|
||||
}
|
||||
|
||||
public void WaitRuntimeInvokes ()
|
||||
{
|
||||
}
|
||||
|
||||
public void AssertTargetInvokeAllowed ()
|
||||
{
|
||||
if (!Options.AllowTargetInvoke)
|
||||
throw new ImplicitEvaluationDisabledException ();
|
||||
}
|
||||
|
||||
public EvaluationContext (EvaluationOptions options)
|
||||
{
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public EvaluationContext Clone ()
|
||||
{
|
||||
var clone = (EvaluationContext) MemberwiseClone ();
|
||||
clone.CopyFrom (this);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public EvaluationContext WithOptions (EvaluationOptions options)
|
||||
{
|
||||
if (options == null || Options == options)
|
||||
return this;
|
||||
|
||||
var clone = Clone ();
|
||||
clone.Options = options;
|
||||
return clone;
|
||||
}
|
||||
|
||||
public virtual void CopyFrom (EvaluationContext ctx)
|
||||
{
|
||||
Options = ctx.Options.Clone ();
|
||||
Evaluator = ctx.Evaluator;
|
||||
Adapter = ctx.Adapter;
|
||||
}
|
||||
|
||||
ExpressionValueSource expressionValueSource;
|
||||
internal ExpressionValueSource ExpressionValueSource {
|
||||
get {
|
||||
if (expressionValueSource == null)
|
||||
expressionValueSource = new ExpressionValueSource (this);
|
||||
return expressionValueSource;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool SupportIEnumerable {
|
||||
get {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExpressionValueSource: RemoteFrameObject, IObjectValueSource
|
||||
{
|
||||
readonly EvaluationContext ctx;
|
||||
|
||||
public ExpressionValueSource (EvaluationContext ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
Connect ();
|
||||
}
|
||||
|
||||
public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
EvaluationContext c = ctx.WithOptions (options);
|
||||
var vals = c.Adapter.GetExpressionValuesAsync (c, new string[] { path.LastName });
|
||||
return vals[0];
|
||||
}
|
||||
|
||||
public object GetRawValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
//
|
||||
// ExceptionInfoSource.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class ExceptionInfoSource
|
||||
{
|
||||
EvaluationContext ctx;
|
||||
|
||||
public ExceptionInfoSource (EvaluationContext ctx, ValueReference exception)
|
||||
{
|
||||
Exception = exception;
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public ValueReference Exception {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public ObjectValue CreateObjectValue (bool withTimeout, EvaluationOptions options)
|
||||
{
|
||||
options = options.Clone ();
|
||||
options.EllipsizeStrings = false;
|
||||
options.AllowTargetInvoke = true;
|
||||
ctx = ctx.WithOptions (options);
|
||||
string type = ctx.Adapter.GetValueTypeName (ctx, Exception.ObjectValue);
|
||||
|
||||
var excInstance = Exception.CreateObjectValue (withTimeout, options);
|
||||
excInstance.Name = "Instance";
|
||||
|
||||
ObjectValue messageValue = null;
|
||||
ObjectValue helpLinkValue = null;
|
||||
var exceptionType = ctx.Adapter.GetValueType (ctx, Exception.Value);
|
||||
|
||||
// Get the message
|
||||
|
||||
if (withTimeout) {
|
||||
messageValue = ctx.Adapter.CreateObjectValueAsync ("Message", ObjectValueFlags.None, delegate {
|
||||
var mref = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "Message");
|
||||
if (mref != null) {
|
||||
string val = (string)mref.ObjectValue;
|
||||
return ObjectValue.CreatePrimitive (null, new ObjectPath ("Message"), "string", new EvaluationResult (val), ObjectValueFlags.Literal);
|
||||
}
|
||||
|
||||
return ObjectValue.CreateUnknown ("Message");
|
||||
});
|
||||
} else {
|
||||
var mref = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "Message");
|
||||
if (mref != null) {
|
||||
string val = (string)mref.ObjectValue;
|
||||
messageValue = ObjectValue.CreatePrimitive (null, new ObjectPath ("Message"), "string", new EvaluationResult (val), ObjectValueFlags.Literal);
|
||||
}
|
||||
}
|
||||
|
||||
if (messageValue == null)
|
||||
messageValue = ObjectValue.CreateUnknown ("Message");
|
||||
|
||||
messageValue.Name = "Message";
|
||||
|
||||
// Get the help link
|
||||
|
||||
if (withTimeout) {
|
||||
helpLinkValue = ctx.Adapter.CreateObjectValueAsync ("HelpLink", ObjectValueFlags.None, delegate {
|
||||
var mref = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "HelpLink");
|
||||
if (mref != null) {
|
||||
string val = (string)mref.ObjectValue;
|
||||
return ObjectValue.CreatePrimitive (null, new ObjectPath ("HelpLink"), "string", new EvaluationResult (val), ObjectValueFlags.Literal);
|
||||
}
|
||||
|
||||
return ObjectValue.CreateUnknown ("HelpLink");
|
||||
});
|
||||
} else {
|
||||
var mref = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "HelpLink");
|
||||
if (mref != null) {
|
||||
string val = (string)mref.ObjectValue;
|
||||
helpLinkValue = ObjectValue.CreatePrimitive (null, new ObjectPath ("HelpLink"), "string", new EvaluationResult (val), ObjectValueFlags.Literal);
|
||||
}
|
||||
}
|
||||
|
||||
if (helpLinkValue == null)
|
||||
helpLinkValue = ObjectValue.CreateUnknown ("HelpLink");
|
||||
|
||||
helpLinkValue.Name = "HelpLink";
|
||||
|
||||
// Inner exception
|
||||
|
||||
ObjectValue childExceptionValue = null;
|
||||
|
||||
if (withTimeout) {
|
||||
childExceptionValue = ctx.Adapter.CreateObjectValueAsync ("InnerException", ObjectValueFlags.None, delegate {
|
||||
var inner = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "InnerException");
|
||||
if (inner != null && !ctx.Adapter.IsNull (ctx, inner.Value)) {
|
||||
//Console.WriteLine ("pp got child:" + type);
|
||||
var innerSource = new ExceptionInfoSource (ctx, inner);
|
||||
var res = innerSource.CreateObjectValue (false, options);
|
||||
return res;
|
||||
}
|
||||
|
||||
return ObjectValue.CreateUnknown ("InnerException");
|
||||
});
|
||||
} else {
|
||||
var inner = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "InnerException");
|
||||
if (inner != null && !ctx.Adapter.IsNull (ctx, inner.Value)) {
|
||||
//Console.WriteLine ("pp got child:" + type);
|
||||
var innerSource = new ExceptionInfoSource (ctx, inner);
|
||||
childExceptionValue = innerSource.CreateObjectValue (false, options);
|
||||
childExceptionValue.Name = "InnerException";
|
||||
}
|
||||
}
|
||||
|
||||
if (childExceptionValue == null)
|
||||
childExceptionValue = ObjectValue.CreateUnknown ("InnerException");
|
||||
|
||||
// Inner exceptions in case of AgregatedException
|
||||
|
||||
ObjectValue childExceptionsValue = null;
|
||||
ObjectEvaluatorDelegate getInnerExceptionsDelegate = delegate {
|
||||
var inner = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "InnerExceptions");
|
||||
if (inner != null && !ctx.Adapter.IsNull (ctx, inner.Value)) {
|
||||
var obj = inner.GetValue (ctx);
|
||||
var objType = ctx.Adapter.GetValueType (ctx, obj);
|
||||
var count = (int)ctx.Adapter.GetMember(ctx, null, obj, "Count").ObjectValue;
|
||||
var childrenList = new List<ObjectValue>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
childrenList.Add (new ExceptionInfoSource(ctx, ctx.Adapter.GetIndexerReference(ctx, obj, objType, new object[] { ctx.Adapter.CreateValue(ctx, i) })).CreateObjectValue (withTimeout, ctx.Options));
|
||||
}
|
||||
return ObjectValue.CreateObject (null, new ObjectPath("InnerExceptions"), "", "", ObjectValueFlags.None, childrenList.ToArray ());
|
||||
}
|
||||
|
||||
return ObjectValue.CreateUnknown ("InnerExceptions");
|
||||
};
|
||||
if (withTimeout) {
|
||||
childExceptionsValue = ctx.Adapter.CreateObjectValueAsync ("InnerExceptions", ObjectValueFlags.None, getInnerExceptionsDelegate);
|
||||
} else {
|
||||
childExceptionsValue = getInnerExceptionsDelegate ();
|
||||
}
|
||||
|
||||
if (childExceptionsValue == null)
|
||||
childExceptionsValue = ObjectValue.CreateUnknown ("InnerExceptions");
|
||||
|
||||
// Stack trace
|
||||
|
||||
ObjectValue stackTraceValue;
|
||||
if (withTimeout) {
|
||||
stackTraceValue = ctx.Adapter.CreateObjectValueAsync ("StackTrace", ObjectValueFlags.None, delegate {
|
||||
var stackTrace = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "StackTrace");
|
||||
if (stackTrace == null)
|
||||
return ObjectValue.CreateUnknown ("StackTrace");
|
||||
return GetStackTrace (stackTrace.ObjectValue as string);
|
||||
});
|
||||
} else {
|
||||
var stackTrace = ctx.Adapter.GetMember (ctx, Exception, exceptionType, Exception.Value, "StackTrace");
|
||||
if (stackTrace == null)
|
||||
return ObjectValue.CreateUnknown ("StackTrace");
|
||||
stackTraceValue = GetStackTrace (stackTrace.ObjectValue as string);
|
||||
}
|
||||
|
||||
var children = new ObjectValue [] { excInstance, messageValue, helpLinkValue, stackTraceValue, childExceptionValue, childExceptionsValue };
|
||||
|
||||
return ObjectValue.CreateObject (null, new ObjectPath ("InnerException"), type, "", ObjectValueFlags.None, children);
|
||||
}
|
||||
|
||||
public static ObjectValue GetStackTrace (string trace)
|
||||
{
|
||||
if (trace == null)
|
||||
return ObjectValue.CreateUnknown ("StackTrace");
|
||||
|
||||
var regex = new Regex ("at (?<MethodName>.*) in (?<FileName>.*):(?<LineNumber>\\d+)(,(?<Column>\\d+))?");
|
||||
var regexLine = new Regex ("at (?<MethodName>.*) in (?<FileName>.*):line (?<LineNumber>\\d+)(,(?<Column>\\d+))?");
|
||||
var frames = new List<ObjectValue> ();
|
||||
|
||||
foreach (var sframe in trace.Split ('\n')) {
|
||||
string text = sframe.Trim (' ', '\r', '\t', '"');
|
||||
string file = "";
|
||||
int column = 0;
|
||||
int line = 0;
|
||||
|
||||
if (text.Length == 0)
|
||||
continue;
|
||||
//Ignore entries like "--- End of stack trace from previous location where exception was thrown ---"
|
||||
if (text.StartsWith ("---", StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
var match = regex.Match (text);
|
||||
if (match.Success) {
|
||||
text = match.Groups ["MethodName"].ToString ();
|
||||
file = match.Groups ["FileName"].ToString ();
|
||||
int.TryParse (match.Groups ["LineNumber"].ToString (), out line);
|
||||
int.TryParse (match.Groups ["Column"].ToString (), out column);
|
||||
} else {
|
||||
match = regexLine.Match (text);
|
||||
if (match.Success) {
|
||||
text = match.Groups ["MethodName"].ToString ();
|
||||
file = match.Groups ["FileName"].ToString ();
|
||||
int.TryParse (match.Groups ["LineNumber"].ToString (), out line);
|
||||
int.TryParse (match.Groups ["Column"].ToString (), out column);
|
||||
}
|
||||
}
|
||||
|
||||
var fileVal = ObjectValue.CreatePrimitive (null, new ObjectPath ("File"), "", new EvaluationResult (file), ObjectValueFlags.None);
|
||||
var lineVal = ObjectValue.CreatePrimitive (null, new ObjectPath ("Line"), "", new EvaluationResult (line.ToString ()), ObjectValueFlags.None);
|
||||
var colVal = ObjectValue.CreatePrimitive (null, new ObjectPath ("Column"), "", new EvaluationResult (column.ToString ()), ObjectValueFlags.None);
|
||||
var children = new ObjectValue [] { fileVal, lineVal, colVal };
|
||||
|
||||
var frame = ObjectValue.CreateObject (null, new ObjectPath (), "", new EvaluationResult (text), ObjectValueFlags.None, children);
|
||||
frames.Add (frame);
|
||||
}
|
||||
|
||||
return ObjectValue.CreateArray (null, new ObjectPath ("StackTrace"), "", frames.Count, ObjectValueFlags.None, frames.ToArray ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
// IExpressionEvaluator.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using Mono.Debugging.Backend;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public abstract class ExpressionEvaluator
|
||||
{
|
||||
public ValueReference Evaluate (EvaluationContext ctx, string expression)
|
||||
{
|
||||
return Evaluate (ctx, expression, null);
|
||||
}
|
||||
|
||||
public virtual ValueReference Evaluate (EvaluationContext ctx, string expression, object expectedType)
|
||||
{
|
||||
foreach (var variable in ctx.Adapter.GetLocalVariables (ctx))
|
||||
if (variable.Name == expression)
|
||||
return variable;
|
||||
|
||||
foreach (var parameter in ctx.Adapter.GetParameters (ctx))
|
||||
if (parameter.Name == expression)
|
||||
return parameter;
|
||||
|
||||
var thisVar = ctx.Adapter.GetThisReference (ctx);
|
||||
if (thisVar != null) {
|
||||
if (thisVar.Name == expression)
|
||||
return thisVar;
|
||||
foreach (var cv in thisVar.GetChildReferences (ctx.Options))
|
||||
if (cv.Name == expression)
|
||||
return cv;
|
||||
}
|
||||
throw new EvaluatorException ("Invalid Expression: '{0}'", expression);
|
||||
}
|
||||
|
||||
public virtual ValidationResult ValidateExpression (EvaluationContext ctx, string expression)
|
||||
{
|
||||
return new ValidationResult (true, null);
|
||||
}
|
||||
|
||||
public string TargetObjectToString (EvaluationContext ctx, object obj)
|
||||
{
|
||||
var res = ctx.Adapter.TargetObjectToObject (ctx, obj);
|
||||
|
||||
if (res == null)
|
||||
return null;
|
||||
|
||||
if (res is EvaluationResult)
|
||||
return ((EvaluationResult) res).DisplayValue ?? ((EvaluationResult) res).Value;
|
||||
|
||||
return res.ToString ();
|
||||
}
|
||||
|
||||
public EvaluationResult TargetObjectToExpression (EvaluationContext ctx, object obj)
|
||||
{
|
||||
return ToExpression (ctx, ctx.Adapter.TargetObjectToObject (ctx, obj));
|
||||
}
|
||||
|
||||
public virtual EvaluationResult ToExpression (EvaluationContext ctx, object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return new EvaluationResult ("null");
|
||||
|
||||
if (obj is IntPtr ptr)
|
||||
return new EvaluationResult ("0x" + ptr.ToInt64 ().ToString ("x"));
|
||||
|
||||
if (obj is char c) {
|
||||
string str;
|
||||
|
||||
if (c == '\'')
|
||||
str = @"'\''";
|
||||
else if (c == '"')
|
||||
str = "'\"'";
|
||||
else
|
||||
str = EscapeString ("'" + c + "'");
|
||||
return new EvaluationResult (str, ((int) c) + " " + str);
|
||||
}
|
||||
|
||||
if (obj is string s)
|
||||
return new EvaluationResult ("\"" + EscapeString (s) + "\"");
|
||||
|
||||
if (obj is bool b)
|
||||
return new EvaluationResult (b ? "true" : "false");
|
||||
|
||||
if (obj is decimal d)
|
||||
return new EvaluationResult (d.ToString (CultureInfo.InvariantCulture));
|
||||
|
||||
if (obj is EvaluationResult result)
|
||||
return result;
|
||||
|
||||
if (ctx.Options.IntegerDisplayFormat == IntegerDisplayFormat.Hexadecimal) {
|
||||
string fval = null;
|
||||
|
||||
if (obj is sbyte)
|
||||
fval = ((sbyte) obj).ToString ("x2");
|
||||
else if (obj is int)
|
||||
fval = ((int) obj).ToString ("x4");
|
||||
else if (obj is short)
|
||||
fval = ((short) obj).ToString ("x8");
|
||||
else if (obj is long)
|
||||
fval = ((long) obj).ToString ("x16");
|
||||
else if (obj is byte)
|
||||
fval = ((byte) obj).ToString ("x2");
|
||||
else if (obj is uint)
|
||||
fval = ((uint) obj).ToString ("x4");
|
||||
else if (obj is ushort)
|
||||
fval = ((ushort) obj).ToString ("x8");
|
||||
else if (obj is ulong)
|
||||
fval = ((ulong) obj).ToString ("x16");
|
||||
|
||||
if (fval != null)
|
||||
return new EvaluationResult ("0x" + fval);
|
||||
}
|
||||
|
||||
return new EvaluationResult (obj.ToString ());
|
||||
}
|
||||
|
||||
public static string EscapeString (string text)
|
||||
{
|
||||
var sb = new StringBuilder ();
|
||||
|
||||
for (int i = 0; i < text.Length; i++) {
|
||||
char c = text[i];
|
||||
string txt;
|
||||
|
||||
switch (c) {
|
||||
case '"': txt = "\\\""; break;
|
||||
case '\0': txt = @"\0"; break;
|
||||
case '\\': txt = @"\\"; break;
|
||||
case '\a': txt = @"\a"; break;
|
||||
case '\b': txt = @"\b"; break;
|
||||
case '\f': txt = @"\f"; break;
|
||||
case '\v': txt = @"\v"; break;
|
||||
case '\n': txt = @"\n"; break;
|
||||
case '\r': txt = @"\r"; break;
|
||||
case '\t': txt = @"\t"; break;
|
||||
default:
|
||||
if (char.GetUnicodeCategory (c) == UnicodeCategory.OtherNotAssigned) {
|
||||
sb.AppendFormat ("\\u{0:x4}", (int) c);
|
||||
} else {
|
||||
sb.Append (c);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
sb.Append (txt);
|
||||
}
|
||||
|
||||
return sb.ToString ();
|
||||
}
|
||||
|
||||
public virtual bool CaseSensitive {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public abstract string Resolve (DebuggerSession session, SourceLocation location, string expression);
|
||||
|
||||
public virtual IEnumerable<ValueReference> GetLocalVariables (EvaluationContext ctx)
|
||||
{
|
||||
return ctx.Adapter.GetLocalVariables (ctx);
|
||||
}
|
||||
|
||||
public virtual ValueReference GetThisReference (EvaluationContext ctx)
|
||||
{
|
||||
return ctx.Adapter.GetThisReference (ctx);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<ValueReference> GetParameters (EvaluationContext ctx)
|
||||
{
|
||||
return ctx.Adapter.GetParameters (ctx);
|
||||
}
|
||||
|
||||
public virtual ValueReference GetCurrentException (EvaluationContext ctx)
|
||||
{
|
||||
return ctx.Adapter.GetCurrentException (ctx);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class EvaluatorException: Exception
|
||||
{
|
||||
protected EvaluatorException (SerializationInfo info, StreamingContext context)
|
||||
: base (info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public EvaluatorException (string msg, params object[] args): base (string.Format (msg, args))
|
||||
{
|
||||
}
|
||||
|
||||
public EvaluatorException (Exception innerException, string msg, params object [] args) : base (string.Format (msg, args), innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class EvaluatorAbortedException: EvaluatorException
|
||||
{
|
||||
protected EvaluatorAbortedException (SerializationInfo info, StreamingContext context)
|
||||
: base (info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public EvaluatorAbortedException ()
|
||||
: base ("Aborted.")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class NotSupportedExpressionException: EvaluatorException
|
||||
{
|
||||
protected NotSupportedExpressionException (SerializationInfo info, StreamingContext context)
|
||||
: base (info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public NotSupportedExpressionException ()
|
||||
: base ("Expression not supported.")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ImplicitEvaluationDisabledException: EvaluatorException
|
||||
{
|
||||
protected ImplicitEvaluationDisabledException (SerializationInfo info, StreamingContext context)
|
||||
: base (info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ImplicitEvaluationDisabledException ()
|
||||
: base ("Implicit property and method evaluation is disabled.")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
//
|
||||
// FilteredMembersSource.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class FilteredMembersSource: RemoteFrameObject, IObjectValueSource
|
||||
{
|
||||
object obj;
|
||||
object type;
|
||||
EvaluationContext ctx;
|
||||
BindingFlags bindingFlags;
|
||||
IObjectSource objectSource;
|
||||
|
||||
public FilteredMembersSource (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
this.obj = obj;
|
||||
this.type = type;
|
||||
this.bindingFlags = bindingFlags;
|
||||
this.objectSource = objectSource;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateNonPublicsNode (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags)
|
||||
{
|
||||
return CreateNode (ctx, objectSource, type, obj, bindingFlags, "Non-public members");
|
||||
}
|
||||
|
||||
public static ObjectValue CreateStaticsNode (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags)
|
||||
{
|
||||
return CreateNode (ctx, objectSource, type, obj, bindingFlags, "Static members");
|
||||
}
|
||||
|
||||
static ObjectValue CreateNode (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags, string label)
|
||||
{
|
||||
FilteredMembersSource src = new FilteredMembersSource (ctx, objectSource, type, obj, bindingFlags);
|
||||
src.Connect ();
|
||||
ObjectValue val = ObjectValue.CreateObject (src, new ObjectPath (label), "", "", ObjectValueFlags.Group|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
|
||||
val.ChildSelector = "";
|
||||
return val;
|
||||
}
|
||||
|
||||
public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
var names = new ObjectValueNameTracker (cctx);
|
||||
object tdataType = null;
|
||||
TypeDisplayData tdata = null;
|
||||
List<ObjectValue> list = new List<ObjectValue> ();
|
||||
foreach (ValueReference val in cctx.Adapter.GetMembersSorted (cctx, objectSource, type, obj, bindingFlags)) {
|
||||
object decType = val.DeclaringType;
|
||||
if (decType != null && decType != tdataType) {
|
||||
tdataType = decType;
|
||||
tdata = cctx.Adapter.GetTypeDisplayData (cctx, decType);
|
||||
}
|
||||
DebuggerBrowsableState state = tdata.GetMemberBrowsableState (val.Name);
|
||||
if (state == DebuggerBrowsableState.Never)
|
||||
continue;
|
||||
ObjectValue oval = val.CreateObjectValue (options);
|
||||
names.Disambiguate (val, oval);
|
||||
list.Add (oval);
|
||||
}
|
||||
if ((bindingFlags & BindingFlags.NonPublic) == 0) {
|
||||
BindingFlags newFlags = bindingFlags | BindingFlags.NonPublic;
|
||||
newFlags &= ~BindingFlags.Public;
|
||||
list.Add (CreateNonPublicsNode (cctx, objectSource, type, obj, newFlags));
|
||||
}
|
||||
return list.ToArray ();
|
||||
}
|
||||
|
||||
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public object GetRawValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// ICollectionAdaptor.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public interface ICollectionAdaptor
|
||||
{
|
||||
int[] GetLowerBounds ();
|
||||
int[] GetDimensions ();
|
||||
object GetElement (int[] indices);
|
||||
Array GetElements (int[] indices, int count);
|
||||
object ElementType { get; }
|
||||
void SetElement (int[] indices, object val);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// IObjectSource.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public interface IObjectSource
|
||||
{
|
||||
object Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// IStringAdaptor.cs
|
||||
//
|
||||
// Author: Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2012 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public interface IStringAdaptor
|
||||
{
|
||||
string Substring (int index, int length);
|
||||
string Value { get; }
|
||||
int Length { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
// Outputs lambda expression inputted on Immediate Pad. Also
|
||||
// this class works for followings.
|
||||
// - Check if body of lambda has not-supported expression
|
||||
// - Output reserved words like `this` or `base` with generated
|
||||
// identifer.
|
||||
// - Collect variable references for outside the lambda
|
||||
// (local variables/properties...)
|
||||
/*public class LambdaBodyOutputVisitor : CSharpSyntaxWalker
|
||||
{
|
||||
readonly Dictionary<string, ValueReference> userVariables;
|
||||
readonly EvaluationContext ctx;
|
||||
|
||||
Dictionary<string, Tuple<string, object>> localValues;
|
||||
List<string> definedIdentifier;
|
||||
int gensymCount;
|
||||
|
||||
public LambdaBodyOutputVisitor (EvaluationContext ctx, Dictionary<string, ValueReference> userVariables)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
this.userVariables = userVariables;
|
||||
this.localValues = new Dictionary<string, Tuple<string, object>> ();
|
||||
this.definedIdentifier = new List<string> ();
|
||||
}
|
||||
|
||||
public Tuple<string, object>[] GetLocalValues ()
|
||||
{
|
||||
var locals = new Tuple<string, object>[localValues.Count];
|
||||
int n = 0;
|
||||
foreach (var localv in localValues.Values) {
|
||||
locals[n] = localv;
|
||||
n++;
|
||||
}
|
||||
return locals;
|
||||
}
|
||||
|
||||
static Exception NotSupported ()
|
||||
{
|
||||
return new NotSupportedExpressionException ();
|
||||
}
|
||||
|
||||
static Exception EvaluationError (string message, params object[] args)
|
||||
{
|
||||
return new EvaluatorException (message, args);
|
||||
}
|
||||
|
||||
bool IsPublicValueFlag (ObjectValueFlags flags)
|
||||
{
|
||||
var isField = (flags & ObjectValueFlags.Field) != 0;
|
||||
var isProperty = (flags & ObjectValueFlags.Property) != 0;
|
||||
var isPublic = (flags & ObjectValueFlags.Public) != 0;
|
||||
|
||||
return !(isField || isProperty) || isPublic;
|
||||
}
|
||||
|
||||
void AssertPublicType (object type)
|
||||
{
|
||||
if (!ctx.Adapter.IsPublic (ctx, type)) {
|
||||
var typeName = ctx.Adapter.GetDisplayTypeName (ctx, type);
|
||||
throw EvaluationError ("Not Support to reference non-public type: `{0}'", typeName);
|
||||
}
|
||||
}
|
||||
|
||||
void AssertPublicValueReference (ValueReference vr)
|
||||
{
|
||||
if (!(vr is NamespaceValueReference)) {
|
||||
var typ = vr.Type;
|
||||
AssertPublicType (typ);
|
||||
}
|
||||
if (!IsPublicValueFlag (vr.Flags)) {
|
||||
throw EvaluationError ("Not Support to reference non-public thing: `{0}'", vr.Name);
|
||||
}
|
||||
}
|
||||
|
||||
ValueReference Evaluate (IdentifierNameSyntax t)
|
||||
{
|
||||
var visitor = new NRefactoryExpressionEvaluatorVisitor (ctx, t.Identifier.ValueText, null, userVariables);
|
||||
return visitor.Visit (t);
|
||||
}
|
||||
|
||||
ValueReference Evaluate (BaseExpressionSyntax t)
|
||||
{
|
||||
var visitor = new NRefactoryExpressionEvaluatorVisitor (ctx, "base", null, userVariables);
|
||||
return visitor.Visit (t);
|
||||
}
|
||||
|
||||
ValueReference Evaluate (ThisExpressionSyntax t)
|
||||
{
|
||||
var visitor = new NRefactoryExpressionEvaluatorVisitor (ctx, "this", null, userVariables);
|
||||
return visitor.Visit (t);
|
||||
}
|
||||
|
||||
string GenerateSymbol (string s)
|
||||
{
|
||||
var prefix = "__" + s;
|
||||
var sym = prefix;
|
||||
while (ExistsLocalName (sym)) {
|
||||
sym = prefix + gensymCount++;
|
||||
}
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
string AddToLocals (string name, ValueReference vr, bool shouldRename = false)
|
||||
{
|
||||
if (localValues.ContainsKey (name))
|
||||
return GetLocalName (name);
|
||||
|
||||
string localName;
|
||||
if (shouldRename) {
|
||||
localName = GenerateSymbol (name);
|
||||
} else if (!ExistsLocalName (name)) {
|
||||
localName = name;
|
||||
} else {
|
||||
throw EvaluationError ("Cannot use a variable named {0} inside lambda", name);
|
||||
}
|
||||
|
||||
AssertPublicValueReference (vr);
|
||||
|
||||
if (!(vr is NamespaceValueReference)) {
|
||||
var valu = vr?.Value;
|
||||
var pair = Tuple.Create(localName, valu);
|
||||
localValues.Add(name, pair);
|
||||
}
|
||||
return localName;
|
||||
}
|
||||
|
||||
string GetLocalName (string name)
|
||||
{
|
||||
Tuple<string, object> pair;
|
||||
if (localValues.TryGetValue (name, out pair))
|
||||
return pair.Item1;
|
||||
return null;
|
||||
}
|
||||
|
||||
bool ExistsLocalName (string localName)
|
||||
{
|
||||
foreach (var pair in localValues.Values) {
|
||||
if (pair.Item1 == localName)
|
||||
return true;
|
||||
}
|
||||
return definedIdentifier.Contains (localName);
|
||||
}
|
||||
|
||||
#region IAstVisitor implementation
|
||||
|
||||
public override void VisitAssignmentExpression (AssignmentExpressionSyntax node)
|
||||
{
|
||||
throw EvaluationError ("Not support assignment expression inside lambda");
|
||||
}
|
||||
|
||||
public override void VisitBaseExpression (BaseExpressionSyntax node)
|
||||
{
|
||||
var basee = "base";
|
||||
var localbase = GetLocalName (basee);
|
||||
if (localbase == null) {
|
||||
var vr = Evaluate (node);
|
||||
localbase = AddToLocals (basee, vr, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitIdentifierName (IdentifierNameSyntax node)
|
||||
{
|
||||
var identifier = node.Identifier.ValueText;
|
||||
var localIdentifier = "";
|
||||
|
||||
if (definedIdentifier.Contains (identifier)) {
|
||||
localIdentifier = identifier;
|
||||
} else {
|
||||
localIdentifier = GetLocalName (identifier);
|
||||
if (localIdentifier == null) {
|
||||
var vr = Evaluate (node);
|
||||
localIdentifier = AddToLocals (identifier, vr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitGenericName (GenericNameSyntax node)
|
||||
{
|
||||
foreach (var arg in node.TypeArgumentList.Arguments) {
|
||||
Visit (arg);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitInvocationExpression (InvocationExpressionSyntax node)
|
||||
{
|
||||
var invocationTarget = node.Expression;
|
||||
if (!(invocationTarget is IdentifierNameSyntax method)) {
|
||||
Visit(invocationTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
var argc = node.ArgumentList.Arguments.Count;
|
||||
var methodName = method.Identifier.ValueText;
|
||||
var vref = ctx.Adapter.GetThisReference (ctx);
|
||||
var vtype = ctx.Adapter.GetEnclosingType (ctx);
|
||||
string accessor = null;
|
||||
|
||||
var hasInstanceMethod = ctx.Adapter.HasMethodWithParamLength (ctx, vtype, methodName, BindingFlags.Instance, argc);
|
||||
var hasStaticMethod = ctx.Adapter.HasMethodWithParamLength (ctx, vtype, methodName, BindingFlags.Static, argc);
|
||||
var publicFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
|
||||
var hasPublicMethod = ctx.Adapter.HasMethodWithParamLength (ctx, vtype, methodName, publicFlags, argc);
|
||||
|
||||
if ((hasInstanceMethod || hasStaticMethod) && !hasPublicMethod)
|
||||
throw EvaluationError ("Only support public method invocation inside lambda");
|
||||
|
||||
if (vref == null && hasStaticMethod) {
|
||||
AssertPublicType (vtype);
|
||||
var typeName = ctx.Adapter.GetTypeName (ctx, vtype);
|
||||
accessor = ctx.Adapter.GetDisplayTypeName (typeName);
|
||||
} else if (vref != null) {
|
||||
AssertPublicValueReference (vref);
|
||||
if (hasInstanceMethod) {
|
||||
if (hasStaticMethod) {
|
||||
// It's hard to determine which one is expected because
|
||||
// we don't have any information of parameter types now.
|
||||
throw EvaluationError ("Not supported invocation of static/instance overloaded method");
|
||||
}
|
||||
accessor = GetLocalName ("this");
|
||||
if (accessor == null)
|
||||
accessor = AddToLocals ("this", vref, true);
|
||||
} else if (hasStaticMethod) {
|
||||
var typeName = ctx.Adapter.GetTypeName (ctx, vtype);
|
||||
accessor = ctx.Adapter.GetDisplayTypeName (typeName);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < node.ArgumentList.Arguments.Count; i++) {
|
||||
Visit (node.ArgumentList.Arguments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void VisitSimpleLambdaExpression (SimpleLambdaExpressionSyntax node)
|
||||
{
|
||||
if (node.Parameter.Modifiers.Count > 0)
|
||||
throw NotSupported ();
|
||||
|
||||
definedIdentifier.Add (node.Parameter.Identifier.ValueText);
|
||||
Visit (node.Body);
|
||||
}
|
||||
|
||||
public override void VisitThisExpression (ThisExpressionSyntax node)
|
||||
{
|
||||
var thiss = "this";
|
||||
var localthis = GetLocalName (thiss);
|
||||
if (localthis == null) {
|
||||
var vr = Evaluate (node);
|
||||
localthis = AddToLocals (thiss, vr, true);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}*/
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
// LiteralValueReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class LiteralValueReference: ValueReference
|
||||
{
|
||||
bool isVoidReturn;
|
||||
bool objLiteral;
|
||||
bool objCreated;
|
||||
object objValue;
|
||||
object value;
|
||||
object type;
|
||||
string name;
|
||||
|
||||
LiteralValueReference (EvaluationContext ctx): base (ctx)
|
||||
{
|
||||
}
|
||||
|
||||
public static LiteralValueReference CreateTargetBaseObjectLiteral (EvaluationContext ctx, string name, object value)
|
||||
{
|
||||
var val = new LiteralValueReference (ctx);
|
||||
var type = ctx.Adapter.GetValueType (ctx, value);
|
||||
val.name = name;
|
||||
val.value = value;
|
||||
val.type = ctx.Adapter.GetBaseType (ctx, type);
|
||||
val.objCreated = true;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static LiteralValueReference CreateTargetObjectLiteral (EvaluationContext ctx, string name, object value, object type = null)
|
||||
{
|
||||
var val = new LiteralValueReference (ctx);
|
||||
val.name = name;
|
||||
val.value = value;
|
||||
val.type = type ?? ctx.Adapter.GetValueType (ctx, value);
|
||||
val.objCreated = true;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static LiteralValueReference CreateObjectLiteral (EvaluationContext ctx, string name, object value)
|
||||
{
|
||||
var val = new LiteralValueReference (ctx);
|
||||
val.name = name;
|
||||
val.objValue = value;
|
||||
val.objLiteral = true;
|
||||
return val;
|
||||
}
|
||||
|
||||
public static LiteralValueReference CreateVoidReturnLiteral (EvaluationContext ctx, string name)
|
||||
{
|
||||
var val = new LiteralValueReference (ctx);
|
||||
val.value = val.objValue = new EvaluationResult ("No return value.");
|
||||
val.type = typeof (EvaluationResult);
|
||||
val.isVoidReturn = true;
|
||||
val.objLiteral = true;
|
||||
val.objCreated = true;
|
||||
val.name = name;
|
||||
return val;
|
||||
}
|
||||
|
||||
void EnsureValueAndType ()
|
||||
{
|
||||
if (!objCreated && objLiteral) {
|
||||
value = Context.Adapter.CreateValue (Context, objValue);
|
||||
type = Context.Adapter.GetValueType (Context, value);
|
||||
objCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override object ObjectValue {
|
||||
get {
|
||||
return objLiteral ? objValue : base.ObjectValue;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
EnsureValueAndType ();
|
||||
return value;
|
||||
}
|
||||
set {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
EnsureValueAndType ();
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return ObjectValueFlags.Field | ObjectValueFlags.ReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
protected override ObjectValue OnCreateObjectValue (EvaluationOptions options)
|
||||
{
|
||||
if (ObjectValue is EvaluationResult) {
|
||||
EvaluationResult exp = (EvaluationResult) ObjectValue;
|
||||
return Mono.Debugging.Client.ObjectValue.CreateObject (this, new ObjectPath (Name), "", exp, Flags, null);
|
||||
}
|
||||
|
||||
return base.OnCreateObjectValue (options);
|
||||
}
|
||||
|
||||
public override ValueReference GetChild (string name, EvaluationOptions options)
|
||||
{
|
||||
object obj = Value;
|
||||
|
||||
if (obj == null)
|
||||
return null;
|
||||
|
||||
if (name [0] == '[' && Context.Adapter.IsArray (Context, obj)) {
|
||||
// Parse the array indices
|
||||
var tokens = name.Substring (1, name.Length - 2).Split (',');
|
||||
var indices = new int [tokens.Length];
|
||||
|
||||
for (int n = 0; n < tokens.Length; n++)
|
||||
indices[n] = int.Parse (tokens[n]);
|
||||
|
||||
return new ArrayValueReference (Context, obj, indices);
|
||||
}
|
||||
|
||||
if (Context.Adapter.IsClassInstance (Context, obj)) {
|
||||
// Note: This is the only difference with the default ValueReference implementation.
|
||||
// We need this because the user may be requesting a base class's implementation, in
|
||||
// which case 'Type' will be the BaseType instead of the actual type of the variable.
|
||||
return Context.Adapter.GetMember (GetChildrenContext (options), this, Type, obj, name);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
if (isVoidReturn)
|
||||
return new ObjectValue[0];
|
||||
|
||||
return base.GetChildren (path, index, count, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
//
|
||||
// NRefactoryExpressionEvaluator.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
/*public class NRefactoryExpressionEvaluator : ExpressionEvaluator
|
||||
{
|
||||
readonly Dictionary<string, ValueReference> userVariables = new Dictionary<string, ValueReference> ();
|
||||
|
||||
public override ValueReference Evaluate (EvaluationContext ctx, string expression, object expectedType)
|
||||
{
|
||||
expression = expression.Trim ();
|
||||
|
||||
if (expression.Length > 0 && expression[0] == '?')
|
||||
expression = expression.Substring (1).TrimStart ();
|
||||
|
||||
if (expression.Length > 3 && expression.StartsWith ("var", StringComparison.Ordinal) && char.IsWhiteSpace (expression[3])) {
|
||||
expression = expression.Substring (4).TrimStart ();
|
||||
string variable = null;
|
||||
|
||||
for (int n = 0; n < expression.Length; n++) {
|
||||
if (!char.IsLetterOrDigit (expression[n]) && expression[n] != '_') {
|
||||
variable = expression.Substring (0, n);
|
||||
if (!expression.Substring (n).TrimStart ().StartsWith ("=", StringComparison.Ordinal))
|
||||
variable = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == expression.Length - 1) {
|
||||
variable = expression;
|
||||
expression = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty (variable))
|
||||
userVariables[variable] = new UserVariableReference (ctx, variable);
|
||||
|
||||
if (expression == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
expression = ReplaceExceptionTag (expression, ctx.Options.CurrentExceptionTag);
|
||||
|
||||
var expr = SyntaxFactory.ParseExpression (expression);
|
||||
if (expr == null)
|
||||
throw new EvaluatorException ("Could not parse expression '{0}'", expression);
|
||||
|
||||
var evaluator = new NRefactoryExpressionEvaluatorVisitor (ctx, expression, expectedType, userVariables);
|
||||
|
||||
return evaluator.Visit (expr);
|
||||
}
|
||||
|
||||
public override string Resolve (DebuggerSession session, SourceLocation location, string exp)
|
||||
{
|
||||
return Resolve (session, location, exp, false);
|
||||
}
|
||||
|
||||
string Resolve (DebuggerSession session, SourceLocation location, string expression, bool tryTypeOf)
|
||||
{
|
||||
expression = expression.Trim ();
|
||||
|
||||
if (expression.Length > 0 && expression[0] == '?')
|
||||
return "?" + Resolve (session, location, expression.Substring (1).Trim ());
|
||||
|
||||
if (expression.Length > 3 && expression.StartsWith ("var", StringComparison.Ordinal) && char.IsWhiteSpace (expression[3]))
|
||||
return "var " + Resolve (session, location, expression.Substring (4).Trim (' ', '\t'));
|
||||
|
||||
expression = ReplaceExceptionTag (expression, session.Options.EvaluationOptions.CurrentExceptionTag);
|
||||
|
||||
|
||||
var expr = SyntaxFactory.ParseExpression (expression);
|
||||
if (expr == null)
|
||||
return expression;
|
||||
|
||||
var resolver = new NRefactoryExpressionResolverVisitor (session, location, expression);
|
||||
resolver.Visit (expr);
|
||||
|
||||
string resolved = resolver.GetResolvedExpression ();
|
||||
if (resolved == expression && !tryTypeOf && (expr is BinaryExpressionSyntax) && IsTypeName (expression)) {
|
||||
// This is a hack to be able to parse expressions such as "List<string>". The NRefactory parser
|
||||
// can parse a single type name, so a solution is to wrap it around a typeof(). We do it if
|
||||
// the evaluation fails.
|
||||
string res = Resolve (session, location, "typeof(" + expression + ")", true);
|
||||
return res.Substring (7, res.Length - 8);
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
public override ValidationResult ValidateExpression (EvaluationContext ctx, string expression)
|
||||
{
|
||||
expression = expression.Trim ();
|
||||
|
||||
if (expression.Length > 0 && expression[0] == '?')
|
||||
expression = expression.Substring (1).TrimStart ();
|
||||
|
||||
if (expression.Length > 3 && expression.StartsWith ("var", StringComparison.Ordinal) && char.IsWhiteSpace (expression[3]))
|
||||
expression = expression.Substring (4).TrimStart ();
|
||||
|
||||
expression = ReplaceExceptionTag (expression, ctx.Options.CurrentExceptionTag);
|
||||
|
||||
ParseOptions options = new CSharpParseOptions ();
|
||||
var expr = SyntaxFactory.ParseExpression (expression, options: options);
|
||||
|
||||
if (expr.ContainsDiagnostics)
|
||||
return new ValidationResult (false, expr.GetDiagnostics().First ().GetMessage());
|
||||
|
||||
return new ValidationResult (true, null);
|
||||
}
|
||||
|
||||
string ReplaceExceptionTag (string exp, string tag)
|
||||
{
|
||||
// FIXME: Don't replace inside string literals
|
||||
return exp.Replace (tag, "__EXCEPTION_OBJECT__");
|
||||
}
|
||||
|
||||
bool IsTypeName (string name)
|
||||
{
|
||||
int pos = 0;
|
||||
bool res = ParseTypeName (name + "$", ref pos);
|
||||
return res && pos >= name.Length;
|
||||
}
|
||||
|
||||
bool ParseTypeName (string name, ref int pos)
|
||||
{
|
||||
EatSpaces (name, ref pos);
|
||||
if (!ParseName (name, ref pos))
|
||||
return false;
|
||||
|
||||
EatSpaces (name, ref pos);
|
||||
if (!ParseGenericArgs (name, ref pos))
|
||||
return false;
|
||||
|
||||
EatSpaces (name, ref pos);
|
||||
if (!ParseIndexer (name, ref pos))
|
||||
return false;
|
||||
|
||||
EatSpaces (name, ref pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EatSpaces (string name, ref int pos)
|
||||
{
|
||||
while (char.IsWhiteSpace (name[pos]))
|
||||
pos++;
|
||||
}
|
||||
|
||||
bool ParseName (string name, ref int pos)
|
||||
{
|
||||
if (name[0] == 'g' && pos < name.Length - 8 && name.Substring (pos, 8) == "global::")
|
||||
pos += 8;
|
||||
|
||||
do {
|
||||
int oldp = pos;
|
||||
while (char.IsLetterOrDigit (name[pos]))
|
||||
pos++;
|
||||
|
||||
if (oldp == pos)
|
||||
return false;
|
||||
|
||||
if (name[pos] != '.')
|
||||
return true;
|
||||
|
||||
pos++;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
bool ParseGenericArgs (string name, ref int pos)
|
||||
{
|
||||
if (name [pos] != '<')
|
||||
return true;
|
||||
|
||||
pos++;
|
||||
EatSpaces (name, ref pos);
|
||||
|
||||
while (true) {
|
||||
if (!ParseTypeName (name, ref pos))
|
||||
return false;
|
||||
|
||||
EatSpaces (name, ref pos);
|
||||
char c = name [pos++];
|
||||
|
||||
if (c == '>')
|
||||
return true;
|
||||
|
||||
if (c == ',')
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParseIndexer (string name, ref int pos)
|
||||
{
|
||||
if (name [pos] != '[')
|
||||
return true;
|
||||
|
||||
do {
|
||||
pos++;
|
||||
EatSpaces (name, ref pos);
|
||||
} while (name [pos] == ',');
|
||||
|
||||
return name [pos++] == ']';
|
||||
}
|
||||
}*/
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,157 @@
|
|||
//
|
||||
// NRefactoryExpressionResolverVisitor.cs
|
||||
//
|
||||
// Author: Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
// FIXME: if we passed the DebuggerSession and SourceLocation into the NRefactoryExpressionEvaluatorVisitor,
|
||||
// we wouldn't need to do this resolve step.
|
||||
/*public class NRefactoryExpressionResolverVisitor : CSharpSyntaxWalker
|
||||
{
|
||||
readonly List<Replacement> replacements = new List<Replacement> ();
|
||||
readonly SourceLocation location;
|
||||
readonly DebuggerSession session;
|
||||
readonly string expression;
|
||||
string parentType;
|
||||
|
||||
class Replacement
|
||||
{
|
||||
public string NewText;
|
||||
public int Offset;
|
||||
public int Length;
|
||||
}
|
||||
|
||||
public NRefactoryExpressionResolverVisitor (DebuggerSession session, SourceLocation location, string expression)
|
||||
{
|
||||
this.expression = expression.Replace ("\n", "").Replace ("\r", "");
|
||||
this.session = session;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
internal string GetResolvedExpression ()
|
||||
{
|
||||
if (replacements.Count == 0)
|
||||
return expression;
|
||||
|
||||
replacements.Sort ((r1, r2) => r1.Offset.CompareTo (r2.Offset));
|
||||
var resolved = new StringBuilder ();
|
||||
int i = 0;
|
||||
|
||||
foreach (var replacement in replacements) {
|
||||
resolved.Append (expression, i, replacement.Offset - i);
|
||||
resolved.Append (replacement.NewText);
|
||||
i = replacement.Offset + replacement.Length;
|
||||
}
|
||||
|
||||
var last = replacements [replacements.Count - 1];
|
||||
resolved.Append (expression, last.Offset + last.Length, expression.Length - (last.Offset + last.Length));
|
||||
|
||||
return resolved.ToString ();
|
||||
}
|
||||
|
||||
string GenerateGenericArgs (int genericArgs)
|
||||
{
|
||||
if (genericArgs == 0)
|
||||
return "";
|
||||
|
||||
string result = "<";
|
||||
for (int i = 0; i < genericArgs; i++)
|
||||
result += "int,";
|
||||
|
||||
return result.Remove (result.Length - 1) + ">";
|
||||
}
|
||||
|
||||
void ReplaceType (string name, int genericArgs, int offset, int length, bool memberType = false)
|
||||
{
|
||||
string type;
|
||||
|
||||
if (genericArgs == 0)
|
||||
type = session.ResolveIdentifierAsType (name, location);
|
||||
else
|
||||
type = session.ResolveIdentifierAsType (name + "`" + genericArgs, location);
|
||||
|
||||
if (string.IsNullOrEmpty (type)) {
|
||||
parentType = null;
|
||||
} else {
|
||||
if (memberType) {
|
||||
type = type.Substring (type.LastIndexOf ('.') + 1);
|
||||
}
|
||||
|
||||
parentType = type + GenerateGenericArgs (genericArgs);
|
||||
|
||||
if (type != name) {
|
||||
var lengthDelta = type.Length - name.Length;
|
||||
var start = offset - lengthDelta;
|
||||
if (start >= 0 && expression.Substring(offset - lengthDelta, type.Length) == type)
|
||||
return;
|
||||
|
||||
var replacement = new Replacement { Offset = offset, Length = length, NewText = type };
|
||||
replacements.Add(replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReplaceType (SyntaxNode type)
|
||||
{
|
||||
int length = type.Span.Length;
|
||||
int offset = type.Span.Start;
|
||||
|
||||
ReplaceType (type.ToString(), 0, offset, length);
|
||||
}
|
||||
|
||||
public override void VisitIdentifierName (IdentifierNameSyntax node)
|
||||
{
|
||||
//base.VisitIdentifierName (node);
|
||||
var loc = node.Identifier.GetLocation();
|
||||
int length = loc.SourceSpan.Length;
|
||||
int offset = loc.SourceSpan.Start;
|
||||
|
||||
ReplaceType (node.Identifier.ValueText, node.Arity, offset, length);
|
||||
}
|
||||
|
||||
public override void VisitSimpleBaseType (SimpleBaseTypeSyntax node)
|
||||
{
|
||||
ReplaceType (node);
|
||||
}
|
||||
|
||||
public override void VisitPredefinedType (PredefinedTypeSyntax node)
|
||||
{
|
||||
ReplaceType (node);
|
||||
}
|
||||
|
||||
public override void VisitGenericName(GenericNameSyntax node)
|
||||
{
|
||||
var loc = node.Identifier.GetLocation();
|
||||
int length = loc.SourceSpan.Length;
|
||||
int offset = loc.SourceSpan.Start;
|
||||
|
||||
ReplaceType(node.Identifier.ValueText, node.TypeArgumentList.Arguments.Count, offset, length);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
//
|
||||
// NRefactoryExtensions.cs
|
||||
//
|
||||
// Author: Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
/*public static class NRefactoryExtensions
|
||||
{
|
||||
#region AstType
|
||||
|
||||
public static object Resolve (this TypeSyntax type, EvaluationContext ctx)
|
||||
{
|
||||
var args = new List<object> ();
|
||||
var name = type.Resolve (ctx, args);
|
||||
|
||||
//if (name.StartsWith ("global::", StringComparison.Ordinal))
|
||||
// name = name.Substring ("global::".Length);
|
||||
|
||||
if (string.IsNullOrEmpty (name))
|
||||
return null;
|
||||
|
||||
if (args.Count > 0)
|
||||
return ctx.Adapter.GetType (ctx, name, args.ToArray ());
|
||||
|
||||
return ctx.Adapter.GetType (ctx, name);
|
||||
}
|
||||
|
||||
static string Resolve (this ExpressionSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
if (type is PredefinedTypeSyntax)
|
||||
return Resolve ((PredefinedTypeSyntax) type, ctx, args);
|
||||
else if (type is PointerTypeSyntax)
|
||||
return Resolve ((PointerTypeSyntax)type, ctx, args);
|
||||
else if (type is NullableTypeSyntax)
|
||||
return Resolve ((NullableTypeSyntax)type, ctx, args);
|
||||
else if (type is RefTypeSyntax)
|
||||
return Resolve ((RefTypeSyntax)type, ctx, args);
|
||||
else if (type is QualifiedNameSyntax)
|
||||
return Resolve ((QualifiedNameSyntax) type, ctx, args);
|
||||
else if (type is IdentifierNameSyntax)
|
||||
return Resolve ((IdentifierNameSyntax)type, ctx, args);
|
||||
else if (type is GenericNameSyntax)
|
||||
return Resolve ((GenericNameSyntax)type, ctx, args);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion AstType
|
||||
|
||||
#region ComposedType
|
||||
|
||||
static string Resolve (this PointerTypeSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
return type.ElementType.Resolve (ctx, args) + "*";
|
||||
}
|
||||
|
||||
static string Resolve (this RefTypeSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
return type.Type.Resolve (ctx, args);
|
||||
}
|
||||
|
||||
static string Resolve (this NullableTypeSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
args.Insert (0, type.ElementType.Resolve (ctx));
|
||||
return "System.Nullable`1";
|
||||
}
|
||||
|
||||
#endregion ComposedType
|
||||
|
||||
#region MemberType
|
||||
|
||||
static string Resolve (this QualifiedNameSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
string name;
|
||||
|
||||
if (!(type.Left is AliasQualifiedNameSyntax)) {
|
||||
var parent = type.Left.Resolve (ctx, args);
|
||||
name = parent + "." + type.Right.Identifier.ValueText;
|
||||
} else {
|
||||
name = type.Right.Identifier.ValueText;
|
||||
}
|
||||
|
||||
|
||||
if (type.Right is GenericNameSyntax genericName) {
|
||||
name += "`" + genericName.TypeArgumentList.Arguments.Count;
|
||||
foreach (var arg in genericName.TypeArgumentList.Arguments) {
|
||||
object resolved;
|
||||
|
||||
if ((resolved = arg.Resolve (ctx)) == null)
|
||||
return null;
|
||||
|
||||
args.Add (resolved);
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
#endregion MemberType
|
||||
|
||||
#region PrimitiveType
|
||||
|
||||
public static string Resolve (this PredefinedTypeSyntax type)
|
||||
{
|
||||
switch (type.Keyword.Kind()) {
|
||||
case SyntaxKind.BoolKeyword: return "System.Boolean";
|
||||
case SyntaxKind.SByteKeyword: return "System.SByte";
|
||||
case SyntaxKind.ByteKeyword: return "System.Byte";
|
||||
case SyntaxKind.CharKeyword: return "System.Char";
|
||||
case SyntaxKind.ShortKeyword: return "System.Int16";
|
||||
case SyntaxKind.UShortKeyword: return "System.UInt16";
|
||||
case SyntaxKind.IntKeyword: return "System.Int32";
|
||||
case SyntaxKind.UIntKeyword: return "System.UInt32";
|
||||
case SyntaxKind.LongKeyword: return "System.Int64";
|
||||
case SyntaxKind.ULongKeyword: return "System.UInt64";
|
||||
case SyntaxKind.FloatKeyword: return "System.Single";
|
||||
case SyntaxKind.DoubleKeyword: return "System.Double";
|
||||
case SyntaxKind.DecimalKeyword: return "System.Decimal";
|
||||
case SyntaxKind.StringKeyword: return "System.String";
|
||||
case SyntaxKind.ObjectKeyword: return "System.Object";
|
||||
case SyntaxKind.VoidKeyword: return "System.Void";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static string Resolve(string shortTypeName)
|
||||
{
|
||||
string longName;
|
||||
switch (shortTypeName) {
|
||||
case "bool": longName = "System.Boolean"; break;
|
||||
case "byte": longName = "System.Byte"; break;
|
||||
case "sbyte": longName = "System.SByte"; break;
|
||||
case "char": longName = "System.Char"; break;
|
||||
case "decimal": longName = "System.Decimal"; break;
|
||||
case "double": longName = "System.Double"; break;
|
||||
case "float": longName = "System.Single"; break;
|
||||
case "int": longName = "System.Int32"; break;
|
||||
case "uint": longName = "System.UInt32"; break;
|
||||
case "nint": longName = "System.IntPtr"; break;
|
||||
case "nuint": longName = "System.UIntPtr"; break;
|
||||
case "long": longName = "System.Int64"; break;
|
||||
case "ulong": longName = "System.UInt64"; break;
|
||||
case "short": longName = "System.Int16"; break;
|
||||
case "ushort": longName = "System.UInt16"; break;
|
||||
case "object": longName = "System.Object"; break;
|
||||
case "string": longName = "System.String"; break;
|
||||
case "dynamic": longName = "System.Object"; break;
|
||||
default: throw new ArgumentException($"Unknown type {shortTypeName}");
|
||||
}
|
||||
return longName;
|
||||
}
|
||||
|
||||
static string Resolve (this PredefinedTypeSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
return Resolve (type);
|
||||
}
|
||||
|
||||
#endregion PrimitiveType
|
||||
|
||||
#region SimpleType
|
||||
|
||||
static string Resolve (this GenericNameSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
string name = type.Identifier.ValueText;
|
||||
|
||||
if (type.TypeArgumentList.Arguments.Count > 0) {
|
||||
name += "`" + type.TypeArgumentList.Arguments.Count;
|
||||
foreach (var arg in type.TypeArgumentList.Arguments) {
|
||||
object resolved;
|
||||
|
||||
if ((resolved = arg.Resolve (ctx)) == null)
|
||||
return null;
|
||||
|
||||
args.Add (resolved);
|
||||
}
|
||||
}
|
||||
|
||||
return type.Identifier.ValueText;
|
||||
}
|
||||
|
||||
static string Resolve (this IdentifierNameSyntax type, EvaluationContext ctx, List<object> args)
|
||||
{
|
||||
return type.Identifier.ValueText;
|
||||
}
|
||||
|
||||
#endregion SimpleType
|
||||
}*/
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
// NamespaceValueReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class NamespaceValueReference: ValueReference
|
||||
{
|
||||
readonly string namspace;
|
||||
readonly string name;
|
||||
|
||||
public NamespaceValueReference (EvaluationContext ctx, string name) : base (ctx)
|
||||
{
|
||||
namspace = name;
|
||||
|
||||
int i = namspace.LastIndexOf ('.');
|
||||
if (i != -1)
|
||||
this.name = namspace.Substring (i+1);
|
||||
else
|
||||
this.name = namspace;
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
set {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override object ObjectValue {
|
||||
get {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return ObjectValueFlags.Namespace;
|
||||
}
|
||||
}
|
||||
|
||||
public override ValueReference GetChild (string name, EvaluationOptions options)
|
||||
{
|
||||
string newNs = namspace + "." + name;
|
||||
|
||||
var ctx = GetContext (options);
|
||||
var type = ctx.Adapter.GetType (ctx, newNs);
|
||||
|
||||
if (type != null)
|
||||
return new TypeValueReference (ctx, type);
|
||||
|
||||
return new NamespaceValueReference (ctx, newNs);
|
||||
}
|
||||
|
||||
public override ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
var children = new List<ObjectValue> ();
|
||||
|
||||
foreach (var val in GetChildReferences (options))
|
||||
children.Add (val.CreateObjectValue (options));
|
||||
|
||||
return children.ToArray ();
|
||||
}
|
||||
|
||||
public override IEnumerable<ValueReference> GetChildReferences (EvaluationOptions options)
|
||||
{
|
||||
// Child types
|
||||
string[] childNamespaces;
|
||||
string[] childTypes;
|
||||
|
||||
var ctx = GetContext (options);
|
||||
ctx.Adapter.GetNamespaceContents (ctx, namspace, out childNamespaces, out childTypes);
|
||||
|
||||
var list = new List<ValueReference> ();
|
||||
foreach (string typeName in childTypes) {
|
||||
object tt = ctx.Adapter.GetType (ctx, typeName);
|
||||
if (tt != null)
|
||||
list.Add (new TypeValueReference (ctx, tt));
|
||||
}
|
||||
|
||||
list.Sort ((v1, v2) => string.Compare (v1.Name, v2.Name, StringComparison.CurrentCulture));
|
||||
|
||||
// Child namespaces
|
||||
var listNs = new List<ValueReference> ();
|
||||
foreach (string ns in childNamespaces)
|
||||
listNs.Add (new NamespaceValueReference (ctx, ns));
|
||||
|
||||
listNs.Sort ((v1, v2) => string.Compare (v1.Name, v2.Name, StringComparison.CurrentCulture));
|
||||
|
||||
list.AddRange (listNs);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override ObjectValue OnCreateObjectValue (EvaluationOptions options)
|
||||
{
|
||||
return Mono.Debugging.Client.ObjectValue.CreateObject (this, new ObjectPath (Name), "<namespace>", namspace, Flags, null);
|
||||
}
|
||||
|
||||
public override string CallToString ()
|
||||
{
|
||||
return namspace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// NullValueReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class NullValueReference: ValueReference
|
||||
{
|
||||
readonly object type;
|
||||
object obj;
|
||||
bool valueCreated;
|
||||
|
||||
public NullValueReference (EvaluationContext ctx, object type) : base (ctx)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
if (!valueCreated) {
|
||||
valueCreated = true;
|
||||
obj = Context.Adapter.CreateNullValue (Context, type);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
set {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public override object ObjectValue {
|
||||
get {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return ObjectValueFlags.Literal;
|
||||
}
|
||||
}
|
||||
|
||||
protected override ObjectValue OnCreateObjectValue (EvaluationOptions options)
|
||||
{
|
||||
string tn = Context.Adapter.GetTypeName (GetContext (options), Type);
|
||||
return Mono.Debugging.Client.ObjectValue.CreateObject (null, new ObjectPath (Name), tn, "null", Flags, null);
|
||||
}
|
||||
|
||||
public override ValueReference GetChild (string name, EvaluationOptions options)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
return new ObjectValue [0];
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,83 @@
|
|||
// RawViewSource.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Backend;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class RawViewSource: RemoteFrameObject, IObjectValueSource
|
||||
{
|
||||
object obj;
|
||||
EvaluationContext ctx;
|
||||
IObjectSource objectSource;
|
||||
|
||||
public RawViewSource (EvaluationContext ctx, IObjectSource objectSource, object obj)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
this.obj = obj;
|
||||
this.objectSource = objectSource;
|
||||
}
|
||||
|
||||
public static ObjectValue CreateRawView (EvaluationContext ctx, IObjectSource objectSource, object obj)
|
||||
{
|
||||
RawViewSource src = new RawViewSource (ctx, objectSource, obj);
|
||||
src.Connect ();
|
||||
ObjectValue val = ObjectValue.CreateObject (src, new ObjectPath ("Raw View"), "", "", ObjectValueFlags.Group|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
|
||||
val.ChildSelector = "";
|
||||
return val;
|
||||
}
|
||||
|
||||
public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
EvaluationContext cctx = ctx.WithOptions (options);
|
||||
return cctx.Adapter.GetObjectValueChildren (cctx, objectSource, cctx.Adapter.GetValueType (cctx, obj), obj, index, count, false);
|
||||
}
|
||||
|
||||
public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public object GetRawValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// RemoteFrameObject.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class RemoteFrameObject: MarshalByRefObject
|
||||
{
|
||||
static List<RemoteFrameObject> connectedValues = new List<RemoteFrameObject> ();
|
||||
|
||||
public static bool TrackConnections { get; set; }
|
||||
|
||||
bool connected;
|
||||
|
||||
public void Connect ()
|
||||
{
|
||||
if (!TrackConnections)
|
||||
return;
|
||||
|
||||
// Registers the value reference. Once a remote reference of this object
|
||||
// is created, it will never be released, until DisconnectAll is called,
|
||||
// which is done every time the current backtrace changes
|
||||
|
||||
lock (connectedValues) {
|
||||
if (!connected) {
|
||||
connectedValues.Add (this);
|
||||
connected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisconnectAll ()
|
||||
{
|
||||
lock (connectedValues) {
|
||||
foreach (RemoteFrameObject val in connectedValues) {
|
||||
#if !NETCOREAPP
|
||||
System.Runtime.Remoting.RemotingServices.Disconnect (val);
|
||||
#endif
|
||||
IDisposable disp = val as IDisposable;
|
||||
if (disp != null)
|
||||
disp.Dispose ();
|
||||
}
|
||||
connectedValues.Clear ();
|
||||
}
|
||||
}
|
||||
|
||||
public override object InitializeLifetimeService ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
//
|
||||
// RemoteRawValue.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Backend;
|
||||
using System.Collections;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
class RemoteRawValue: RemoteFrameObject, IRawValue
|
||||
{
|
||||
readonly EvaluationContext ctx;
|
||||
readonly IObjectSource source;
|
||||
readonly object targetObject;
|
||||
|
||||
public RemoteRawValue (EvaluationContext gctx, IObjectSource source, object targetObject)
|
||||
{
|
||||
this.ctx = gctx.Clone ();
|
||||
ctx.Options.AllowTargetInvoke = true;
|
||||
ctx.Options.AllowMethodEvaluation = true;
|
||||
this.targetObject = targetObject;
|
||||
this.source = source;
|
||||
Connect ();
|
||||
}
|
||||
|
||||
public object TargetObject {
|
||||
get { return targetObject; }
|
||||
}
|
||||
|
||||
#region IRawValue implementation
|
||||
public object CallMethod (string name, object[] parameters, EvaluationOptions options)
|
||||
{
|
||||
object[] outArgs;
|
||||
return CallMethod (name, parameters, false, out outArgs, options);
|
||||
}
|
||||
|
||||
public object CallMethod (string name, object[] parameters, out object[] outArgs, EvaluationOptions options)
|
||||
{
|
||||
return CallMethod (name, parameters, true, out outArgs, options);
|
||||
}
|
||||
|
||||
private object CallMethod (string name, object[] parameters, bool enableOutArgs, out object[] outArgs, EvaluationOptions options)
|
||||
{
|
||||
var localContext = ctx.WithOptions (options);
|
||||
|
||||
var argValues = new object [parameters.Length];
|
||||
var argTypes = new object [parameters.Length];
|
||||
|
||||
for (int n = 0; n < argValues.Length; n++) {
|
||||
argValues[n] = localContext.Adapter.FromRawValue (localContext, parameters[n]);
|
||||
argTypes[n] = localContext.Adapter.GetValueType (localContext, argValues[n]);
|
||||
}
|
||||
|
||||
var type = localContext.Adapter.GetValueType (localContext, targetObject);
|
||||
if (enableOutArgs) {
|
||||
object[] outArgsTemp;
|
||||
var res = localContext.Adapter.RuntimeInvoke (localContext, type, targetObject, name, null, argTypes, argValues, out outArgsTemp);
|
||||
outArgs = new object[outArgsTemp.Length];
|
||||
for (int i = 0; i < outArgs.Length; i++) {
|
||||
outArgs [i] = localContext.Adapter.ToRawValue (localContext, null, outArgsTemp [i]);
|
||||
}
|
||||
return localContext.Adapter.ToRawValue (localContext, null, res);
|
||||
} else {
|
||||
outArgs = null;
|
||||
var res = localContext.Adapter.RuntimeInvoke (localContext, type, targetObject, name, argTypes, argValues);
|
||||
return localContext.Adapter.ToRawValue (localContext, null, res);
|
||||
}
|
||||
}
|
||||
|
||||
public object GetMemberValue (string name, EvaluationOptions options)
|
||||
{
|
||||
var localContext = ctx.WithOptions (options);
|
||||
var type = localContext.Adapter.GetValueType (localContext, targetObject);
|
||||
var val = localContext.Adapter.GetMember (localContext, source, type, targetObject, name);
|
||||
|
||||
if (val == null)
|
||||
throw new EvaluatorException ("Member '{0}' not found", name);
|
||||
|
||||
return localContext.Adapter.ToRawValue (localContext, val, val.Value);
|
||||
}
|
||||
|
||||
public void SetMemberValue (string name, object value, EvaluationOptions options)
|
||||
{
|
||||
var localContext = ctx.WithOptions (options);
|
||||
var type = localContext.Adapter.GetValueType (localContext, targetObject);
|
||||
var val = localContext.Adapter.GetMember (localContext, source, type, targetObject, name);
|
||||
|
||||
if (val == null)
|
||||
throw new EvaluatorException ("Member '{0}' not found", name);
|
||||
|
||||
val.Value = localContext.Adapter.FromRawValue (localContext, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
class RemoteRawValueArray: RemoteFrameObject, IRawValueArray
|
||||
{
|
||||
readonly ICollectionAdaptor targetArray;
|
||||
readonly EvaluationContext ctx;
|
||||
readonly IObjectSource source;
|
||||
readonly object targetObject;
|
||||
|
||||
public RemoteRawValueArray (EvaluationContext ctx, IObjectSource source, ICollectionAdaptor targetArray, object targetObject)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
this.targetArray = targetArray;
|
||||
this.targetObject = targetObject;
|
||||
this.source = source;
|
||||
Connect ();
|
||||
}
|
||||
|
||||
public object TargetObject {
|
||||
get { return targetObject; }
|
||||
}
|
||||
|
||||
public object GetValue (int[] index)
|
||||
{
|
||||
return ctx.Adapter.ToRawValue (ctx, source, targetArray.GetElement (index));
|
||||
}
|
||||
|
||||
public Array GetValues (int[] index, int count)
|
||||
{
|
||||
var values = targetArray.GetElements (index, count);
|
||||
var idx = new int[index.Length];
|
||||
var array = new ArrayList ();
|
||||
|
||||
for (int i = 0; i < index.Length; i++)
|
||||
idx[i] = index[i];
|
||||
|
||||
Type commonType = null;
|
||||
for (int i = 0; i < count; i++) {
|
||||
var rv = ctx.Adapter.ToRawValue (ctx, new ArrayObjectSource (targetArray, idx), values.GetValue (i));
|
||||
if (commonType == null)
|
||||
commonType = rv.GetType ();
|
||||
else if (commonType != rv.GetType ())
|
||||
commonType = typeof (void);
|
||||
array.Add (rv);
|
||||
|
||||
idx[idx.Length - 1]++;
|
||||
}
|
||||
|
||||
if (array.Count > 0 && commonType != typeof (void))
|
||||
return array.ToArray (commonType);
|
||||
|
||||
return array.ToArray ();
|
||||
}
|
||||
|
||||
public void SetValue (int[] index, object value)
|
||||
{
|
||||
targetArray.SetElement (index, ctx.Adapter.FromRawValue (ctx, value));
|
||||
}
|
||||
|
||||
public int[] Dimensions {
|
||||
get {
|
||||
return targetArray.GetDimensions ();
|
||||
}
|
||||
}
|
||||
|
||||
public Array ToArray ()
|
||||
{
|
||||
int[] dims = targetArray.GetDimensions ();
|
||||
var array = new ArrayList ();
|
||||
|
||||
if (dims.Length != 1)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
var idx = new int [1];
|
||||
Type commonType = null;
|
||||
for (int n = 0; n < dims[0]; n++) {
|
||||
idx[0] = n;
|
||||
|
||||
var rv = ctx.Adapter.ToRawValue (ctx, new ArrayObjectSource (targetArray, idx), targetArray.GetElement (idx));
|
||||
if (commonType == null)
|
||||
commonType = rv.GetType ();
|
||||
else if (commonType != rv.GetType ())
|
||||
commonType = typeof(void);
|
||||
array.Add (rv);
|
||||
}
|
||||
|
||||
if (array.Count > 0 && commonType != typeof(void))
|
||||
return array.ToArray (commonType);
|
||||
|
||||
return array.ToArray ();
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteRawValueString: RemoteFrameObject, IRawValueString
|
||||
{
|
||||
readonly IStringAdaptor targetString;
|
||||
readonly object targetObject;
|
||||
|
||||
public RemoteRawValueString (IStringAdaptor targetString, object targetObject)
|
||||
{
|
||||
this.targetString = targetString;
|
||||
this.targetObject = targetObject;
|
||||
Connect ();
|
||||
}
|
||||
|
||||
public object TargetObject {
|
||||
get { return targetObject; }
|
||||
}
|
||||
|
||||
public int Length {
|
||||
get { return targetString.Length; }
|
||||
}
|
||||
|
||||
public string Value {
|
||||
get { return targetString.Value; }
|
||||
}
|
||||
|
||||
public string Substring (int index, int length)
|
||||
{
|
||||
return targetString.Substring (index, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// TimeOutException.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class TimeOutException: EvaluatorException
|
||||
{
|
||||
public TimeOutException (): base ("Timed out.")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
// EvaluationContext.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class TimedEvaluator
|
||||
{
|
||||
const int maxThreads = 1;
|
||||
|
||||
object runningLock = new object ();
|
||||
Queue<Task> pendingTasks = new Queue<Task> ();
|
||||
ManualResetEvent newTaskEvent = new ManualResetEvent (false);
|
||||
AutoResetEvent threadNotBusyEvent = new AutoResetEvent (false);
|
||||
ManualResetEvent disposedEvent = new ManualResetEvent (false);
|
||||
List<Task> executingTasks = new List<Task> ();
|
||||
int runningThreads;
|
||||
int busyThreads;
|
||||
bool useTimeout;
|
||||
bool disposed;
|
||||
static int threadNameId;
|
||||
|
||||
public TimedEvaluator () : this (true)
|
||||
{
|
||||
}
|
||||
|
||||
public TimedEvaluator (bool useTimeout)
|
||||
{
|
||||
RunTimeout = 1000;
|
||||
this.useTimeout = useTimeout;
|
||||
}
|
||||
|
||||
public int RunTimeout { get; set; }
|
||||
|
||||
public bool IsEvaluating {
|
||||
get {
|
||||
lock (runningLock) {
|
||||
return pendingTasks.Count > 0 || busyThreads > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the provided evaluator. If a result is obtained before RunTimeout milliseconds,
|
||||
/// the method ends returning True.
|
||||
/// If it does not finish after RunTimeout milliseconds, the method ends retuning False, although
|
||||
/// the evaluation continues in the background. In that case, when evaluation ends, the provided
|
||||
/// delayedDoneCallback delegate is called.
|
||||
/// </summary>
|
||||
public bool Run (EvaluatorDelegate evaluator, EvaluatorDelegate delayedDoneCallback)
|
||||
{
|
||||
if (!useTimeout) {
|
||||
SafeRun (evaluator);
|
||||
return true;
|
||||
}
|
||||
|
||||
Task task = new Task ();
|
||||
task.Evaluator = evaluator;
|
||||
task.FinishedCallback = delayedDoneCallback;
|
||||
|
||||
lock (runningLock) {
|
||||
if (disposed)
|
||||
return false;
|
||||
if (busyThreads == runningThreads && runningThreads < maxThreads) {
|
||||
runningThreads++;
|
||||
var tr = new Thread (Runner);
|
||||
tr.Name = "Debugger evaluator " + threadNameId++;
|
||||
tr.IsBackground = true;
|
||||
tr.Start ();
|
||||
}
|
||||
pendingTasks.Enqueue (task);
|
||||
if (busyThreads == runningThreads) {
|
||||
task.TimedOut = true;
|
||||
return false;
|
||||
}
|
||||
newTaskEvent.Set ();
|
||||
}
|
||||
WaitHandle.WaitAny (new WaitHandle [] { task.RunningEvent, disposedEvent });
|
||||
if (WaitHandle.WaitAny (new WaitHandle [] { task.RunFinishedEvent, disposedEvent }, TimeSpan.FromMilliseconds (RunTimeout), false) != 0) {
|
||||
lock (task) {
|
||||
if (task.Processed) {
|
||||
return true;
|
||||
} else {
|
||||
task.TimedOut = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Runner ()
|
||||
{
|
||||
Task threadTask = null;
|
||||
|
||||
while (!disposed) {
|
||||
|
||||
if (threadTask == null) {
|
||||
lock (runningLock) {
|
||||
if (disposed) {
|
||||
runningThreads--;
|
||||
return;
|
||||
}
|
||||
if (pendingTasks.Count > 0) {
|
||||
threadTask = pendingTasks.Dequeue ();
|
||||
executingTasks.Add (threadTask);
|
||||
busyThreads++;
|
||||
} else if (busyThreads + 1 < runningThreads) {
|
||||
runningThreads--;//If we got extra non-busy threads, close this one...
|
||||
return;
|
||||
}
|
||||
if (threadTask == null) {
|
||||
newTaskEvent.Reset ();
|
||||
}
|
||||
}
|
||||
//No pending task, wait for it
|
||||
if (threadTask == null) {
|
||||
WaitHandle.WaitAny (new WaitHandle [] { newTaskEvent, disposedEvent });
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
lock (runningLock) {
|
||||
executingTasks.Remove (threadTask);
|
||||
busyThreads--;
|
||||
}
|
||||
threadNotBusyEvent.Set ();
|
||||
threadTask = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
threadTask.RunningEvent.Set ();
|
||||
SafeRun (threadTask.Evaluator);
|
||||
threadTask.RunFinishedEvent.Set ();
|
||||
lock (threadTask) {
|
||||
threadTask.Processed = true;
|
||||
if (threadTask.TimedOut && !disposed) {
|
||||
SafeRun (threadTask.FinishedCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
lock (runningLock) {
|
||||
disposed = true;
|
||||
CancelAll ();
|
||||
disposedEvent.Set ();
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelAll ()
|
||||
{
|
||||
lock (runningLock) {
|
||||
pendingTasks.Clear ();
|
||||
// If there is a task waiting the be picked by the runner,
|
||||
// set the task wait events to avoid deadlocking the caller.
|
||||
executingTasks.ForEach (t => {
|
||||
t.RunningEvent.Set ();
|
||||
t.RunFinishedEvent.Set ();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void WaitForStopped ()
|
||||
{
|
||||
while (busyThreads > 0) {
|
||||
threadNotBusyEvent.WaitOne (1000);
|
||||
}
|
||||
}
|
||||
|
||||
void SafeRun (EvaluatorDelegate del)
|
||||
{
|
||||
try {
|
||||
del ();
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
|
||||
class Task
|
||||
{
|
||||
public ManualResetEvent RunningEvent = new ManualResetEvent (false);
|
||||
public ManualResetEvent RunFinishedEvent = new ManualResetEvent (false);
|
||||
public EvaluatorDelegate Evaluator;
|
||||
public EvaluatorDelegate FinishedCallback;
|
||||
public bool TimedOut;
|
||||
public bool Processed;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void EvaluatorDelegate ();
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
// TypeValueReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class TypeValueReference: ValueReference
|
||||
{
|
||||
readonly string fullName;
|
||||
readonly string name;
|
||||
readonly object type;
|
||||
|
||||
public TypeValueReference (EvaluationContext ctx, object type) : base (ctx)
|
||||
{
|
||||
this.type = type;
|
||||
fullName = ctx.Adapter.GetDisplayTypeName (ctx, type);
|
||||
name = GetTypeName (fullName);
|
||||
}
|
||||
|
||||
internal static string GetTypeName (string tname)
|
||||
{
|
||||
tname = tname.Replace ('+', '.');
|
||||
|
||||
int sep1 = tname.IndexOf ('<');
|
||||
int sep2 = tname.IndexOf ('[');
|
||||
|
||||
if (sep2 != -1 && (sep2 < sep1 || sep1 == -1))
|
||||
sep1 = sep2;
|
||||
|
||||
if (sep1 == -1)
|
||||
sep1 = tname.Length - 1;
|
||||
|
||||
int dot = tname.LastIndexOf ('.', sep1);
|
||||
|
||||
return dot != -1 ? tname.Substring (dot + 1) : tname;
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
set {
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
public override object ObjectValue {
|
||||
get {
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return ObjectValueFlags.Type;
|
||||
}
|
||||
}
|
||||
|
||||
protected override ObjectValue OnCreateObjectValue (EvaluationOptions options)
|
||||
{
|
||||
return Mono.Debugging.Client.ObjectValue.CreateObject (this, new ObjectPath (Name), "<type>", fullName, Flags, null);
|
||||
}
|
||||
|
||||
public override ValueReference GetChild (string name, EvaluationOptions options)
|
||||
{
|
||||
var ctx = GetContext (options);
|
||||
|
||||
foreach (var val in ctx.Adapter.GetMembers (ctx, this, type, null)) {
|
||||
if (val.Name == name)
|
||||
return val;
|
||||
}
|
||||
|
||||
foreach (var nestedType in ctx.Adapter.GetNestedTypes (ctx, type)) {
|
||||
string typeName = ctx.Adapter.GetTypeName (ctx, nestedType);
|
||||
|
||||
if (GetTypeName (typeName) == name)
|
||||
return new TypeValueReference (ctx, nestedType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
var ctx = GetContext (options);
|
||||
|
||||
try {
|
||||
BindingFlags flattenFlag = options.FlattenHierarchy ? (BindingFlags)0 : BindingFlags.DeclaredOnly;
|
||||
BindingFlags flags = BindingFlags.Static | BindingFlags.Public | flattenFlag;
|
||||
bool groupPrivateMembers = options.GroupPrivateMembers || ctx.Adapter.IsExternalType (ctx, type);
|
||||
var list = new List<ObjectValue> ();
|
||||
|
||||
if (!groupPrivateMembers)
|
||||
flags |= BindingFlags.NonPublic;
|
||||
|
||||
var tdata = ctx.Adapter.GetTypeDisplayData (ctx, type);
|
||||
var tdataType = type;
|
||||
|
||||
foreach (var val in ctx.Adapter.GetMembersSorted (ctx, this, type, null, flags)) {
|
||||
var decType = val.DeclaringType;
|
||||
if (decType != null && decType != tdataType) {
|
||||
tdataType = decType;
|
||||
tdata = ctx.Adapter.GetTypeDisplayData (ctx, decType);
|
||||
}
|
||||
|
||||
var state = tdata.GetMemberBrowsableState (val.Name);
|
||||
if (state == DebuggerBrowsableState.Never)
|
||||
continue;
|
||||
|
||||
var oval = val.CreateObjectValue (options);
|
||||
list.Add (oval);
|
||||
}
|
||||
|
||||
var nestedTypes = new List<ObjectValue> ();
|
||||
foreach (var nestedType in ctx.Adapter.GetNestedTypes (ctx, type))
|
||||
nestedTypes.Add (new TypeValueReference (ctx, nestedType).CreateObjectValue (options));
|
||||
|
||||
nestedTypes.Sort ((v1, v2) => string.Compare (v1.Name, v2.Name, StringComparison.CurrentCulture));
|
||||
|
||||
list.AddRange (nestedTypes);
|
||||
|
||||
if (groupPrivateMembers)
|
||||
list.Add (FilteredMembersSource.CreateNonPublicsNode (ctx, this, type, null, BindingFlags.NonPublic | BindingFlags.Static | flattenFlag));
|
||||
|
||||
if (!options.FlattenHierarchy) {
|
||||
object baseType = ctx.Adapter.GetBaseType (ctx, type, false);
|
||||
if (baseType != null) {
|
||||
var baseRef = new TypeValueReference (ctx, baseType);
|
||||
var baseVal = baseRef.CreateObjectValue (false);
|
||||
baseVal.Name = "base";
|
||||
list.Insert (0, baseVal);
|
||||
}
|
||||
}
|
||||
|
||||
return list.ToArray ();
|
||||
} catch (Exception ex) {
|
||||
ctx.WriteDebuggerOutput (ex.Message);
|
||||
return new ObjectValue [0];
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<ValueReference> GetChildReferences (EvaluationOptions options)
|
||||
{
|
||||
var ctx = GetContext (options);
|
||||
|
||||
try {
|
||||
var list = new List<ValueReference> ();
|
||||
|
||||
list.AddRange (ctx.Adapter.GetMembersSorted (ctx, this, type, null, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static));
|
||||
|
||||
var nestedTypes = new List<ValueReference> ();
|
||||
foreach (var nestedType in ctx.Adapter.GetNestedTypes (ctx, type))
|
||||
nestedTypes.Add (new TypeValueReference (ctx, nestedType));
|
||||
|
||||
nestedTypes.Sort ((v1, v2) => string.Compare (v1.Name, v2.Name, StringComparison.CurrentCulture));
|
||||
list.AddRange (nestedTypes);
|
||||
|
||||
return list;
|
||||
} catch (Exception ex) {
|
||||
ctx.WriteDebuggerOutput (ex.Message);
|
||||
return new ValueReference[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// UserVariableReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public class UserVariableReference: ValueReference
|
||||
{
|
||||
readonly string name;
|
||||
object currentValue;
|
||||
|
||||
public UserVariableReference (EvaluationContext ctx, string name): base (ctx)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
if (currentValue != null)
|
||||
return currentValue;
|
||||
|
||||
throw new EvaluatorException ("Value undefined.");
|
||||
}
|
||||
set {
|
||||
currentValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
return Context.Adapter.GetValueType (Context, Value);
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return ObjectValueFlags.Variable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
// ValueReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
using DC = Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Evaluation
|
||||
{
|
||||
public abstract class ValueReference: RemoteFrameObject, IObjectValueSource, IObjectSource
|
||||
{
|
||||
readonly EvaluationOptions originalOptions;
|
||||
|
||||
protected ValueReference (EvaluationContext ctx)
|
||||
{
|
||||
originalOptions = ctx.Options;
|
||||
Context = ctx;
|
||||
}
|
||||
|
||||
public virtual object ObjectValue {
|
||||
get {
|
||||
object ob = Value;
|
||||
if (Context.Adapter.IsNull (Context, ob))
|
||||
return null;
|
||||
|
||||
if (Context.Adapter.IsPrimitive (Context, ob))
|
||||
return Context.Adapter.TargetObjectToObject (Context, ob);
|
||||
|
||||
return ob;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract object Value { get; set; }
|
||||
public abstract string Name { get; }
|
||||
public abstract object Type { get; }
|
||||
public abstract ObjectValueFlags Flags { get; }
|
||||
|
||||
// For class members, the type declaring the member (null otherwise)
|
||||
public virtual object DeclaringType {
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public EvaluationContext Context {
|
||||
get; set;
|
||||
}
|
||||
|
||||
public EvaluationContext GetContext (EvaluationOptions options)
|
||||
{
|
||||
return Context.WithOptions (options);
|
||||
}
|
||||
|
||||
public ObjectValue CreateObjectValue (bool withTimeout)
|
||||
{
|
||||
return CreateObjectValue (withTimeout, Context.Options);
|
||||
}
|
||||
|
||||
public ObjectValue CreateObjectValue (bool withTimeout, EvaluationOptions options)
|
||||
{
|
||||
if (!CanEvaluate (options))
|
||||
return DC.ObjectValue.CreateImplicitNotSupported (this, new ObjectPath (Name), Context.Adapter.GetDisplayTypeName (GetContext (options), Type), Flags);
|
||||
|
||||
if (withTimeout) {
|
||||
return Context.Adapter.CreateObjectValueAsync (Name, Flags, delegate {
|
||||
return CreateObjectValue (options);
|
||||
});
|
||||
}
|
||||
|
||||
return CreateObjectValue (options);
|
||||
}
|
||||
|
||||
public ObjectValue CreateObjectValue (EvaluationOptions options)
|
||||
{
|
||||
if (!CanEvaluate (options)) {
|
||||
if (options.AllowTargetInvoke)//If it can't evaluate and target invoke is allowed, mark it as not supported.
|
||||
return DC.ObjectValue.CreateNotSupported (this, new ObjectPath (Name), Context.Adapter.GetDisplayTypeName (GetContext (options), Type), "Can not evaluate", Flags);
|
||||
return DC.ObjectValue.CreateImplicitNotSupported (this, new ObjectPath (Name), Context.Adapter.GetDisplayTypeName (GetContext (options), Type), Flags);
|
||||
}
|
||||
Connect ();
|
||||
try {
|
||||
return OnCreateObjectValue (options);
|
||||
} catch (ImplicitEvaluationDisabledException) {
|
||||
return DC.ObjectValue.CreateImplicitNotSupported (this, new ObjectPath (Name), Context.Adapter.GetDisplayTypeName (GetContext (options), Type), Flags);
|
||||
} catch (NotSupportedExpressionException ex) {
|
||||
return DC.ObjectValue.CreateNotSupported (this, new ObjectPath (Name), Context.Adapter.GetDisplayTypeName (GetContext (options), Type), ex.Message, Flags);
|
||||
} catch (EvaluatorException ex) {
|
||||
return DC.ObjectValue.CreateError (this, new ObjectPath (Name), Context.Adapter.GetDisplayTypeName (GetContext (options), Type), ex.Message, Flags);
|
||||
} catch (Exception ex) {
|
||||
Context.WriteDebuggerError (ex);
|
||||
return DC.ObjectValue.CreateUnknown (Name);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool CanEvaluate (EvaluationOptions options)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual ObjectValue OnCreateObjectValue (EvaluationOptions options)
|
||||
{
|
||||
string name = Name;
|
||||
if (string.IsNullOrEmpty (name))
|
||||
name = "?";
|
||||
|
||||
var ctx = GetContext (options);
|
||||
object val = null;
|
||||
|
||||
// Note: The Value property implementation may make use of the EvaluationOptions,
|
||||
// so we need to override our context temporarily to do the evaluation.
|
||||
val = GetValue (ctx);
|
||||
|
||||
if (val != null && !ctx.Adapter.IsNull (ctx, val))
|
||||
return ctx.Adapter.CreateObjectValue (ctx, this, new ObjectPath (name), val, Flags);
|
||||
|
||||
return DC.ObjectValue.CreateNullObject (this, name, ctx.Adapter.GetDisplayTypeName (ctx.Adapter.GetTypeName (ctx, Type)), Flags);
|
||||
}
|
||||
|
||||
ObjectValue IObjectValueSource.GetValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
return CreateObjectValue (true, options);
|
||||
}
|
||||
|
||||
EvaluationResult IObjectValueSource.SetValue (ObjectPath path, string value, EvaluationOptions options)
|
||||
{
|
||||
try {
|
||||
Context.WaitRuntimeInvokes ();
|
||||
|
||||
var ctx = GetContext (options);
|
||||
ctx.Options.AllowMethodEvaluation = true;
|
||||
ctx.Options.AllowTargetInvoke = true;
|
||||
|
||||
var vref = ctx.Evaluator.Evaluate (ctx, value, Type);
|
||||
var newValue = ctx.Adapter.Convert (ctx, vref.Value, Type);
|
||||
SetValue (ctx, newValue);
|
||||
} catch (Exception ex) {
|
||||
Context.WriteDebuggerError (ex);
|
||||
Context.WriteDebuggerOutput ("Value assignment failed: {0}: {1}\n", ex.GetType (), ex.Message);
|
||||
}
|
||||
|
||||
try {
|
||||
return Context.Evaluator.TargetObjectToExpression (Context, Value);
|
||||
} catch (Exception ex) {
|
||||
Context.WriteDebuggerError (ex);
|
||||
Context.WriteDebuggerOutput ("Value assignment failed: {0}: {1}\n", ex.GetType (), ex.Message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
object IObjectValueSource.GetRawValue (ObjectPath path, EvaluationOptions options)
|
||||
{
|
||||
var ctx = GetContext (options);
|
||||
|
||||
return ctx.Adapter.ToRawValue (ctx, this, GetValue (ctx));
|
||||
}
|
||||
|
||||
void IObjectValueSource.SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
SetRawValue (path, value, options);
|
||||
}
|
||||
|
||||
public object GetRawValue (EvaluationOptions options)
|
||||
{
|
||||
var ctx = GetContext (options);
|
||||
return ctx.Adapter.ToRawValue (ctx, this, GetValue (ctx));
|
||||
}
|
||||
|
||||
public void SetRawValue (object value, EvaluationOptions options)
|
||||
{
|
||||
SetRawValue (new ObjectPath (), value, options);
|
||||
}
|
||||
|
||||
protected virtual void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
|
||||
{
|
||||
var ctx = GetContext (options);
|
||||
|
||||
SetValue (ctx, Context.Adapter.FromRawValue (ctx, value));
|
||||
}
|
||||
|
||||
ObjectValue[] IObjectValueSource.GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
return GetChildren (path, index, count, options);
|
||||
}
|
||||
|
||||
public virtual string CallToString ()
|
||||
{
|
||||
return Context.Adapter.CallToString (Context, Value);
|
||||
}
|
||||
|
||||
public virtual object GetValue (EvaluationContext ctx)
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public virtual void SetValue (EvaluationContext ctx, object value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
[Obsolete ("Use GetValue(EvaluationContext) instead.")]
|
||||
protected virtual object GetValueExplicitly ()
|
||||
{
|
||||
var options = Context.Options.Clone ();
|
||||
options.AllowTargetInvoke = true;
|
||||
var ctx = GetContext (options);
|
||||
|
||||
return GetValue (ctx);
|
||||
}
|
||||
|
||||
public virtual ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
|
||||
{
|
||||
try {
|
||||
var ctx = GetChildrenContext (options);
|
||||
|
||||
return ctx.Adapter.GetObjectValueChildren (ctx, this, GetValue (ctx), index, count);
|
||||
} catch (Exception ex) {
|
||||
return new [] { DC.ObjectValue.CreateFatalError ("", ex.Message, ObjectValueFlags.ReadOnly) };
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<ValueReference> GetChildReferences (EvaluationOptions options)
|
||||
{
|
||||
try {
|
||||
object val = Value;
|
||||
if (Context.Adapter.IsClassInstance (Context, val))
|
||||
return Context.Adapter.GetMembersSorted (GetChildrenContext (options), this, Type, val);
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
return new ValueReference [0];
|
||||
}
|
||||
|
||||
public IObjectSource ParentSource { get; set; }
|
||||
|
||||
protected EvaluationContext GetChildrenContext (EvaluationOptions options)
|
||||
{
|
||||
var ctx = Context.Clone ();
|
||||
|
||||
if (options != null)
|
||||
ctx.Options = options;
|
||||
|
||||
ctx.Options.EvaluationTimeout = originalOptions.MemberEvaluationTimeout;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public virtual ValueReference GetChild (ObjectPath vpath, EvaluationOptions options)
|
||||
{
|
||||
if (vpath.Length == 0)
|
||||
return this;
|
||||
|
||||
var val = GetChild (vpath[0], options);
|
||||
|
||||
return val != null ? val.GetChild (vpath.GetSubpath (1), options) : null;
|
||||
}
|
||||
|
||||
public virtual ValueReference GetChild (string name, EvaluationOptions options)
|
||||
{
|
||||
object obj = Value;
|
||||
|
||||
if (obj == null)
|
||||
return null;
|
||||
|
||||
if (name[0] == '[' && Context.Adapter.IsArray (Context, obj)) {
|
||||
// Parse the array indices
|
||||
var tokens = name.Substring (1, name.Length - 2).Split (',');
|
||||
var indices = new int [tokens.Length];
|
||||
|
||||
for (int n = 0; n < tokens.Length; n++)
|
||||
indices[n] = int.Parse (tokens[n]);
|
||||
|
||||
return new ArrayValueReference (Context, obj, indices);
|
||||
}
|
||||
|
||||
if (Context.Adapter.IsClassInstance (Context, obj))
|
||||
return Context.Adapter.GetMember (GetChildrenContext (options), this, Type, obj, name);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
102
VisualPascalABCNETLinux/MonoDebugging/Soft/ArrayAdaptor.cs
Normal file
102
VisualPascalABCNETLinux/MonoDebugging/Soft/ArrayAdaptor.cs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//
|
||||
// ArrayAdaptor.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Mono.Debugging.Evaluation;
|
||||
using Mono.Debugger.Soft;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class ArrayAdaptor : ICollectionAdaptor
|
||||
{
|
||||
readonly ArrayMirror array;
|
||||
int[] dimensions, bounds;
|
||||
|
||||
public ArrayAdaptor (ArrayMirror array)
|
||||
{
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public int[] GetLowerBounds ()
|
||||
{
|
||||
if (bounds == null) {
|
||||
bounds = new int[array.Rank];
|
||||
for (int i = 0; i < array.Rank; i++)
|
||||
bounds[i] = array.GetLowerBound (i);
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public int[] GetDimensions ()
|
||||
{
|
||||
if (dimensions == null) {
|
||||
dimensions = new int[array.Rank];
|
||||
for (int i = 0; i < array.Rank; i++)
|
||||
dimensions[i] = array.GetLength (i);
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
public object GetElement (int[] indices)
|
||||
{
|
||||
int i = GetIndex (indices);
|
||||
return array.GetValues (i, 1)[0];
|
||||
}
|
||||
|
||||
public Array GetElements (int[] indices, int count)
|
||||
{
|
||||
int i = GetIndex (indices);
|
||||
return array.GetValues (i, count).ToArray ();
|
||||
}
|
||||
|
||||
public void SetElement (int[] indices, object val)
|
||||
{
|
||||
array.SetValues (GetIndex (indices), new Value[] { (Value) val });
|
||||
}
|
||||
|
||||
int GetIndex (int [] indices)
|
||||
{
|
||||
int ts = 1;
|
||||
int i = 0;
|
||||
int [] dims = GetDimensions ();
|
||||
var lowerBounds = GetLowerBounds ();
|
||||
for (int n = indices.Length - 1; n >= 0; n--) {
|
||||
i += (indices [n] - lowerBounds [n]) * ts;
|
||||
ts *= dims [n];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public object ElementType {
|
||||
get {
|
||||
return array.Type.GetElementType ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// FieldReferenceBatch.cs
|
||||
//
|
||||
// Authors: David Karlaš <david.karlas@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2014 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using Mono.Debugger.Soft;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class FieldReferenceBatch
|
||||
{
|
||||
readonly object locker = new object ();
|
||||
readonly object obj;
|
||||
List<FieldInfoMirror> fields = new List<FieldInfoMirror> ();
|
||||
object[] results;
|
||||
|
||||
public FieldReferenceBatch (object obj)
|
||||
{
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
public void Add (FieldInfoMirror fieldVal)
|
||||
{
|
||||
lock (locker) {
|
||||
fields.Add (fieldVal);
|
||||
}
|
||||
}
|
||||
|
||||
public object GetValue (FieldInfoMirror field)
|
||||
{
|
||||
lock (locker) {
|
||||
if (results == null || fields.Count != results.Length)
|
||||
results = ((ObjectMirror)obj).GetValues (fields);
|
||||
return results [fields.IndexOf (field)];
|
||||
}
|
||||
}
|
||||
|
||||
public void Invalidate ()
|
||||
{
|
||||
lock (locker) {
|
||||
results = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
//
|
||||
// FieldValueReference.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Mono.Debugging.Evaluation;
|
||||
using Mono.Debugger.Soft;
|
||||
using Mono.Debugging.Client;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class FieldValueReference: SoftValueReference
|
||||
{
|
||||
FieldInfoMirror field;
|
||||
object obj;
|
||||
TypeMirror declaringType;
|
||||
ObjectValueFlags flags;
|
||||
string vname;
|
||||
FieldReferenceBatch batch;
|
||||
|
||||
public FieldValueReference (EvaluationContext ctx, FieldInfoMirror field, object obj, TypeMirror declaringType, FieldReferenceBatch batch = null)
|
||||
: this (ctx, field, obj, declaringType, null, ObjectValueFlags.Field, batch)
|
||||
{
|
||||
}
|
||||
|
||||
public FieldValueReference (EvaluationContext ctx, FieldInfoMirror field, object obj, TypeMirror declaringType, string vname, ObjectValueFlags vflags, FieldReferenceBatch batch = null): base (ctx)
|
||||
{
|
||||
this.field = field;
|
||||
this.obj = obj;
|
||||
this.declaringType = declaringType;
|
||||
this.vname = vname;
|
||||
this.batch = batch;
|
||||
|
||||
if (field.IsStatic)
|
||||
this.obj = null;
|
||||
|
||||
var objectMirror = obj as ObjectMirror;
|
||||
if (objectMirror != null)
|
||||
EnsureContextHasDomain (objectMirror.Domain);
|
||||
|
||||
flags = GetFlags (field);
|
||||
|
||||
// if `vflags` already has an origin specified, we need to unset the `Field` flag which is always returned by GetFlags().
|
||||
if ((vflags & ObjectValueFlags.OriginMask) != 0)
|
||||
flags &= ~ObjectValueFlags.Field;
|
||||
|
||||
flags |= vflags;
|
||||
|
||||
if (obj is PrimitiveValue)
|
||||
flags |= ObjectValueFlags.ReadOnly;
|
||||
}
|
||||
|
||||
internal static ObjectValueFlags GetFlags (FieldInfoMirror field)
|
||||
{
|
||||
var flags = ObjectValueFlags.Field;
|
||||
|
||||
if (field.IsStatic)
|
||||
flags |= ObjectValueFlags.Global;
|
||||
|
||||
if (field.IsPublic)
|
||||
flags |= ObjectValueFlags.Public;
|
||||
else if (field.IsPrivate)
|
||||
flags |= ObjectValueFlags.Private;
|
||||
else if (field.IsFamily)
|
||||
flags |= ObjectValueFlags.Protected;
|
||||
else if (field.IsFamilyAndAssembly)
|
||||
flags |= ObjectValueFlags.Internal;
|
||||
else if (field.IsFamilyOrAssembly)
|
||||
flags |= ObjectValueFlags.InternalProtected;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
return vname ?? field.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
return field.FieldType;
|
||||
}
|
||||
}
|
||||
|
||||
public override object DeclaringType {
|
||||
get {
|
||||
return field.DeclaringType;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
if (obj == null) {
|
||||
// If the type hasn't already been loaded, invoke the .cctor() for types w/ the BeforeFieldInit attribute.
|
||||
Context.Adapter.ForceLoadType (Context, declaringType);
|
||||
|
||||
return declaringType.GetValue (field, ((SoftEvaluationContext)Context).Thread);
|
||||
} else if (obj is ObjectMirror) {
|
||||
if (batch != null)
|
||||
return batch.GetValue (field);
|
||||
return ((ObjectMirror)obj).GetValue (field);
|
||||
} else if (obj is StructMirror) {
|
||||
StructMirror sm = (StructMirror)obj;
|
||||
int idx = 0;
|
||||
foreach (FieldInfoMirror f in sm.Type.GetFields ()) {
|
||||
if (f.IsStatic) continue;
|
||||
if (f == field)
|
||||
break;
|
||||
idx++;
|
||||
}
|
||||
return sm.Fields [idx];
|
||||
} else if (obj is StringMirror) {
|
||||
SoftEvaluationContext cx = (SoftEvaluationContext) Context;
|
||||
StringMirror val = (StringMirror) obj;
|
||||
FieldInfo rfield = typeof(string).GetField (field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
return cx.Session.VirtualMachine.CreateValue (rfield.GetValue (val.Value));
|
||||
} else {
|
||||
SoftEvaluationContext cx = (SoftEvaluationContext) Context;
|
||||
PrimitiveValue val = (PrimitiveValue) obj;
|
||||
if (val.Value == null)
|
||||
return null;
|
||||
FieldInfo rfield = val.Value.GetType ().GetField (field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
return cx.Session.VirtualMachine.CreateValue (rfield.GetValue (val.Value));
|
||||
}
|
||||
}
|
||||
set {
|
||||
if (obj == null)
|
||||
declaringType.SetValue (field, (Value)value);
|
||||
else if (obj is ObjectMirror) {
|
||||
if (batch != null)
|
||||
batch.Invalidate ();
|
||||
((ObjectMirror)obj).SetValue (field, (Value)value);
|
||||
}
|
||||
else if (obj is StructMirror) {
|
||||
StructMirror sm = (StructMirror)obj;
|
||||
int idx = 0;
|
||||
foreach (FieldInfoMirror f in sm.Type.GetFields ()) {
|
||||
if (f.IsStatic) continue;
|
||||
if (f == field)
|
||||
break;
|
||||
idx++;
|
||||
}
|
||||
if (idx != -1) {
|
||||
sm.Fields [idx] = (Value)value;
|
||||
// Structs are handled by-value in the debugger, so the source of the object has to be updated
|
||||
if (ParentSource != null && obj != null)
|
||||
ParentSource.Value = obj;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
internal string [] GetTupleElementNames ()
|
||||
{
|
||||
return GetTupleElementNames (field.GetCustomAttributes (true));
|
||||
}
|
||||
|
||||
internal static string [] GetTupleElementNames (CustomAttributeDataMirror [] attrs)
|
||||
{
|
||||
var attr = attrs.FirstOrDefault (at => at.Constructor.DeclaringType.Name == "TupleElementNamesAttribute");
|
||||
if (attr == null)
|
||||
return null;
|
||||
var attributeValue = attr.ConstructorArguments.Single ().Value;
|
||||
var array = attributeValue as ArrayMirror;
|
||||
if (array == null)
|
||||
return null;
|
||||
var values = array.GetValues (0, array.Length);
|
||||
if (!values.Any ())
|
||||
return null;
|
||||
var result = new string [values.Count];
|
||||
for (int i = 0; i < result.Length; i++) {
|
||||
if (values [i] is StringMirror s)//other than string is null
|
||||
result [i] = s.Value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Mono.Debugging.Client;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
[Serializable]
|
||||
public class InstructionBreakpoint : Breakpoint
|
||||
{
|
||||
public string MethodName { get; set; }
|
||||
public long ILOffset { get; private set; }
|
||||
|
||||
public InstructionBreakpoint (string fileName, int line, int column, long ilOffset) : base (fileName, line, column)
|
||||
{
|
||||
this.ILOffset = ilOffset;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class JsonSourceLink
|
||||
{
|
||||
public Dictionary<string, string> Maps { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// LocalVariableValueBatch.cs
|
||||
//
|
||||
// Author: Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2014 Xamarin Inc. (www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
|
||||
using Mono.Debugger.Soft;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class LocalVariableBatch
|
||||
{
|
||||
readonly LocalVariable[] variables;
|
||||
Value[] values;
|
||||
int version;
|
||||
|
||||
public LocalVariableBatch (LocalVariable[] variables)
|
||||
{
|
||||
this.variables = variables;
|
||||
}
|
||||
|
||||
public Value GetValue (SoftEvaluationContext ctx, LocalVariable variable)
|
||||
{
|
||||
if (variable == null)
|
||||
throw new ArgumentNullException ("variable");
|
||||
|
||||
if (values == null || version != ctx.Session.StackVersion) {
|
||||
values = ctx.Frame.GetValues (variables);
|
||||
version = ctx.Session.StackVersion;
|
||||
}
|
||||
|
||||
for (int i = 0; i < variables.Length; i++) {
|
||||
if (variable == variables[i])
|
||||
return values[i];
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException ("variable");
|
||||
}
|
||||
|
||||
public void SetValue (SoftEvaluationContext ctx, LocalVariable variable, Value value)
|
||||
{
|
||||
var canUpdateCache = values != null && version == ctx.Session.StackVersion;
|
||||
|
||||
ctx.Frame.SetValue (variable, value);
|
||||
ctx.Session.StackVersion++;
|
||||
|
||||
if (canUpdateCache) {
|
||||
for (int i = 0; i < variables.Length; i++) {
|
||||
if (variable == variables[i]) {
|
||||
values[i] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
version = ctx.Session.StackVersion;
|
||||
} else {
|
||||
values = null;
|
||||
version = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
171
VisualPascalABCNETLinux/MonoDebugging/Soft/PortablePdbData.cs
Normal file
171
VisualPascalABCNETLinux/MonoDebugging/Soft/PortablePdbData.cs
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
//
|
||||
// PortablePdbData.cs
|
||||
//
|
||||
// Author:
|
||||
// David Karlaš <david.karlas@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2017 Xamarin, Inc (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
using Mono.Debugger.Soft;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
class PortablePdbData
|
||||
{
|
||||
static readonly Guid AsyncMethodSteppingInformationBlob = new Guid ("54FD2AC5-E925-401A-9C2A-F94F171072F8");
|
||||
static readonly Guid StateMachineHoistedLocalScopes = new Guid ("6DA9A61E-F8C7-4874-BE62-68BC5630DF71");
|
||||
static readonly Guid DynamicLocalVariables = new Guid ("83C563C4-B4F3-47D5-B824-BA5441477EA8");
|
||||
static readonly Guid TupleElementNames = new Guid ("ED9FDF71-8879-4747-8ED3-FE5EDE3CE710");
|
||||
static readonly Guid DefaultNamespace = new Guid ("58b2eab6-209f-4e4e-a22c-b2d0f910c782");
|
||||
static readonly Guid EncLocalSlotMap = new Guid ("755F52A8-91C5-45BE-B4B8-209571E552BD");
|
||||
static readonly Guid EncLambdaAndClosureMap = new Guid ("A643004C-0240-496F-A783-30D64F4979DE");
|
||||
static readonly Guid SourceLinkGuid = new Guid ("CC110556-A091-4D38-9FEC-25AB9A351A6A");
|
||||
static readonly Guid EmbeddedSource = new Guid ("0E8A571B-6926-466E-B4AD-8AB04611F5FE");
|
||||
|
||||
public static bool IsPortablePdb (string pdbFileName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (pdbFileName) || !File.Exists (pdbFileName))
|
||||
return false;
|
||||
using (var file = new FileStream (pdbFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
|
||||
var data = new byte [4];
|
||||
int read = file.Read (data, 0, data.Length);
|
||||
return read == 4 && BitConverter.ToUInt32 (data, 0) == 0x424a5342;
|
||||
}
|
||||
}
|
||||
|
||||
readonly byte [] pdbBytes;
|
||||
private readonly string pdbFileName;
|
||||
|
||||
public PortablePdbData (string pdbFileName)
|
||||
{
|
||||
this.pdbFileName = Path.GetFullPath (pdbFileName);
|
||||
}
|
||||
|
||||
public PortablePdbData (byte [] pdbBytes)
|
||||
{
|
||||
this.pdbBytes = pdbBytes ?? throw new ArgumentNullException (nameof(pdbBytes));
|
||||
}
|
||||
|
||||
internal class SoftScope
|
||||
{
|
||||
public int LiveRangeStart;
|
||||
|
||||
public int LiveRangeEnd;
|
||||
}
|
||||
|
||||
Stream GetStream()
|
||||
{
|
||||
if (pdbBytes != null)
|
||||
return new MemoryStream (pdbBytes);
|
||||
return new FileStream (pdbFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
}
|
||||
|
||||
public string GetSourceLinkBlob ()
|
||||
{
|
||||
/*using (var provider = MetadataReaderProvider.FromPortablePdbStream (GetStream ())) {
|
||||
var pdbReader = provider.GetMetadataReader ();
|
||||
|
||||
var jsonBlob =
|
||||
pdbReader.GetCustomDebugInformation (EntityHandle.ModuleDefinition)
|
||||
.Select (cdiHandle => pdbReader.GetCustomDebugInformation (cdiHandle))
|
||||
.Where (cdi => pdbReader.GetGuid (cdi.Kind) == SourceLinkGuid)
|
||||
.Select (cdi => pdbReader.GetBlobBytes (cdi.Value))
|
||||
.FirstOrDefault ();
|
||||
|
||||
if (jsonBlob == null)
|
||||
return null;
|
||||
|
||||
return System.Text.Encoding.UTF8.GetString (jsonBlob);
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need proxy method to make sure VS2013/15 doesn't crash(this method won't be called if portable .pdb file doesn't exist, which means 2017+)
|
||||
[MethodImpl (MethodImplOptions.NoInlining)]
|
||||
internal SoftScope [] GetHoistedScopes (MethodMirror method) => GetHoistedScopesPrivate (method);
|
||||
|
||||
internal SoftScope [] GetHoistedScopesPrivate (MethodMirror method)
|
||||
{
|
||||
/*using (var metadataReader = MetadataReaderProvider.FromPortablePdbStream (GetStream ())) {
|
||||
var reader = metadataReader.GetMetadataReader ();
|
||||
var methodHandle = MetadataTokens.MethodDefinitionHandle (method.MetadataToken);
|
||||
var customDebugInfos = reader.GetCustomDebugInformation (methodHandle);
|
||||
foreach (var item in customDebugInfos) {
|
||||
var debugInfo = reader.GetCustomDebugInformation (item);
|
||||
if (reader.GetGuid (debugInfo.Kind) == StateMachineHoistedLocalScopes) {
|
||||
var bytes = reader.GetBlobBytes (debugInfo.Value);
|
||||
var result = new SoftScope [bytes.Length / 8];
|
||||
for (int i = 0; i < bytes.Length; i += 8) {
|
||||
var offset = BitConverter.ToInt32 (bytes, i);
|
||||
var len = BitConverter.ToInt32 (bytes, i + 4);
|
||||
result [i / 8] = new SoftScope () {
|
||||
LiveRangeStart = offset,
|
||||
LiveRangeEnd = offset + len
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need proxy method to make sure VS2013/15 doesn't crash(this method won't be called if portable .pdb file doesn't exist, which means 2017+)
|
||||
[MethodImpl (MethodImplOptions.NoInlining)]
|
||||
internal string [] GetTupleElementNames (MethodMirror method, int localVariableIndex) => TupleElementNamesPrivate (method, localVariableIndex);
|
||||
|
||||
/*private static string [] DecodeTupleElementNames (BlobReader reader)
|
||||
{
|
||||
var list = new List<string> ();
|
||||
while (reader.RemainingBytes > 0) {
|
||||
int byteCount = reader.IndexOf (0);
|
||||
string value = reader.ReadUTF8 (byteCount);
|
||||
byte terminator = reader.ReadByte ();
|
||||
list.Add (value.Length == 0 ? null : value);
|
||||
}
|
||||
return list.ToArray ();
|
||||
}*/
|
||||
|
||||
internal string [] TupleElementNamesPrivate (MethodMirror method, int localVariableIndex)
|
||||
{
|
||||
/*using (var metadataReader = MetadataReaderProvider.FromPortablePdbStream (GetStream())) {
|
||||
var reader = metadataReader.GetMetadataReader ();
|
||||
var methodHandle = MetadataTokens.MethodDefinitionHandle (method.MetadataToken);
|
||||
var localScopes = reader.GetLocalScopes (methodHandle);
|
||||
// localVariableIndex is not really il_index, but sequential index when fetching locals
|
||||
// hence use Skip(index) instead of Index matching.
|
||||
var localVar = localScopes.Select (s => reader.GetLocalScope (s)).SelectMany (s => s.GetLocalVariables ()).Skip (localVariableIndex).First ();
|
||||
var customDebugInfos = reader.GetCustomDebugInformation (localVar);
|
||||
foreach (var item in customDebugInfos) {
|
||||
var debugInfo = reader.GetCustomDebugInformation (item);
|
||||
if (reader.GetGuid (debugInfo.Kind) == TupleElementNames) {
|
||||
return DecodeTupleElementNames (reader.GetBlobReader (debugInfo.Value));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// PropertyValueReference.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using Mono.Debugging.Evaluation;
|
||||
using Mono.Debugger.Soft;
|
||||
using Mono.Debugging.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class PropertyValueReference: SoftValueReference
|
||||
{
|
||||
PropertyInfoMirror property;
|
||||
TypeMirror declaringType;
|
||||
ObjectValueFlags flags;
|
||||
MethodMirror getter;
|
||||
Value[] indexerArgs;
|
||||
object obj, value;
|
||||
bool haveValue;
|
||||
bool safe;
|
||||
|
||||
public PropertyValueReference (EvaluationContext ctx, PropertyInfoMirror property, object obj, TypeMirror declaringType, MethodMirror getter, Value[] indexerArgs): base (ctx)
|
||||
{
|
||||
this.safe = Context.Adapter.IsSafeToInvokeMethod (ctx, getter, obj ?? declaringType);
|
||||
this.declaringType = declaringType;
|
||||
this.indexerArgs = indexerArgs;
|
||||
this.property = property;
|
||||
this.getter = getter;
|
||||
this.obj = obj;
|
||||
|
||||
if (getter.IsStatic)
|
||||
this.obj = null;
|
||||
|
||||
var objectMirror = obj as ObjectMirror;
|
||||
if (objectMirror != null)
|
||||
EnsureContextHasDomain (objectMirror.Domain);
|
||||
|
||||
flags = GetFlags (property, getter);
|
||||
}
|
||||
|
||||
internal static ObjectValueFlags GetFlags (PropertyInfoMirror property, MethodMirror getter)
|
||||
{
|
||||
var flags = ObjectValueFlags.Property;
|
||||
|
||||
if (property.GetSetMethod (true) == null)
|
||||
flags |= ObjectValueFlags.ReadOnly;
|
||||
|
||||
if (getter.IsStatic)
|
||||
flags |= ObjectValueFlags.Global;
|
||||
|
||||
if (getter.IsPublic)
|
||||
flags |= ObjectValueFlags.Public;
|
||||
else if (getter.IsPrivate)
|
||||
flags |= ObjectValueFlags.Private;
|
||||
else if (getter.IsFamily)
|
||||
flags |= ObjectValueFlags.Protected;
|
||||
else if (getter.IsFamilyAndAssembly)
|
||||
flags |= ObjectValueFlags.Internal;
|
||||
else if (getter.IsFamilyOrAssembly)
|
||||
flags |= ObjectValueFlags.InternalProtected;
|
||||
|
||||
if (property.DeclaringType.IsValueType)
|
||||
flags |= ObjectValueFlags.ReadOnly; // Setting property values on structs is not supported by sdb
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public override ObjectValueFlags Flags {
|
||||
get {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get {
|
||||
return property.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Type {
|
||||
get {
|
||||
return property.PropertyType;
|
||||
}
|
||||
}
|
||||
|
||||
public override object DeclaringType {
|
||||
get {
|
||||
return property.DeclaringType;
|
||||
}
|
||||
}
|
||||
|
||||
public override object Value {
|
||||
get {
|
||||
return GetValue (Context);
|
||||
}
|
||||
set {
|
||||
SetValue (Context, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override object GetValue (EvaluationContext ctx)
|
||||
{
|
||||
if (!haveValue) {
|
||||
if (!safe)
|
||||
throw new EvaluatorException ("This property is not safe to evaluate.");
|
||||
|
||||
value = ((SoftEvaluationContext) ctx).RuntimeInvoke (getter, obj ?? declaringType, indexerArgs);
|
||||
haveValue = true;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public override void SetValue (EvaluationContext ctx, object value)
|
||||
{
|
||||
ctx.AssertTargetInvokeAllowed ();
|
||||
|
||||
var args = new Value [indexerArgs != null ? indexerArgs.Length + 1 : 1];
|
||||
if (indexerArgs != null)
|
||||
indexerArgs.CopyTo (args, 0);
|
||||
|
||||
args [args.Length - 1] = (Value) value;
|
||||
|
||||
var setter = property.GetSetMethod (true);
|
||||
if (setter == null)
|
||||
throw new EvaluatorException ("Property is read-only");
|
||||
|
||||
this.value = null;
|
||||
haveValue = false;
|
||||
|
||||
((SoftEvaluationContext) ctx).RuntimeInvoke (setter, obj ?? declaringType, args);
|
||||
|
||||
this.value = value;
|
||||
haveValue = true;
|
||||
}
|
||||
|
||||
protected override bool CanEvaluate (EvaluationOptions options)
|
||||
{
|
||||
if (options.AllowTargetInvoke)
|
||||
return safe;
|
||||
|
||||
if (!safe)
|
||||
return false;
|
||||
|
||||
try {
|
||||
GetValue (Context.WithOptions (options));
|
||||
return true;
|
||||
} catch (ImplicitEvaluationDisabledException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal string [] GetTupleElementNames ()
|
||||
{
|
||||
return FieldValueReference.GetTupleElementNames (property.GetCustomAttributes (true));
|
||||
}
|
||||
}
|
||||
}
|
||||
2706
VisualPascalABCNETLinux/MonoDebugging/Soft/SoftDebuggerAdaptor.cs
Normal file
2706
VisualPascalABCNETLinux/MonoDebugging/Soft/SoftDebuggerAdaptor.cs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,232 @@
|
|||
//
|
||||
// SoftDebuggerBacktrace.cs
|
||||
//
|
||||
// Authors: Lluis Sanchez Gual <lluis@novell.com>
|
||||
// Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Debugging.Client;
|
||||
using Mono.Debugging.Backend;
|
||||
using MDB = Mono.Debugger.Soft;
|
||||
using DC = Mono.Debugging.Client;
|
||||
using Mono.Debugging.Evaluation;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
internal class SoftDebuggerStackFrame : Mono.Debugging.Client.StackFrame {
|
||||
public Mono.Debugger.Soft.StackFrame StackFrame {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SoftDebuggerStackFrame (Mono.Debugger.Soft.StackFrame frame, string addressSpace, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo, bool isDebuggerHidden, string fullModuleName, string fullTypeName)
|
||||
: base (frame.ILOffset, addressSpace, location, language, isExternalCode, hasDebugInfo, isDebuggerHidden, fullModuleName, fullTypeName)
|
||||
{
|
||||
StackFrame = frame;
|
||||
}
|
||||
}
|
||||
|
||||
public class SoftDebuggerBacktrace: BaseBacktrace
|
||||
{
|
||||
readonly SoftDebuggerSession session;
|
||||
readonly MDB.ThreadMirror thread;
|
||||
readonly int stackVersion;
|
||||
MDB.StackFrame[] frames;
|
||||
|
||||
public SoftDebuggerBacktrace (SoftDebuggerSession session, MDB.ThreadMirror thread): base (session.Adaptor)
|
||||
{
|
||||
this.session = session;
|
||||
this.thread = thread;
|
||||
stackVersion = session.StackVersion;
|
||||
if (thread != null)
|
||||
this.frames = thread.GetFrames ();
|
||||
else
|
||||
this.frames = new MDB.StackFrame[0];
|
||||
}
|
||||
|
||||
void ValidateStack ()
|
||||
{
|
||||
if (stackVersion != session.StackVersion && thread != null)
|
||||
frames = thread.GetFrames ();
|
||||
}
|
||||
|
||||
public override DC.StackFrame[] GetStackFrames (int firstIndex, int lastIndex)
|
||||
{
|
||||
ValidateStack ();
|
||||
|
||||
if (lastIndex < 0)
|
||||
lastIndex = frames.Length - 1;
|
||||
|
||||
List<DC.StackFrame> list = new List<DC.StackFrame> ();
|
||||
for (int n = firstIndex; n <= lastIndex && n < frames.Length; n++)
|
||||
list.Add (CreateStackFrame (frames[n], n));
|
||||
|
||||
return list.ToArray ();
|
||||
}
|
||||
|
||||
public override int FrameCount {
|
||||
get {
|
||||
ValidateStack ();
|
||||
return frames.Length;
|
||||
}
|
||||
}
|
||||
|
||||
DC.StackFrame CreateStackFrame (MDB.StackFrame frame, int frameIndex)
|
||||
{
|
||||
MDB.MethodMirror method = frame.Method;
|
||||
MDB.TypeMirror type = method.DeclaringType;
|
||||
string fileName = frame.FileName;
|
||||
string typeFullName = null;
|
||||
string typeFQN = null;
|
||||
string methodName;
|
||||
|
||||
if (fileName != null)
|
||||
fileName = SoftDebuggerSession.NormalizePath (fileName);
|
||||
|
||||
if (method.VirtualMachine.Version.AtLeast (2, 12) && method.IsGenericMethod) {
|
||||
StringBuilder name = new StringBuilder (method.Name);
|
||||
|
||||
name.Append ('<');
|
||||
|
||||
if (method.VirtualMachine.Version.AtLeast (2, 15)) {
|
||||
bool first = true;
|
||||
|
||||
foreach (var argumentType in method.GetGenericArguments ()) {
|
||||
if (!first)
|
||||
name.Append (", ");
|
||||
|
||||
name.Append (session.Adaptor.GetDisplayTypeName (argumentType.FullName));
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
name.Append ('>');
|
||||
|
||||
methodName = name.ToString ();
|
||||
} else {
|
||||
methodName = method.Name;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty (methodName))
|
||||
methodName = "[Function Without Name]";
|
||||
|
||||
// Compiler generated anonymous/lambda methods
|
||||
bool special_method = false;
|
||||
if (methodName [0] == '<' && methodName.Contains (">m__")) {
|
||||
int nidx = methodName.IndexOf (">m__", StringComparison.Ordinal) + 2;
|
||||
methodName = "AnonymousMethod" + methodName.Substring (nidx, method.Name.Length - nidx);
|
||||
special_method = true;
|
||||
}
|
||||
|
||||
if (type != null) {
|
||||
string typeDisplayName = session.Adaptor.GetDisplayTypeName (type.FullName);
|
||||
|
||||
if (SoftDebuggerAdaptor.IsGeneratedType (type)) {
|
||||
// The user-friendly method name is embedded in the generated type name
|
||||
var mn = SoftDebuggerAdaptor.GetNameFromGeneratedType (type);
|
||||
|
||||
// Strip off the generated type name
|
||||
int dot = typeDisplayName.LastIndexOf ('.');
|
||||
var tname = typeDisplayName.Substring (0, dot);
|
||||
|
||||
// Keep any type arguments
|
||||
int targs = typeDisplayName.LastIndexOf ('<');
|
||||
if (targs > dot + 1)
|
||||
mn += typeDisplayName.Substring (targs, typeDisplayName.Length - targs);
|
||||
|
||||
typeDisplayName = tname;
|
||||
|
||||
if (special_method)
|
||||
typeDisplayName += "." + mn;
|
||||
else
|
||||
methodName = mn;
|
||||
}
|
||||
|
||||
methodName = typeDisplayName + "." + methodName;
|
||||
|
||||
typeFQN = type.Module.FullyQualifiedName;
|
||||
typeFullName = type.FullName;
|
||||
}
|
||||
bool external = false;
|
||||
bool hidden = false;
|
||||
if (session.VirtualMachine.Version.AtLeast (2, 21)) {
|
||||
var ctx = GetEvaluationContext (frameIndex, session.EvaluationOptions);
|
||||
var hiddenAttr = session.Adaptor.GetType (ctx, "System.Diagnostics.DebuggerHiddenAttribute") as MDB.TypeMirror;
|
||||
if (hiddenAttr != null)
|
||||
hidden = method.GetCustomAttributes (hiddenAttr, true).Any ();
|
||||
}
|
||||
if (hidden) {
|
||||
external = true;
|
||||
} else {
|
||||
external = session.IsExternalCode (frame);
|
||||
if (!external && session.Options.ProjectAssembliesOnly && session.VirtualMachine.Version.AtLeast (2, 21)) {
|
||||
var ctx = GetEvaluationContext (frameIndex, session.EvaluationOptions);
|
||||
var nonUserCodeAttr = session.Adaptor.GetType (ctx, "System.Diagnostics.DebuggerNonUserCodeAttribute") as MDB.TypeMirror;
|
||||
if (nonUserCodeAttr != null)
|
||||
external = method.GetCustomAttributes (nonUserCodeAttr, true).Any ();
|
||||
}
|
||||
}
|
||||
|
||||
var sourceLink = session.GetSourceLink (frame.Method, frame.FileName);
|
||||
var location = new DC.SourceLocation (methodName, fileName, frame.LineNumber, frame.ColumnNumber, frame.Location.EndLineNumber, frame.Location.EndColumnNumber, frame.Location.SourceFileHash, sourceLink);
|
||||
|
||||
string addressSpace = string.Empty;
|
||||
bool hasDebugInfo = false;
|
||||
string language;
|
||||
|
||||
if (frame.Method != null) {
|
||||
if (frame.IsNativeTransition) {
|
||||
language = "Transition";
|
||||
} else {
|
||||
addressSpace = method.FullName;
|
||||
language = "Managed";
|
||||
hasDebugInfo = true;
|
||||
}
|
||||
} else {
|
||||
language = "Native";
|
||||
}
|
||||
|
||||
return new SoftDebuggerStackFrame (frame, addressSpace, location, language, external, hasDebugInfo, hidden, typeFQN, typeFullName);
|
||||
}
|
||||
|
||||
protected override EvaluationContext GetEvaluationContext (int frameIndex, EvaluationOptions options)
|
||||
{
|
||||
ValidateStack ();
|
||||
|
||||
if (frameIndex >= frames.Length)
|
||||
return null;
|
||||
|
||||
var frame = frames[frameIndex];
|
||||
|
||||
return new SoftEvaluationContext (session, frame, options);
|
||||
}
|
||||
|
||||
public override AssemblyLine[] Disassemble (int frameIndex, int firstLine, int count)
|
||||
{
|
||||
return session.Disassemble (frames [frameIndex], firstLine, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
3551
VisualPascalABCNETLinux/MonoDebugging/Soft/SoftDebuggerSession.cs
Normal file
3551
VisualPascalABCNETLinux/MonoDebugging/Soft/SoftDebuggerSession.cs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,215 @@
|
|||
//
|
||||
// SoftDebuggerStartInfo.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Hutchinson <mhutchinson@novell.com>
|
||||
//
|
||||
// Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
using Mono.Debugging.Client;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Mono.Debugger.Soft;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class SoftDebuggerStartInfo : DebuggerStartInfo
|
||||
{
|
||||
public SoftDebuggerStartInfo (string monoRuntimePrefix, Dictionary<string,string> monoRuntimeEnvironmentVariables)
|
||||
: this (new SoftDebuggerLaunchArgs (monoRuntimePrefix, monoRuntimeEnvironmentVariables))
|
||||
{
|
||||
}
|
||||
|
||||
public SoftDebuggerStartInfo (SoftDebuggerStartArgs startArgs)
|
||||
{
|
||||
if (startArgs == null)
|
||||
throw new ArgumentNullException ("startArgs");
|
||||
this.StartArgs = startArgs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Names of assemblies that are user code.
|
||||
/// </summary>
|
||||
public List<AssemblyName> UserAssemblyNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A mapping of AssemblyNames to their paths.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> AssemblyPathMap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A mapping of AssemblyNames to their symbol paths. If no symbols maps are provided, the symbols will be found next to the assemblies in AssemblyPathMap.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> SymbolPathMap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The session will output this to the debug log as soon as it starts. It can be used to log warnings from
|
||||
/// creating the SoftDebuggerStartInfo
|
||||
/// </summary>
|
||||
public string LogMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Args for starting the debugger connection.
|
||||
/// </summary>
|
||||
public SoftDebuggerStartArgs StartArgs { get; set; }
|
||||
}
|
||||
|
||||
public interface ISoftDebuggerConnectionProvider
|
||||
{
|
||||
IAsyncResult BeginConnect (DebuggerStartInfo dsi, AsyncCallback callback);
|
||||
void EndConnect (IAsyncResult result, out VirtualMachine vm, out string appName);
|
||||
void CancelConnect (IAsyncResult result);
|
||||
bool ShouldRetryConnection (Exception ex);
|
||||
}
|
||||
|
||||
public abstract class SoftDebuggerStartArgs
|
||||
{
|
||||
protected SoftDebuggerStartArgs ()
|
||||
{
|
||||
MaxConnectionAttempts = 1;
|
||||
TimeBetweenConnectionAttempts = 500;
|
||||
}
|
||||
|
||||
public abstract ISoftDebuggerConnectionProvider ConnectionProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of connection attempts. Zero or less means infinite attempts. Default is 1.
|
||||
/// </summary>
|
||||
public int MaxConnectionAttempts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time between connection attempts, in milliseconds. Default is 500.
|
||||
/// </summary>
|
||||
public int TimeBetweenConnectionAttempts { get; set; }
|
||||
}
|
||||
|
||||
public abstract class SoftDebuggerRemoteArgs : SoftDebuggerStartArgs
|
||||
{
|
||||
protected SoftDebuggerRemoteArgs (string appName, IPAddress address, int debugPort, int outputPort)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException ("address");
|
||||
if (debugPort < 0)
|
||||
throw new ArgumentException ("Debug port cannot be less than zero", "debugPort");
|
||||
|
||||
this.AppName = appName;
|
||||
this.Address = address;
|
||||
this.DebugPort = debugPort;
|
||||
this.OutputPort = outputPort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The IP address for the connection.
|
||||
/// </summary>
|
||||
public IPAddress Address { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Port for the debugger connection. Zero means random port.
|
||||
/// </summary>
|
||||
public int DebugPort { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Port for the console connection. Zero means random port, less than zero means that output is not redirected.
|
||||
/// </summary>
|
||||
public int OutputPort { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Application name that will be shown in the debugger.
|
||||
/// </summary>
|
||||
public string AppName { get; private set; }
|
||||
|
||||
public bool RedirectOutput { get { return OutputPort >= 0; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Args for the debugger to listen for an incoming connection from a debuggee.
|
||||
/// </summary>
|
||||
public sealed class SoftDebuggerListenArgs : SoftDebuggerRemoteArgs
|
||||
{
|
||||
public SoftDebuggerListenArgs (string appName, IPAddress address, int debugPort)
|
||||
: this (appName, address, debugPort, -1) {}
|
||||
|
||||
public SoftDebuggerListenArgs (string appName, IPAddress address, int debugPort, int outputPort)
|
||||
: base (appName, address, debugPort, outputPort)
|
||||
{
|
||||
}
|
||||
|
||||
public override ISoftDebuggerConnectionProvider ConnectionProvider { get { return null; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Args for the debugger to connect to target that is listening.
|
||||
/// </summary>
|
||||
public sealed class SoftDebuggerConnectArgs : SoftDebuggerRemoteArgs
|
||||
{
|
||||
public SoftDebuggerConnectArgs (string appName, IPAddress address, int debugPort)
|
||||
: this (appName, address, debugPort, -1) {}
|
||||
|
||||
public SoftDebuggerConnectArgs (string appName, IPAddress address, int debugPort, int outputPort)
|
||||
: base (appName, address, debugPort, outputPort)
|
||||
{
|
||||
if (debugPort == 0)
|
||||
throw new ArgumentException ("Debug port cannot be zero when connecting", "debugPort");
|
||||
if (outputPort == 0)
|
||||
throw new ArgumentException ("Output port cannot be zero when connecting", "outputPort");
|
||||
}
|
||||
|
||||
public override ISoftDebuggerConnectionProvider ConnectionProvider { get { return null; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options for the debugger to start a process directly.
|
||||
/// </summary>
|
||||
public sealed class SoftDebuggerLaunchArgs : SoftDebuggerStartArgs
|
||||
{
|
||||
public SoftDebuggerLaunchArgs (string monoRuntimePrefix, Dictionary<string,string> monoRuntimeEnvironmentVariables)
|
||||
{
|
||||
this.MonoRuntimePrefix = monoRuntimePrefix;
|
||||
this.MonoRuntimeEnvironmentVariables = monoRuntimeEnvironmentVariables;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prefix into which the target Mono runtime is installed.
|
||||
/// </summary>
|
||||
public string MonoRuntimePrefix { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Environment variables for the Mono runtime.
|
||||
/// </summary>
|
||||
public Dictionary<string,string> MonoRuntimeEnvironmentVariables { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Launcher for the external console. May be null if the app does not run on an external console.
|
||||
/// </summary>
|
||||
public Mono.Debugger.Soft.LaunchOptions.TargetProcessLauncher ExternalConsoleLauncher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the mono executable file. e.g. "mono", "mono32", "mono64"...
|
||||
/// </summary>
|
||||
public string MonoExecutableFileName { get; set; }
|
||||
|
||||
public override ISoftDebuggerConnectionProvider ConnectionProvider { get { return null; } }
|
||||
|
||||
internal Mono.Debugger.Soft.LaunchOptions.ProcessLauncher CustomProcessLauncher { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
//
|
||||
// SoftEvaluationContext.cs
|
||||
//
|
||||
// Author:
|
||||
// Lluis Sanchez Gual <lluis@novell.com>
|
||||
//
|
||||
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using Mono.Debugging.Evaluation;
|
||||
using Mono.Debugger.Soft;
|
||||
using DC = Mono.Debugging.Client;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class SoftEvaluationContext: EvaluationContext
|
||||
{
|
||||
SoftDebuggerSession session;
|
||||
int stackVersion;
|
||||
StackFrame frame;
|
||||
bool sourceAvailable;
|
||||
|
||||
public ThreadMirror Thread { get; set; }
|
||||
public AppDomainMirror Domain { get; set; }
|
||||
|
||||
public SoftEvaluationContext (SoftDebuggerSession session, StackFrame frame, DC.EvaluationOptions options): base (options)
|
||||
{
|
||||
Frame = frame;
|
||||
Thread = frame.Thread;
|
||||
Domain = frame.Domain;
|
||||
|
||||
string method = frame.Method.Name;
|
||||
if (frame.Method.DeclaringType != null)
|
||||
method = frame.Method.DeclaringType.FullName + "." + method;
|
||||
|
||||
var sourceLink = session.GetSourceLink(frame.Method, frame.FileName);
|
||||
|
||||
var location = new DC.SourceLocation (method, frame.FileName, frame.LineNumber, frame.ColumnNumber, frame.EndLineNumber, frame.EndColumnNumber, frame.Location.SourceFileHash, sourceLink);
|
||||
string language;
|
||||
|
||||
if (frame.Method != null) {
|
||||
language = frame.IsNativeTransition ? "Transition" : "Managed";
|
||||
} else {
|
||||
language = "Native";
|
||||
}
|
||||
|
||||
Evaluator = session.GetEvaluator (new DC.StackFrame (frame.ILOffset, location, language, session.IsExternalCode (frame), true));
|
||||
Adapter = session.Adaptor;
|
||||
this.session = session;
|
||||
stackVersion = session.StackVersion;
|
||||
sourceAvailable = !string.IsNullOrEmpty (frame.FileName) && System.IO.File.Exists (frame.FileName);
|
||||
}
|
||||
|
||||
public StackFrame Frame {
|
||||
get {
|
||||
if (stackVersion != session.StackVersion)
|
||||
UpdateFrame ();
|
||||
return frame;
|
||||
}
|
||||
set {
|
||||
frame = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SourceCodeAvailable {
|
||||
get {
|
||||
if (stackVersion != session.StackVersion)
|
||||
sourceAvailable = !string.IsNullOrEmpty (Frame.FileName) && System.IO.File.Exists (Frame.FileName);
|
||||
return sourceAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
public SoftDebuggerSession Session {
|
||||
get { return session; }
|
||||
}
|
||||
|
||||
public override void WriteDebuggerError (Exception ex)
|
||||
{
|
||||
session.WriteDebuggerOutput (true, ex.ToString ());
|
||||
}
|
||||
|
||||
public override void WriteDebuggerOutput (string message, params object[] values)
|
||||
{
|
||||
session.WriteDebuggerOutput (false, string.Format (message, values));
|
||||
}
|
||||
|
||||
public override void CopyFrom (EvaluationContext ctx)
|
||||
{
|
||||
base.CopyFrom (ctx);
|
||||
|
||||
var other = (SoftEvaluationContext) ctx;
|
||||
frame = other.frame;
|
||||
stackVersion = other.stackVersion;
|
||||
Thread = other.Thread;
|
||||
session = other.session;
|
||||
Domain = other.Domain;
|
||||
}
|
||||
|
||||
internal static bool IsValueTypeOrPrimitive (TypeMirror type)
|
||||
{
|
||||
return type != null && (type.IsValueType || type.IsPrimitive);
|
||||
}
|
||||
|
||||
static bool IsValueTypeOrPrimitive (Type type)
|
||||
{
|
||||
return type != null && (type.IsValueType || type.IsPrimitive);
|
||||
}
|
||||
|
||||
public Value RuntimeInvoke (MethodMirror method, object target, Value[] values)
|
||||
{
|
||||
Value[] outArgs;
|
||||
return RuntimeInvoke (method, target, values, false, out outArgs);
|
||||
}
|
||||
|
||||
public Value RuntimeInvoke (MethodMirror method, object target, Value[] values, out Value[] outArgs)
|
||||
{
|
||||
return RuntimeInvoke (method, target, values, true, out outArgs);
|
||||
}
|
||||
|
||||
Value RuntimeInvoke (MethodMirror method, object target, Value[] values, bool enableOutArgs, out Value[] outArgs)
|
||||
{
|
||||
outArgs = null;
|
||||
if (values != null) {
|
||||
// Some arguments may need to be boxed
|
||||
var mparams = method.GetParameters ();
|
||||
if (mparams.Length != values.Length)
|
||||
throw new EvaluatorException ("Invalid number of arguments when calling: " + method.Name);
|
||||
|
||||
for (int n = 0; n < mparams.Length; n++) {
|
||||
var tm = mparams[n].ParameterType;
|
||||
if (tm.IsValueType || tm.IsPrimitive || tm.FullName.StartsWith ("System.Nullable`1", StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
var type = Adapter.GetValueType (this, values[n]);
|
||||
var argTypeMirror = type as TypeMirror;
|
||||
var argType = type as Type;
|
||||
|
||||
if (IsValueTypeOrPrimitive (argTypeMirror) || IsValueTypeOrPrimitive (argType)) {
|
||||
// A value type being assigned to a parameter which is not a value type. The value has to be boxed.
|
||||
try {
|
||||
values[n] = Thread.Domain.CreateBoxedValue (values [n]);
|
||||
} catch (NotSupportedException) {
|
||||
// This runtime doesn't support creating boxed values
|
||||
throw new EvaluatorException ("This runtime does not support creating boxed values.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!method.IsStatic && method.DeclaringType.IsClass && !IsValueTypeOrPrimitive (method.DeclaringType)) {
|
||||
object type = Adapter.GetValueType (this, target);
|
||||
var targetTypeMirror = type as TypeMirror;
|
||||
var targetType = type as Type;
|
||||
|
||||
if ((target is StructMirror && ((StructMirror) target).Type != method.DeclaringType) ||
|
||||
(IsValueTypeOrPrimitive (targetTypeMirror) || IsValueTypeOrPrimitive (targetType))) {
|
||||
// A value type being assigned to a parameter which is not a value type. The value has to be boxed.
|
||||
try {
|
||||
target = Thread.Domain.CreateBoxedValue ((Value) target);
|
||||
} catch (NotSupportedException) {
|
||||
// This runtime doesn't support creating boxed values
|
||||
throw new EvaluatorException ("This runtime does not support creating boxed values.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return method.Evaluate (target is TypeMirror ? null : (Value) target, values);
|
||||
} catch (NotSupportedException) {
|
||||
AssertTargetInvokeAllowed ();
|
||||
var threadState = Thread.ThreadState;
|
||||
if ((threadState & ThreadState.WaitSleepJoin) == ThreadState.WaitSleepJoin) {
|
||||
DC.DebuggerLoggingService.LogMessage ("Thread state before evaluation is {0}", threadState);
|
||||
throw new EvaluatorException ("Evaluation is not allowed when the thread is in 'Wait' state");
|
||||
}
|
||||
var mc = new MethodCall (this, method, target, values, enableOutArgs);
|
||||
//Since runtime is returning NOT_SUSPENDED error if two methods invokes are executed
|
||||
//at same time we have to lock invoking to prevent this...
|
||||
lock (method.VirtualMachine) {
|
||||
Adapter.AsyncExecute (mc, Options.EvaluationTimeout);
|
||||
}
|
||||
if (enableOutArgs) {
|
||||
outArgs = mc.OutArgs;
|
||||
}
|
||||
return mc.ReturnValue;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFrame ()
|
||||
{
|
||||
stackVersion = session.StackVersion;
|
||||
foreach (StackFrame f in Thread.GetFrames ()) {
|
||||
if (f.FileName == Frame.FileName && f.LineNumber == Frame.LineNumber && f.ILOffset == Frame.ILOffset) {
|
||||
Frame = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SupportIEnumerable {
|
||||
get {
|
||||
return session.VirtualMachine.Version.AtLeast (2, 35);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using Mono.Debugging.Evaluation;
|
||||
using Mono.Debugger.Soft;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public abstract class SoftValueReference: ValueReference
|
||||
{
|
||||
public SoftValueReference (EvaluationContext ctx) : base(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
protected void EnsureContextHasDomain (AppDomainMirror domain)
|
||||
{
|
||||
var softEvaluationContext = (SoftEvaluationContext)Context;
|
||||
if (softEvaluationContext.Domain == domain)
|
||||
return;
|
||||
|
||||
var clone = (SoftEvaluationContext)softEvaluationContext.Clone ();
|
||||
clone.Domain = domain;
|
||||
Context = clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
VisualPascalABCNETLinux/MonoDebugging/Soft/SourceLinkMap.cs
Normal file
14
VisualPascalABCNETLinux/MonoDebugging/Soft/SourceLinkMap.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
internal class SourceLinkMap
|
||||
{
|
||||
public string RelativePathWildcard { get; }
|
||||
public string UriWildcard { get; }
|
||||
|
||||
public SourceLinkMap (string relativePathWildcard, string uriWildcard)
|
||||
{
|
||||
UriWildcard = uriWildcard;
|
||||
RelativePathWildcard = relativePathWildcard;
|
||||
}
|
||||
}
|
||||
}
|
||||
75
VisualPascalABCNETLinux/MonoDebugging/Soft/StringAdaptor.cs
Normal file
75
VisualPascalABCNETLinux/MonoDebugging/Soft/StringAdaptor.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// StringAdaptor.cs
|
||||
//
|
||||
// Author: Jeffrey Stedfast <jeff@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2012 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using Mono.Debugging.Evaluation;
|
||||
using Mono.Debugger.Soft;
|
||||
|
||||
namespace Mono.Debugging.Soft
|
||||
{
|
||||
public class StringAdaptor: IStringAdaptor
|
||||
{
|
||||
readonly bool atleast_2_10;
|
||||
readonly StringMirror str;
|
||||
string val;
|
||||
|
||||
public StringAdaptor (StringMirror str)
|
||||
{
|
||||
atleast_2_10 = str.VirtualMachine.Version.AtLeast (2, 10);
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
public int Length {
|
||||
get {
|
||||
if (atleast_2_10)
|
||||
return str.Length;
|
||||
|
||||
if (val == null)
|
||||
val = str.Value;
|
||||
|
||||
return val.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public string Value {
|
||||
get {
|
||||
if (val == null)
|
||||
val = str.Value;
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
public string Substring (int index, int length)
|
||||
{
|
||||
if (val == null && atleast_2_10)
|
||||
return new string (str.GetChars (index, length));
|
||||
|
||||
if (val == null)
|
||||
val = str.Value;
|
||||
|
||||
return val.Substring (index, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue