Debugger: Inspect/Evaluate windows, when opened from watches or each-other transfer settings for eval-flags and converter

This commit is contained in:
Martin 2022-08-05 16:51:58 +02:00
parent f3bf79fa35
commit 847436a56f
6 changed files with 140 additions and 43 deletions

View File

@ -49,7 +49,7 @@ uses
LazarusIDEStrConsts, BaseDebugManager, InputHistory, IDEProcs, Debugger, LazarusIDEStrConsts, BaseDebugManager, InputHistory, IDEProcs, Debugger,
IdeDebuggerWatchResPrinter, IdeDebuggerWatchResult, IdeDebuggerOpts, IdeDebuggerWatchResPrinter, IdeDebuggerWatchResult, IdeDebuggerOpts,
IdeDebuggerFpDbgValueConv, WatchInspectToolbar, DebuggerDlg, DebuggerStrConst, IdeDebuggerFpDbgValueConv, WatchInspectToolbar, DebuggerDlg, DebuggerStrConst,
IdeDebuggerStringConstants, EnvironmentOpts; IdeDebuggerStringConstants, IdeDebuggerBase, EnvironmentOpts;
type type
@ -87,7 +87,7 @@ type
public public
constructor Create(TheOwner: TComponent); override; constructor Create(TheOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
procedure Execute(const AExpression: String); procedure Execute(const AExpression: String; AWatch: TWatch = nil);
property EvalExpression: string read GetEvalExpression write SetEvalExpression; property EvalExpression: string read GetEvalExpression write SetEvalExpression;
end; end;
@ -161,9 +161,12 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TEvaluateDlg.Execute(const AExpression: String); procedure TEvaluateDlg.Execute(const AExpression: String; AWatch: TWatch);
begin begin
SetEvalExpression(AExpression); if AWatch <> nil then
WatchInspectNav1.ReadFromWatch(AWatch, AExpression)
else
SetEvalExpression(AExpression);
end; end;
procedure TEvaluateDlg.DoAddWatch(Sender: TObject); procedure TEvaluateDlg.DoAddWatch(Sender: TObject);
@ -288,8 +291,13 @@ begin
end; end;
procedure TEvaluateDlg.DoAddInspect(Sender: TObject); procedure TEvaluateDlg.DoAddInspect(Sender: TObject);
var
w: TIdeWatch;
begin begin
DebugBoss.Inspect(WatchInspectNav1.Expression); w := nil;
if WatchInspectNav1.CurrentWatchValue <> nil then
w := WatchInspectNav1.CurrentWatchValue.Watch;
DebugBoss.Inspect(WatchInspectNav1.Expression, w);
end; end;
procedure TEvaluateDlg.SetEvalExpression(const NewExpression: string); procedure TEvaluateDlg.SetEvalExpression(const NewExpression: string);

View File

@ -127,7 +127,7 @@ type
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
procedure Execute(const AExpression: ansistring); procedure Execute(const AExpression: ansistring; AWatch: TWatch = nil);
end; end;
implementation implementation
@ -1164,9 +1164,12 @@ begin
end; end;
procedure TIDEInspectDlg.Execute(const AExpression: ansistring); procedure TIDEInspectDlg.Execute(const AExpression: ansistring; AWatch: TWatch);
begin begin
WatchInspectNav1.Execute(AExpression); if AWatch <> nil then
WatchInspectNav1.ReadFromWatch(AWatch, AExpression)
else
WatchInspectNav1.Execute(AExpression);
end; end;
procedure TIDEInspectDlg.DoWatchUpdated(const ASender: TIdeWatches; procedure TIDEInspectDlg.DoWatchUpdated(const ASender: TIdeWatches;
@ -1318,8 +1321,13 @@ begin
end; end;
procedure TIDEInspectDlg.DoAddEval(Sender: TObject); procedure TIDEInspectDlg.DoAddEval(Sender: TObject);
var
w: TIdeWatch;
begin begin
DebugBoss.EvaluateModify(WatchInspectNav1.Expression); w := nil;
if WatchInspectNav1.CurrentWatchValue <> nil then
w := WatchInspectNav1.CurrentWatchValue.Watch;
DebugBoss.EvaluateModify(WatchInspectNav1.Expression, w);
end; end;
procedure TIDEInspectDlg.DoAddWatch(Sender: TObject); procedure TIDEInspectDlg.DoAddWatch(Sender: TObject);

View File

@ -750,7 +750,7 @@ var
begin begin
CurWatch := GetSelected; CurWatch := GetSelected;
if CurWatch <> nil then if CurWatch <> nil then
DebugBoss.EvaluateModify(CurWatch.Expression); DebugBoss.EvaluateModify(CurWatch.Expression, CurWatch);
end; end;
procedure TWatchesDlg.actInspectExecute(Sender: TObject); procedure TWatchesDlg.actInspectExecute(Sender: TObject);
@ -759,7 +759,7 @@ var
begin begin
CurWatch := GetSelected; CurWatch := GetSelected;
if CurWatch <> nil then if CurWatch <> nil then
DebugBoss.Inspect(CurWatch.Expression); DebugBoss.Inspect(CurWatch.Expression, CurWatch);
end; end;
procedure TWatchesDlg.actDisableSelectedExecute(Sender: TObject); procedure TWatchesDlg.actDisableSelectedExecute(Sender: TObject);

View File

@ -52,7 +52,8 @@ uses
LazDebuggerIntf, LazDebuggerIntf,
IdeDebuggerOpts, IdeDebuggerOpts,
// IDE // IDE
Debugger, SourceMarks, Project, ProjectDefs, LazarusIDEStrConsts; Debugger, IdeDebuggerBase, SourceMarks, Project, ProjectDefs,
LazarusIDEStrConsts;
type type
TDebugDialogType = ( TDebugDialogType = (
@ -188,8 +189,8 @@ type
out Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract; out Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract;
function GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract; function GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract;
procedure EvaluateModify(const AExpression: String); virtual; abstract; procedure EvaluateModify(const AExpression: String; AWatch: TWatch = nil); virtual; abstract;
procedure Inspect(const AExpression: String); virtual; abstract; procedure Inspect(const AExpression: String; AWatch: TWatch = nil); virtual; abstract;
function DoCreateBreakPoint(const AFilename: string; ALine: integer; function DoCreateBreakPoint(const AFilename: string; ALine: integer;
WarnIfNoDebugger: boolean): TModalResult; virtual; abstract; WarnIfNoDebugger: boolean): TModalResult; virtual; abstract;
@ -213,8 +214,11 @@ type
procedure CreateDebugDialog(Sender: TObject; aFormName: string; procedure CreateDebugDialog(Sender: TObject; aFormName: string;
var AForm: TCustomForm; DoDisableAutoSizing: boolean); virtual; abstract; var AForm: TCustomForm; DoDisableAutoSizing: boolean); virtual; abstract;
procedure ViewDebugDialog(const ADialogType: TDebugDialogType; procedure ViewDebugDialog(const ADialogType: TDebugDialogType;
BringToFront: Boolean = True; Show: Boolean = true; BringToFront: Boolean = true;
DoDisableAutoSizing: boolean = false); virtual; abstract; Show: Boolean = true;
DoDisableAutoSizing: boolean = false;
InitFromSourceEdit: boolean = True
); virtual; abstract;
procedure ViewDisassembler(AnAddr: TDBGPtr; procedure ViewDisassembler(AnAddr: TDBGPtr;
BringToFront: Boolean = True; Show: Boolean = true; BringToFront: Boolean = True; Show: Boolean = true;
DoDisableAutoSizing: boolean = false); virtual; abstract; DoDisableAutoSizing: boolean = false); virtual; abstract;

View File

@ -58,9 +58,9 @@ uses
BreakPointsdlg, BreakPropertyDlg, LocalsDlg, WatchPropertyDlg, CallStackDlg, BreakPointsdlg, BreakPropertyDlg, LocalsDlg, WatchPropertyDlg, CallStackDlg,
EvaluateDlg, RegistersDlg, AssemblerDlg, DebugOutputForm, ExceptionDlg, EvaluateDlg, RegistersDlg, AssemblerDlg, DebugOutputForm, ExceptionDlg,
InspectDlg, DebugEventsForm, PseudoTerminalDlg, FeedbackDlg, ThreadDlg, InspectDlg, DebugEventsForm, PseudoTerminalDlg, FeedbackDlg, ThreadDlg,
HistoryDlg, ProcessDebugger, DbgIntfBaseTypes, DbgIntfDebuggerBase, HistoryDlg, ProcessDebugger, IdeDebuggerBase, DbgIntfBaseTypes,
DbgIntfMiscClasses, DbgIntfPseudoTerminal, LazDebuggerIntf, DbgIntfDebuggerBase, DbgIntfMiscClasses, DbgIntfPseudoTerminal,
LazDebuggerIntfBaseTypes, BaseDebugManager; LazDebuggerIntf, LazDebuggerIntfBaseTypes, BaseDebugManager;
type type
@ -253,8 +253,8 @@ type
EvalFlags: TWatcheEvaluateFlags = []): Boolean; override; EvalFlags: TWatcheEvaluateFlags = []): Boolean; override;
function Modify(const AExpression, ANewValue: String): Boolean; override; function Modify(const AExpression, ANewValue: String): Boolean; override;
procedure EvaluateModify(const AExpression: String); override; procedure EvaluateModify(const AExpression: String; AWatch: TWatch = nil); override;
procedure Inspect(const AExpression: String); override; procedure Inspect(const AExpression: String; AWatch: TWatch = nil); override;
function GetFullFilename(const AUnitinfo: TDebuggerUnitInfo; out Filename: string; function GetFullFilename(const AUnitinfo: TDebuggerUnitInfo; out Filename: string;
AskUserIfNotFound: Boolean): Boolean; override; AskUserIfNotFound: Boolean): Boolean; override;
@ -282,7 +282,12 @@ type
// Dialog routines // Dialog routines
procedure CreateDebugDialog(Sender: TObject; aFormName: string; procedure CreateDebugDialog(Sender: TObject; aFormName: string;
var AForm: TCustomForm; DoDisableAutoSizing: boolean); override; var AForm: TCustomForm; DoDisableAutoSizing: boolean); override;
procedure ViewDebugDialog(const ADialogType: TDebugDialogType; BringToFront: Boolean = true; Show: Boolean = true; DoDisableAutoSizing: boolean = false); override; procedure ViewDebugDialog(const ADialogType: TDebugDialogType;
BringToFront: Boolean = true;
Show: Boolean = true;
DoDisableAutoSizing: boolean = false;
InitFromSourceEdit: boolean = True
); override;
procedure ViewDisassembler(AnAddr: TDBGPtr; procedure ViewDisassembler(AnAddr: TDBGPtr;
BringToFront: Boolean = True; Show: Boolean = true; BringToFront: Boolean = True; Show: Boolean = true;
DoDisableAutoSizing: boolean = false); override; DoDisableAutoSizing: boolean = false); override;
@ -1658,7 +1663,8 @@ begin
end; end;
procedure TDebugManager.ViewDebugDialog(const ADialogType: TDebugDialogType; procedure TDebugManager.ViewDebugDialog(const ADialogType: TDebugDialogType;
BringToFront: Boolean; Show: Boolean; DoDisableAutoSizing: boolean); BringToFront: Boolean; Show: Boolean; DoDisableAutoSizing: boolean;
InitFromSourceEdit: boolean);
const const
DEBUGDIALOGCLASS: array[TDebugDialogType] of TDebuggerDlgClass = ( DEBUGDIALOGCLASS: array[TDebugDialogType] of TDebuggerDlgClass = (
TDbgOutputForm, TDbgEventsForm, TBreakPointsDlg, TWatchesDlg, TLocalsDlg, TDbgOutputForm, TDbgEventsForm, TBreakPointsDlg, TWatchesDlg, TLocalsDlg,
@ -1711,19 +1717,21 @@ begin
then begin then begin
TAssemblerDlg(CurDialog).SetLocation(FDebugger, FCurrentLocation.Address); TAssemblerDlg(CurDialog).SetLocation(FDebugger, FCurrentLocation.Address);
end; end;
if (CurDialog is TIDEInspectDlg) and (SourceEditorManager.GetActiveSE <> nil) if InitFromSourceEdit then begin
then begin if (CurDialog is TIDEInspectDlg) and (SourceEditorManager.GetActiveSE <> nil)
if SourceEditorManager.GetActiveSE.SelectionAvailable then then begin
TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection) if SourceEditorManager.GetActiveSE.SelectionAvailable then
else TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection)
TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret); else
end; TIDEInspectDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret);
if (CurDialog is TEvaluateDlg) and (SourceEditorManager.GetActiveSE <> nil) end;
then begin if (CurDialog is TEvaluateDlg) and (SourceEditorManager.GetActiveSE <> nil)
if SourceEditorManager.GetActiveSE.SelectionAvailable then then begin
TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection) if SourceEditorManager.GetActiveSE.SelectionAvailable then
else TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.Selection)
TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret); else
TEvaluateDlg(CurDialog).Execute(SourceEditorManager.GetActiveSE.GetOperandAtCurrentCaret);
end;
end; end;
end; end;
if not DoDisableAutoSizing then if not DoDisableAutoSizing then
@ -3011,21 +3019,22 @@ begin
and FDebugger.Modify(AExpression, ANewValue); and FDebugger.Modify(AExpression, ANewValue);
end; end;
procedure TDebugManager.EvaluateModify(const AExpression: String); procedure TDebugManager.EvaluateModify(const AExpression: String; AWatch: TWatch
);
begin begin
if Destroying then Exit; if Destroying then Exit;
ViewDebugDialog(ddtEvaluate); ViewDebugDialog(ddtEvaluate, True, True, False, False);
if FDialogs[ddtEvaluate] <> nil then if FDialogs[ddtEvaluate] <> nil then
TEvaluateDlg(FDialogs[ddtEvaluate]).EvalExpression := AExpression; TEvaluateDlg(FDialogs[ddtEvaluate]).Execute(AExpression, AWatch);
end; end;
procedure TDebugManager.Inspect(const AExpression: String); procedure TDebugManager.Inspect(const AExpression: String; AWatch: TWatch);
begin begin
if Destroying then Exit; if Destroying then Exit;
ViewDebugDialog(ddtInspect); // TODO: If not yet open, this will get Expression from SourceEdit, and trigger uneeded eval. ViewDebugDialog(ddtInspect, True, True, False, False);
if FDialogs[ddtInspect] <> nil then if FDialogs[ddtInspect] <> nil then
begin begin
TIDEInspectDlg(FDialogs[ddtInspect]).Execute(AExpression); TIDEInspectDlg(FDialogs[ddtInspect]).Execute(AExpression, AWatch);
end; end;
end; end;

