pascalabcnet/VisualPascalABCNETLinux/IB/Debugger/Debugger.cs
AlexanderZemlyak 0c29ac92b2
Refactoring of Compiler.cs (#2984)
* Add first comments

* Finish commenting for Compile and CompileUnit

* Write TODO sections

* Add a few clarifications

* splitted some functions from compile

* Written some methods from Compile to functions

* Update variable names

* Refactor - stage 1

Refactor GetUsesSection and IsPossibleNameSpace

* Refactor - stage 2

Rename a few functions and variables

* Correct an inaccuracy

* Added comments, look through CompileUnit

* Rename a few functions and add new comments

* Split CompileUnit to Subfunctions

Add IsUnitCompiled, IsUnitInPCU, InitializeNewUnit, GetSourceCode, GenSyntaxTree, GenUnitDocumentation, CheckDLLDirectiveOnlyForLibraries, MatchErrorsToBadNodes, CheckIfUnitModule, SetUseDLLForSystemUnits,
CompileInterfaceDependencies, CompileCurrentUnitInterface, GetImplementationUsesSection, CompileImplementationDependencies, CompileCurrentUnitImplementation

* Added some TODOs

* Return uses_unit_in original name

Renaming of syntax tree nodes leads to internal compiler errors

* Extract GenerateILCode method

* Add checking if recompilation needed method

Needs to be discussed and revised

* Add functions for catch blocks in Compile

* Extract building semantic tree method

Creating main function to be moved to another class

* Rename UnitsSortedList

* Edit CompileUnitsFromDelayedList method

* Change a few variable names, make CreateRCFile function and add comments

* Make code more "user-friendly"

* Add TODOs 31.11.23

* Create PrebuildSemanticTreeActionsMethod

* Refactor semantic checks section in initialize new unit method

* Refactor Adding standard units to uses method

* Return file_name and compiler_directives original names to avoid internal compilation errors

* Refactor GetReferences Method

* Initial refactoring of IncludeNamespaces function

* Create three more methods and wrap important code in regions

* Add TODO's

* Resolve merge conflicts

* Add returned value to ConstructSyntaxTree method

* Fix UnitsSortedList NotFoundError in PCUWriter

* Workaround commit

* Update PABCSystem after tests' changes

* Rename syntax trees in some methods

* Delete CurrentSyntaxUnit variable

* Revert unnecessary project files changes

* Squashed commit of the following:

commit f4d7599f1a39252feac97bd5391f46dfdc25f6f4
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 11:43:29 2023 +0300

    added links to identarranger

commit 3bd5d33e2b2969884e61a3279ff9c353013b57fe
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 11:43:03 2023 +0300

    Change extension for verybasic to yavb

commit 61294c6e7d405e1c68516cc81d3a109e8a1ee295
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Tue Nov 21 09:33:57 2023 +0300

    Change Program Example

commit 86971488341ed6bf13c39e13a513d7ac0c51c285
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Tue Nov 21 09:28:59 2023 +0300

    Add IndentArranger to Compile

commit 2ce50bbbf9db22c4243b247b870f6935ce206d26
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Fri Nov 17 10:00:31 2023 +0300

    Add Semicolon After Each Statement

commit 796309d340e8d8ba730ff9418fa376f34fb7fd36
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Wed Nov 15 18:49:11 2023 +0300

    Add Alpha Version of Python-style If-statement

commit 5eb88f946fe8254b4f5c5a56ed0a567b3be51227
Merge: ab4ce5b0 0162b637
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 15 16:54:26 2023 +0300

    Merge branch 'IndentArranger' into VeryBasicLanguage

commit ab4ce5b0e32d42004726e3dc45cc0d8a65e53f56
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 15 16:53:51 2023 +0300

    Fixes from seminar

commit af74012289d0d08517c13499a2a66cb543fc06d2
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Sun Nov 12 18:57:29 2023 +0300

    finally working!

    fully implemented compatibility

commit 58a39c313324b468d1eec207ba3f5f6eddf74ef2
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Sun Nov 12 11:58:16 2023 +0300

    more compatibility with pabc

    Now verybasic statements translate to pascal compiler
    added .bat script for autobuilding verybasic

commit 0162b6376b8fe970704f26213bf9f0f670dfb12e
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Sun Nov 12 10:06:14 2023 +0300

    Update test.txt

commit 1b759ab1cd7ee2ffeb14afff0418ddf0f30b0399
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Sun Nov 12 10:05:36 2023 +0300

    Add Indent and Unindent Keywords to Generated File

commit cabda7f3985651cff2a8740f1a5bdea8fe7ac892
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Fri Nov 10 21:25:52 2023 +0300

    Add Generation of Output File

commit 306f033d0176ab559e3622b8505427dbe2e0e203
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Thu Nov 9 20:42:18 2023 +0300

    Update IndentArranger.sln

commit 60c0ceced1aa3a7d2e33de0facb1126e295f43b5
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Thu Nov 9 20:41:22 2023 +0300

    Add IndentArranger

commit 1f4556c4573dae154fcc167b41ff6ab9e8122136
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Mon Nov 6 22:48:36 2023 +0300

    Made my own VeryBasicParser project

    Copied some code from SaushkinParser
    Tried to compile it and implement into Pascal
    Doesn't work due to grammatik issue

* Squashed commit of the following:

commit 4e73d9ac3ffef68312f06a74dc83afffcf3ccbee
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 15:08:10 2023 +0300

    Fixed GPPG (i think so at least)

commit e5cfc220828b37fb2f35e565683019716ec3f0ce
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 11:44:27 2023 +0300

    Update Compiler.cs

commit 4698e2e75a5f3b4f523a8bc7733a50e8abb4fca1
Merge: 22aaf2b2 f4d7599f
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 11:43:54 2023 +0300

    Merge branch 'IndentArrangerTemp' into VeryBasicLanguage

commit f4d7599f1a39252feac97bd5391f46dfdc25f6f4
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 11:43:29 2023 +0300

    added links to identarranger

commit 3bd5d33e2b2969884e61a3279ff9c353013b57fe
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 11:43:03 2023 +0300

    Change extension for verybasic to yavb

commit 22aaf2b2508278a9ffce525ffed52419bf72c23f
Merge: c326174f 61294c6e
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 22 11:26:36 2023 +0300

    Merge branch 'IndentArrangerTemp' into VeryBasicLanguage

commit 61294c6e7d405e1c68516cc81d3a109e8a1ee295
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Tue Nov 21 09:33:57 2023 +0300

    Change Program Example

commit 86971488341ed6bf13c39e13a513d7ac0c51c285
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Tue Nov 21 09:28:59 2023 +0300

    Add IndentArranger to Compile

commit c326174ff5ecccf9c4f76d58aea4653f047af049
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Sun Nov 19 15:03:19 2023 +0300

    Added UniversalParserHelper and GPPG

    ShiftReduceParser moved to another project
    UniversalParserHelper project added, most of it copied from SaushkinParser

commit 2ce50bbbf9db22c4243b247b870f6935ce206d26
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Fri Nov 17 10:00:31 2023 +0300

    Add Semicolon After Each Statement

commit 796309d340e8d8ba730ff9418fa376f34fb7fd36
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Wed Nov 15 18:49:11 2023 +0300

    Add Alpha Version of Python-style If-statement

commit 5eb88f946fe8254b4f5c5a56ed0a567b3be51227
Merge: ab4ce5b0 0162b637
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 15 16:54:26 2023 +0300

    Merge branch 'IndentArranger' into VeryBasicLanguage

commit ab4ce5b0e32d42004726e3dc45cc0d8a65e53f56
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Wed Nov 15 16:53:51 2023 +0300

    Fixes from seminar

commit af74012289d0d08517c13499a2a66cb543fc06d2
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Sun Nov 12 18:57:29 2023 +0300

    finally working!

    fully implemented compatibility

commit 58a39c313324b468d1eec207ba3f5f6eddf74ef2
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Sun Nov 12 11:58:16 2023 +0300

    more compatibility with pabc

    Now verybasic statements translate to pascal compiler
    added .bat script for autobuilding verybasic

commit 0162b6376b8fe970704f26213bf9f0f670dfb12e
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Sun Nov 12 10:06:14 2023 +0300

    Update test.txt

commit 1b759ab1cd7ee2ffeb14afff0418ddf0f30b0399
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Sun Nov 12 10:05:36 2023 +0300

    Add Indent and Unindent Keywords to Generated File

commit cabda7f3985651cff2a8740f1a5bdea8fe7ac892
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Fri Nov 10 21:25:52 2023 +0300

    Add Generation of Output File

commit 306f033d0176ab559e3622b8505427dbe2e0e203
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Thu Nov 9 20:42:18 2023 +0300

    Update IndentArranger.sln

commit 60c0ceced1aa3a7d2e33de0facb1126e295f43b5
Author: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Date:   Thu Nov 9 20:41:22 2023 +0300

    Add IndentArranger

commit 1f4556c4573dae154fcc167b41ff6ab9e8122136
Author: Владислав Крылов <krylov@sfedu.ru>
Date:   Mon Nov 6 22:48:36 2023 +0300

    Made my own VeryBasicParser project

    Copied some code from SaushkinParser
    Tried to compile it and implement into Pascal
    Doesn't work due to grammatik issue

* Changed GPPG project NET Framework version, added .dll to gitignore

* Adding UniversalParserHelper to project, trying to include VeryBasic

* Managed dependencies and got VeryBasicLanguage to work

* Change extension of a test program

* Rebuild changes

What should be added to .gitignore?

* Fix bug related to err0524_res_unit.pas

* Rebuild Parser

* Change Indent and Unindent tokens

* Add Symbol Table to ParserABC.y

* Change Indent Space Number to 2

* Add While Loop

* Add Some Operations to Parser

* Make Initialization Node at the Beginning of a program

* Create Grammar.txt

* Test program added

* Add ELIF and SyntaxHighlight

* Fix TableSymbol

* Add Division

* Add Method Call

* Add For Loop

* Rename SPython Parser Folder

* Add documented comments for CompileUnit method

* Added Errors to SPython

Added Errors.cs
Removed link to PABCSaushkinParser
Minor fixes

* Create default constructor for SourceContext

* Move null check of currentUnit to upper level in CompileUnit

* Move CreateMainFunction method from Compiler to TreeConverter class

* Add gppg and parserhelper to visualpascalabcnet dependencies

* Updated installer files to include GPPG and UniversalParserHelper

* Rename GPPG to ShiftReduceParser

* Fix ShiftReduceParser project dependencies

* Fix ShiftReduceParserDependencies second iteration

* Workaround commit

* Update PABCSystem after tests' changes

* Refactor ConvertDirectives method

* Get rid of legacy standard modules code

* Return varBeginOffset and beginOffset calculation to Compiler class

Размещение метода в SyntaxTreeToSemanticTreeConverter не целесообразно. В комментарии видимо имелось в виду что-то другое.

* Workaround commit

* Update PABCSystem after tests' changes

* Revert SPython changes

Оставляем только изменения связанные с рефакторингом.

* Update .gitignore

Co-authored-by: Sun Serega <sunserega2@gmail.com>

* Resolve a few Sun Serega treds

* Delete comments in ParsersController.cs

* Replace specific path with path variable in Studio.bat

* Add comment in Studio.bat file and return FileName in CompilerError.cs

* Fix TreeSubsidiary.cs encoding and sectCore.nsh indents

* Return old version of TestRunner.exe

* Rename some variables and polish a few methods

* Uncomment accidentally commented code

* Replace spaces with tabs

* Changed dll name from GPPG

* Revert "Changed dll name from GPPG"

This reverts commit c485cc8cb787809b7e9dfa8a361e75f17ed39893.

* Update .gitignore

* Delete Libraries/ShiftReduceParser.dll

* Delete bin\ShiftReduceParser.dll

* Replace tabs with spaces

* Update encoding in Studio.bat

* Fix bug with PABCrtl excluded files

* Refactor StandardModule class

* Add null checks to make debuging easier

* Delete unnecessary null checks in SymTable.cs

---------

Co-authored-by: Владислав Крылов <krylov@sfedu.ru>
Co-authored-by: MovchanGitHub <92666028+MovchanGitHub@users.noreply.github.com>
Co-authored-by: Sun Serega <sunserega2@gmail.com>
2023-12-18 22:33:27 +03:00

2265 lines
95 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;
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 List<Mono.Debugger.Soft.TypeMirror> unit_mono_types;
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 List<Mono.Debugger.Soft.TypeMirror> GetUsesMonoTypes(Mono.Debugging.Soft.SoftDebuggerSession session)
{
if (unit_mono_types == null)
{
unit_mono_types = new List<Mono.Debugger.Soft.TypeMirror>();
foreach (var t in unit_types)
unit_mono_types.Add(session.GetType(t.FullName));
}
return unit_mono_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;
if (unit_mono_types != null)
unit_mono_types.Clear();
unit_mono_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 Mono.Debugging.Client.Breakpoint brPoint;
private Mono.Debugging.Client.Breakpoint currentBreakpoint;
private int CurrentLine;
public DebugStatus Status;
private bool MustDebug = false;
public bool IsRunning = false;
public string ExeFileName;
public bool ShowDebugTabs=true;
public PascalABCCompiler.Parsers.IParser parser = null;
EventHandler<EventArgs> debuggerStateEvent;
private Mono.Debugging.Soft.SoftDebuggerSession monoDebuggerSession;
private Mono.Debugging.Client.StackFrame stackFrame;
public DebugHelper()
{
//System.Threading.Thread.CurrentThread.SetApartmentState(System.Threading.ApartmentState.MTA);
dbg = new NDebugger();
monoDebuggerSession = new Mono.Debugging.Soft.SoftDebuggerSession();
//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 Mono.Debugging.Client.Breakpoint CurrentBreakpoint
{
get { return currentBreakpoint; }
set { currentBreakpoint = value; }
}
/// <summary>
/// Добавить Breakpoint в файл file_name строку line
/// </summary>
public Mono.Debugging.Client.Breakpoint AddBreakPoint(string fileName, int line, bool commonBreakpoint)
{
Mono.Debugging.Client.Breakpoint br = null;
bool added = false;
if (!workbench.UserOptions.AlwaysAttachDebuggerAtStart && handle != 0 && commonBreakpoint && this.debuggedProcess == null)
{
Attach(handle, ExeFileName, true,true);
}
foreach (Mono.Debugging.Client.Breakpoint bp in monoDebuggerSession.Breakpoints.GetBreakpoints())
{
if (bp.FileName == fileName && bp.Line == line)
{
added = true;
br = bp;
}
}
if (!added)
br = monoDebuggerSession.Breakpoints.Add(fileName, line);
return br;
}
/// <summary>
/// Получить список Breakpointov в файле file_name
/// </summary>
public List<Mono.Debugging.Client.Breakpoint> GetBreakpointsInFile(string fileName)
{
List<Mono.Debugging.Client.Breakpoint> lst = new List<Mono.Debugging.Client.Breakpoint>();
foreach (Mono.Debugging.Client.Breakpoint bp in monoDebuggerSession.Breakpoints.GetBreakpoints())
{
if (bp.FileName == fileName)
{
lst.Add(bp);
}
}
return lst;
}
/// <summary>
/// Удалить Breakpoint
/// </summary>
public void RemoveBreakpoint(Mono.Debugging.Client.Breakpoint br)
{
monoDebuggerSession.Breakpoints.Remove(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(file_name, 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 DEBUG
Console.WriteLine("null process handle");
#endif
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();
if (WorkbenchServiceFactory.Workbench.DisassemblyWindow != null)
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.parser = CodeCompletion.CodeCompletionController.ParsersController.selectParser(Path.GetExtension(FullFileName).ToLower());
this.PrevFullFileName = FullFileName;
AssemblyHelper.LoadAssembly(fileName);
//dbg.ProcessStarted += debugProcessStarted;
//dbg.ProcessExited += debugProcessExit;
monoDebuggerSession.TargetHitBreakpoint += MonoDebuggerSession_TargetHitBreakpoint;
monoDebuggerSession.AttachToProcess(new Mono.Debugging.Client.ProcessInfo(handle, fileName), new Mono.Debugging.Client.DebuggerSessionOptions());
}
public System.Diagnostics.Process RunWithMonoDebugger(System.Diagnostics.ProcessStartInfo psi, string fileName, string args)
{
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.parser = CodeCompletion.CodeCompletionController.ParsersController.selectParser(Path.GetExtension(FullFileName).ToLower());
this.PrevFullFileName = FullFileName;
AssemblyHelper.LoadAssembly(fileName);
Mono.Debugging.Client.DebuggerSessionOptions dso = new Mono.Debugging.Client.DebuggerSessionOptions();
dso.EvaluationOptions = Mono.Debugging.Client.EvaluationOptions.DefaultOptions.Clone();
//monoDebuggerSession.AttachToProcess(new Mono.Debugging.Client.ProcessInfo(handle, file_name), dso);
Mono.Debugging.Soft.SoftDebuggerStartInfo dsi = new Mono.Debugging.Soft.SoftDebuggerStartInfo("", new Dictionary<string, string>());
dsi.Command = fileName;
dsi.Arguments = args;
dsi.StartArgs = new Mono.Debugging.Soft.SoftDebuggerLaunchArgs("", new Dictionary<string, string>());
dsi.WorkingDirectory = psi.WorkingDirectory;
try
{
monoDebuggerSession.TargetHitBreakpoint += MonoDebuggerSession_TargetHitBreakpoint;
monoDebuggerSession.TargetStopped += MonoDebuggerSession_TargetStopped;
monoDebuggerSession.TargetStarted += MonoDebuggerSession_TargetStarted;
monoDebuggerSession.TargetUnhandledException += MonoDebuggerSession_TargetExceptionThrown;
//monoDebuggerSession.TargetThreadStopped += MonoDebuggerSession_TargetThreadStopped;
monoDebuggerSession.Run(dsi, dso);
int i = 0;
while (Mono.Debugger.Soft.VirtualMachineManager.currentProcess == null && i < 5)
{
System.Threading.Thread.Sleep(100);
i++;
}
workbench.WidgetController.SetDebugTabsVisible(true);
workbench.WidgetController.SetPlayButtonsVisible(true);
workbench.WidgetController.SetDebugStopEnabled();//e.Process.LogMessage += messageEventProc;
workbench.WidgetController.SetStartDebugDisabled();
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, file_name);
var process = (Mono.Debugger.Soft.VirtualMachineManager.currentProcess as Mono.Debugger.Soft.ProcessWrapper).Process;
process.Exited += Process_Exited;
return (Mono.Debugger.Soft.VirtualMachineManager.currentProcess as Mono.Debugger.Soft.ProcessWrapper).Process;
}
catch (System.Exception ex)
{
#if (DEBUG)
Console.WriteLine(ex.Message);
#endif
}
return null;
}
private delegate void EndDebuggerSessionDelegate();
private void EndDebuggerSessionSafe()
{
if (Mono.Debugger.Soft.VirtualMachineManager.currentProcess == null)
return;
if (Exited != null && ExeFileName != null)
Exited(ExeFileName);
curPage = null;
ShowDebugTabs = true;
workbench.WidgetController.SetPlayButtonsVisible(false);
workbench.WidgetController.SetAddExprMenuVisible(false);
workbench.WidgetController.SetDisassemblyMenuVisible(false);
if (DebugWatchListWindowForm.WatchWindow != null)
DebugWatchListWindowForm.WatchWindow.ClearAllSubTrees();
IsRunning = false;
workbench.WidgetController.SetDebugStopDisabled();
workbench.WidgetController.ChangeContinueDebugNameOnStart();
CurrentLineBookmark.Remove();
WorkbenchServiceFactory.DebuggerOperationsService.ClearLocalVarTree();
WorkbenchServiceFactory.DebuggerOperationsService.ClearDebugTabs();
WorkbenchServiceFactory.DebuggerOperationsService.ClearWatch();
if (WorkbenchServiceFactory.Workbench.DisassemblyWindow != null)
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;
parser = null;
FileName = null;
handle = 0;
ExeFileName = null;
FullFileName = null;
PrevFullFileName = null;
stackFrame = null;
monoDebuggerSession.TargetHitBreakpoint -= MonoDebuggerSession_TargetHitBreakpoint;
monoDebuggerSession.TargetStopped -= MonoDebuggerSession_TargetStopped;
monoDebuggerSession.TargetStarted -= MonoDebuggerSession_TargetStarted;
monoDebuggerSession.TargetUnhandledException += MonoDebuggerSession_TargetExceptionThrown;
//monoDebuggerSession.TargetThreadStopped -= MonoDebuggerSession_TargetThreadStopped;
Status = DebugStatus.None;
Mono.Debugger.Soft.VirtualMachineManager.currentProcess = null;
var oldSession = monoDebuggerSession;
monoDebuggerSession = new Mono.Debugging.Soft.SoftDebuggerSession();
foreach (var bp in oldSession.Breakpoints.GetBreakpoints())
monoDebuggerSession.Breakpoints.Add(bp);
}
private void Process_Exited(object sender, EventArgs e)
{
EndDebuggerSession();
}
public void EndDebuggerSession()
{
VisualPABCSingleton.MainForm.Invoke(new EndDebuggerSessionDelegate(EndDebuggerSessionSafe));
}
private void MonoDebuggerSession_TargetThreadStopped(object sender, Mono.Debugging.Client.TargetEventArgs e)
{
stackFrame = e.Thread.Backtrace.GetFrame(0);
if (evaluator != null)
evaluator.SetCurrentMonoFrame(monoDebuggerSession, stackFrame);
JumpToCurrentLine();
}
private void MonoDebuggerSession_TargetStopped(object sender, Mono.Debugging.Client.TargetEventArgs e)
{
stackFrame = e.Thread.Backtrace.GetFrame(0);
if (evaluator != null)
evaluator.SetCurrentMonoFrame(monoDebuggerSession, stackFrame);
JumpToCurrentLine();
workbench.WidgetController.SetStartDebugEnabled();
WorkbenchServiceFactory.DebuggerOperationsService.RefreshPad(new FunctionItem(stackFrame).SubItems);
}
private void MonoDebuggerSession_TargetStarted(object sender, EventArgs e)
{
stackFrame = null;
}
private void MonoDebuggerSession_TargetExceptionThrown(object sender, Mono.Debugging.Client.TargetEventArgs e)
{
monoDebuggerSession.NextLine();
}
private void MonoDebuggerSession_TargetHitBreakpoint(object sender, Mono.Debugging.Client.TargetEventArgs e)
{
stackFrame = e.Thread.Backtrace.GetFrame(0);
if (evaluator != null)
evaluator.SetCurrentMonoFrame(monoDebuggerSession, stackFrame);
JumpToCurrentLine();
workbench.WidgetController.SetStartDebugEnabled();
}
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.SetStartDebugEnabled();
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(file_name, line);
brPoint = new Mono.Debugging.Client.Breakpoint(fileName, line, 1);
monoDebuggerSession.Breakpoints.Add(brPoint);
}
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.SetStartDebugEnabled();
}
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)
{
monoDebuggerSession.Breakpoints.Remove(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;
parser= 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;
public Mono.Debugging.Soft.SoftDebuggerSession DebuggerSession
{
get
{
return monoDebuggerSession;
}
}
public Mono.Debugging.Client.StackFrame StackFrame
{
get
{
return stackFrame;
}
}
void debugProcessStarted(object sender, ProcessEventArgs e)
{
workbench.WidgetController.SetDebugTabsVisible(true);
workbench.WidgetController.SetPlayButtonsVisible(true);
workbench.WidgetController.SetDebugStopEnabled();//e.Process.LogMessage += messageEventProc;
workbench.WidgetController.SetStartDebugDisabled();
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)
evaluator = new ExpressionEvaluator(workbench.VisualEnvironmentCompiler, FileName);
evaluator.SetCurrentMonoFrame(monoDebuggerSession, stackFrame);
return evaluator.Evaluate(expr, false);
}
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 Mono.Debugging.Client.SourceLocation stepin_stmt = null;
private bool tab_changed=false;
private delegate void JumpToLineDelegate(int line);
private delegate void JumpToLinePreActionsDelegate();
private delegate void SetDebugTabsVisibleInvokeDelegate(bool value);
private delegate void SetCurrentLineBookmarkDelegate(string fileName, IDocument document, int makerStartLine, int makerStartColumn, int makerEndLine, int makerEndColumn);
void JumpToLineInvoke(int line)
{
curPage.TextEditor.ActiveTextAreaControl.JumpTo(line, 0);
}
void JumpToLinePreActionsInvoke()
{
workbench.MainForm.Activate();
CurrentLineBookmark.Remove();//udalajem zheltyj kursor otladki
}
void SetCurrentLineBookmarkInvoke(string fileName, IDocument document, int makerStartLine, int makerStartColumn, int makerEndLine, int makerEndColumn)
{
CurrentLineBookmark.SetPosition(fileName, document, makerStartLine, makerStartColumn, makerEndLine, makerEndColumn);
}
void SetDebugTabsVisibleInvoke(bool value)
{
workbench.WidgetController.SetDebugTabsVisible(true);
workbench.WidgetController.SetAddExprMenuVisible(true);
}
/// <summary>
/// Перейти к следующей строке при отладке
/// </summary>
private void JumpToCurrentLine(bool fromBreakpoint = false)
{
workbench.MainForm.Invoke(new JumpToLinePreActionsDelegate(JumpToLinePreActionsInvoke));
//System.Threading.Thread.Sleep(70);
if (stackFrame != null)
{
//debuggedProcess.Modules[0].SymReader.GetMethod(debuggedProcess.SelectedFunction.Token);
string save_PrevFullFileName = PrevFullFileName;
#if (DEBUG)
Console.WriteLine("jump to "+stackFrame.SourceLocation.FileName + ":" + stackFrame.SourceLocation.Line);
#endif
//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.MainForm.Invoke(new SetDebugTabsVisibleInvokeDelegate(SetDebugTabsVisibleInvoke), true);
}
if (stackFrame.SourceLocation.Line == 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;
monoDebuggerSession.StepLine();//vhodim neposredstvenno v proceduru
return;
}
/*else if (AssemblyHelper.IsDebuggerStepThrough(stackFrame))
{
MustDebug = true;
monoDebuggerSession.StepLine();
return;
}*/
else if (is_out)
{
is_out = false;
if (stepin_stmt.FileName == stackFrame.SourceLocation.FileName && stepin_stmt.Line != stackFrame.SourceLocation.Line)
stepin_stmt = stackFrame.SourceLocation;
else
{
monoDebuggerSession.StepLine();
return;
}
}
if (stackFrame.SourceLocation.FileName != this.PrevFullFileName || !WorkbenchServiceFactory.DocumentService.ContainsTab(stackFrame.SourceLocation.FileName))
{
tab_changed = true;
curPage = WorkbenchServiceFactory.FileService.OpenFileForDebug(stackFrame.SourceLocation.FileName);
if (curPage == null)
{
MustDebug = true;
return;
}
PrevFullFileName = stackFrame.SourceLocation.FileName;
}
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(stackFrame.SourceLocation.Line - 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)
{
monoDebuggerSession.NextLine();
return;
}
if (fromBreakpoint)
{
var br = monoDebuggerSession.Breakpoints.Add(stackFrame.SourceLocation.FileName, stackFrame.SourceLocation.Line);
if (br != null && !BreakPointFactory.MustHit(br))
{
if (Status == DebugStatus.StepOver || Status == DebugStatus.StepIn)
{
remove_breakpoints = false;
}
else
{
monoDebuggerSession.Continue();
return;
}
}
}
//CurrentLineBookmark.SetPosition(stackFrame.SourceLocation.file_name, curPage.TextEditor.Document, stackFrame.SourceLocation.Line, 1, stackFrame.SourceLocation.Line,
// len);
curPage.TextEditor.ActiveTextAreaControl.Invoke(new JumpToLineDelegate(JumpToLineInvoke), stackFrame.SourceLocation.Line - 1);
curPage.TextEditor.ActiveTextAreaControl.Invoke(new SetCurrentLineBookmarkDelegate(SetCurrentLineBookmarkInvoke), stackFrame.SourceLocation.FileName, curPage.TextEditor.Document, stackFrame.SourceLocation.Line, 1, stackFrame.SourceLocation.Line,
len);
//curPage.TextEditor.ActiveTextAreaControl.JumpTo(stackFrame.SourceLocation.Line - 1, 0);
if ((Status == DebugStatus.StepOver || Status == DebugStatus.StepIn) && (CurrentLine == stackFrame.SourceLocation.Line
&& save_PrevFullFileName == stackFrame.SourceLocation.FileName))
{
if (curILOffset != stackFrame.Address)
{
curILOffset = stackFrame.Address;
//debuggedProcess.StepOver();
MustDebug = true;
}
CurrentLine = stackFrame.SourceLocation.Line;
//return;
}
else
{
curILOffset = stackFrame.Address;
CurrentLine = stackFrame.SourceLocation.Line;
MustDebug = false;
}
#if (DEBUG)
Console.WriteLine("jumped to " + stackFrame.SourceLocation.FileName + ":" + stackFrame.SourceLocation.Line);
#endif
RemoveBreakpoints();
if (currentBreakpoint != null)
{
monoDebuggerSession.Breakpoints.Remove(currentBreakpoint);
currentBreakpoint = null; //RemoveBreakpoints();
}
}
}
private long 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;
}*/
action();
}
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.CurrentParser.LanguageInformation.
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;
Mono.Debugging.Client.ObjectValue global_lv = null;
Mono.Debugging.Client.ObjectValue disp_lv = null;
Mono.Debugging.Client.ObjectValue ret_lv = null;
List<Mono.Debugging.Client.ObjectValue> unit_lvs = new List<Mono.Debugging.Client.ObjectValue>();
var lvc = stackFrame.GetAllLocals();
foreach (var lv in lvc)
{
if (lv.Name == var)
return new ValueItem(lv);
}
foreach (var lv in lvc)
{
#if (DEBUG)
Console.WriteLine("local var " + lv.Name);
#endif
if (lv.Name.IndexOf("<>local_variables") != -1)
{
foreach (var fi in lv.GetAllChildren())
if (string.Compare(fi.Name, var, true) == 0)
return new ValueItem(fi);
}
if (lv.Name.IndexOf(':') != -1)
{
int pos = lv.Name.IndexOf(':');
string name = lv.Name.Substring(0, pos);
if (string.Compare(name, var, true) == 0)
{
int start_line = Convert.ToInt32(lv.Name.Substring(pos + 1, lv.Name.LastIndexOf(':') - pos - 1));
int end_line = Convert.ToInt32(lv.Name.Substring(lv.Name.LastIndexOf(':') + 1));
if (num_line >= start_line - 1 && num_line <= end_line - 1)
return new ValueItem(lv);
}
}
if (string.Compare(lv.Name, var, true) == 0)
{
return new ValueItem(lv);
}
else if (string.Compare(lv.Name, "self", true) == 0 && stackFrame.GetThisReference() != null)
return new ValueItem(stackFrame.GetThisReference());
else if (lv.Name.Contains("$class_var"))
{
global_lv = lv;
#if (DEBUG)
Console.WriteLine("found global variables class " + lv.Name + " " + lv.TypeName);
#endif
}
else if (lv.Name.Contains("$unit_var"))
unit_lvs.Add(lv);
else if (lv.Name == "$disp$")
disp_lv = lv;//vo vlozhennyh procedurah ssylka na verh zapis aktivacii
else if (lv.Name.StartsWith("$rv"))
ret_lv = lv;//vozvrashaemoe znachenie
}
lvc = stackFrame.GetParameters();
Mono.Debugging.Client.ObjectValue self_lv = null;
foreach (var lv in lvc)
{
if (string.Compare(lv.Name, var, true) == 0)
return new ValueItem(lv);
if (lv.Name == "$obj$")
self_lv = lv;
}
if (var.ToLower() == "result" && ret_lv != null)
return new ValueItem(ret_lv);
if (var.ToLower() == "self")
{
try
{
return new ValueItem(stackFrame.GetThisReference());
}
catch
{
if (self_lv != null)
return new ValueItem(self_lv);
}
}
if (disp_lv != null)//prohodimsja po vlozhennym podprogrammam
{
Mono.Debugging.Client.ObjectValue parent_val = null;
var fields = disp_lv.GetAllChildren();
foreach (var fi in fields)
if (string.Compare(fi.Name, var, true) == 0)
return new ValueItem(fi);
else if (fi.Name == "$parent$")
parent_val = fi;
var pv = parent_val;
while (!pv.IsNull)
{
fields = parent_val.GetAllChildren();
foreach (var fi in fields)
if (string.Compare(fi.Name, var, true) == 0)
return new ValueItem(fi);
else if (fi.Name == "$parent$")
pv = fi;
if (!pv.IsNull)
parent_val = pv;
}
}
if (stackFrame.GetThisReference() != null)
{
var fields = stackFrame.GetThisReference().GetAllChildren();
foreach (var fi in fields)
{
if (string.Compare(fi.Name, var, true) == 0)
return new ValueItem(fi);
}
}
if (self_lv != null)
{
#if (DEBUG)
Console.WriteLine("search in this");
#endif
var fields = self_lv.GetAllChildren();
foreach (var fi in fields)
{
if (string.Compare(fi.Name, var, true) == 0)
return new ValueItem(fi);
}
}
if (global_lv != null)
{
#if (DEBUG)
Console.WriteLine(global_lv.TypeName);
#endif
var tm = monoDebuggerSession.GetType(global_lv.TypeName);
if (tm != null)
{
var tr = new Mono.Debugging.Evaluation.TypeValueReference(stackFrame.SourceBacktrace.GetEvaluationContext(stackFrame.Index, Mono.Debugging.Client.EvaluationOptions.DefaultOptions), tm);
var fields = tr.GetChildReferences(Mono.Debugging.Client.EvaluationOptions.DefaultOptions);
foreach (var fi in fields)
{
if (string.Compare(fi.Name, var, true) == 0)
{
var val = fi.CreateObjectValue(false, Mono.Debugging.Client.EvaluationOptions.DefaultOptions);
val.parentFrame = stackFrame;
return new ValueItem(val);
}
}
}
Type global_type = AssemblyHelper.GetType(global_lv.TypeName);
if (global_type != null)
{
var 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)
{
var tm = monoDebuggerSession.GetType(t.FullName);
#if (DEBUG)
Console.WriteLine("type for static " + tm);
#endif
var tr = new Mono.Debugging.Evaluation.TypeValueReference(stackFrame.SourceBacktrace.GetEvaluationContext(stackFrame.Index, Mono.Debugging.Client.EvaluationOptions.DefaultOptions), tm);
return new BaseTypeItem(tr, t);
}
List<Mono.Debugger.Soft.TypeMirror> types = AssemblyHelper.GetUsesMonoTypes(monoDebuggerSession);
foreach (var tm in types)
{
var tr = new Mono.Debugging.Evaluation.TypeValueReference(stackFrame.SourceBacktrace.GetEvaluationContext(stackFrame.Index, Mono.Debugging.Client.EvaluationOptions.DefaultOptions), tm);
var fields = tr.GetChildReferences(Mono.Debugging.Client.EvaluationOptions.DefaultOptions);
foreach (var fi in fields)
{
if (string.Compare(fi.Name, var, true) == 0)
{
var val = fi.CreateObjectValue(false, Mono.Debugging.Client.EvaluationOptions.DefaultOptions);
val.parentFrame = stackFrame;
return new ValueItem(val);
}
}
Type unit_type = AssemblyHelper.GetType(tm.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.MakeMonoValue(fi.GetRawConstantValue()));
}
}
/*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);
}
}
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);
}
}
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);
}
}
if (ret_nv != null && string.Compare(var, "Result", true) == 0)
return new ValueItem(ret_nv, null);*/
}
else
{
#if (DEBUG)
Console.WriteLine("expression "+var);
#endif
if (evaluator == null)
evaluator = new ExpressionEvaluator(workbench.VisualEnvironmentCompiler, FileName);
evaluator.SetCurrentMonoFrame(monoDebuggerSession, stackFrame);
// 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.monoValue != null)
{
ValueItem vi = new ValueItem(rv.monoValue);
vi.SpecialName = preformat;
return vi;
}
else if (rv.prim_val != null)
{
ValueItem vi = new ValueItem(DebugUtils.MakeMonoValue(rv.prim_val));
vi.SpecialName = preformat;
return vi;
}
else if (rv.monoType != null)
{
return new BaseTypeItem(rv.monoType, rv.managed_type);
}
}
}
catch (System.Exception e)
{
#if (DEBUG)
Console.WriteLine(e.Message + " "+ e.StackTrace);
#endif
}
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 (stackFrame == null)
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 && !oldToolTipControl.IsMouseOver)
{
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.SetStartDebugEnabled();
dbg.Processes[0].Terminate();
}
catch (System.Exception e)
{
}
}
/// <summary>
/// Прервать процесс
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void DebugBreak()
{
try
{
workbench.WidgetController.SetStartDebugEnabled();
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.SetStartDebugDisabled();
CurrentLineBookmark.Remove();
monoDebuggerSession.NextLine();
}
catch (System.Exception e)
{
#if (DEBUG)
Console.WriteLine(e.Message);
#endif
}
}
/// <summary>
/// Продолжить выполнение процесса
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void Continue()
{
try
{
workbench.WidgetController.SetStartDebugDisabled();
monoDebuggerSession.Continue();
CurrentLineBookmark.Remove();
}
catch (System.Exception e)
{
#if (DEBUG)
Console.WriteLine(e.Message);
#endif
}
}
/// <summary>
/// Шаг с входом в подпрограмму
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void StepInto()
{
try
{
workbench.WidgetController.SetStartDebugDisabled();
stepin_stmt = monoDebuggerSession.ActiveThread.Backtrace.GetFrame(0).SourceLocation;
monoDebuggerSession.StepLine();
CurrentLineBookmark.Remove();
}
catch (System.Exception e)
{
#if (DEBUG)
Console.WriteLine(e.Message);
#endif
}
}
/// <summary>
/// Шаг с входом из подпрограммы
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
public void StepOut()
{
try
{
if (IsRunning)
{
workbench.WidgetController.SetStartDebugDisabled();
monoDebuggerSession.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.SetStartDebugDisabled();
currentBreakpoint = monoDebuggerSession.Breakpoints.Add(WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument.FileName, WorkbenchServiceFactory.DocumentService.CurrentCodeFileDocument.TextEditor.ActiveTextAreaControl.Caret.Line + 1);
AddGoToBreakPoint(currentBreakpoint);
Status = DebugStatus.None;
monoDebuggerSession.Continue();
//dbg.RemoveBreakpoint(cur_brpt);
CurrentLineBookmark.Remove();
}
catch (System.Exception e)
{
}
}
private Stack<Mono.Debugging.Client.Breakpoint> goto_brs = new Stack<Mono.Debugging.Client.Breakpoint>();
/// <summary>
/// Добавляет Breakpoint по F4
/// </summary>
public void AddGoToBreakPoint(Mono.Debugging.Client.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(monoDebuggerSession.Breakpoints.Add(fileName, line));
}
/// <summary>
/// Удаляет все F4-Breakpoint
/// </summary>
[HandleProcessCorruptedStateExceptionsAttribute]
private void RemoveGotoBreakpoints()
{
while (goto_brs.Count > 0)
{
Mono.Debugging.Client.Breakpoint br = goto_brs.Pop();
try
{
monoDebuggerSession.Breakpoints.Remove(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;
}
}
}
}