pascalabcnet/VisualPascalABCNET/IB/Debugger/Debugger.cs
2026-05-26 21:39:12 +03:00

1851 lines
75 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using VisualPascalABCPlugins;
using VisualPascalABC.Utils;
using Debugger;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;
using System.Runtime.ExceptionServices;
using Languages.Integration;
namespace VisualPascalABC
{
//Klass predostavljaushij informaciju ob otlazhivaemoj programme
public class AssemblyHelper
{
private static System.Reflection.Assembly a;
private static List<System.Reflection.Assembly> ref_modules = new List<System.Reflection.Assembly>();
private static Hashtable ns_ht = new Hashtable();
private static Hashtable stand_types = new Hashtable(StringComparer.OrdinalIgnoreCase);
private static List<Type> unit_types = new List<Type>();//spisok tipov-obertok nad moduljami
private static List<DebugType> unit_debug_types;//to zhe samoe, no tipy Debugger.Core
private static DebugType pabc_system_type = null;
static AssemblyHelper()
{
stand_types["integer"] = typeof(int);
stand_types["byte"] = typeof(byte);
stand_types["shortint"] = typeof(sbyte);
stand_types["word"] = typeof(ushort);
stand_types["smallint"] = typeof(short);
stand_types["longint"] = typeof(int);
stand_types["longword"] = typeof(uint);
stand_types["int64"] = typeof(long);
stand_types["uint64"] = typeof(ulong);
stand_types["real"] = typeof(double);
stand_types["single"] = typeof(float);
stand_types["char"] = typeof(char);
stand_types["string"] = typeof(string);
stand_types["boolean"] = typeof(bool);
stand_types["object"] = typeof(object);
}
public static bool Is32BitAssembly()
{
if (!Environment.Is64BitProcess)
return false;
System.Reflection.PortableExecutableKinds peKind;
System.Reflection.ImageFileMachine machine;
a.ManifestModule.GetPEKind(out peKind, out machine);
return peKind == System.Reflection.PortableExecutableKinds.Required32Bit;
}
public static void LoadAssembly(string file_name)
{
//ad = AppDomain.CreateDomain("DebugDomain",null,Path.GetDirectoryName(file_name),Path.GetDirectoryName(file_name),false);
try
{
FileStream fs = File.OpenRead(file_name);
byte[] buf = new byte[fs.Length];
fs.Read(buf, 0, (int)fs.Length);
fs.Close();
a = System.Reflection.Assembly.Load(buf);
Type[] tt = a.GetTypes();
foreach (Type t in tt)
{
if (t.Namespace != null)
ns_ht[t.Namespace] = t.Namespace;
if (t.Namespace == t.Name)
{
unit_types.Add(t);
}
try
{
object[] attrs = t.GetCustomAttributes(false);
foreach (Attribute attr in attrs)
{
Type attr_t = attr.GetType();
if (attr_t.Name == "$UsedNsAttr")
{
int count = (int)attr_t.GetField("count").GetValue(attr);
string ns = attr_t.GetField("ns").GetValue(attr) as string;
int j = 0;
for (int i = 0; i < count; i++)
{
byte str_len = (byte)ns[j];
string ns_s = ns.Substring(j + 1, str_len);
ns_ht[ns_s] = ns_s;
j += str_len + 1;
}
break;
}
}
}
catch
{
}
}
}
catch (System.Exception e)
{
}
}
[HandleProcessCorruptedStateExceptionsAttribute]
public static bool IsDebuggerStepThrough(Function f)
{
if (f == null)
return false;
try
{
System.Reflection.MethodBase mb = a.ManifestModule.ResolveMethod((int)f.Token);
if (mb != null)
return mb.GetCustomAttributes(typeof(System.Diagnostics.DebuggerStepThroughAttribute), false).Length > 0;
}
catch
{
}
return false;
}
public static DebugType GetPABCSystemType()
{
if (pabc_system_type == null)
{
string file_name = PascalABCCompiler.Compiler.GetReferenceFileName("PABCRtl.dll");
System.Reflection.Assembly assm = PascalABCCompiler.NetHelper.NetHelper.LoadAssembly(file_name);
PascalABCCompiler.NetHelper.NetHelper.init_namespaces(assm);
pabc_system_type = DebugUtils.GetDebugType(PascalABCCompiler.NetHelper.NetHelper.PABCSystemType);
}
return pabc_system_type;
}
public static Type GetTypeForStatic(string name)
{
Type t = null;
foreach (string s in ns_ht.Keys)
{
t = a.GetType(s + "." + name, false, true);
if (t != null)
return t;
}
t = stand_types[name] as Type;
if (t != null) return t;
t = PascalABCCompiler.NetHelper.NetHelper.FindType(name);
if (t == null) t = PascalABCCompiler.NetHelper.NetHelper.FindType("System." + name);
if (t == null)
foreach (string s in ns_ht.Keys)
{
t = PascalABCCompiler.NetHelper.NetHelper.FindType(s + "." + name);
if (t != null)
break;
}
return t;
}
public static Type GetTypeForStatic(string name, List<Type> gen_types)
{
Type t = null;
foreach (string s in ns_ht.Keys)
{
t = a.GetType(s+"."+name+"`"+gen_types.Count,false,true);
if (t != null)
{
//t = t.MakeGenericType(gen_types.ToArray());
return t;
}
}
t = PascalABCCompiler.NetHelper.NetHelper.FindType(name+"`"+gen_types.Count);
if (t == null) t = PascalABCCompiler.NetHelper.NetHelper.FindType("System."+name+"`"+gen_types.Count);
if (t == null)
foreach (string s in ns_ht.Keys)
{
t = PascalABCCompiler.NetHelper.NetHelper.FindType(s+"."+name+"`"+gen_types.Count);
if (t != null)
break;
}
//if (t != null)
// t = t.MakeGenericType(gen_types.ToArray());
return t;
}
public static Type GetType(string name)
{
Type t = stand_types[name] as Type;
if (t != null) return t;
t = a.GetType(name,false,true);
if (t == null)
foreach (string s in ns_ht.Keys)
{
t = a.GetType(s+"."+name,false,true);
if (t != null) break;
}
if (t == null) t = PascalABCCompiler.NetHelper.NetHelper.FindType(name);
if (t == null) t = PascalABCCompiler.NetHelper.NetHelper.FindType("System."+name);
if (t == null)
foreach (string s in ns_ht.Keys)
{
t = PascalABCCompiler.NetHelper.NetHelper.FindType(s+"."+name);
if (t != null)
break;
}
// if (t == null) t = Type.GetType(name,false,true);
// if (t == null) t = Type.GetType("System."+name,false,true);
// if (t == null)
// foreach(System.Reflection.Assembly ass in ref_modules)
// {
// t = ass.GetType(name);
// if (t != null)
// break;
// }
return t;
}
public static List<DebugType> GetUsesTypes(Process p, DebugType dt)
{
if (unit_debug_types == null)
{
unit_debug_types = new List<DebugType>();
foreach (Type t in unit_types)
unit_debug_types.Add(DebugType.Create(p.GetModule(t.Assembly.ManifestModule.ScopeName),(uint)t.MetadataToken));
}
return unit_debug_types;
}
public static void Unload()
{
//if (ad != null) AppDomain.Unload(ad);
//GC.Collect();
ns_ht.Clear();
unit_types.Clear();
if (unit_debug_types != null)
unit_debug_types.Clear();
unit_debug_types = null;
}
}
public class ProcessDelegator : IProcess
{
private Process process;
public ProcessDelegator(Process process)
{
this.process = process;
}
public bool HasExited
{
get
{
return process.HasExited;
}
}
}
public class ProcessEventArgsDelegator : EventArgs, IProcessEventArgs
{
private ProcessDelegator process;
public ProcessEventArgsDelegator(ProcessDelegator process)
{
this.process = process;
}
public IProcess Process
{
get
{
return process;
}
}
}
/// <summary>
/// Класс для отладки программ
/// </summary>
public class DebugHelper : IDebuggerManager
{
private NDebugger dbg;
private Process debuggedProcess;
private IWorkbench workbench;
private string FileName;
private string FullFileName;
private string PrevFullFileName;
private Breakpoint brPoint;
private Breakpoint currentBreakpoint;
private int CurrentLine;
public DebugStatus Status;
private bool MustDebug = false;
public bool IsRunning = false;
public string ExeFileName;
public bool ShowDebugTabs=true;
public Languages.Facade.ILanguage language = null;
EventHandler<EventArgs> debuggerStateEvent;
public DebugHelper()
{
//System.Threading.Thread.CurrentThread.SetApartmentState(System.Threading.ApartmentState.MTA);
dbg = new NDebugger();
//th = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(frm.RefreshPad));
this.workbench = WorkbenchServiceFactory.Workbench;
}
public Process DebuggedProcess
{
get
{
return debuggedProcess;
}
}
event EventHandler<EventArgs> IDebuggerManager.DebuggeeStateChanged
{
add
{
debuggerStateEvent += value;
}
remove
{
debuggerStateEvent -= value;
}
}
public Breakpoint CurrentBreakpoint
{
get { return currentBreakpoint; }
set { currentBreakpoint = value; }
}
/// <summary>
/// Добавить Breakpoint в файл file_name строку line
/// </summary>
public Breakpoint AddBreakPoint(string fileName, int line, bool commonBreakpoint)
{
Breakpoint br = null;
bool added = false;
if (!workbench.UserOptions.AlwaysAttachDebuggerAtStart && handle != 0 && commonBreakpoint && this.debuggedProcess == null)
{
Attach(handle, ExeFileName, true,true);
}
foreach (Breakpoint bp in dbg.Breakpoints)
{
if (bp.SourcecodeSegment.SourceFullFilename == fileName && bp.SourcecodeSegment.StartLine == line)
{
added = true;
br = bp;
}
}
if (!added)
br = dbg.AddBreakpoint(fileName, line);
return br;
}
/// <summary>
/// Получить список Breakpointov в файле file_name
/// </summary>
public List<Breakpoint> GetBreakpointsInFile(string fileName)
{
List<Breakpoint> lst = new List<Breakpoint>();
foreach (Breakpoint bp in dbg.Breakpoints)
{
if (bp.SourcecodeSegment.SourceFullFilename == fileName)
{
lst.Add(bp);
}
}
return lst;
}
/// <summary>
/// Удалить Breakpoint
/// </summary>
public void RemoveBreakpoint(Breakpoint br)
{
dbg.RemoveBreakpoint(br);
}
public delegate void DebugHelperActionDelegate(string FileName);
public event DebugHelperActionDelegate Exited;
public event DebugHelperActionDelegate Starting;
/// <summary>
/// Запуск процесса на отладку
/// </summary>
/// <param name="fileName">Имя ехе-файла</param>
/// <param name="sourceFileName">Имя исходного файла</param>
/// <param name="workingDirectory">Каталог файла</param>
/// <param name="arguments">Аргументы командной строки</param>
/// <param name="need_first_brpt">Флаг, нужно ли устанавливать Breakpoint на первом операторе (F8, F7)</param>
/// <param name="redirectOutput">Временно не используется</param>
public void Start(string fileName, string sourceFileName, string workingDirectory, string arguments, bool need_first_brpt, bool redirectOutput)
{
if (Starting != null)
Starting(fileName);
//dbg = new NDebugger();
dbg.ProcessStarted += debugProcessStarted;
dbg.ProcessExited += debugProcessExit;
dbg.BreakpointHit += debugBreakpointHit;
//if (brPoint != null) dbg.RemoveBreakpoint(brPoint);
this.FileName = sourceFileName;//Path.GetFileNameWithoutExtension(file_name) + ".pas";
this.FullFileName = Path.Combine(Path.GetDirectoryName(fileName), this.FileName);
this.ExeFileName = fileName;
this.PrevFullFileName = FullFileName;
if (need_first_brpt) brPoint = dbg.AddBreakpoint(FileName, workbench.VisualEnvironmentCompiler.Compiler.BeginOffset);
AssemblyHelper.LoadAssembly(fileName);
debuggedProcess = dbg.Start(fileName, workingDirectory, arguments);
SelectProcess(debuggedProcess);
}
private uint handle=0;
public void NullProcessHandleIfNeed(string fileName)
{
if (string.Compare(fileName,this.ExeFileName,true)==0)
{
FileName = null;
handle = 0;
if (debuggedProcess == null)
{
IsRunning = false;
ExeFileName = null;
WorkbenchServiceFactory.OperationsService.ClearTabStack();
WorkbenchServiceFactory.DebuggerOperationsService.ClearDebugTabs();
WorkbenchServiceFactory.Workbench.DisassemblyWindow.ClearWindow();
}
}
}
public void Attach(uint handle, string fileName, bool real_attach, bool late_attach)
{
if (!real_attach)
{
this.handle = handle;
this.ExeFileName = fileName;
IsRunning = true;
return;
}
if (handle == 0)
return;
if (Starting != null)
Starting(fileName);
string sourceFileName = null;
if (!ProjectFactory.Instance.ProjectLoaded)
sourceFileName = workbench.VisualEnvironmentCompiler.Compiler.CompilerOptions.SourceFileName;
else
sourceFileName = ProjectFactory.Instance.CurrentProject.MainFile;
this.FileName = sourceFileName;//Path.GetFileNameWithoutExtension(file_name) + ".pas";
this.FullFileName = Path.Combine(Path.GetDirectoryName(fileName), this.FileName);
this.ExeFileName = fileName;
CurrentLine = 0;
this.language = Languages.Facade.LanguageProvider.Instance.SelectLanguageByExtension(FullFileName);
this.PrevFullFileName = FullFileName;
AssemblyHelper.LoadAssembly(fileName);
dbg.ProcessStarted += debugProcessStarted;
dbg.ProcessExited += debugProcessExit;
//brPoint = dbg.AddBreakpoint(file_name, frm.VisualEnvironmentCompiler.Compiler.BeginOffset);
try
{
debuggedProcess = dbg.DebugActiveProcess(handle, fileName);
}
catch (System.Exception ex)
{
return;
}
SelectProcess(debuggedProcess);
//debuggedProcess.Break();
}
Function currentFunction;
Dictionary<int, int> sourceMap;
public void UpdateBreakpoints()
{
try
{
Dictionary<string, List<int>> dict = new Dictionary<string, List<int>>();
List<Breakpoint> toRemove = new List<Breakpoint>();
foreach (CurrentBreakpointBookmark b in BreakPointFactory.breakpoints.Keys)
{
try
{
if (dbg.GetBreakpoint(b.FileName, b.LineNumber + 1) == null)
dbg.AddBreakpoint(b.FileName, b.LineNumber + 1);
if (!dict.ContainsKey(b.FileName))
dict.Add(b.FileName, new List<int>());
if (!dict[b.FileName].Contains(b.LineNumber + 1))
dict[b.FileName].Add(b.LineNumber + 1);
}
catch
{
if (!dict.ContainsKey(b.FileName))
dict.Add(b.FileName, new List<int>());
}
}
foreach (Breakpoint b in dbg.Breakpoints)
if (dict.ContainsKey(b.SourcecodeSegment.SourceFullFilename) && !dict[b.SourcecodeSegment.SourceFullFilename].Contains(b.SourcecodeSegment.StartLine))
toRemove.Add(b);
foreach (Breakpoint b in toRemove)
dbg.RemoveBreakpoint(b);
}
catch
{
}
}
void debuggedProcess_DebuggeeStateChanged(object sender, ProcessEventArgs e)
{
if (currentBreakpoint != null)
{
dbg.RemoveBreakpoint(currentBreakpoint);
RemoveGotoBreakpoints();
currentBreakpoint = null; //RemoveBreakpoints();
}
JumpToCurrentLine();
//ChangeLocalVars(e.Process);
//if (e.Process.IsPaused)
WorkbenchServiceFactory.DebuggerOperationsService.RefreshPad(new FunctionItem(e.Process.SelectedFunction).SubItems);
workbench.WidgetController.SetStartDebugAndRunEnabled();
if (currentFunction != e.Process.SelectedFunction)
{
if (WorkbenchServiceFactory.Workbench.DisassemblyWindow.IsVisible)
{
var tp = GetNativeCodeOfSelectedFunction(e.Process.SelectedFunction);
WorkbenchServiceFactory.DebuggerOperationsService.DisplayDisassembledCode(tp.Item1);
sourceMap = tp.Item2;
currentFunction = e.Process.SelectedFunction;
}
}
if (debuggerStateEvent != null)
debuggerStateEvent(this, new ProcessEventArgsDelegator(new ProcessDelegator(this.debuggedProcess)));
}
private void debugBreakpointHit(object sender, BreakpointEventArgs e)
{
}
public void SetFirstBreakpoint(string fileName, int line)
{
brPoint = dbg.AddBreakpoint(fileName, line);
}
private void SelectProcess(Debugger.Process process)
{
if (debuggedProcess != null)
{
//debuggedProcess.DebuggingPaused -= debuggedProcess_DebuggingPaused;
//debuggedProcess.ExceptionThrown -= debuggedProcess_ExceptionThrown;
debuggedProcess.DebuggeeStateChanged -= debuggedProcess_DebuggeeStateChanged;
debuggedProcess.DebuggingResumed -= debuggedProcess_DebuggingResumed;
debuggedProcess.DebuggingPaused -= debuggedProcess_DebuggingPaused;
debuggedProcess.ExceptionThrown -= debuggedProcess_ExceptionThrown;
debuggedProcess.Expired -= debuggedProcess_Expired;
//debuggedProcess.LogMessage -= debuggedProcess_logMessage;
}
debuggedProcess = process;
if (debuggedProcess != null)
{
//debuggedProcess.DebuggingPaused += debuggedProcess_DebuggingPaused;
//debuggedProcess.ExceptionThrown += debuggedProcess_ExceptionThrown;
debuggedProcess.DebuggeeStateChanged += debuggedProcess_DebuggeeStateChanged;
debuggedProcess.DebuggingResumed += debuggedProcess_DebuggingResumed;
debuggedProcess.DebuggingPaused += debuggedProcess_DebuggingPaused;
debuggedProcess.ExceptionThrown += debuggedProcess_ExceptionThrown;
debuggedProcess.Expired += debuggedProcess_Expired;
//debuggedProcess.LogMessage += debuggedProcess_logMessage;
}
JumpToCurrentLine();
OnProcessSelected(new ProcessEventArgs(process));
}
private void debuggerTraceMessage(object sender, MessageEventArgs e)
{
//frm.WriteToOutputBox(e.Message);
}
private void debuggedProcess_logMessage(object sender, MessageEventArgs e)
{
WorkbenchServiceFactory.OperationsService.WriteToOutputBox(e.Message, false);
//debuggedProcess.TraceMessage("kkkk");
}
private void debuggedProcess_Expired(object sender, EventArgs e)
{
workbench.WidgetController.SetStartDebugAndRunEnabled();
}
private void debuggedProcess_ExceptionThrown(object sender, ExceptionEventArgs e)
{
if (e.Exception.Message == "System.StackOverflowException")
WorkbenchServiceFactory.OperationsService.WriteToOutputBox(RuntimeExceptionsStringResources.Get("Process is terminated due to StackOverflowException."), true);
else
WorkbenchServiceFactory.OperationsService.WriteToOutputBox(e.Exception.Message, true);
}
private void debuggedProcess_DebuggingPaused(object sender, ProcessEventArgs e)
{
if (MustDebug && e.Process.PausedReason != PausedReason.Exception)
{
//System.Threading.Thread.Sleep(10);
if (Status == DebugStatus.StepOver)
e.Process.StepOver();
else
e.Process.StepInto();
MustDebug = false;
}
workbench.WidgetController.SetDebugPausedDisabled();
}
protected virtual void OnProcessSelected(ProcessEventArgs e)
{
}
void RemoveBreakpoints()
{
if (brPoint != null)
{
dbg.RemoveBreakpoint(brPoint);
brPoint = null;
}
}
void debugProcessExit(object sender, ProcessEventArgs e)
{
if (Exited != null && ExeFileName != null)
Exited(ExeFileName);
curPage = null;
ShowDebugTabs = true;
workbench.WidgetController.SetPlayButtonsVisible(false);
workbench.WidgetController.SetAddExprMenuVisible(false);
workbench.WidgetController.SetDisassemblyMenuVisible(false);
DebugWatchListWindowForm.WatchWindow.ClearAllSubTrees();
IsRunning = false;
workbench.WidgetController.SetDebugStopDisabled();
workbench.WidgetController.ChangeContinueDebugNameOnStart();
CurrentLineBookmark.Remove();
WorkbenchServiceFactory.DebuggerOperationsService.ClearLocalVarTree();
WorkbenchServiceFactory.DebuggerOperationsService.ClearDebugTabs();
WorkbenchServiceFactory.DebuggerOperationsService.ClearWatch();
WorkbenchServiceFactory.Workbench.DisassemblyWindow.ClearWindow();
workbench.WidgetController.SetDebugTabsVisible(false);
WorkbenchServiceFactory.OperationsService.ClearTabStack();
workbench.WidgetController.EnableCodeCompletionToolTips(true);
RemoveGotoBreakpoints();
AssemblyHelper.Unload();
CloseOldToolTip();
workbench.ServiceContainer.EditorService.SetEditorDisabled(false);
//RemoveMarker(frm.CurrentCodeFileDocument.TextEditor.ActiveTextAreaControl.Document);
evaluator = null;
language= null;
FileName = null;
handle = 0;
ExeFileName = null;
FullFileName = null;
PrevFullFileName = null;
Status = DebugStatus.None;
dbg.ProcessStarted -= debugProcessStarted;
dbg.ProcessExited -= debugProcessExit;
dbg.BreakpointHit -= debugBreakpointHit;
debuggedProcess = null;
//GC.Collect();
//dbg = null;
}
void debuggedProcess_DebuggingResumed(object sender, ProcessEventArgs e)
{
//CurrentLineBookmark.Remove();
//frm.SetDebugStopDisabled();
}
public ExpressionEvaluator evaluator;
void debugProcessStarted(object sender, ProcessEventArgs e)
{
workbench.WidgetController.SetDebugTabsVisible(true);
workbench.WidgetController.SetPlayButtonsVisible(true);
workbench.WidgetController.SetDebugStopEnabled();//e.Process.LogMessage += messageEventProc;
workbench.WidgetController.SetStartDebugAndRunDisabled();
workbench.WidgetController.ChangeStartDebugNameOnContinue();
workbench.WidgetController.EnableCodeCompletionToolTips(false);
workbench.WidgetController.SetAddExprMenuVisible(true);
workbench.WidgetController.SetDisassemblyMenuVisible(true);
workbench.ServiceContainer.EditorService.SetEditorDisabled(true);
TooltipServiceManager.hideToolTip();
IsRunning = true;
evaluator = new ExpressionEvaluator(e.Process,workbench.VisualEnvironmentCompiler, FileName);
}
/// <summary>
/// Вычисляет значение выражения (WATCH)
/// </summary>
public RetValue Evaluate(string expr)
{
if (evaluator != null)
return evaluator.Evaluate(expr, false);
else return new RetValue();
}
private NamedValue GetNullBasedArray(Value val)
{
IList<FieldInfo> flds = val.Type.GetFields();
//if (flds.Count != 3) return null;
foreach (FieldInfo fi in flds)
if (fi.Name == "NullBasedArray") return fi.GetValue(val);
return null;
}
/// <summary>
/// Возвращает текстовое представление для значения val
/// </summary>
public string MakeValueView(Value val)
{
bool by_ref = false;
if ((val.Type.IsByRef() && !val.Type.IsPrimitive))
{
by_ref = true;
val = val.Dereference;
}
int v = 0;
NamedValue nv = GetNullBasedArray(val);//mozhet eto massiv
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (nv != null)//staticheskij massiv
{
sb.Append('(');
NamedValueCollection nvc = nv.GetArrayElements();
for (int i = 0; i < nvc.Count; i++)
{
if (i > 10)
{
sb.Append("...");
break;
}
sb.Append(MakeValueView(nvc[i]));
if (i < nvc.Count - 1) sb.Append(',');
}
sb.Append(')');
//sb.AppendLine();
//sb.Remove(
}
else if (val.IsPrimitive)
{
if (val.Type.ManagedType == typeof(string) || val.Type.ManagedType == typeof(char))
sb.Append("'" + val.AsString + "'");
else
sb.Append(val.AsString);
}
else if (val.IsNull)
{
sb.Append("nil");
}
else if (DebugUtils.IsEnum(val, out v))
{
sb.Append(ValueItem.MakeEnumText(val));
}
else if (val.Type.IsValueType && val.Type.GetMembers().Count <= 7)
{
sb.Append('{');
NamedValueCollection nvc = val.GetMembers();
for (int i = 0; i < nvc.Count; i++)
{
sb.Append(nvc[i].Name + ": " + MakeValueView(nvc[i]));
if (i < nvc.Count - 1) sb.Append("; ");
}
sb.Append('}');
}
else if (val.IsArray)//dinamicheskij massiv
{
NamedValueCollection nvc = val.GetArrayElements();
sb.Append('(');
for (int i = 0; i < nvc.Count; i++)
{
if (i > 10)
{
sb.Append("...");
break;
}
sb.Append(MakeValueView(nvc[i]));
if (i < nvc.Count - 1) sb.Append(',');
}
sb.Append(')');
//sb.AppendLine();
}
else if (val.IsObject)
{
if (val.Type.FullName == "PABCSystem.TypedSet")
sb.Append((val.Type.GetMember("ToString", BindingFlags.All)[0] as MethodInfo).Invoke(val, new Value[0] { }).AsString);
else
if (!val.Type.IsPrimitive)
{
if (DebugUtils.CheckForCollection(val.Type))
return DebugUtils.MakeViewForCollection(val);//esli eto kollekcija, to vyvodim ee po osobomu
bool is_failed = false;
string s = ExpressionEvaluator.GetToString(val, out is_failed);
if (s != null) return s;
else return val.AsString;
}
else
return val.AsString;
}
else return val.AsString;
return sb.ToString();
}
private void OnAddBreakpoint(object sender, EventArgs e)
{
}
private TextArea curTextArea = null;
private ICodeFileDocument curPage;
private bool is_out = false;
private SourcecodeSegment stepin_stmt = null;
private bool tab_changed=false;
/// <summary>
/// Перейти к следующей строке при отладке
/// </summary>
private void JumpToCurrentLine()
{
workbench.MainForm.Activate();
CurrentLineBookmark.Remove();//udalajem zheltyj kursor otladki
//System.Threading.Thread.Sleep(70);
if (debuggedProcess != null)
{
SourcecodeSegment nextStatement = debuggedProcess.NextStatement;
//debuggedProcess.Modules[0].SymReader.GetMethod(debuggedProcess.SelectedFunction.Token);
if (nextStatement != null)
{
string save_PrevFullFileName = PrevFullFileName;
//CodeFileDocumentControl page = null;
//DebuggerService.JumpToCurrentLine(nextStatement.SourceFullFilename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
if (!ShowDebugTabs)//esli eshe ne pokazany watch i lokal, pokazyvaem
{
ShowDebugTabs = true;
workbench.WidgetController.SetDebugTabsVisible(true);
workbench.WidgetController.SetAddExprMenuVisible(true);
}
if (debuggedProcess.NextStatement.StartLine == 0xFFFFFF)
{
//sjuda popadem, esli vyzyvaem Test(arr), gde arr - massiv peredavaemyj po znacheniju
//metod $Copy ne imeet sequence pointov, poetomu chtoby vojti v proceduru vyzovy $Copy my pomechaem 0xFFFFFFF
//dolgo s etoj badjagoj muchalsja
is_out = true;
debuggedProcess.StepInto();//vhodim neposredstvenno v proceduru
return;
}
else if (AssemblyHelper.IsDebuggerStepThrough(debuggedProcess.SelectedFunction))
{
MustDebug = true;
debuggedProcess.StepOut();
return;
}
else if (is_out)
{
is_out = false;
if (stepin_stmt.SourceFullFilename == debuggedProcess.NextStatement.SourceFullFilename && stepin_stmt.StartLine != debuggedProcess.NextStatement.StartLine)
stepin_stmt = debuggedProcess.NextStatement;
else
{
debuggedProcess.StepInto();
return;
}
}
if (debuggedProcess.NextStatement.SourceFullFilename != this.PrevFullFileName || !WorkbenchServiceFactory.DocumentService.ContainsTab(debuggedProcess.NextStatement.SourceFullFilename))
{
tab_changed = true;
curPage = WorkbenchServiceFactory.FileService.OpenFileForDebug(debuggedProcess.NextStatement.SourceFullFilename);
if (curPage == null)
{
MustDebug = true;
return;
}
PrevFullFileName = debuggedProcess.NextStatement.SourceFullFilename;
}
else if (curPage != WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument)
WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument = curPage;
bool remove_breakpoints = true;
IDocument doc = curPage.TextEditor.Document;
curTextArea = curPage.TextEditor.ActiveTextAreaControl.TextArea;
LineSegment lseg = curPage.TextEditor.ActiveTextAreaControl.Document.GetLineSegment(debuggedProcess.NextStatement.StartLine - 1);
int len = lseg.Length + 1;
/*if (lseg.Words.Count == 1 && string.Compare(lseg.Words[0].Word,"begin",true)==0)
{
debuggedProcess.StepOver();
return;
}*/
//eto badjaga prepjatstvuet popadaniju na begin
//luchshego sposoba naverno net
bool in_comm = false;
bool beg = false;
bool in_str = false;
for (int i = 0; i < lseg.Words.Count; i++)
{
if (lseg.Words[i].Type == TextWordType.Word)
{
string word = lseg.Words[i].Word;
if (string.Compare(word, "begin", true) == 0 && !in_str && !in_comm)
beg = true;
else if (string.Compare(word, "{") == 0)
{
if (!in_str) in_comm = true;
}
else if (string.Compare(word, "}") == 0)
{
if (!in_str && in_comm) in_comm = false;
}
else if (string.Compare(word, "'") == 0)
in_str = !in_str;
else if (string.Compare(word, "/") == 0)
{
if (i < lseg.Words.Count - 1 && string.Compare(lseg.Words[i + 1].Word, "/") == 0)
break;
}
else if (string.Compare(word, "(") == 0)
{
if (i < lseg.Words.Count - 1 && string.Compare(lseg.Words[i + 1].Word, "*") == 0)
{
beg = false;
break;
}
}
else if (!in_str && !in_comm)
{
beg = false;
break;
}
}
}
if (beg)
{
if (debuggedProcess.PausedReason != PausedReason.Exception)
debuggedProcess.StepOver();
return;
}
if (debuggedProcess.PausedReason == PausedReason.Breakpoint)
{
Breakpoint br = dbg.GetBreakpoint(debuggedProcess.NextStatement.SourceFullFilename, nextStatement.StartLine);
if (br != null && !BreakPointFactory.MustHit(br))
{
if (Status == DebugStatus.StepOver || Status == DebugStatus.StepIn)
{
remove_breakpoints = false;
}
else
{
debuggedProcess.Continue();
return;
}
}
}
//for (int i=0; i<lseg.Words.Count; i++)
CurrentLineBookmark.SetPosition(debuggedProcess.NextStatement.SourceFilename, curPage.TextEditor.Document, nextStatement.StartLine, 1, nextStatement.StartLine,
len);
curPage.TextEditor.ActiveTextAreaControl.JumpTo(nextStatement.StartLine - 1, 0);
if ((Status == DebugStatus.StepOver || Status == DebugStatus.StepIn) && (CurrentLine == nextStatement.StartLine && save_PrevFullFileName == debuggedProcess.NextStatement.SourceFilename))
{
if (curILOffset != nextStatement.ILOffset)
{
curILOffset = nextStatement.ILOffset;
//debuggedProcess.StepOver();
MustDebug = true;
}
CurrentLine = nextStatement.StartLine;
//return;
}
else
{
curILOffset = nextStatement.ILOffset;
CurrentLine = nextStatement.StartLine;
MustDebug = false;
//MustDebug = ((nextStatement.ILOffset + 1) == nextStatement.ILEnd);
}
//MustDebug = false;
//if (remove_breakpoints)
{
RemoveBreakpoints();
if (currentBreakpoint != null)
{
dbg.RemoveBreakpoint(currentBreakpoint);
currentBreakpoint = null; //RemoveBreakpoints();
}
}
}
}
}
private int curILOffset = 0;
struct COR_DEBUG_IL_TO_NATIVE_MAP
{
public uint ilOffset;
public uint nativeStartOffset;
public uint nativeEndOffset;
}
public Tuple<string, Dictionary<int, int>> GetNativeCodeOfSelectedFunction(Function selectedFunction=null)
{
if (selectedFunction == null)
selectedFunction = debuggedProcess.SelectedFunction;
uint size = selectedFunction.CorFunction.NativeCode.Size;
byte[] buffer = new byte[size];
uint mapSize;
COR_DEBUG_IL_TO_NATIVE_MAP[] mapBuffer = new COR_DEBUG_IL_TO_NATIVE_MAP[selectedFunction.CorFunction.ILCode.Size];
unsafe
{
fixed (byte* ptr = &buffer[0])
{
IntPtr iptr = new IntPtr((void*)ptr);
selectedFunction.CorFunction.NativeCode.GetCode(0, size, size, iptr);
}
fixed (void* ptr = &mapBuffer[0])
{
IntPtr iptr = new IntPtr(ptr);
selectedFunction.CorFunction.NativeCode.GetILToNativeMapping((uint)mapBuffer.Length, out mapSize, iptr);
}
}
Dictionary<uint, uint> il2asm = new Dictionary<uint, uint>();
for (int i = 0; i < mapSize; i++)
{
if (i < mapBuffer.Length)
il2asm.Add(mapBuffer[i].nativeStartOffset, mapBuffer[i].ilOffset);
}
SharpDisasm.Disassembler disasm = new SharpDisasm.Disassembler(buffer, AssemblyHelper.Is32BitAssembly()?SharpDisasm.ArchitectureMode.x86_32: SharpDisasm.ArchitectureMode.x86_64);
IEnumerable<SharpDisasm.Instruction> instructions = disasm.Disassemble();
StringBuilder sb = new StringBuilder();
int linesNum = 0;
Dictionary<int, int> sourceMap = new Dictionary<int, int>();
Dictionary<int, int> linesDict = new Dictionary<int, int>();
bool firstLine = true;
foreach (var instruction in instructions)
{
linesNum++;
uint ilOffset;
if (il2asm.TryGetValue((uint)instruction.Offset, out ilOffset))
{
var segment = selectedFunction.GetSegmentForOffet(ilOffset);
if (segment != null && !linesDict.ContainsKey(segment.StartLine))
{
if (ilOffset > 2000000000)
{
if (firstLine)
continue;
}
else
firstLine = false;
int line = segment.StartLine;
string text = curPage.TextEditor.Document.GetText(curPage.TextEditor.Document.GetLineSegment(line - 1));
sb.AppendLine((segment.StartLine+":").PadRight(10, ' ') + text.Trim());
linesDict.Add(segment.StartLine, segment.StartLine);
}
}
sb.Append("///"+selectedFunction.CorFunction.NativeCode.Address.ToString("X") + "+0x"+instruction.Offset.ToString("X") + ": " + instruction.ToString());
sb.AppendLine();
}
return new Tuple<string, Dictionary<int, int>>(sb.ToString(),sourceMap);
}
public void DoInPausedState(MethodInvoker action)
{
Debugger.Process process = debuggedProcess;
if (process.IsPaused)
{
//System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ThreadStart(delegate{action();}));
//th.Start();
action();
}
else
{
EventHandler<ProcessEventArgs> onDebuggingPaused = null;
onDebuggingPaused = delegate
{
action();
process.DebuggingPaused -= onDebuggingPaused;
};
process.DebuggingPaused += onDebuggingPaused;
}
}
private NamedValue GetVariableFromName(string variableName)
{
if (debuggedProcess == null || debuggedProcess.IsRunning)
{
return null;
}
else
{
return debuggedProcess.GetValue(variableName);
}
}
DebuggerGridControl oldToolTipControl;
void TextAreaMouseLeave(object source, EventArgs e)
{
if (CanCloseOldToolTip && !oldToolTipControl.IsMouseOver)
CloseOldToolTip();
}
/// <summary>
/// Получить выражение под курсором
/// </summary>
public string GetVariable(TextArea textArea, out int num_line)
{
IDocument doc = textArea.Document;
string textContent = doc.TextContent;
num_line = textArea.Caret.Line;
int start_off = 0;
int end_off = 0;
string expressionResult = FindFullExpression(textContent, textArea.Caret.Offset,doc, out start_off, out end_off);
return expressionResult;
}
private string GetVariable(ToolTipRequestEventArgs e, TextArea textArea, out int num_line, out int start_off, out int end_off)
{
//Point logicPos = e.LogicalPosition;
ICSharpCode.TextEditor.TextLocation logicPos = e.LogicalPosition;
IDocument doc = textArea.Document;
LineSegment seg = doc.GetLineSegment(logicPos.Y);
num_line = seg.LineNumber;
start_off = 0;
end_off = 0;
if (logicPos.X > seg.Length - 1)
return null;
string textContent = doc.TextContent;
string expressionResult = FindFullExpression(textContent, seg.Offset + logicPos.X,doc, out start_off, out end_off);
return expressionResult;
}
private string FindFullExpression(string text, int offset, IDocument doc, out int start_off, out int end_off)
{
int i = offset;
int beg_line = 1;
int off = 0;
start_off = 0;
end_off = 0;
if (debuggedProcess != null)
{
beg_line = (int)debuggedProcess.SelectedFunction.symMethod.SequencePoints[0].Line;
off = doc.LineSegmentCollection[beg_line - 1].Offset;
}
//int lll = doc.GetLineNumberForOffset(offset) - 1;
int cur_str_off = doc.LineSegmentCollection[doc.GetLineNumberForOffset(offset)].Offset;
List<int> strs = new List<int>();
i = cur_str_off;
int cur_sk = 0;
//while (i >= 0 && text[i] != '\n')
//int len = text.Length;
bool format_str = false;
bool var_in_format_str = false;
while (text[i] != '\n')
if (text[i] == '\'')
{
if (i == offset) return null;
if (i > 0 && text[i - 1] == '$')
format_str = true;
cur_sk = (cur_sk == 0) ? 1 : 0;
i++;
}
//else if (i == offset && cur_sk == 1) return null;
else i++;
i = offset;
bool new_line = false;
while (i >= off)
if (text[i] == '\n') { new_line = true; i--; }
else
if (text[i] == '/' && i > 0 && text[i - 1] == '/') if (!new_line) return null; else i--;
else if (text[i] == '}') break;
else if (text[i] == '{')
{
if (!format_str)
return null;
else
{
var_in_format_str = true;
i--;
}
}
else i--;
i = offset;
if (format_str && !var_in_format_str)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (i >= 0 && !(Char.IsLetterOrDigit(text[i]) || text[i] == '_')) i--;
while (i >= 0 && (Char.IsLetterOrDigit(text[i]) || text[i] == '_'))
i--;
bool is_dot = false;
if (i >= 0)
{
if (text[i] == '.') is_dot = true;
int j = i + 1;
while (j < text.Length && (Char.IsLetterOrDigit(text[j]) || text[j] == '_'))
sb.Append(text[j++]);
if (j < text.Length && text[j] == '(')
return null;
end_off = j - 1;
start_off = i + 1;
}
else
{
int j = i + 1;
while (j < text.Length && (Char.IsLetterOrDigit(text[j]) || text[j] == '_'))
sb.Append(text[j++]);
if (j < text.Length && text[j] == '(')
return null;
end_off = j - 1;
start_off = i + 1;
}
if (is_dot)
{
sb.Insert(0, '.');
PascalABCCompiler.Parsers.KeywordKind keyw = PascalABCCompiler.Parsers.KeywordKind.None;
string s = CodeCompletion.CodeCompletionController.CurrentLanguage.LanguageIntellisenseSupport.
FindExpression(i, text, 0, 0, out keyw);
if (s != null)
{
sb.Insert(0, s);
string tmp = s.TrimStart(' ', '\n', '\t', '\r');
start_off = i - tmp.Length;
}
}
else
{
string s = sb.ToString().Trim(' ', '\n', '\t', '\r');
if (string.Compare(s, "array", true) == 0)
return "";
}
return sb.ToString();
}
/// <summary>
/// Возвращает значение переменной при отладке
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public ListItem FindVarByName(string var, int num_line)
{
try
{
if (!var.Contains("."))
{
List<NamedValue> unit_vars = new List<NamedValue>();
NamedValueCollection nvc = null;
NamedValue global_nv = null;
NamedValue disp_nv = null;
NamedValue ret_nv = null;
nvc = debuggedProcess.SelectedFunction.LocalVariables;
List<NamedValue> val_list = new List<NamedValue>();
foreach (NamedValue nv in nvc)//smotrim sredi lokalnyh peremennyh
{
if (nv.Name.IndexOf("<>local_variables") == -1)
val_list.Add(nv);
else
{
foreach (NamedValue nv2 in nv.GetMembers())//smotrim sredi lokalnyh peremennyh
{
val_list.Add(nv2);
}
}
}
foreach (NamedValue nv in val_list)//smotrim sredi lokalnyh peremennyh
{
if (nv.Name.IndexOf(':') != -1)
{
int pos = nv.Name.IndexOf(':');
string name = nv.Name.Substring(0, pos);
if (string.Compare(name, var, true) == 0)
{
int start_line = Convert.ToInt32(nv.Name.Substring(pos + 1, nv.Name.LastIndexOf(':') - pos - 1));
int end_line = Convert.ToInt32(nv.Name.Substring(nv.Name.LastIndexOf(':') + 1));
if (num_line >= start_line - 1 && num_line <= end_line - 1)
return new ValueItem(nv, null);
}
}
}
foreach (NamedValue nv in val_list)//smotrim sredi lokalnyh peremennyh
{
if (nv.Name.IndexOf(':') != -1)
{
continue;
}
if (string.Compare(nv.Name, var, true) == 0)
{
return new ValueItem(nv, null);
}
else if (string.Compare(nv.Name, "self", true) == 0 && debuggedProcess.SelectedFunction.ThisValue != null)
return new ValueItem(debuggedProcess.SelectedFunction.ThisValue, null);
else if (nv.Name.Contains("$class_var")) global_nv = nv;
else if (nv.Name.Contains("$unit_var")) unit_vars.Add(nv);
else if (nv.Name == "$disp$") disp_nv = nv;//vo vlozhennyh procedurah ssylka na verh zapis aktivacii
else if (nv.Name.StartsWith("$rv")) ret_nv = nv;//vozvrashaemoe znachenie
}
nvc = debuggedProcess.SelectedFunction.Arguments;
NamedValue self_nv = null;
foreach (NamedValue nv in nvc)
{
if (string.Compare(nv.Name, var, true) == 0) return new ValueItem(nv, null);
if (nv.Name == "$obj$")
self_nv = nv;
}
if (var.ToLower() == "self")
{
try
{
return new ValueItem(debuggedProcess.SelectedFunction.ThisValue, null);
}
catch
{
if (self_nv != null)
return new ValueItem(self_nv, null);
}
}
if (disp_nv != null)//prohodimsja po vlozhennym podprogrammam
{
NamedValue parent_val = null;
IList<FieldInfo> fields = disp_nv.Type.GetFields(BindingFlags.All);
foreach (FieldInfo fi in fields)
if (string.Compare(fi.Name, var, true) == 0) return new ValueItem(fi.GetValue(disp_nv), fi.DeclaringType);
else if (fi.Name == "$parent$") parent_val = fi.GetValue(disp_nv);
NamedValue pv = parent_val;
while (!pv.IsNull)
{
fields = parent_val.Type.GetFields(BindingFlags.All);
foreach (FieldInfo fi in fields)
if (string.Compare(fi.Name, var, true) == 0) return new ValueItem(fi.GetValue(parent_val), fi.DeclaringType);
else if (fi.Name == "$parent$") pv = fi.GetValue(parent_val);
if (!pv.IsNull) parent_val = pv;
}
}
// nvc = debuggedProcess.SelectedFunction.ContaingClassVariables;
// foreach (NamedValue nv in nvc)
// {
// if (string.Compare(nv.Name, var, true) == 0) return new ValueItem(nv,null);
// }
// try
// {
// if (debuggedProcess.SelectedFunction.ThisValue != null)
// {
// NamedValue nv = debuggedProcess.SelectedFunction.ThisValue.GetMember(var);
// if (nv != null) return new ValueItem(nv,null);
// }
// }
// catch(System.Exception e)
// {
//
// }
nvc = debuggedProcess.SelectedFunction.ContaingClassVariables;
foreach (NamedValue nv in nvc)//chleny klassa
{
if (string.Compare(nv.Name, var, true) == 0) return new ValueItem(nv, nv.Type);
}
if (self_nv != null)
{
IList<FieldInfo> fields = self_nv.Dereference.Type.GetFields(BindingFlags.All);
foreach (FieldInfo fi in fields)
if (string.Compare(fi.Name, var, true) == 0)
return new ValueItem(fi.GetValue(self_nv.Dereference), fi.DeclaringType);
}
if (global_nv != null)
{
IList<FieldInfo> fields = global_nv.Type.GetFields(BindingFlags.All);
foreach (FieldInfo fi in fields)
if (string.Compare(fi.Name, var, true) == 0) return new ValueItem(fi.GetValue(global_nv), fi.DeclaringType);
Type global_type = AssemblyHelper.GetType(global_nv.Type.FullName);
if (global_type != null)
{
System.Reflection.FieldInfo fi = global_type.GetField(var, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.IgnoreCase);
if (fi != null && fi.IsLiteral)
return new ValueItem(DebugUtils.MakeValue(fi.GetRawConstantValue()), var, global_nv.Type);
}
}
Type t = AssemblyHelper.GetTypeForStatic(var);
if (t != null)
{
DebugType dt = DebugUtils.GetDebugType(t);//DebugType.Create(this.debuggedProcess.GetModule(var),(uint)t.MetadataToken);
return new BaseTypeItem(dt, t);
}
List<DebugType> types = AssemblyHelper.GetUsesTypes(debuggedProcess, debuggedProcess.SelectedFunction.DeclaringType);
foreach (DebugType dt in types)
{
IList<FieldInfo> fields = dt.GetFields(BindingFlags.All);
foreach (FieldInfo fi in fields)
if (fi.IsStatic && string.Compare(fi.Name, var, true) == 0)
return new ValueItem(fi.GetValue(null), fi.DeclaringType);
Type unit_type = AssemblyHelper.GetType(dt.FullName);
if (unit_type != null)
{
System.Reflection.FieldInfo fi = unit_type.GetField(var, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.IgnoreCase);
if (fi != null && fi.IsLiteral)
return new ValueItem(DebugUtils.MakeValue(fi.GetRawConstantValue()), var, dt);
}
}
/*foreach (NamedValue nv in unit_vars)
{
IList<FieldInfo> fields = nv.Type.GetFields(BindingFlags.All);
foreach (FieldInfo fi in fields)
if (string.Compare(fi.Name, var, true) == 0) return new ValueItem(fi.GetValue(nv),fi.DeclaringType);
}*/
if (ret_nv != null && string.Compare(var, "Result", true) == 0)
return new ValueItem(ret_nv, null);
}
else
{
if (evaluator == null) return null;
Debugger.Wrappers.CorSym.ISymUnmanagedMethod sym_meth = debuggedProcess.SelectedFunction.symMethod;
// if (sym_meth == null) return null;
// if (sym_meth.SequencePoints.Length > 0)
// if (num_line < sym_meth.SequencePoints[0].Line || num_line > sym_meth.SequencePoints[sym_meth.SequencePoints.Length - 1].EndLine)
// return null;
string preformat;
RetValue rv = evaluator.GetValueForExpression(var, out preformat);
if (rv.obj_val != null && rv.obj_val is NamedValue)
{
Value v = rv.obj_val;
ValueItem vi = new ValueItem(v, var, evaluator.declaringType);
vi.SpecialName = preformat;
return vi;
}
else if (rv.prim_val != null)
{
ValueItem vi = new ValueItem(DebugUtils.MakeValue(rv.prim_val), var, evaluator.declaringType);
vi.SpecialName = preformat;
return vi;
}
else if (rv.type != null)
{
return new BaseTypeItem(rv.type, rv.managed_type);
}
}
}
catch (System.Exception e)
{
}
return null;
}
private TextMarker oldMarker;
public void RemoveMarker(IDocument doc)
{
try
{
if (oldMarker != null && doc != null && doc.TextLength >= oldMarker.Offset)
{
doc.MarkerStrategy.RemoveMarker(oldMarker);
doc.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine,doc.GetLineNumberForOffset(oldMarker.Offset)));
doc.CommitUpdate();
}
}
catch(System.Exception e)
{
}
}
public bool HasBreakpoints()
{
return BreakPointFactory.HasBreakpoints();
}
/// <summary>
/// Обработчик события запроса на подсказку значения переменной
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void TextAreaToolTipRequest(object sender, ToolTipRequestEventArgs e)
{
DebuggerGridControl toolTipControl = null;
TextMarker marker = null;
//RemoveMarker((sender as TextArea).Document);
if (debuggedProcess == null) return;
if (debuggedProcess.SelectedFunction == null || !debuggedProcess.IsPaused) return;
try
{
TextArea textArea = (TextArea)sender;
if (textArea != curTextArea) return;
if (e.ToolTipShown) return;
if (oldToolTipControl != null && !oldToolTipControl.AllowClose) return;
if (!IsRunning) return;
if (e.InDocument)
{
ToolTipInfo ti = null;
int num_line = 0;
int start_off = 0;
int end_off = 0;
string var = GetVariable(e,textArea,out num_line, out start_off, out end_off);
if (var == null || var == "") return;
//if (debuggedProcess.SelectedFunction.LocalVariables.Count > 0)
{
//NamedValue nv = FindVarByName(var, num_line);
ListItem nv = FindVarByName(var, num_line);
if (nv != null)
{
System.Threading.Thread.Sleep(50);
DebuggerGridControl dgc = new DebuggerGridControl(new DynamicTreeDebuggerRow(nv));
dgc.doc = textArea.Document;
ti = new ToolTipInfo(dgc);
ICSharpCode.TextEditor.TextLocation logicPos = e.LogicalPosition;
LineSegment seg = textArea.Document.GetLineSegment(logicPos.Y);
marker = new TextMarker(start_off, end_off-start_off+1, TextMarkerType.Cant, Color.Black, Color.White);
textArea.Document.MarkerStrategy.AddMarker(marker);
textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine,seg.LineNumber));
textArea.Document.CommitUpdate();
}
}
if (ti != null)
{
toolTipControl = ti.ToolTipControl as DebuggerGridControl;
if (ti.ToolTipText != null)
{
e.ShowToolTip(ti.ToolTipText);
}
}
CloseOldToolTip();
if (toolTipControl != null)
{
toolTipControl.ShowForm(textArea, e.LogicalPosition);
}
oldToolTipControl = toolTipControl;
RemoveMarker(textArea.Document);
oldMarker = marker;
}
}
catch (System.Exception ex)
{
//frm.WriteToOutputBox(ex.Message);// ICSharpCode.Core.MessageService.ShowError(ex);
}
finally
{
if (toolTipControl == null && CanCloseOldToolTip)
{
CloseOldToolTip();
RemoveMarker((sender as TextArea).Document);
}
}
}
bool CanCloseOldToolTip
{
get
{
return oldToolTipControl != null && oldToolTipControl.AllowClose;
}
}
void CloseOldToolTip()
{
if (oldToolTipControl != null)
{
Form frm = oldToolTipControl.FindForm();
if (frm != null) frm.Close();
oldToolTipControl = null;
}
}
/// <summary>
/// Завершить процесс
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void Stop(string ExeFileName)
{
try
{
workbench.WidgetController.SetStartDebugAndRunEnabled();
dbg.Processes[0].Terminate();
}
catch (System.Exception e)
{
}
}
/// <summary>
/// Прервать процесс
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void DebugBreak()
{
try
{
workbench.WidgetController.SetStartDebugAndRunEnabled();
dbg.Processes[0].Break();
}
catch (System.Exception e)
{
}
}
/// <summary>
/// Проверяет, запущен ли процесс с именем ExeFileName на отладку
/// </summary>
public bool IsRun(string ExeFileName)
{
return IsRunning && string.Compare(this.ExeFileName,ExeFileName,true)==0;
}
public bool IsRun(string ExeFileName, string SourceFileName)
{
return IsRunning && string.Compare(this.ExeFileName, ExeFileName, true) == 0 && string.Compare(this.FullFileName, SourceFileName, true) == 0;
}
/// <summary>
/// Проверяет, запущен ли процесс с именем ExeFileName на отладку
/// </summary>
public bool IsRunAndInThisTabPage(string ExeFileName, ICodeFileDocument cfdc)
{
if (WorkbenchServiceFactory.DocumentService.ContainsTab(cfdc))
return true;
return IsRunning && (/*string.Compare(this.ExeFileName,ExeFileName,true)==0 || */WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument == this.curPage);
}
public void SetAsPossibleDebugPage(CodeFileDocumentControl ctrl)
{
if (IsRunning && tab_changed && ctrl != this.curPage)
{
curPage = ctrl;
}
tab_changed = false;
}
public CodeFileDocumentControl CurPage
{
get
{
return curPage as CodeFileDocumentControl;
}
}
public void SetAsDebugPage(ICodeFileDocument ctrl)
{
curPage = ctrl;
}
public bool IsRunAndInThisTabPage()
{
return IsRunning && (WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument == this.curPage || WorkbenchServiceFactory.DocumentService.ContainsTab(WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument));
}
/// <summary>
/// Шаг без входа в подпрограмму
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void StepOver()
{
try
{
workbench.WidgetController.SetStartDebugAndRunDisabled();
if (debuggedProcess.SelectedFunction.Name == ".cctor")
{
var sequencePoints = debuggedProcess.SelectedFunction.symMethod.SequencePoints;
if (sequencePoints != null && debuggedProcess.NextStatement.StartLine == sequencePoints[sequencePoints.Length-1].Line)
{
debuggedProcess.StepOut();
}
else
debuggedProcess.StepOver();
}
else
debuggedProcess.StepOver();
CurrentLineBookmark.Remove();
}
catch (System.Exception e)
{
}
}
/// <summary>
/// Продолжить выполнение процесса
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void Continue()
{
try
{
workbench.WidgetController.SetStartDebugAndRunDisabled();
dbg.Processes[0].Continue();
CurrentLineBookmark.Remove();
}
catch (System.Exception e)
{
}
}
/// <summary>
/// Шаг с входом в подпрограмму
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void StepInto()
{
try
{
workbench.WidgetController.SetStartDebugAndRunDisabled();
stepin_stmt = dbg.Processes[0].NextStatement;
dbg.Processes[0].StepInto();
CurrentLineBookmark.Remove();
}
catch (System.Exception e)
{
}
}
/// <summary>
/// Шаг с входом из подпрограммы
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void StepOut()
{
try
{
if (IsRunning)
{
workbench.WidgetController.SetStartDebugAndRunDisabled();
dbg.Processes[0].StepOut();
CurrentLineBookmark.Remove();
}
}
catch (System.Exception e)
{
}
}
/// <summary>
/// Идти к курсору
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void RunToCursor()
{
try
{
//cur_brpt = dbg.AddBreakpoint(new SourcecodeSegment((frm.CurrentTabPage.ag as CodeFileDocumentControl).file_name,(frm.CurrentTabPage.ag as CodeFileDocumentControl).TextEditor.ActiveTextAreaControl.Caret.Line + 1,(frm.CurrentTabPage.Tag as CodeFileDocumentControl).TextEditor.ActiveTextAreaControl.Caret.Column + 1,
// (frm.CurrentTabPage.ag as CodeFileDocumentControl).TextEditor.ActiveTextAreaControl.Caret.Column+100), true);
workbench.WidgetController.SetStartDebugAndRunDisabled();
currentBreakpoint = dbg.AddBreakpoint(WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument.FileName, WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument.TextEditor.ActiveTextAreaControl.Caret.Line + 1);
AddGoToBreakPoint(currentBreakpoint);
Status = DebugStatus.None;
dbg.Processes[0].Continue();
//dbg.RemoveBreakpoint(cur_brpt);
CurrentLineBookmark.Remove();
}
catch (System.Exception e)
{
}
}
private Stack<Breakpoint> goto_brs = new Stack<Breakpoint>();
/// <summary>
/// Добавляет Breakpoint по F4
/// </summary>
public void AddGoToBreakPoint(Breakpoint br)
{
goto_brs.Push(br);
}
public string ExecuteImmediate(string stmt)
{
RetValue rv = evaluator.Evaluate(stmt, true);
if (rv.prim_val != null)
return rv.prim_val.ToString();
if (rv.obj_val != null)
return rv.obj_val.AsString;
if (rv.err_mes != null)
return rv.err_mes;
if (rv.syn_err)
return PascalABCCompiler.StringResources.Get("EXPR_VALUE_SYNTAX_ERROR_IN_EXPR");
else
return PascalABCCompiler.StringResources.Get("EXPR_VALUE_ERROR_IN_EXPR");
}
public void AddGoToBreakPoint(string fileName, int line)
{
goto_brs.Push(dbg.AddBreakpoint(fileName, line));
}
/// <summary>
/// Удаляет все F4-Breakpoint
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
private void RemoveGotoBreakpoints()
{
while (goto_brs.Count > 0)
{
Breakpoint br = goto_brs.Pop();
try
{
dbg.RemoveBreakpoint(br);
}
catch (System.Exception e)
{
}
}
}
IRetValue IDebuggerManager.Evaluate(string expr)
{
return Evaluate(expr);
}
string IDebuggerManager.MakeValueView(IValue value)
{
return MakeValueView(value as Value);
}
bool IDebuggerManager.IsRunning
{
get
{
return IsRunning;
}
}
}
}