View File

@ -8,7 +8,7 @@ uses
Classes, SysUtils, Forms, Controls, ComCtrls, Buttons, StdCtrls, ExtCtrls, Classes, SysUtils, Forms, Controls, ComCtrls, Buttons, StdCtrls, ExtCtrls,
Menus, LCLType, SpinEx, IDEImagesIntf, LazUTF8, LazClasses, LazDebuggerIntf, Menus, LCLType, SpinEx, IDEImagesIntf, LazUTF8, LazClasses, LazDebuggerIntf,
IdeDebuggerStringConstants, ArrayNavigationFrame, IdeDebuggerOpts, Debugger, IdeDebuggerStringConstants, ArrayNavigationFrame, IdeDebuggerOpts, Debugger,
IdeDebuggerFpDbgValueConv; IdeDebuggerFpDbgValueConv, IdeDebuggerBase;
type type
@ -92,6 +92,8 @@ type
FThreadsMonitor: TIdeThreadsMonitor; FThreadsMonitor: TIdeThreadsMonitor;
FCallStackMonitor: TIdeCallStackMonitor; FCallStackMonitor: TIdeCallStackMonitor;
FInspectWatches: TCurrentWatches; FInspectWatches: TCurrentWatches;
FUpdateCount: Integer;
FExecAfterUpdate: Boolean;
procedure ArrayNavSizeChanged(Sender: TObject); procedure ArrayNavSizeChanged(Sender: TObject);
procedure DoDbpConvMenuClicked(Sender: TObject); procedure DoDbpConvMenuClicked(Sender: TObject);
@ -124,7 +126,12 @@ type
ADefaultEvalOpts: TWatcheEvaluateFlags ADefaultEvalOpts: TWatcheEvaluateFlags
); );
procedure BeginUpdate;
procedure EndUpdate;
procedure InitWatch(AWatch: TIdeWatch); procedure InitWatch(AWatch: TIdeWatch);
procedure ReadFromWatch(AWatch: TWatch; AlternateExpression: String = '');
procedure Execute(const AnExpression: ansistring; ASkipHistory: Boolean = False); procedure Execute(const AnExpression: ansistring; ASkipHistory: Boolean = False);
procedure UpdateData(AForceClear: Boolean = False);// context changed instead procedure UpdateData(AForceClear: Boolean = False);// context changed instead
procedure DoContextChanged; procedure DoContextChanged;
@ -616,6 +623,21 @@ begin
FDefaultEvalOpts := ADefaultEvalOpts; FDefaultEvalOpts := ADefaultEvalOpts;
end; end;
procedure TWatchInspectNav.BeginUpdate;
begin
if FUpdateCount = 0 then
FExecAfterUpdate := False;
inc(FUpdateCount);
end;
procedure TWatchInspectNav.EndUpdate;
begin
if FUpdateCount > 0 then
dec(FUpdateCount);
if (FUpdateCount = 0) and FExecAfterUpdate then
UpdateData(True);
end;
procedure TWatchInspectNav.InitWatch(AWatch: TIdeWatch); procedure TWatchInspectNav.InitWatch(AWatch: TIdeWatch);
var var
Opts: TWatcheEvaluateFlags; Opts: TWatcheEvaluateFlags;
@ -640,6 +662,46 @@ begin
AWatch.FpDbgConverter := Conv; AWatch.FpDbgConverter := Conv;
end; end;
procedure TWatchInspectNav.ReadFromWatch(AWatch: TWatch;
AlternateExpression: String);
var
i: Integer;
begin
BeginUpdate;
try
btnUseInstance.Down := defClassAutoCast in AWatch.EvaluateFlags;
btnFunctionEval.Down := defAllowFunctionCall in AWatch.EvaluateFlags;
if defSkipValConv in AWatch.EvaluateFlags then begin
if popConverter.Items.Count > 1 then
popConverter.Items[1].Click;
end
else if AWatch.FpDbgConverter = nil then begin
if popConverter.Items.Count > 0 then
popConverter.Items[0].Click;
end
else begin
i := DebuggerOptions.FpDbgConverterConfig.Count - 1;
while i >= 0 do begin
if DebuggerOptions.FpDbgConverterConfig.IdeItems[i] = AWatch.FpDbgConverter then begin
if popConverter.Items.Count > i+2 then
popConverter.Items[i+2].Click;
break;
end;
dec(i);
end;
end;
if AlternateExpression <> '' then
Execute(AlternateExpression)
else
Execute(AWatch.Expression);
finally
EndUpdate;
end;
end;
procedure TWatchInspectNav.Execute(const AnExpression: ansistring; procedure TWatchInspectNav.Execute(const AnExpression: ansistring;
ASkipHistory: Boolean); ASkipHistory: Boolean);
begin begin
@ -709,6 +771,12 @@ var
expr: String; expr: String;
Conv: TIdeFpDbgConverterConfig; Conv: TIdeFpDbgConverterConfig;
begin begin
if FUpdateCount > 0 then begin
FExecAfterUpdate := True;
exit;
end;
FExecAfterUpdate := False;
if AForceClear then if AForceClear then
FInspectWatches.Clear; FInspectWatches.Clear;